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 | } |