-
Notifications
You must be signed in to change notification settings - Fork 94
/
Copy pathrfm12b_send_lm35.ino
195 lines (153 loc) · 5.24 KB
/
rfm12b_send_lm35.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
181
182
183
184
185
186
187
#include <JeeLib.h> // https://github.com/jcw/jeelib
#include <Ports.h> // https://github.com/jcw/jeelib
#include <avr/pgmspace.h> // http://excamera.com/sphinx/article-crc.html
#include <avr/sleep.h>
#define BLIP_DEBUG
#define BLIP_NODE 2 // set this to a unique NODE to disambiguate multiple nodes
#define BLIP_GRP 17 // wireless net group to use for sending blips
#define LM35_PIN A2
#define SEND_MODE 2 // set to 3 if fuses are e=06/h=DE/l=CE, else set to 2
#define RF_CHIPSELECT 10
// this must be defined since we're using the watchdog for low-power waiting
ISR(WDT_vect) {
Sleepy::watchdogEvent();
}
typedef struct message_t {
unsigned long id;
unsigned long counter;
float value1;
float value2;
float value3;
float value4;
float value5;
unsigned long crc;
};
message_t message;
float previous1 = 0, previous2 = 0;
/*****************************************************************************/
void setup () {
#ifdef BLIP_DEBUG
Serial.begin(57600);
Serial.print("\n[rfm12b_send_lm35 / ");
Serial.print(__DATE__);
Serial.print(" / ");
Serial.print(__TIME__);
Serial.println("]");
#endif
pinMode(LM35_PIN, INPUT);
pinMode(RF_CHIPSELECT, OUTPUT);
rf12_set_cs(RF_CHIPSELECT);
rf12_initialize(BLIP_NODE, RF12_868MHZ, BLIP_GRP);
rf12_sleep(RF12_SLEEP);
delay(100); // give it some time to send before falling asleep
message.id = BLIP_NODE;
message.counter = 0;
message.value1 = NAN;
message.value2 = NAN;
message.value3 = NAN;
message.value4 = NAN;
message.value5 = NAN;
}
/*****************************************************************************/
void loop () {
boolean stable = false;
while (!stable) {
long vcc = readVcc();
float sensorValue = analogRead(LM35_PIN);
sensorValue *= vcc;
sensorValue /= 10230;
message.value1 = 0.001*readVcc(); // this is in mV, we want V
message.value2 = sensorValue; // this is Celcius
// compute the difference with the previous values
previous1 -= message.value1;
previous1 = abs(previous1);
previous2 -= message.value2;
previous2 = abs(previous2);
// the voltage should be stable within 0.1, the temperature within 1
stable = (previous1<0.1) && (previous2<1);
// update the previous values
previous1 = message.value1;
previous2 = message.value2;
} // if stable
message.counter += 1;
message.crc = crc_buf((char *)&message, sizeof(message_t) - sizeof(unsigned long));
rf12_sleep(RF12_WAKEUP);
rf12_sendNow(0, &message, sizeof message);
rf12_sendWait(SEND_MODE);
rf12_sleep(RF12_SLEEP);
#ifdef BLIP_DEBUG
// DISPLAY DATA
Serial.print("LM35,\t");
Serial.print(message.id);
Serial.print(",\t");
Serial.print(message.counter);
Serial.print(",\t");
Serial.print(message.value1, 2);
Serial.print(",\t");
Serial.print(message.value2, 2);
Serial.print(",\t");
Serial.print(message.value3, 2);
Serial.print(",\t");
Serial.print(message.value4, 2);
Serial.print(",\t");
Serial.print(message.value5, 2);
Serial.print(",\t");
Serial.println(message.crc);
delay(100); // give it some time to send before falling asleep
#endif
Sleepy::loseSomeTime(62000);
}
/*****************************************************************************/
long readVcc() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
long result = (high<<8) | low;
result = 1108848L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
return result; // Vcc in millivolts
}
/*****************************************************************************/
static PROGMEM prog_uint32_t crc_table[16] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
unsigned long crc_update(unsigned long crc, byte data)
{
byte tbl_NODEx;
tbl_NODEx = crc ^ (data >> (0 * 4));
crc = pgm_read_dword_near(crc_table + (tbl_NODEx & 0x0f)) ^ (crc >> 4);
tbl_NODEx = crc ^ (data >> (1 * 4));
crc = pgm_read_dword_near(crc_table + (tbl_NODEx & 0x0f)) ^ (crc >> 4);
return crc;
}
unsigned long crc_buf(char *b, long l)
{
unsigned long crc = ~0L;
for (unsigned long i=0; i<l; i++)
crc = crc_update(crc, ((char *)b)[i]);
crc = ~crc;
return crc;
}
unsigned long crc_string(char *s)
{
unsigned long crc = ~0L;
while (*s)
crc = crc_update(crc, *s++);
crc = ~crc;
return crc;
}