Arduino Dragino Lora shield (Semtech SX1278 chip) can tune into frequency quite fast. Fasthop feature works at best in OOK continuous mode.
RegPllHop (0x44) bit 7:
Bypasses the main state machine for a quick frequency hop. Writing RegFrfLsb will trigger the frequency change.
1 -> Frf is validated triggered when RegFrfLsb is written.
1. set FastHopOn=1
2. set new Frf (*)
3. wait for TS_HOP
TS_HOP = Frequency synthesizer hop time at most 10 kHz away from the target frequency.
(*) RegFrfLsb must be written to trigger a frequency change.
SX1278 library: https://github.com/open-electronics/LoRa/releases
SX1278 datasheet: http://www.semtech.com/apps/filedown/down.php?file=sx1276_77_78_79.pdf
#include <SX1278.h>
#define SERIAL_SPEED 9600
#define F_START 433 // start freq
#define F_STEP 0.025 // 25 kHz step
#define F_CH 50 // channels to rx hop
#define BPS 1200
#define STATE_STANDBY 1
#define STATE_FSRX 4
#define STATE_RX 5
#define H_DELAY 2
#define M_DELAY 10
#define L_DELAY 100
#define SX_BEGIN "SX.begin"
#define SX_BITRATE "SX.readBPS "
#define SX_FREQ "SX.readFreq "
#define RSSI_THRESHOLD -80 // dBm
#define CH_FILTER_BW B00001100 // 25 kHz
#define RegRssiConfig 0x0e
#define RegRxBw 0x12
#define RegPacketConfig1 0x30
#define RegOpMode 0x01
#define RegPaRamp 0x0a
#define RegRssiThresh 0x10
#define RegOokPeak 0x14
#define RegPreambleDetect 0x1f
#define RegSyncConfig 0x27
#define RegPacketConfig2 0x31
#define RegIrqFlags1 0x3e
#define RegIrqFlags2 0x3f
#define RegPllHop 0x44
bool rx = false;
void setup() {
Serial.begin(SERIAL_SPEED);
if (SX.begin()) {
Serial.println(F(SX_BEGIN));
delay(M_DELAY);
SX.startModeFSKOOK();
// OOK
byte b = SX.SPIread(RegOpMode);
bitClear(b, 6);
bitSet(b, 5);
SX.SPIwrite(RegOpMode, b);
fastHop(0);
SX.setFreq(F_START);
Serial.print(F(SX_FREQ));
Serial.println(SX.readFreq(), DEC);
SX.setBPS(BPS);
Serial.print(F(SX_BITRATE));
Serial.println(SX.readBPS(), DEC);
// Channel filter bandwidth control
SX.SPIwrite(RegRxBw, CH_FILTER_BW);
// 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-0: Size of the Sync word (SyncSize + 1)
b = SX.SPIread(RegSyncConfig);
bitClear(b, 7);
bitSet(b, 6);
bitClear(b, 4);
bitClear(b, 5);
bitClear(b, 2);
bitClear(b, 1);
bitClear(b, 0);
SX.SPIwrite(RegSyncConfig, b);
// 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.
// Bit 0: Selects the CRC and whitening algorithms:
// 0 -> CCITT CRC implementation with standard whitening
// 1 -> IBM CRC implementation with alternate whitening
b = 0;
SX.SPIwrite(RegPacketConfig1, b);
// Bits 6-5: FSK data shaping:
// 00 -> no shaping, 01 -> Gaussian filter BT = 1.0
// 10 -> Gaussian filter BT = 0.5, 11 -> Gaussian filter BT = 0.3
// Bits 3-0: Rise/Fall time of ramp up/down in FSK:
// 1001 -> 40 us
b = SX.SPIread(RegPaRamp);
bitClear(b, 6);
bitClear(b, 5);
bitSet(b, 3);
bitClear(b, 2);
bitSet(b, 0);
SX.SPIwrite(RegPaRamp, b);
// Data processing mode: 0 ->Â Continuous mode, 1 -> Packet mode
b = SX.SPIread(RegPacketConfig2);
bitClear(b, 6);
SX.SPIwrite(RegPacketConfig2, b);
// RSSI smoothing.
// Defines the number of samples taken to average the RSSI result. 001 -> 4 samples
b = SX.SPIread(RegRssiConfig);
bitClear(b, 2);
bitClear(b, 1);
bitSet(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
b = SX.SPIread(RegOokPeak);
bitClear(b, 5);
SX.SPIwrite(RegOokPeak, b);
// 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);
bitClear(b, 5);
SX.SPIwrite(RegPreambleDetect, b);
clearFifoAndFlags();
SX.setState(STATE_FSRX);
delay(L_DELAY);
SX.setState(STATE_RX);
delay(M_DELAY);
rx = true;
}
}
void loop() {
if (rx) {
float f = F_START;
for (int c = 0; c < F_CH; c++) {
fastHop(1);
SX.setFreq(f);
delay(H_DELAY);
float rssi = SX.readRSSIval();
if (rssi > RSSI_THRESHOLD) {
Serial.print(f, DEC);
Serial.print("\t");
Serial.println(rssi, DEC);
}
f = f + F_STEP;
}
}
}
void clearFifoAndFlags() {
// Flag(s) and FIFO are cleared when this bit is set
byte b = SX.SPIread(RegIrqFlags2);
bitSet(b, 4);
SX.SPIwrite(RegIrqFlags2, b);
delay(M_DELAY);
}
void fastHop(int val) {
byte b = SX.SPIread(RegPllHop);
bitWrite(b, 7, val);
SX.SPIwrite(RegPllHop, b);
}
Kommentit
Tämän blogin kommentit tarkistetaan ennen julkaisua.