No puedo hacer funcionar el receptor LoRa simple

Estoy en el proceso de intentar crear un sensor LoRa muy simple y pequeño basado en un módulo sx1276 y un ATmega328P. Mi ATmega328p se está comunicando felizmente con el módulo sx1276, pero parece que no puedo lograr que la comunicación real funcione.

Además, he soldado dos Arduinos con módulos sx1276 como Draginos ejecutando los ejemplos de cliente y servidor, y conversan felizmente entre ellos. En realidad, fue muy fácil configurarlo. Estoy usando estas placas como ejemplos de trabajo verificados para probar los modos de transmisión y recepción de mi propia placa. Por ahora solo estoy probando el modo de recepción. Configuré mi placa para que la configuración en el chip sx1276 sea la misma que la de las placas Dragino, y las verifiqué entre sí haciendo que cada placa imprimiera el contenido completo de sus registros al inicializarse (así que siéntase seguro asumiendo la configuración que proporciono a continuación es de hecho la configuración del sx1276). Mientras los dos módulos de Dragino conversan entre sí, tengo mi tablero en modo receptor y los escucho como un tercero.No puedo recibir ningún paquete. Mi RX simplemente se agota en cada ciclo.

Escribí mi código en una forma relativamente uniforme y abstracta para aumentar la legibilidad. Esta es mi sección de inicialización del código...

/*------------ Hardware Settings ------------*/
// Set the sx127X to LoRa mode
sx127X_setLongRangeMode(LRM_LORA);
// Set the access-shared-registers mode
sx127X_setASRMode(ASR_LORA);
// Set low or high frequency mode
sx127X_setFrequencyMode(LFM_HF);
// Set either PA_RFO (+14dB) or PA_BOOST (+20dB)
sx127X_setPaSelect(PA_BOOST);
// Set the output power in dBm
sx127X_setOutputPowerDBm(11);
// Set the PA ramp-up time
sx127X_setPARampTime(RAMP_50US); // LoRaWAN recommended
// Set overload current protection
sx127X_setOCP(OCP_ON);
// Set overload current protection limit
sx127X_setOCPLimit(OCP_90MA);
// Set the low noise amp gain
sx127X_setLNAGain(LNA_GAIN_G1);
// set LNA boost for low frequency
sx127X_setLNABoostLF(LNA_BOOST_LF_DEFAULT);
// set LNA boost for high frequency
sx127X_setLNABoostHF(LNA_BOOST_HF_DEFAULT);
// Set LNA gain manual or auto
sx127X_setLNAGainAuto(LNA_GAIN_AUTO_ON);
// Set PaDAC to 'default' (NOT +20dBm)
sx127X_SPIWriteReg(REG_LR_PADAC, 0x84);

/*----------- Common Communication Settings -----------*/
// Set base frequency (channel) of the LoRa module
sx127X_setChannel(channel); // 915.8MHz
// Set the data rate (bandwidth and spreading factor) of the LoRa module
sx127X_setDataRate(dataRate); // SF7, BW=125,000kHz
// Set the coding rate of the LoRa module
sx127X_setCodeRate(CR_4OF5);
// Set the toggle for implicit header
sx127X_setImplHeaderMode(IHM_OFF); // Explicit
// Set TX continuous mode on or off(normal/packet mode)
sx127X_setTXContMode(TXCM_NORM);
// Set RX payload CRC mode on or off
sx127X_setRXPayloadCRC(RXPL_CRC_ON);
// Set the RX symbol timeout in symbols
sx127X_setRXSymbolTimeout(SYMB_TIMEOUT_1023SYM);
// Set preamble length in symbols
sx127X_setPreambleLength(0x10);
// Set the payload length in bytes
sx127X_setPayloadLength(0x01); // default
// Set payload maximum length in bytes
sx127X_setPayloadMaxLength(0x80);
// Set the frequency hopping period (0=disable)
sx127X_setFreqHopPeriod(0);
// Set Sync Word
sx127X_setSyncWord(0xAA);
// Select inversion of I and Q signals
sx127X_invertIQ(INVERT_IQ_OFF);

/*------------ RX Communication Settings ------------*/
// Set DIO0 for the RX done flag
sx127X_SPIWriteReg(REG_LR_DIOMAPPING1, 0x00);
// Set interrupt mask for RX timeout and RX done
sx127X_SPIWriteReg(LR_RegIrqFlagsMask, 0x3F);
// Set the RX base address to bottom of FIFO
sx127X_SPIWriteReg(LR_RegFifoRxBaseAddr, 0x00);
// Set address pointer to bottom of FIFO as well
sx127X_SPIWriteReg(LR_RegFifoAddrPtr, 0x00);

Y este es el bucle para recibir y mostrar (a través de USART) paquetes...

while(1) {
    loopFlashLED();
    // Check for received packet
     USARTSendString("Listening for packets...\n");

    if (sx127X_RxPacket((uint8_t *)recievedData)) {
        // print received string over UART
        USARTSendString("Received string!!: ");
        for (idx = 0; idx < 20; idx++) {
            USARTSendByte(recievedData[idx]);
        }
        USARTSendByte('\n');
        // reset received data array
        for (idx = 0; idx < 20; idx++) {
            recievedData[idx] = 0;
        }
    }
}

Y esta es la rutina de recepción de paquetes del bucle principal anterior...

uint8_t sx127X_RxPacket(uint8_t* dataPtr) {
    uint8_t var = 0;
    uint8_t returnValue = 0;

    // Clear interrupts
    sx127X_ClearIrq();

    // Set to receive mode
    setMode(MODE_RXSINGLE);

    // Poll for timeout, sx127x will go to MODE_STDBY upon timeout
    while (!(sx127X_SPIReadReg(LR_RegIrqFlags) & 0x80)) { 

        // Poll for the RX-done flag
        if (sx127X_SPIReadReg(LR_RegIrqFlags) & 0x40) {

            // Read starting address of the last received packet...
            var = sx127X_SPIReadReg(LR_RegFifoRxCurrentaddr);
            // ... Write it to the SPI address pointer for the FIFO buffer
            sx127X_SPIWriteReg(LR_RegFifoAddrPtr, var);

            // Retrieve packet size of last received packet
            var = sx127X_SPIReadReg(LR_RegRxNbBytes);

            // Use packet size and FIFO to read RX packet
            sx127X_SPIBurstRead(LR_RegFifo, dataPtr, var);

            // If successfully retrieved a packet return true
            returnValue = 1;
            break;
        }
    }
    // If no packet has been retrieved this call return false
    return returnValue;
}

He pasado muchas horas tratando de averiguar qué hice mal, pero parece que no puedo resolverlo.

No pretendo publicar esto como una publicación de "depura mi código por mí", sino para ver si alguien familiarizado con los chips de Semtech puede detectar algún problema inmediato con la forma en que estoy operando el módulo sx1276. Esta es mi primera incursión en el mundo de los dispositivos de RF, por lo que es posible que haya pasado por alto algo muy simple. Gracias de antemano por todos y cada uno de los aportes útiles.

EDITAR 1:

Para aclarar la configuración del hardware: tanto mi placa como las placas dragino son simplemente un ATmega328P conectado a un módulo sx1276 listo para transmitir (Dorji DRF1276G) (con antena) a través de su interfaz SPI. El único pin DIO conectado de los módulos sx1276 en AMBOS es el pin DIO0. Los Draginos están basados ​​en Arduino, mientras que el mío es Atmel en bruto. También hay algunos circuitos periféricos simples en mi placa.

EDITAR 2:

Encontré un error en mi código que habría impedido una comunicación confiable; el módulo DRF1276G utiliza el pin PA_BOOST, no el pin PA_RFO como había pensado. He actualizado mis listados de códigos para reflejar esto. Sin embargo, el problema sigue en pie; No se ha logrado ninguna comunicación.

ACTUALIZAR:

Soldé un nuevo módulo DRF1276G en mi placa para verificar que no se trata de un problema de hardware. Agregué un código para imprimir sobre uart las lecturas de RSSI en mi ciclo de tiempo de espera y la siguiente imagen muestra esos valores graficados: ingrese la descripción de la imagen aquíPuede ver claramente las dos unidades de Dragino hablando entre sí dos veces en la ventana de tiempo de espera. Entonces parece que es un problema de software.

¿Qué información puede proporcionar sobre la configuración del hardware de las configuraciones que no funcionan frente a las que funcionan? ¿Son los DIO lo mismo? ¿Es posible que la parte de RF del módulo esté mal implementada o dañada mientras que la parte orientada hacia SPI funciona bien? La recepción requiere que sucedan muchas cosas, incluida la detección de condiciones específicas, ¿ha intentado transmitir desde el módulo defectuoso? ¿Están todos en la misma frecuencia y no saltan como deberían? ¿Ha intentado leer el registro RSSI SX1276 (continuo, no por paquetes) tanto en general como para ver si da alguna pista de las transmisiones en curso?
He agregado información sobre la configuración del hardware en la publicación original. La parte de RF del circuito definitivamente se implementa correctamente, aunque tiene razón en que no sé con certeza si la parte de RF del Semtech IC se ha dañado o no. Intenté transmitir desde el mismo módulo y, de manera similar, la transmisión no funciona, pero quería centrarme en la recepción por ahora, ya que recibir como un tercero tiene menos variables en la mezcla.
Los draginos y mi tablero tienen la misma configuración exacta (canal, ancho de banda, factor de dispersión, longitud del preámbulo, encabezados explícitos, salto de frecuencia = 0, etc.). No he probado a recibir en modo RX continuo, no. Me gusta tu idea de verificar el RSSI... Lo probaré la próxima vez que pueda.
He actualizado la publicación original con los resultados de la prueba RSSI

Respuestas (1)

¡Ya tengo el módulo funcionando!

Yo, nuevamente, comparé los registros de mi placa y las placas dragino, y noté que había una diferencia en el registro 0x37 (Umbral de detección). Le había escrito un valor de 0xCA donde quería escribir 0x0A.

En efecto cambié esto...

// If spreading factor is 6, optimize module
temp = sx127X_SPIReadReg(LR_RegDetectOptimize) & 0xF8;
if (dataRates[dr][0] == 6) {
    sx127X_SPIWriteReg(LR_RegDetectOptimize, (temp | 0x05)); // SF6
    sx127X_SPIWriteReg(LR_RegDetectionThreshold, (temp | 0x0C)); // SF6
} else {
    sx127X_SPIWriteReg(LR_RegDetectOptimize, (temp | 0x03)); // SF7-12
    sx127X_SPIWriteReg(LR_RegDetectionThreshold, (temp | 0x0A)); // SF7-12  
}

a esto...

// If spreading factor is 6, optimize module
temp = sx127X_SPIReadReg(LR_RegDetectOptimize) & 0xF8;
if (dataRates[dr][0] == 6) {
    sx127X_SPIWriteReg(LR_RegDetectOptimize, (temp | 0x05)); // SF6
    sx127X_SPIWriteReg(LR_RegDetectionThreshold, 0x0C); // SF6
} else {
    sx127X_SPIWriteReg(LR_RegDetectOptimize, (temp | 0x03)); // SF7-12
    sx127X_SPIWriteReg(LR_RegDetectionThreshold, 0x0A); // SF7-12  
}

¡Y pude recibir y mostrar paquetes!

PERO,

En mi comparación anterior de los registros, en realidad tenía el valor correcto de 0x0A. Entonces, en algún momento, cuando estaba depurando y solucionando otro problema, debo haber cambiado accidentalmente ese fragmento de código e introducido el error. Sospecho que otro error que estaba arreglando en ese momento era el uso de PA_RFO en lugar de PA_BOOST como se menciona en 'EDIT 2' de mi publicación original. Quizás fue incluso el cambio de hardware como se menciona en 'ACTUALIZAR' de mi publicación original.

Gracias a todos los que pasaron tiempo tratando de resolver esto. Como mínimo, el código en mi publicación original es bueno y debería ser útil para que otros creen su propio tablero.