AVR ATmega328 con DWM1000

0

Hace poco pregunté sobre esto en la pila de Arduino, pero era una pregunta amplia, y he avanzado y acotado los problemas.

Tengo dos Arduino Nano's, cada uno conectado a un DWM1000. Esto es en una tabla de ruptura personalizada y una placa de pruebas. Aquí hay una biblioteca Arduino DWM1000 que utilizo para probar con los tableros. Los bocetos básicos de tx / rx funcionan perfectamente y pueden enviar mensajes de ping-pong.

Esta biblioteca no está completa y necesito más funciones avanzadas para un proyecto en el que estoy trabajando. Así que DecaWave (el fabricante del DWM1000) tiene un controlador completamente escrito para él: (Interfaz de programación de aplicaciones DW1000 con STM32F10x Ejemplos de aplicaciones) Porté las funciones necesarias para usar el chip ATmega.

Al usar el controlador DecaWave, puedo leer / escribir todos los registros pero tengo problemas con los ejemplos básicos de tx / rx. Parece que la transmisión no se está enviando correctamente. Puedo enviar código desde mi única placa utilizando el ejemplo de la biblioteca Arduino, y recibirlo con el ejemplo de rx básico de DecaWave sin errores.

Si envío desde el ejemplo de DecaWave basic tx, y lo recibo del ejemplo de DecaWave basic rx, lo recibo, pero con errores.

A veces estos bits se establecen:

CPLOCK, RXPRD, RXSFDD, RXPHE, SLP2INIT, CLKPLL_LL

Otras veces, estos están configurados:

CPLOCK, RXPRD, RXSFDD, RXPHD, RXRFSL, SLP2INIT, CLKPLL_LL

A partir del código de envío, se establecen los bits apropiados ( TXFRB, TXPRS, TXPHS, TXFRS )

El código de mi controlador DecaWave:

#include <Arduino.h>
#include <SPI.h>
#include <prescaler.h>
#include <deca_device_api.h>
#include <deca_regs.h>
//#include "DW1000.h"
//#include "usart.h"


 static dwt_config_t config = {
     5,               /* Channel number. */
     DWT_PRF_16M,     /* Pulse repetition frequency. */
     DWT_PLEN_1024,   /* Preamble length. Used in TX only. */
     DWT_PAC32,       /* Preamble acquisition chunk size. Used in RX only. */
     4,               /* TX preamble code. Used in TX only. */
     4,               /* RX preamble code. Used in RX only. */
     0,               /* 0 to use standard SFD, 1 to use non-standard SFD. */
     DWT_BR_110K,     /* Data rate. */
     DWT_PHRMODE_STD, /* PHY header mode. */
     (1025 + 64 - 32) /* SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. */
};

 static uint8 tx_msg[] = {0xC5, 0, 'D', 'E', 'C', 'A', 'W', 'A', 'V', 'E', 0, 0};
 /* Index to access to sequence number of the blink frame in the tx_msg array. */
 #define BLINK_FRAME_SN_IDX 1

 /* Inter-frame delay period, in milliseconds. */
 #define TX_DELAY_MS 1000

void reset_DW1000()
{
  digitalWrite(5, LOW);
  pinMode(5, OUTPUT);
  delay(10);
  pinMode(5, INPUT);
  delay(10);
}

void setup()
{
  SPI.begin();
  Serial.begin(9600);
  while (!Serial) { ; };
  delay(50);

  reset_DW1000();
  setClockPrescaler(CLOCK_PRESCALER_8);
  if (dwt_initialise(DWT_LOADNONE) == DWT_ERROR)
  {
      setClockPrescaler(CLOCK_PRESCALER_1);
      Serial.println("INIT FAILED");
      while (1)
      { };
  }
  setClockPrescaler(CLOCK_PRESCALER_1);

  dwt_configure(&config);
}

void loop()
{
  /* Write frame data to DW1000 and prepare transmission. See NOTE 4 below.*/
  dwt_writetxdata(sizeof(tx_msg), tx_msg, 0); /* Zero offset in TX buffer. */
  dwt_writetxfctrl(sizeof(tx_msg), 0, 0); /* Zero offset in TX buffer, no ranging. */

  /* Start transmission. */
  dwt_starttx(DWT_START_TX_IMMEDIATE);

  while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS))
  { };

  /* Clear TX frame sent event. */
  dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);

  /* Execute a delay between transmissions. */
  delay(TX_DELAY_MS);

  /* Increment the blink frame sequence number (modulo 256). */
  tx_msg[BLINK_FRAME_SN_IDX]++;
}

Mi código DecaWave rx rx:

#include <Arduino.h>
#include <SPI.h>
#include <prescaler.h>
#include <deca_device_api.h>
#include <deca_regs.h>
//#include "USART.h"
/*! ----------------------------------------------------------------------------
 *  @file    main.c
 *  @brief   Simple RX example code
 *
 * @attention
 *
 * Copyright 2015 (c) Decawave Ltd, Dublin, Ireland.
 *
 * All rights reserved.
 *
 * @author Decawave
 */

 static dwt_config_t config = {
     5,               /* Channel number. */
     DWT_PRF_16M,     /* Pulse repetition frequency. */
     DWT_PLEN_1024,   /* Preamble length. Used in TX only. */
     DWT_PAC32,       /* Preamble acquisition chunk size. Used in RX only. */
     4,               /* TX preamble code. Used in TX only. */
     4,               /* RX preamble code. Used in RX only. */
     0,               /* 0 to use standard SFD, 1 to use non-standard SFD. */
     DWT_BR_110K,     /* Data rate. */
     DWT_PHRMODE_STD, /* PHY header mode. */
     (1025 + 64 - 32) /* SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. */
};

#define FRAME_LEN_MAX 127
static uint8 rx_buffer[FRAME_LEN_MAX];

static uint32 status_reg = 0;

static uint16 frame_len = 0;

void reset_DW1000()
{
  digitalWrite(5, LOW);
  pinMode(5, OUTPUT);
  delay(10);
  pinMode(5, INPUT);
  delay(10);
}

void debug_register(uint16_t reg, uint8_t len)
{
  uint8_t ar[len];
  dwt_readfromdevice (reg, 0, len, ar) ;
  for (int i=0; i<len; i++)
  {
    Serial.print(i); Serial.print(" = "); Serial.println(ar[i]);
  }
}

void setup()
{
  SPI.begin();
  Serial.begin(9600);
  //initUSART();
  while (!Serial) { ; };
  delay(50);
  Serial.println("Hi hello hi hello fdaffasd?");

  reset_DW1000();
  setClockPrescaler(CLOCK_PRESCALER_8);
  if (dwt_initialise(DWT_LOADNONE) == DWT_ERROR)
  {
      setClockPrescaler(CLOCK_PRESCALER_1);
      Serial.println("INIT FAILED");
      while (1)
      { };
  }
  setClockPrescaler(CLOCK_PRESCALER_1);
  delay(50);

  dwt_configure(&config);
}
void loop()
{
  int i;

  for (i = 0 ; i < FRAME_LEN_MAX; i++ )
  {
      rx_buffer[i] = 0;
  }
  dwt_rxenable(DWT_START_RX_IMMEDIATE);

  while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR))) { ; }

  if (status_reg & SYS_STATUS_RXFCG)
  {
      frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;
      if (frame_len <= FRAME_LEN_MAX)
      {
          dwt_readrxdata(rx_buffer, frame_len, 0);
      }
      dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);
  }
  else
  {
    dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR);
  }
}

EDITAR: Entonces, me está costando mucho pensar que es algo de mi parte, y ahora, ¿puedo pensar que podría haber algún problema con el controlador? Al menos con el dwm1000 específicamente.

Ahora tengo dos DWM1000s conectados con STM32s. Ahora estoy usando la arquitectura de tablero para la cual fue diseñada la api. Tengo exactamente los mismos resultados ...

Si comento el mensaje "dwt_configure (& config);" Soy capaz de recibir mensajes con los bits de error mencionados anteriormente, el rx stm32 imprime "err".

Si utilizo cualquier configuración, nunca recibo ningún mensaje.

Estos módulos aún funcionan bien usando la biblioteca arduino, así que no hay nada de malo en ellos, y tengo 4 módulos que he probado con cada uno.

Por favor, si alguien tiene alguna sugerencia, hágamelo saber. Si no, parece que me moveré a un nuevo chip UWB.

¡Gracias!

Código tx STM32:

#include <mbed.h>
#include "decadriver/deca_device_api.h"
#include "decadriver/deca_regs.h"


static dwt_config_t config = {
    2,               /* Channel number. */
    DWT_PRF_64M,     /* Pulse repetition frequency. */
    DWT_PLEN_1024,   /* Preamble length. Used in TX only. */
    DWT_PAC32,       /* Preamble acquisition chunk size. Used in RX only. */
    9,               /* TX preamble code. Used in TX only. */
    9,               /* RX preamble code. Used in RX only. */
    1,               /* 0 to use standard SFD, 1 to use non-standard SFD. */
    DWT_BR_110K,     /* Data rate. */
    DWT_PHRMODE_STD, /* PHY header mode. */
    (1025 + 64 - 32) /* SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. */
};

DigitalOut myled(PC_13);


static uint8 tx_msg[] = {0xC5, 0, 'D', 'E', 'C', 'A', 'W', 'A', 'V', 'E', 0, 0};

#define BLINK_FRAME_SN_IDX 1

#define TX_DELAY_MS 1000

DigitalInOut pin_rst(PA_10);

void reset_DW1000()
{
  pin_rst.write(0);
  wait(0.01);
  pin_rst.write(1);
}

int main(void)
{
    myled = 0;
    Serial serial(PB_6, PB_7);
    wait(0.5);
    serial.baud(9600);

    pin_rst.output();
    pin_rst.mode(OpenDrain);
    SPI bus(PA_7, PA_6, PA_5);//mosi, miso, clk

    serial.printf("Device ID: %u\r\n", dwt_readdevid());

    reset_DW1000();
    bus.frequency(2000000);
    if (dwt_initialise(DWT_LOADNONE) == DWT_ERROR)
    {
        serial.printf("Error on init11\n\r");
        while (1) { ; };
    }
    bus.frequency(20000000);

    //dwt_configure(&config);

    while(1)
    {
      dwt_writetxdata(sizeof(tx_msg), tx_msg, 0); /* Zero offset in TX buffer. */
      dwt_writetxfctrl(sizeof(tx_msg), 0, 0); /* Zero offset in TX buffer, no ranging. */

      dwt_starttx(DWT_START_TX_IMMEDIATE);

      while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS))
      { };

      dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);

      myled = 1;
      wait(1);
      myled = 0;

      tx_msg[BLINK_FRAME_SN_IDX]++;
    }
}

STM32 código rx:

#include <mbed.h>
#include "decadriver/deca_device_api.h"
#include "decadriver/deca_regs.h"


static dwt_config_t config = {
    2,               /* Channel number. */
    DWT_PRF_64M,     /* Pulse repetition frequency. */
    DWT_PLEN_1024,   /* Preamble length. Used in TX only. */
    DWT_PAC32,       /* Preamble acquisition chunk size. Used in RX only. */
    9,               /* TX preamble code. Used in TX only. */
    9,               /* RX preamble code. Used in RX only. */
    1,               /* 0 to use standard SFD, 1 to use non-standard SFD. */
    DWT_BR_110K,     /* Data rate. */
    DWT_PHRMODE_STD, /* PHY header mode. */
    (1025 + 64 - 32) /* SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. */
};

#define FRAME_LEN_MAX 127
static uint8 rx_buffer[FRAME_LEN_MAX];

static uint32 status_reg = 0;

static uint16 frame_len = 0;

DigitalInOut pin_rst(PA_10);

void reset_DW1000()
{
  pin_rst.write(0);
  wait(0.01);
  pin_rst.write(1);
}



int main(void)
{
    //myled = 0;
    Serial serial(PB_6, PB_7);
    wait(0.5);
    serial.baud(9600);

    pin_rst.output();
    pin_rst.mode(OpenDrain);
    SPI bus(PA_7, PA_6, PA_5);//mosi, miso, clk

    serial.printf("Device ID: %u\r\n", dwt_readdevid());

    reset_DW1000();
    bus.frequency(2000000);
    if (dwt_initialise(DWT_LOADNONE) == DWT_ERROR)
    {
        serial.printf("Error on init11\n\r");
        while (1) { ; };
    }
    bus.frequency(20000000);

    //dwt_configure(&config);

    while(1)
    {
      int i;

      for (i = 0 ; i < FRAME_LEN_MAX; i++ )
      {
          rx_buffer[i] = 0;
      }
      dwt_rxenable(DWT_START_RX_IMMEDIATE);

      while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR))) { ; }

      if (status_reg & SYS_STATUS_RXFCG)
      {
          frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;
          if (frame_len <= FRAME_LEN_MAX)
          {
              dwt_readrxdata(rx_buffer, frame_len, 0);
              for(int s=0; s<frame_len-3; s++)
              {
                serial.printf("%c", rx_buffer[s]);
              }
              serial.printf("\r\n");
          }
          dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);
      }
      else
      {
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR);
        serial.printf("Err\r\n");
      }
    }
}
    
pregunta Kyle Hunter

1 respuesta

1

Le recomendaría que use más el controlador de DecaWave, especialmente porque está buscando funciones más avanzadas. Específicamente, desea utilizar su marco de interrupciones para manejar los detalles de TX y RX.

Por ejemplo, observe la función dwt_isr() . Hay bastante trabajo detrás de las escenas. Maneja múltiples interacciones de bits de estado complejas, busca desbordamientos, ha implementado algunas soluciones para errores de hardware, etc.

Para hacer esto, debe proporcionar dos funciones (denominadas "funciones de devolución de llamada") a su controlador: una para el manejo de RX y otra para el manejo de TX. Informa a su conductor de los nombres de sus funciones usando dwt_setcallbacks() .

Luego, debe configurar el Arduino para que responda de manera apropiada al pin de interrupción DW1000. Cuando el DW1000 causa una interrupción, su controlador se encarga de todo y luego llama a la adecuada de sus funciones de devolución de llamada.

Finalmente, cuando el controlador DecaWave llama a su (s) función (es), pasa una estructura de datos que contiene información sobre la transmisión o recepción. Puede analizar estos datos para asegurarse de que todo haya ido bien o para ayudar a descubrir qué fue lo que no funcionó.

Si usa su controlador, nunca debería tener que usar funciones de nivel inferior como dwt_read32bitreg() . La API está bastante bien desarrollada.

El uso del controlador DecaWave no es trivial, pero tendrá sentido una vez que lo hagas. Debe consultar sus ejemplos de aplicación para ver cómo unirlos todos.

Buena suerte :)

    
respondido por el bitsmack

Lea otras preguntas en las etiquetas