Statistics
| Revision:

root / Ports / examples / bmp085demo / bmp085demo.pde

History | View | Annotate | Download (4 KB)

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