Skip to content

Commit bb7c5de

Browse files
author
Torben van Hees
committed
Merge remote-tracking branch 'ChocotovLora/cadmode' into cadmode
merged cadmode
2 parents 55d49c5 + 7c22552 commit bb7c5de

File tree

5 files changed

+654
-4
lines changed

5 files changed

+654
-4
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#include <SPI.h>
2+
#include <LoRa.h>
3+
4+
#include <avr/sleep.h>
5+
#include <avr/power.h>
6+
#include <avr/wdt.h>
7+
8+
ISR(WDT_vect) {
9+
}
10+
11+
volatile bool dio0_rise;
12+
volatile bool dio1_rise;
13+
14+
byte dio0_pin = 2;
15+
byte dio1_pin = 3;
16+
17+
void setup() {
18+
// disable ADC
19+
ADCSRA = 0;
20+
21+
Serial.begin(9600);
22+
while (!Serial);
23+
24+
Serial.println("LoRa Receiver");
25+
26+
pinMode(dio0_pin, INPUT);
27+
pinMode(dio1_pin, INPUT);
28+
29+
// Set sleep to full power down. Only external interrupts or
30+
// the watchdog timer can wake the CPU!
31+
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
32+
33+
// wdt sleep settings:
34+
// 10.8 Watchdog Timer
35+
WDTCSR |= 1<<WDCE | 1<<WDE;
36+
37+
// Table 10-3. Watchdog Timer Prescale Select
38+
//WDTCSR = 1<<WDP3 | 1<<WDP0; // 8 seconds
39+
//WDTCSR = 1<<WDP3; // 4 seconds
40+
//WDTCSR = 1<<WDP2 | 1<<WDP1 | 1<<WDP0; // 2 seconds
41+
//WDTCSR = 1<<WDP2 | 1<<WDP1; // 1 seconds
42+
//WDTCSR = 1<<WDP0; // 32 ms
43+
WDTCSR = 0; // 16 ms
44+
45+
WDTCSR |= 1<<WDIE;
46+
47+
// Setup external interrupt INT0 and INT1
48+
//
49+
//12.2 Register Description
50+
//12.2.1 EICRA – External Interrupt Control Register A
51+
EICRA = 0;
52+
//EICRA |= (1<<ISC10); // Any logical change on INT1 generates an interrupt request.
53+
//EICRA |= (1<<ISC00); // Any logical change on INT0 generates an interrupt request.
54+
EICRA |= 1<<ISC11 | 1<<ISC10; // The rising edge of INT1 generates an interrupt request.
55+
EICRA |= 1<<ISC01 | 1<<ISC00; // The rising edge of INT0 generates an interrupt request.
56+
57+
//12.2.2 EIMSK – External Interrupt Mask Register
58+
EIMSK = 0;
59+
EIMSK |= (1<<INT1); // Bit 1 – INT1: External Interrupt Request 1 Enable
60+
EIMSK |= (1<<INT0); // Bit 0 – INT0: External Interrupt Request 0 Enable
61+
62+
if (!LoRa.begin(915E6)) {
63+
Serial.println("Starting LoRa failed!");
64+
while (1);
65+
}
66+
67+
LoRa.setPreambleLength(30);
68+
69+
// initiates the first cadMode
70+
LoRa.cadMode();
71+
}
72+
73+
void go_to_sleep() {
74+
// reset wdt counter
75+
wdt_reset();
76+
77+
//sleep_mode: Put the device into sleep mode, taking care of setting the SE bit before, and clearing it afterwards.
78+
sleep_mode();
79+
}
80+
81+
ISR (INT0_vect){
82+
dio0_rise = true;
83+
}
84+
85+
ISR (INT1_vect){
86+
dio1_rise = true;
87+
}
88+
89+
void parse_packet(){
90+
// try to parse packet
91+
int packetSize = LoRa.parsePacket();
92+
if (packetSize) {
93+
// received a packet
94+
Serial.print("Received packet '");
95+
96+
// read packet
97+
while (LoRa.available()) {
98+
Serial.print((char)LoRa.read());
99+
}
100+
101+
// print RSSI of packet
102+
Serial.print("' with RSSI ");
103+
Serial.println(LoRa.packetRssi());
104+
}
105+
}
106+
107+
void send_message(){
108+
LoRa.beginPacket();
109+
LoRa.print("hello");
110+
LoRa.endPacket();
111+
}
112+
113+
void loop() {
114+
if (LoRa.cadModeActive && dio0_rise){
115+
// dio0: CadDone
116+
// dio1: CadDetected
117+
118+
if (dio1_rise){
119+
dio0_rise = false;
120+
dio1_rise = false;
121+
// prepare radio to receive a single packet
122+
LoRa.setRxSingle();
123+
} else {
124+
125+
// nothing detected: wait before initiating the next cadMode
126+
// put both radio and microcontroller to sleep
127+
LoRa.sleep();
128+
go_to_sleep();
129+
130+
/*
131+
// send a message periodically
132+
static uint16_t send_message_counter{0};
133+
send_message_counter++;
134+
if (send_message_counter > 250){
135+
send_message_counter = 0;
136+
send_message();
137+
}
138+
*/
139+
140+
dio0_rise = false;
141+
dio1_rise = false;
142+
LoRa.cadMode();
143+
}
144+
} else if (LoRa.rxSingleMode){
145+
// dio0: RxDone
146+
// dio1: RxTimeout
147+
148+
// only take action if either of the pins went high
149+
if (dio0_rise || dio1_rise){
150+
if (dio0_rise){
151+
parse_packet();
152+
Serial.flush();
153+
}
154+
155+
dio0_rise = false;
156+
dio1_rise = false;
157+
LoRa.cadMode();
158+
}
159+
}
160+
161+
go_to_sleep();
162+
}
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#include <SPI.h>
2+
#include <LoRa.h>
3+
4+
#include <avr/sleep.h>
5+
#include <avr/power.h>
6+
#include <avr/wdt.h>
7+
8+
ISR(WDT_vect) {
9+
}
10+
11+
volatile bool dio0_rise;
12+
//volatile bool dio1_rise;
13+
14+
byte dio0_pin = 2;
15+
//byte dio1_pin = 3;
16+
17+
void setup() {
18+
// disable ADC
19+
ADCSRA = 0;
20+
21+
Serial.begin(9600);
22+
while (!Serial);
23+
24+
Serial.println("LoRa Receiver");
25+
26+
pinMode(dio0_pin, INPUT);
27+
//pinMode(dio1_pin, INPUT);
28+
29+
// Set sleep to full power down. Only external interrupts or
30+
// the watchdog timer can wake the CPU!
31+
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
32+
33+
// wdt sleep settings:
34+
// 10.8 Watchdog Timer
35+
WDTCSR |= 1<<WDCE | 1<<WDE;
36+
37+
// Table 10-3. Watchdog Timer Prescale Select
38+
//WDTCSR = 1<<WDP3 | 1<<WDP0; // 8 seconds
39+
//WDTCSR = 1<<WDP3; // 4 seconds
40+
//WDTCSR = 1<<WDP2 | 1<<WDP1 | 1<<WDP0; // 2 seconds
41+
//WDTCSR = 1<<WDP2 | 1<<WDP1; // 1 seconds
42+
//WDTCSR = 1<<WDP0; // 32 ms
43+
WDTCSR = 0; // 16 ms
44+
45+
WDTCSR |= 1<<WDIE;
46+
47+
// Setup external interrupt INT0 and INT1
48+
//
49+
//12.2 Register Description
50+
//12.2.1 EICRA – External Interrupt Control Register A
51+
EICRA = 0;
52+
//EICRA |= (1<<ISC10); // Any logical change on INT1 generates an interrupt request.
53+
//EICRA |= (1<<ISC00); // Any logical change on INT0 generates an interrupt request.
54+
//EICRA |= 1<<ISC11 | 1<<ISC10; // The rising edge of INT1 generates an interrupt request.
55+
EICRA |= 1<<ISC01 | 1<<ISC00; // The rising edge of INT0 generates an interrupt request.
56+
57+
//12.2.2 EIMSK – External Interrupt Mask Register
58+
EIMSK = 0;
59+
//EIMSK |= (1<<INT1); // Bit 1 – INT1: External Interrupt Request 1 Enable
60+
EIMSK |= (1<<INT0); // Bit 0 – INT0: External Interrupt Request 0 Enable
61+
62+
if (!LoRa.begin(915E6)) {
63+
Serial.println("Starting LoRa failed!");
64+
while (1);
65+
}
66+
67+
LoRa.setPreambleLength(30);
68+
69+
// initiates the first cadMode
70+
LoRa.cadMode();
71+
}
72+
73+
void go_to_sleep() {
74+
// reset wdt counter
75+
wdt_reset();
76+
77+
//sleep_mode: Put the device into sleep mode, taking care of setting the SE bit before, and clearing it afterwards.
78+
sleep_mode();
79+
}
80+
81+
ISR (INT0_vect){
82+
dio0_rise = true;
83+
}
84+
85+
//ISR (INT1_vect){
86+
// dio1_rise = true;
87+
//}
88+
89+
bool parse_packet(){
90+
// try to parse packet
91+
int packetSize = LoRa.parsePacket();
92+
if (packetSize) {
93+
// received a packet
94+
Serial.print("Received packet '");
95+
96+
// read packet
97+
while (LoRa.available()) {
98+
Serial.print((char)LoRa.read());
99+
}
100+
101+
// print RSSI of packet
102+
Serial.print("' with RSSI ");
103+
Serial.println(LoRa.packetRssi());
104+
return true;
105+
}
106+
107+
return false;
108+
}
109+
110+
void send_message(){
111+
LoRa.beginPacket();
112+
LoRa.print("hello");
113+
LoRa.endPacket();
114+
}
115+
116+
void loop() {
117+
if (LoRa.cadModeActive && dio0_rise){
118+
// dio0: CadDone
119+
// dio1: CadDetected
120+
dio0_rise = false;
121+
// dio1 is not used in this sketch: CadDetected is looked up in RegIrqFlags
122+
123+
if (LoRa.irqCadDetected()){
124+
LoRa.receive();
125+
126+
// these attributes are not really needed in this sketch anymore
127+
LoRa.cadModeActive = false;
128+
//LoRa.rxSingleMode = true;
129+
130+
// sleep a while until RxDone is triggered
131+
for (uint8_t i = 0; i < 20; i++){
132+
go_to_sleep();
133+
if (dio0_rise){
134+
dio0_rise = false;
135+
parse_packet();
136+
Serial.flush();
137+
break;
138+
}
139+
}
140+
141+
// this idle() solves the problem of the power consumption sometimes staying at 12 mA when
142+
// a packet couldn't be received
143+
LoRa.idle();
144+
145+
LoRa.cadMode();
146+
} else {
147+
// nothing detected: wait before initiating the next cadMode
148+
// put both radio and microcontroller to sleep
149+
LoRa.sleep();
150+
go_to_sleep();
151+
152+
/*
153+
// send a message periodically
154+
static uint16_t send_message_counter{0};
155+
send_message_counter++;
156+
if (send_message_counter > 250){
157+
send_message_counter = 0;
158+
send_message();
159+
}
160+
*/
161+
162+
LoRa.cadMode();
163+
}
164+
}
165+
166+
go_to_sleep();
167+
}

0 commit comments

Comments
 (0)