Statistics
| Revision:

root / Ports / examples / bmp085demo / bmp085demo.pde

History | View | Annotate | Download (4 KB)

1
//>>> The latest version of this code can be found at https://github.com/jcw/ !!
2
3
// Ports demo, reads out a BMP085 sensor connected via I2C
4
// 2009-02-17 <jcw@equi4.com> http://opensource.org/licenses/mit-license.php
5
// $Id: bmp085demo.pde 7763 2011-12-11 01:28:16Z jcw $
6
7
// 2010-05-22: added support for all resolution modes
8
// 2010-05-25: extended to also broadcast all readings over wireless
9
// 2010-06-17: add power saving logic, should reduce consumption by over 90%
10
// 2010-06-24: improved power savings, several "hot spots" optimized
11
12
// see http://news.jeelabs.org/2010/06/20/battery-savings-for-the-pressure-plug/
13
// see http://news.jeelabs.org/2010/06/30/going-for-gold-with-the-bmp085/
14
15
#include <Ports.h>
16
#include "PortsBMP085.h"
17
#include <RF12.h>
18
#include <avr/sleep.h>
19
20
PortI2C two (2);
21
BMP085 psensor (two, 3); // ultra high resolution
22
MilliTimer timer;
23
24
// This power-saving code was shamelessly stolen from the rooms.pde sketch,
25
// see http://code.jeelabs.org/viewvc/svn/jeelabs/trunk/jeemon/sketches/rooms/
26
27
EMPTY_INTERRUPT(WDT_vect); // just wakes us up to resume
28
29
static void watchdogInterrupts (char mode) {
30
    MCUSR &= ~(1<<WDRF); // only generate interrupts, no reset
31
    cli();
32
    WDTCSR |= (1<<WDCE) | (1<<WDE); // start timed sequence
33
    WDTCSR = mode >= 0 ? bit(WDIE) | mode : 0;
34
    sei();
35
}
36
37
static void lowPower (byte mode) {
38
    // prepare to go into power down mode
39
    set_sleep_mode(mode);
40
    // disable the ADC
41
    byte prrSave = PRR, adcsraSave = ADCSRA;
42
    ADCSRA &= ~ bit(ADEN);
43
    PRR |=  bit(PRADC);
44
    // zzzzz...
45
    sleep_mode();
46
    // re-enable the ADC
47
    PRR = prrSave;
48
    ADCSRA = adcsraSave;
49
}
50
51
static byte loseSomeTime (word msecs) {
52
    // only slow down for periods longer than the watchdog granularity
53
    if (msecs >= 16) {
54
        // watchdog needs to be running to regularly wake us from sleep mode
55
        watchdogInterrupts(0); // 16ms
56
        for (word ticks = msecs / 16; ticks > 0; --ticks) {
57
            lowPower(SLEEP_MODE_PWR_DOWN); // now completely power down
58
            // adjust the milli ticks, since we will have missed several
59
            extern volatile unsigned long timer0_millis;
60
            timer0_millis += 16;
61
        }
62
        watchdogInterrupts(-1); // off
63
        return 1;
64
    }
65
    return 0;
66
}
67
68
// End of new power-saving code.
69
70
void setup() {
71
    Serial.begin(57600);
72
    Serial.print("\n[bmp085demo]");
73
    rf12_initialize(3, RF12_868MHZ, 5); // 868 Mhz, net group 5, node 3
74
    
75
    psensor.getCalibData();
76
}
77
78
void loop() {
79
    // spend most of the waiting time in a low-power sleep mode
80
    // note: the node's sense of time is no longer 100% accurate after sleeping
81
    rf12_sleep(RF12_SLEEP);          // turn the radio off
82
    loseSomeTime(timer.remaining()); // go into a (controlled) comatose state
83
    
84
    while (!timer.poll(1000))
85
        lowPower(SLEEP_MODE_IDLE);   // still not running at full power
86
87
    // sensor readout takes some time, so go into power down while waiting
88
    // int32_t traw = psensor.measure(BMP085::TEMP);
89
    // int32_t praw = psensor.measure(BMP085::PRES);
90
    
91
    psensor.startMeas(BMP085::TEMP);
92
    loseSomeTime(16);
93
    int32_t traw = psensor.getResult(BMP085::TEMP);
94
95
    psensor.startMeas(BMP085::PRES);
96
    loseSomeTime(32);
97
    int32_t praw = psensor.getResult(BMP085::PRES);
98
    
99
    struct { int16_t temp; int32_t pres; } payload;
100
    psensor.calculate(payload.temp, payload.pres);
101
    
102
    // this code is not needed for use as remote node, keep it for debugging
103
    Serial.print("\nBMP ");
104
    Serial.print(traw);
105
    Serial.print(' ');
106
    Serial.print(praw);    
107
    Serial.print(' ');
108
    Serial.print(payload.temp);
109
    Serial.print(' ');
110
    Serial.print(payload.pres);
111
    
112
    rf12_sleep(RF12_WAKEUP);         // turn radio back on at the last moment
113
    
114
    MilliTimer wait;                 // radio needs some time to power up, why?
115
    while (!wait.poll(5)) {
116
        rf12_recvDone();
117
        lowPower(SLEEP_MODE_IDLE);
118
    }
119
        
120
    while (!rf12_canSend())
121
        rf12_recvDone();
122
    
123
    rf12_sendStart(0, &payload, sizeof payload, 1); // sync mode!
124
}