BayEOSArduino Library
LowCurrentBoard.h
1 /*
2  * This is a header file, designed to make scetches of Low Current Board easier
3  *
4  * It depends on some conventions:
5  * 1. bayeos.client must be named "client"
6  * 2. Dallas is called "ds"
7  * 3. Changes in CONSTANTS must be declared before include
8  */
9 
10 #include <Sleep.h>
11 #include <RTClib.h>
12 
13 
14 #ifndef LCB_BAT_MULTIPLIER
15 #define LCB_BAT_MULTIPLIER 1.1*320/100/1023
16 #endif
17 
18 #ifndef LCB_BAT_REFERENCE
19 #define LCB_BAT_REFERENCE INTERNAL
20 #endif
21 
22 #ifndef LCB_BAT_ADCPIN
23 #define LCB_BAT_ADCPIN A0
24 #endif
25 
26 
27 #ifndef TICKS_PER_SECOND
28 #define TICKS_PER_SECOND 16
29 #endif
30 
31 #ifndef SAMPLING_INT
32 #define SAMPLING_INT 16
33 #endif
34 
35 #ifndef WITHRAINGAUGE
36 #define WITHRAINGAUGE 0
37 #endif
38 
39 #ifndef LED_PIN
40 #define LED_PIN 5
41 #endif
42 
43 #ifndef POWER_PIN
44 #define POWER_PIN 7
45 #endif
46 
47 #define ISSET_ACTION(nr) ((1<<nr)&action)
48 #define UNSET_ACTION(nr) (action&= ~(1<<nr))
49 
50 #ifndef ACTION_COUNT
51 #define ACTION_COUNT 7
52 #endif
53 
54 #ifndef CHECKSUM_FRAMES
55 #define CHECKSUM_FRAMES 0
56 #endif
57 
58 #ifndef RESET_COUNT
59 #define RESET_COUNT 0
60 #endif
61 
62 
63 #if TICKS_PER_SECOND>3
64 #define LED_TICK_DIV (TICKS_PER_SECOND/4)
65 #else
66 #define LED_TICK_DIV 1
67 #endif
68 
69 volatile uint16_t ticks;
70 volatile uint8_t action;
71 
72 #if RESET_COUNT
73 volatile uint8_t action0_pending_count=0;
74 #endif
75 
76 volatile uint8_t seconds;
77 volatile unsigned long current_micros, last_micros;
78 volatile uint8_t adjust_osccal_flag;
79 volatile uint8_t led_blink = 0;
80 uint8_t startup = 10;
81 float batLCB;
82 RTC_Timer2 myRTC;
83 
84 #ifdef RTC_SECOND_CORRECT
85 volatile long rtc_seconds_correct;
86 #endif
87 
88 
89 /*
90  * ISR for timer2
91  * increments RTC-Time
92  * sets action bits
93  */
94 ISR(TIMER2_OVF_vect) {
95  #ifdef WITH_TIMER2_ISR_TASK
96  timer2_isr_task();
97  #endif
98  ticks++;
99  if(adjust_osccal_flag){
100  last_micros=current_micros;
101  current_micros=micros();
102  adjust_osccal_flag++;
103  if(adjust_osccal_flag>2){
104  if((current_micros-last_micros)>(1006000L/TICKS_PER_SECOND)){
105  if(OSCCAL) OSCCAL--;
106  else adjust_osccal_flag=0; //reached limit!
107  }
108  else if((current_micros-last_micros)<(994000L/TICKS_PER_SECOND)){
109  if(OSCCAL<252) OSCCAL++;
110  else adjust_osccal_flag=0; //reached limit!
111  }
112  else {
113  //Timing is ok :-)
114  adjust_osccal_flag=0;
115  }
116 
117  }
118 
119  }
120 
121  if((ticks % TICKS_PER_SECOND)==0) {
122  myRTC._seconds ++; //RTC_Timer2.get() and adjust() are interrupt save now!
123  seconds++;
124 #ifdef RTC_SECOND_CORRECT
125 
126 #if RTC_SECOND_CORRECT < 0
127  rtc_seconds_correct--;
128  if(rtc_seconds_correct<=RTC_SECOND_CORRECT){
129  rtc_seconds_correct=0;
130  myRTC._seconds --;
131  seconds--;
132  }
133 #else
134  rtc_seconds_correct++;
135  if(rtc_seconds_correct>=RTC_SECOND_CORRECT){
136  rtc_seconds_correct=0;
137  myRTC._seconds ++;
138  seconds++;
139  }
140 
141 #endif
142 #endif
143  uint16_t tick_mod=myRTC._seconds%SAMPLING_INT;
144  if(tick_mod<ACTION_COUNT) {
145 #if RESET_COUNT
146  if(tick_mod==0){
147  if(ISSET_ACTION(0))
148  action0_pending_count++;
149 
150  else
151  action0_pending_count=0;
152  if(action0_pending_count>RESET_COUNT){
153  #ifdef RESET_FUN
154  RESET_FUN
155  #endif
156  asm volatile (" jmp 0"); //restart programm
157 
158  }
159 
160  }
161 #endif
162  action|=(1<<tick_mod);
163  } else {
164  action|=(1<<7);
165  }
166  }
167 
168  if((led_blink>0) && ((ticks%LED_TICK_DIV)==0)) {
169  if(digitalRead(LED_PIN)) led_blink--;
170  digitalWrite(LED_PIN,!digitalRead(LED_PIN));
171  }
172 
173 }
174 
175 inline void handleRtcLCB(void) {
176  // no longer needed!!
177 }
178 
179 /*
180  * Adjust the OSCCAL of internal oscillator using TIMER2 RTC
181  */
182 void adjust_OSCCAL(void){
183  adjust_osccal_flag=1;
184  while(adjust_osccal_flag){
185  delay(1);
186  }
187 }
188 
189 
190 #if WITHRAINGAUGE
191 float rain_count=0;
192 volatile uint8_t rain_event=0;
193 volatile uint16_t rain_event_ticks;
194 void rain_isr(void) {
195  if(rain_event && ((ticks-rain_event_ticks)>(TICKS_PER_SECOND/2))){
196  rain_count++;
197  }
198  rain_event=1;
199  rain_event_ticks=ticks;
200 }
201 
202 //Wird in loop aufgerufen
203 void handleRainEventLCB(void) {
204  if(rain_event){
205  noInterrupts();
206  if(rain_event && ((ticks-rain_event_ticks)>(TICKS_PER_SECOND/2))){
207  rain_count++;
208  rain_event=0;
209  }
210  interrupts();
211  }
212 }
213 #endif
214 
215 #if WITHWIND
216 volatile uint16_t wind_count=0;
217 volatile uint8_t wind_event=0;
218 volatile uint16_t wind_event_ticks;
219 volatile uint16_t min_wind_ticks=65535;
220 long windn=0;
221 long windo=0;
222 uint16_t wind_direction_count=0;
223 void wind_isr(void) {
224  if((ticks-wind_event_ticks)>4) {
225  if((ticks-wind_event_ticks)<min_wind_ticks)
226  min_wind_ticks=ticks-wind_event_ticks;
227  wind_count++;
228  wind_event=1;
229  wind_event_ticks=ticks;
230  }
231 }
232 
233 #ifndef WIND_DIRECTION_PIN
234 #define WIND_DIRECTION_PIN A2
235 #endif
236 #ifndef WIND_POWER_PIN
237 #define WIND_POWER_PIN A3
238 #endif
239 
240 void readWindDirectionLCB() {
241  wind_direction_count++;
242  pinMode(WIND_POWER_PIN,OUTPUT);
243  digitalWrite(WIND_POWER_PIN,HIGH);
244  int adc=analogRead(WIND_DIRECTION_PIN);
245  digitalWrite(WIND_POWER_PIN,LOW);
246  pinMode(WIND_POWER_PIN,INPUT);
247 
248  if(adc<552) {
249  windn+=7071;
250  windo+=7071;
251  return;
252  }
253  if(adc<602) {
254  windo+=7071;
255  windn+=-7071;
256  return;
257  }
258  if(adc<683) {
259  windo+=10000;
260  return;
261  }
262  if(adc<761) {
263  windn+=7071;
264  windo+=-7071;
265  return;
266  }
267  if(adc<806) {
268  windn+=10000;
269  return;
270  }
271  if(adc<857) {
272  windn+=-7071;
273  windo+=-7071;
274  return;
275  }
276  if(adc<916) {
277  windn+=-10000;
278  return;
279  }
280  windo+=-10000;
281  return;
282 }
283 
284 #endif
285 
286 #if WITHDALLAS
287 #include <DS18B20.h>
288 
289 uint8_t channel;
290 const byte* new_addr;
291 #ifndef DALLAS_PIN
292 #define DALLAS_PIN 6
293 #endif
294 
295 #ifndef DALLAS_CHANNELS
296 #define DALLAS_CHANNELS 4
297 #endif
298 
299 #ifndef DALLAS_OFFSET
300 #define DALLAS_OFFSET 20
301 #endif
302 
303 DS18B20 ds=DS18B20(DALLAS_PIN,DALLAS_OFFSET,DALLAS_CHANNELS); //Allow four sensors on the bus - channel 11-14
304 
305 void readAndSendDallasLCB(uint8_t send=1) {
306  float temp;
307  client.startDataFrame(BayEOS_ChannelFloat32le,CHECKSUM_FRAMES);
308  while(channel=ds.getNextChannel()) {
309  if(! ds.readChannel(channel,&temp)) {
310  client.addChannelValue(temp,channel);
311  }
312  }
313 #if CHECKSUM_FRAMES
314  client.addChecksum();
315 #endif
316  if(send) client.sendOrBuffer();
317  else client.writeToBuffer();
318 }
319 
320 #endif
321 
322 /*
323  * blinkLED is done by timer2
324  */
325 void blinkLED(uint8_t times) {
326  if (LED_PIN > -1)
327  led_blink = times;
328 }
329 
330 /*
331  * init Time2 and LED pin
332  */
333 void initLCB() {
334 #if TICKS_PER_SECOND==128
335  Sleep.setupTimer2(1); //init timer2 to 0,0078125sec
336 #elif TICKS_PER_SECOND==16
337  Sleep.setupTimer2(2); //init timer2 to 0,0625sec
338 #elif TICKS_PER_SECOND==4
339  Sleep.setupTimer2(3); //init timer2 to 0,25sec
340 #elif TICKS_PER_SECOND==2
341  Sleep.setupTimer2(4); //init timer2 to 0,5sec
342 #elif TICKS_PER_SECOND==1
343  Sleep.setupTimer2(5); //init timer2 to 1sec
344 #else
345 #error unsupported TICKS_PER_SECOND
346 #endif
347 
348 #if LED_PIN>-1
349  pinMode(LED_PIN, OUTPUT);
350 #endif
351 #if WITHRAINGAUGE
352 #ifndef RAINGAUGEPIN
353 #define RAINGAUGEPIN 2
354 #endif
355  digitalWrite(RAINGAUGEPIN,HIGH); //Enable Pullup on Pin 2 == INT0
356  attachInterrupt(digitalPinToInterrupt(RAINGAUGEPIN),rain_isr,FALLING);
357  rain_count=0;
358  rain_event=0;
359 #endif
360 
361 #if WITHWIND
362  attachInterrupt(1,wind_isr,RISING);
363  wind_count=0;
364  wind_event=0;
365  windn=0;
366  windo=0;
367 #endif
368 
369 #if WITHDALLAS
371  // Search and Delete
372  while(channel=ds.checkSensors()) {
373  new_addr=ds.getChannelAddress(channel);
374  client.createMessage(String("DS:")+channel+"-"+ds.addr2String(new_addr),CHECKSUM_FRAMES);
375  client.writeToBuffer();
376  ds.deleteChannel(new_addr);
377  }
378  while(new_addr=ds.search()) {
379  if(channel=ds.getNextFreeChannel()) {
380  ds.addSensor(new_addr,channel);
381  client.createMessage(String("DS:")+channel+"+"+ds.addr2String(new_addr),CHECKSUM_FRAMES);
382  client.writeToBuffer();
383  }
384  }
385 #endif
386 
387 }
388 
389 void sleepLCB() {
390  Sleep.sleep(TIMER2_ON, SLEEP_MODE_PWR_SAVE);
391 }
392 
393 void delayLCB(uint16_t _millis) {
394  _millis /= (1000 / TICKS_PER_SECOND);
395  noInterrupts();
396  uint16_t end_ticks = ticks + _millis + 2;
397  interrupts();
398  do {
399  sleepLCB();
400  } while ((ticks != end_ticks));
401 }
402 
403 void readBatLCB() {
404  analogReference (LCB_BAT_REFERENCE);
405  pinMode(POWER_PIN, OUTPUT);
406  digitalWrite(POWER_PIN, HIGH);
407  batLCB = LCB_BAT_MULTIPLIER * analogRead(LCB_BAT_ADCPIN);
408  digitalWrite(POWER_PIN, LOW);
409  pinMode(POWER_PIN, INPUT);
410  analogReference (DEFAULT);
411 }
412 
413 void startLCB() {
414  blinkLED(3);
415  delayLCB(2000);
416  noInterrupts();
417  action = 0;
418  ticks = 0;
419  myRTC._seconds=SAMPLING_INT-1;
420  interrupts();
421 }
422 
423 void sendOrBufferLCB() {
424  if (startup) {
425  if (client.sendPayload()) {
426  client.writeToBuffer();
427  blinkLED(2);
428  } else
429  blinkLED(1);
430  startup--;
431  } else {
432  client.sendOrBuffer();
433  }
434 
435 }
uint8_t addChannelValue(float v, uint8_t channel_number=0)
Definition: BayEOS.cpp:61
uint8_t writeToBuffer(void)
Definition: BayEOS.cpp:322
uint8_t createMessage(const char *s, uint8_t checksum=0, uint8_t frametype=BayEOS_Message)
Definition: BayEOS.cpp:301
void startDataFrame(uint8_t subtype=BayEOS_Float32le, uint8_t checksum=0)
Definition: BayEOS.cpp:12
uint8_t sendOrBuffer(void)
Definition: BayEOS.cpp:369
uint8_t sendPayload(void)
Definition: BayRF24.cpp:15
Definition: DS18B20.h:31
const String addr2String(const uint8_t *addr)
Definition: DS18B20.cpp:199
uint8_t readChannel(uint8_t channel, float *f, uint8_t tries=1)
Definition: DS18B20.cpp:147
uint8_t setAllAddrFromEEPROM(void)
Definition: DS18B20.cpp:81
uint8_t deleteChannel(const uint8_t *addr)
Definition: DS18B20.cpp:175
uint8_t getNextChannel(void)
Definition: DS18B20.cpp:14
uint8_t getNextFreeChannel(void)
Definition: DS18B20.cpp:168
const uint8_t * search(void)
Definition: DS18B20.cpp:30
uint8_t addSensor(const uint8_t *new_addr, uint8_t channel)
Definition: DS18B20.cpp:58
uint8_t checkSensors(void)
Definition: DS18B20.cpp:40
const uint8_t * getChannelAddress(uint8_t channel) const
Definition: DS18B20.cpp:184
Definition: RTClib.h:39