Dragino Arduino Lora module (433/868/915 MHz versions, Semtech SX127x receiver chip) can modulate/demodulate Lora, OOK and many FSK modes in packet and continuous modes. The packet engine is quite sophisticated with many adjustable parameters (sync detect, preamble detect, crc ...). With some experimenting I managed to receive packet data from Prego wireless thermometer & Nordica Thermo Sensor model no. THCN128 (433 MHz OOK transmitters). Decoding packets requires adjusting several SX1278 OOK parameters (RSSI threshold, size of each decrement of the RSSI threshold in the OOK demodulator ...). Sometimes SX1278 receiver is saturated (constant FIFO overruns ...) and requires resetting.
http://www.dragino.com/products/module/item/102-lora-shield.html
http://www.semtech.com/apps/filedown/down.php?file=sx1276_77_78_79.pdf
Open-Electronics sx1278 library is available in GitHub. https://github.com/open-electronics/LoRa/releases
#include <SX1278.h>
#define SERIAL_SPEED 9600
#define FREQ 433.98
#define BPS 1200
#define STATE_STANDBY 1
#define STATE_FSRX 4
#define STATE_RX 5
#define S_DELAY 10
#define L_DELAY 100
#define RX_BUFFER_LEN 64
#define SX_BEGIN "SX.begin"
#define SX_BITRATE "SX.readBPS "
#define SX_FREQ "SX.readFreq "
#define OOK_THRESHOLD 16
#define RSSI_THRESHOLD 100 // -rssi/2,100 = -50 dBm
#define CH_FILTER_BW B00001011 // 50 kHz
#define SYNC_VALUE 0x01
#define RegRssiConfig 0x0e
#define RegRxBw 0x12
#define RegPacketConfig1 0x30
#define RegFifo 0x00
#define RegRssiThresh 0x10
#define RegOokPeak 0x14
#define RegOokFix 0x15
#define RegPreambleDetect 0x1f
#define RegSyncConfig 0x27
#define RegSyncValue1 0x28
#define RegSyncValue2 0x29
#define RegSyncValue3 0x2a
#define RegPacketConfig2 0x31
#define RegPayloadLength 0x32
#define RegIrqFlags1 0x3e
#define RegIrqFlags2 0x3f
bool rx = false;
byte b;
byte RegIrqFlags1_value;
byte RegIrqFlags2_value;
byte rxBuffer[RX_BUFFER_LEN];
void setup() {
Serial.begin(SERIAL_SPEED);
if (SX.begin()) {
Serial.println(F(SX_BEGIN));
delay(S_DELAY);
SX.startModeFSKOOK();
SX.setModulation(1); // OOK
// Channel filter bandwidth control
SX.SPIwrite(RegRxBw, CH_FILTER_BW);
SX.setFreq(FREQ);
Serial.print(F(SX_FREQ));
Serial.println(SX.readFreq(), DEC);
SX.setBPS(BPS);
Serial.print(F(SX_BITRATE));
Serial.println(SX.readBPS(), DEC);
// Bits 7-6: AutoRestartRxMode, 01 On, without waiting for the PLL to re-lock
// Bit 4: Enables the Sync word generation and detection: 0 => Off, 1 => On
// Bit 5: Sets the polarity of the Preamble. 0 0xAA, 1 0x55
// Bits 2-1: Size of the Sync word (SyncSize + 1)
b = SX.SPIread(RegSyncConfig);
bitClear(b, 7);
bitSet(b, 6);
bitSet(b, 4);
bitClear(b, 5);
bitClear(b, 2);
bitClear(b, 1);
bitSet(b, 0);
SX.SPIwrite(RegSyncConfig, b);
SX.SPIwrite(RegSyncValue1, SYNC_VALUE);
SX.SPIwrite(RegSyncValue2, SYNC_VALUE);
SX.SPIwrite(RegSyncValue3, SYNC_VALUE);
// Bits 6-5: Defines DC-free encoding/decoding performed: 00->none, 01->manchester, 10->whitening
// Bit 7: packet format, 0 = fixed length, 1 = variable length
// Bit 4: crc calc/check, 0 = off, 1 = on
// Bits 2-1: Defines address based filtering in Rx: 00 ïƒ None (Off)
// Bit 3: Defines the behavior of the packet handler when CRC check fails:
// 0 => Clear FIFO and restart new packet reception.
// No PayloadReady interrupt issued. 1 => Do not clear FIFO. PayloadReady interrupt issued.
b = SX.SPIread(RegPacketConfig1);
bitClear(b, 6);
bitClear(b, 5);
bitClear(b, 7);
bitClear(b, 4);
bitSet(b, 3);
bitClear(b, 2);
bitClear(b, 1);
SX.SPIwrite(RegPacketConfig1, b);
SX.SPIwrite(RegPayloadLength, RX_BUFFER_LEN);
// Data processing mode: 0 => Continuous mode, 1 => Packet mode
b = SX.SPIread(RegPacketConfig2);
bitSet(b, 6);
SX.SPIwrite(RegPacketConfig2, b);
// RSSI smoothing.
// Defines the number of samples taken to average the RSSI result. 000 -> 2 samples
b = SX.SPIread(RegRssiConfig);
bitClear(b, 2);
bitClear(b, 1);
bitClear(b, 0);
SX.SPIwrite(RegRssiConfig, b);
SX.SPIwrite(RegRssiThresh, RSSI_THRESHOLD);
// Bit 5: enables the Bit Synchronizer:
// 0 -> bit sync disabled (not possible in packet mode), 1 -> bit sync enabled
// Bits 4-3: Selects the type of threshold in the OOK data slicer: (01 = peak mode)
// Bits 2-0: Size of each decrement of the RSSI threshold in the OOK demodulator
b = SX.SPIread(RegOokPeak);
bitSet(b, 5);
bitClear(b, 4);
bitSet(b, 3);
bitClear(b, 2);
bitClear(b, 1);
bitClear(b, 0);
SX.SPIwrite(RegOokPeak, b);
SX.SPIwrite(RegOokFix, OOK_THRESHOLD);
// RegPreambleDetect (0x1f). Enables Preamble detector when set to 1.
// The AGC settings supersede this bit during the startup / AGC phase.
// Bit 7: 0 -> turned off, 1 -> turned on
// Bits 6-5: Number of Preamble bytes to detect to trigger an interrupt.
// 00 1 byte, 10 3 bytes, 01 2 bytes
b = SX.SPIread(RegPreambleDetect);
bitClear(b, 7);
bitClear(b, 6);
bitSet(b, 5);
SX.SPIwrite(RegPreambleDetect, b);
// Flag(s) and FIFO are cleared when this bit is set
b = SX.SPIread(RegIrqFlags2);
bitSet(b, 4);
SX.SPIwrite(RegIrqFlags2, b);
SX.setState(STATE_FSRX);
delay(L_DELAY);
SX.setState(STATE_RX);
RegIrqFlags1_value = SX.SPIread(RegIrqFlags1);
RegIrqFlags2_value = SX.SPIread(RegIrqFlags2);
Serial.print("RegIrqFlags1_value ");
Serial.println(RegIrqFlags1_value, BIN);
Serial.print("RegIrqFlags2_value ");
Serial.println(RegIrqFlags2_value, BIN);
rx = true;
}
}
void loop() {
if (rx) {
byte r1 = SX.SPIread(RegIrqFlags1);
byte r2 = SX.SPIread(RegIrqFlags2);
if (r1 != RegIrqFlags1_value) {
RegIrqFlags1_value = r1;
Serial.print("RegIrqFlags1_value ");
Serial.println(RegIrqFlags1_value, BIN);
}
if (r2 != RegIrqFlags2_value) {
RegIrqFlags2_value = r2;
Serial.print("RegIrqFlags2_value ");
Serial.println(RegIrqFlags2_value, BIN);
}
if (bitRead(r2, 2) == 1) {
b = SX.SPIread(RegPayloadLength);
if (b > 0) {
Serial.print("RegPayloadLength ");
Serial.println(b, DEC);
b = SX.dataReceived(rxBuffer, b);
if (b > 0) {
for (int i = 0; i < b; i++) { Serial.print(rxBuffer[i]); }
Serial.println();
}
}
}
}
}
Kommentit
Tämän blogin kommentit tarkistetaan ennen julkaisua.