-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathTX868_HTU21_LowPower.ino
180 lines (152 loc) · 3.92 KB
/
TX868_HTU21_LowPower.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
* Production code to build a weather sensor/transmitter
* similar to the S300 by ELV.
*
* It measures temperature and humidity with a HTU21D sensor
* and transmits these values using the TX868.
* The address of the transmitter may be configured with a DIP switch.
* The processor is put into power down sleep and waked up
* by the watchdog timer periodically to reduce power consumption.
*
* Required libraries:
* - TempHygroTX868: https://github.com/skaringa/TempHygroTX868
* - SparkFunHTU21D: https://github.com/sparkfun/SparkFun_HTU21D_Breakout_Arduino_Library
*
* Hardware setup:
* - TX868 Data pin connected to digital pin 5
* - HTU21D SDA connected to A4 and SCL to A5
* - 3 DIP switches are connected to digital pins 7, 8, 9 with one contact
* and to ground with the other contact
*/
#include <TempHygroTX868.h>
#include <Wire.h>
#include <SparkFunHTU21D.h>
#include <avr/sleep.h>
#include <avr/power.h>
HTU21D htu;
TempHygroTX868 tx;
// transmission timer:
// it holds the number of seconds remaining until the next transmission
volatile int nextTxTimer;
// pin of build-in signal LED
#define LED 13
// lowest pin of DIP switch
#define SWITCH 7
// you may define DEBUG macro here
// to get debug output at the serial line
void setup()
{
#ifdef DEBUG
Serial.begin(9600);
Serial.println();
Serial.println("Address\tHumidity (%)\tTemperature (C)");
#endif
htu.begin();
tx.setup(5); // transmitter is at data pin 5
pinMode(LED, OUTPUT); // signal LED
nextTxTimer = 0;
/* Setup the Watchdog timer */
// clear the reset flag
MCUSR &= ~(1<<WDRF);
// enable configuration changes
WDTCSR |= (1<<WDCE) | (1<<WDE);
// set new watchdog timeout prescaler value to maximum
WDTCSR = 1<<WDP0 | 1<<WDP3;
// Enable the watchdog interrupt
WDTCSR |= _BV(WDIE);
}
void loop()
{
// are we required to send?
if (nextTxTimer <= 9) {
// yes - delay remaining time
delay(nextTxTimer * 1000);
// reset time to next transmission
#ifdef DEBUG
nextTxTimer = 30;
#else
nextTxTimer = tx.getPause();
#endif
// read address from DIP switch
byte addr = readSwitch();
#ifdef DEBUG
Serial.print(addr);
Serial.print("\t");
#endif
tx.setAddress(addr);
// read sensor and transmit
sendData();
}
// go into power down sleep
pwrDownSleep();
}
/*
* Read address from DIP switch
*/
byte readSwitch()
{
pinMode(SWITCH, INPUT_PULLUP);
pinMode(SWITCH+1, INPUT_PULLUP);
pinMode(SWITCH+2, INPUT_PULLUP);
delay(1);
byte val = digitalRead(SWITCH+2);
val <<= 1;
val |= digitalRead(SWITCH+1);
val <<= 1;
val |= digitalRead(SWITCH);
// disconnect pullups to save power
pinMode(SWITCH, INPUT);
pinMode(SWITCH+1, INPUT);
pinMode(SWITCH+2, INPUT);
return val;
}
/*
* Read data from sensor and transmit.
*/
void sendData()
{
digitalWrite(LED, HIGH);
float humidity = htu.readHumidity();
float temperature = htu.readTemperature();
#ifdef DEBUG
Serial.print(humidity);
Serial.print("\t");
Serial.println(temperature);
#endif
delay(100);
if (humidity < 900 && temperature < 900) {
// valid reading
tx.send(temperature, humidity);
}
digitalWrite(LED, LOW);
}
/*
* Interrupt service routine triggered by watchdog.
*/
ISR(WDT_vect)
{
// Watchdog oscillator freq is about 116 kHz
// at 3 V and 25 °C
// Therefore time between interrupts is
// 1,048,576 / 116,000 = 9.039 seconds.
// So decrement the transmission timer by this value.
nextTxTimer -= 9;
}
/*
* Go into power down mode
*/
void pwrDownSleep()
{
byte adcsra = ADCSRA;
ADCSRA = 0; // disable the ADC - saves 80 µA
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
cli(); // stop interrupts
sleep_bod_disable(); // disable brown-out detection
sei(); // enable interrupts
sleep_cpu();
// At this point the CPU is sleeping until watchdog bites
sleep_disable();
power_all_enable();
ADCSRA = adcsra; // restore ADCSRA
}