#include “DW3000.h”
#include <wire.h>
#include <Adafruit_SSD1306.h>
#define APP_NAME “SS TWR INIT v1.0”
#define SCREEN_WIDTH 128 // Ancho de pantalla OLED en píxeles
#define SCREEN_HEIGHT 64 // Altura de pantalla OLED en píxeles
#define OLED_RESET 4 // Restablecer pin # (o -1 si comparte el pin de restablecimiento de Arduino)
#define SCREEN_ADDRESS 0x3C // 0x3D para 128×64, 0x3C para 128×32
Adafruit_SSD1306 Monitor(SCREEN_WIDTH, SCREEN_HEIGHT, &wire, OLED_RESET);
Pines de conexión
constante uint8_t PIN_RST = 27; Restablecer terminal
constante uint8_t PIN_IRQ = 34; IRQ Pin
constante uint8_t PIN_SS = 4; Seleccionar PIN SPI
/* Configuración de comunicación predeterminada. Utilice el modo DW predeterminado que no es STS. */
estático dwt_config_t establecimiento = {
5, /* Número de canal. */
DWT_PLEN_128, /* La longitud del preámbulo. Usado solo en TX. */
DWT_PAC8, /* Tamaño del fragmento de recuperación del preámbulo. Se usa solo en RX. */
9, /* Código del preámbulo TX. Usado solo en TX. */
9, /* Código de preámbulo RX. Se usa solo en RX. */
1, /* 0 usa SFD estándar de 8 símbolos, 1 usa SFD de 8 símbolos no estándar, 2 usa SFD no estándar de 16 símbolos, 3 usa 4z tipo SDF de 8 símbolos */
DWT_BR_6M8, /*Datos. */
DWT_PHRMODE_STD, /* Modo de encabezado PHY. */
DWT_PHRRATE_STD, /* Tasa de encabezado PHY. */
(129 + 8 – 8), /* Tiempo de espera SFD (longitud del preámbulo + 1 + longitud SFD – tamaño PAC). Se usa solo en RX. */
DWT_STS_MODE_OFF, /* STS no es válido */
DWT_STS_LEN_64,/* La longitud STS se refiere a la tolerancia para el tipo de enumeración dwt_sts_lengths_e */
DWT_PDOA_M0 /* El modo PDOA está desactivado */
};
/* Período de retardo de intervario, en milisegundos. */
#define RNG_DELAY_MS 1000
/* Valor de retardo de antena predeterminado para 64 MHz PRF. Véase la nota 2 infra. */
#define TX_ANT_DLY 16385
#define RX_ANT_DLY 16385
/* Fotogramas utilizados en el proceso de variado. Véase la nota 3 infra. */
estático uint8_t tx_poll_msg[] = {0x41, 0x88, 0, 0xCA, 0xDE, ‘W’, “Oh.”, ‘V’, 「E」, 0xE0, 0, 0};
estático uint8_t rx_resp_msg[] = {0x41, 0x88, 0, 0xCA, 0xDE, ‘V’, 「E」, ‘W’, “Oh.”, 0xE1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
/* La longitud de la intersección del mensaje (hasta el código de función), véase la nota 3 a continuación). */
#define ALL_MSG_COMMON_LEN 10
/* El índice para acceder a algunos de los campos del marco definido anteriormente. */
#define ALL_MSG_SN_IDX 2
#define RESP_MSG_POLL_RX_TS_IDX 10
#define RESP_MSG_RESP_TX_TS_IDX 14
#define RESP_MSG_TS_LEN 4
/* Número de secuencia de tramas que se incrementará después de cada transmisión. */
estático uint8_t frame_seq_nb = 0;
/* Un búfer que contiene mensajes de respuesta recibidos.
Su tamaño se ajusta al fotograma más largo que se supone que debe procesar este código de ejemplo. */
#define RX_BUF_LEN 20
estático uint8_t rx_buffer[RX_BUF_LEN];
/* Guarde una copia del estado del registro de estado aquí como referencia para que pueda examinarlo en los puntos de interrupción de depuración. */
estático uint32_t status_reg = 0;
/* Retardo entre fotogramas, en microsegundos UWB. Véase la nota 1 infra. */
#ifdef RPI_BUILD
#define POLL_TX_TO_RESP_RX_DLY_UUS 240
#endif RPI_BUILD
#ifdef STM32F429xx
#define POLL_TX_TO_RESP_RX_DLY_UUS 240
#endif //STM32F429xx
#ifdef NRF52840_XXAA
#define POLL_TX_TO_RESP_RX_DLY_UUS 240
#endif //NRF52840_XXAA
/* Tiempo de espera de recepción de respuesta. Véase la nota 5 infra. */
#ifdef RPI_BUILD
#define RESP_RX_TIMEOUT_UUS 270
#endif //RPI_BUILD
#ifdef STM32F429xx
#define RESP_RX_TIMEOUT_UUS 210
#endif //STM32F429xx
#ifdef NRF52840_XXAA
#define RESP_RX_TIMEOUT_UUS 400
#endif //NRF52840_XXAA
#define POLL_TX_TO_RESP_RX_DLY_UUS 240
#define RESP_RX_TIMEOUT_UUS 400
/* Guarde una copia del tiempo y la distancia de vuelo calculados aquí como referencia para que pueda examinarlo en los puntos de interrupción de depuración. */
estático doble Toph;
estático doble distancia;
/* PG_DELAY y los valores de registro TX_POWER reflejan el ancho de banda y la potencia del espectro en la corriente
Temperatura. Estos valores se pueden calibrar antes de tomar medidas de referencia. Véase la nota 2 infra. */
Extern dwt_txconfig_t txconfig_options;
No válido arreglo()
{
UART_init();
test_run_info((Unsigned chamuscar *)APP_NAME);
alambre.empezar();
Si (!Monitor.empezar(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS))
{
serial.Printrung(F(“Error al asignar SSD1306”));
para (;;); No continúes, bucle para siempre
}
Monitor.Borrar pantalla();
/* Establecer velocidad SPI, DW3000 soporta hasta 38 MHz */
/* Restablecer DW IC */
Spibigin(PIN_IRQ, PIN_RST);
Selección de SPI(PIN_SS);
demorar(2); Tiempo necesario para iniciar DW3000 (puede pasar de INIT_RC a IDLE_RC o esperar el evento SPIRDY)
mientras (!dwt_checkidlerc()) Debe asegurarse de que el CI DW esté IDLE_RC antes de continuar
{
UART_puts(“Error de inactividad\r\n”);
mientras (1) ;
}
Si (dwt_initialise(DWT_DW_INIT) == DWT_ERROR)
{
UART_puts(“Error de inicialización\r\n”);
mientras (1) ;
}
Ahora habilite los LED para la depuración de modo que el LED D1 de cada TX parpadee en la placa de blindaje EVAL roja DW3000.
dwt_setleds(DWT_LEDS_ENABLE | DWT_LEDS_INIT_BLINK);
/* Configurar DW IC. Véase la nota 6 infra. */
Si (dwt_configure(&config)) // Si la calibración PLL o RX falla y devuelve DWT_ERROR dwt_configure, el host debe restablecer el dispositivo
{
UART_puts(“Error de configuración\r\n”);
mientras (1) ;
}
/* Establecer parámetros de espectro TX (potencia, retardo PG y recuento PG) */
dwt_configuretxrf(&txconfig_options);
/* Aplica el valor predeterminado de retardo de antena. Véase la nota 2 infra. */
dwt_setrxantennadelay(RX_ANT_DLY);
dwt_settxantennadelay(TX_ANT_DLY);
/* Establezca el retraso de respuesta esperado y el tiempo de espera. Véanse las notas 1 y 5 infra.
En este ejemplo, siempre se procesa un fotograma entrante con el mismo retraso y tiempo de espera, por lo que estos valores solo se pueden establecer una vez aquí. */
dwt_setrxaftertxdelay(POLL_TX_TO_RESP_RX_DLY_UUS);
dwt_setrxtimeout(RESP_RX_TIMEOUT_UUS);
/* A continuación, puede habilitar las salidas de estado TX/RX para GPIO 5 y 6 para ayudar con la depuración, y también habilitar el TX/RX LED.
No utilice LED en aplicaciones reales de baja potencia. */
dwt_setlnapamode(DWT_LNA_ENABLE | DWT_PA_ENABLE);
}
No válido bucle()
{
/* Escriba datos de trama en DW IC y prepárese para la transmisión. Véase la nota 7 infra. */
tx_poll_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS_BIT_MASK);
dwt_writetxdata(tamaño(tx_poll_msg), tx_poll_msg, 0); /* Desplazamiento cero en el búfer TX. */
dwt_writetxfctrl(tamaño(tx_poll_msg), 0, 1); /* Compensación cero del búfer TX, rango. */
/* Indica que se espera que una respuesta inicie un envío y la recepción se habilita automáticamente después de enviar la trama, con un retraso.
dwt_setrxaftertxdelay establecido por (). */
dwt_starttx(DWT_START_TX_IMMEDIATE | DWT_RESPONSE_EXPECTED);
/* Suponiendo que el envío se realizó correctamente, sondee la recepción de fotogramas o el error/tiempo de espera. Véase la nota 8 infra. */
mientras (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG_BIT_MASK |SYS_STATUS_ALL_RX_TO |SYS_STATUS_ALL_RX_ERR)))
{ };
/* Incremente el número de secuencia de fotogramas después de enviar el mensaje de sondeo (módulo 256). */
frame_seq_nb++;
Si (status_reg y SYS_STATUS_RXFCG_BIT_MASK)
{
uint32_t frame_len;
/* Borra los eventos de fotogramas RX correctos en el registro de estado de DW IC. */
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG_BIT_MASK);
/* Cuando se recibe una trama, se lee en el búfer local. */
frame_len = dwt_read32bitreg(RX_FINFO_ID) y RXFLEN_MASK;
Si (frame_len <= tamaño(rx_buffer))
{
dwt_readrxdata(rx_buffer, frame_len, 0);
/* Verifique que el marco sea la respuesta esperada del ejemplo complementario “SS TWR Responder”.
El campo de número de secuencia del fotograma no es relevante y se borra para simplificar la validación del fotograma. */
rx_buffer[ALL_MSG_SN_IDX] = 0;
Si (Memmum(rx_buffer, rx_resp_msg, ALL_MSG_COMMON_LEN) == 0)
{
uint32_t poll_tx_ts, resp_rx_ts, poll_rx_ts, resp_tx_ts;
int32_t rtd_init, rtd_resp;
flotar Relación de desplazamiento del reloj ;
/* Obtenga las marcas de tiempo de la encuesta enviada y la respuesta recibida. Véase la nota 9 infra. */
poll_tx_ts = dwt_readtxtimestamplo32();
resp_rx_ts = dwt_readrxtimestamplo32();
/* Lea el valor del integrador de portadores y calcule la relación de desplazamiento del reloj. Véase la nota 11 infra. */
Relación de desplazamiento del reloj = ((flotar)dwt_readclockoffset()) / (uint32_t)(1 << 26);
/* Obtiene la marca de tiempo incrustada en el mensaje de respuesta. */
resp_msg_get_ts(△rx_buffer[RESP_MSG_POLL_RX_TS_IDX]、&poll_rx_ts)。
resp_msg_get_ts(△rx_buffer[RESP_MSG_RESP_TX_TS_IDX]、&resp_tx_ts)。
/* Calcule el tiempo de vuelo y la distancia utilizando la relación de desplazamiento del reloj para compensar las diferencias entre las velocidades de reloj locales y remotas */
rtd_init = resp_rx_ts – poll_tx_ts;
rtd_resp = resp_tx_ts – poll_rx_ts;
Toph = ((rtd_init – rtd_resp * (1 – Relación de desplazamiento del reloj)) / 2.0) * DWT_TIME_UNITS;
distancia = Toph* SPEED_OF_LIGHT;
/* Muestra la distancia calculada en la pantalla LCD. */
SNPRINTF(dist_str, tamaño(dist_str), “DIST: %3.2f m”, distancia);
test_run_info((Unsigned chamuscar *)dist_str);
Monitor.Establecer cursor(15, 0); Pantalla OLED
Monitor.Establecer tamaño de texto(2);
Monitor.Establecer color de texto(Blanco);
Monitor.Impresión(“Distancia”);
Monitor.Establecer cursor(30, 30); Pantalla OLED
Monitor.Establecer tamaño de texto(2);
Monitor.Impresión(distancia);
Monitor.Impresión(“m”);
Monitor.Monitor();
Monitor.Borrar pantalla();
}
}
}
de otra manera
{
/* Borra el evento de error/tiempo de espera de RX en el registro de estado de DW IC. */
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR);
}
/* Realizar un retraso entre intercambios de rango. */
dormir(RNG_DELAY_MS);
}