Advertisement
nathanchantrell

TinyTX V2 with BMP085

Jul 17th, 2013
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.79 KB | None | 0 0
  1. //----------------------------------------------------------------------------------------------------------------------
  2. // TinyTX - An ATtiny84 and BMP085 Wireless Air Pressure/Temperature Sensor Node
  3. // By Nathan Chantrell. For hardware design see http://nathan.chantrell.net/tinytx
  4. //
  5. // Using the BMP085 sensor connected via I2C
  6. // I2C can be connected withf SDA to D8 and SCL to D7 or SDA to D10 and SCL to D9
  7. //
  8. // Licenced under the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) licence:
  9. // http://creativecommons.org/licenses/by-sa/3.0/
  10. //
  11. // Requires Arduino IDE with arduino-tiny core: http://code.google.com/p/arduino-tiny/
  12. //----------------------------------------------------------------------------------------------------------------------
  13.  
  14. #include <JeeLib.h> // https://github.com/jcw/jeelib
  15. #include <PortsBMP085.h> // Part of JeeLib
  16.  
  17. ISR(WDT_vect) { Sleepy::watchdogEvent(); } // interrupt handler for JeeLabs Sleepy power saving
  18.  
  19. #define myNodeID 8        // RF12 node ID in the range 1-30
  20. #define network 210       // RF12 Network group
  21. #define freq RF12_433MHZ  // Frequency of RFM12B module
  22.  
  23. //#define USE_ACK           // Enable ACKs, comment out to disable
  24. #define RETRY_PERIOD 5    // How soon to retry (in seconds) if ACK didn't come in
  25. #define RETRY_LIMIT 5     // Maximum number of times to retry
  26. #define ACK_TIME 10       // Number of milliseconds to wait for an ack
  27.  
  28. //PortI2C i2c (2);         // BMP085 SDA to D8 and SCL to D7
  29.  PortI2C i2c (1);      // BMP085 SDA to D10 and SCL to D9
  30. BMP085 psensor (i2c, 3); // ultra high resolution
  31. #define BMP085_POWER 9   // BMP085 Power pin is connected on D9
  32.  
  33. //########################################################################################################################
  34. //Data Structure to be sent
  35. //########################################################################################################################
  36.  
  37.  typedef struct {
  38.       int16_t temp; // Temperature reading
  39.       int supplyV;  // Supply voltage
  40.           int32_t pres; // Pressure reading
  41.  } Payload;
  42.  
  43.  Payload tinytx;
  44.  
  45. // Wait a few milliseconds for proper ACK
  46.  #ifdef USE_ACK
  47.   static byte waitForAck() {
  48.    MilliTimer ackTimer;
  49.    while (!ackTimer.poll(ACK_TIME)) {
  50.      if (rf12_recvDone() && rf12_crc == 0 &&
  51.         rf12_hdr == (RF12_HDR_DST | RF12_HDR_CTL | myNodeID))
  52.         return 1;
  53.      }
  54.    return 0;
  55.   }
  56.  #endif
  57.  
  58. //--------------------------------------------------------------------------------------------------
  59. // Send payload data via RF
  60. //-------------------------------------------------------------------------------------------------
  61.  static void rfwrite(){
  62.   #ifdef USE_ACK
  63.    for (byte i = 0; i <= RETRY_LIMIT; ++i) {  // tx and wait for ack up to RETRY_LIMIT times
  64.      rf12_sleep(-1);              // Wake up RF module
  65.       while (!rf12_canSend())
  66.       rf12_recvDone();
  67.       rf12_sendStart(RF12_HDR_ACK, &tinytx, sizeof tinytx);
  68.       rf12_sendWait(2);           // Wait for RF to finish sending while in standby mode
  69.       byte acked = waitForAck();  // Wait for ACK
  70.       rf12_sleep(0);              // Put RF module to sleep
  71.       if (acked) { return; }      // Return if ACK received
  72.  
  73.    Sleepy::loseSomeTime(RETRY_PERIOD * 1000);     // If no ack received wait and try again
  74.    }
  75.   #else
  76.      rf12_sleep(-1);              // Wake up RF module
  77.      while (!rf12_canSend())
  78.      rf12_recvDone();
  79.      rf12_sendStart(0, &tinytx, sizeof tinytx);
  80.      rf12_sendWait(2);           // Wait for RF to finish sending while in standby mode
  81.      rf12_sleep(0);              // Put RF module to sleep
  82.      return;
  83.   #endif
  84.  }
  85.  
  86. //--------------------------------------------------------------------------------------------------
  87. // Read current supply voltage
  88. //--------------------------------------------------------------------------------------------------
  89. long readVcc() {
  90.    bitClear(PRR, PRADC); ADCSRA |= bit(ADEN); // Enable the ADC
  91.    long result;
  92.    // Read 1.1V reference against Vcc
  93.    #if defined(__AVR_ATtiny84__)
  94.     ADMUX = _BV(MUX5) | _BV(MUX0); // For ATtiny84
  95.    #else
  96.     ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);  // For ATmega328
  97.    #endif
  98.    delay(2); // Wait for Vref to settle
  99.    ADCSRA |= _BV(ADSC); // Convert
  100.    while (bit_is_set(ADCSRA,ADSC));
  101.    result = ADCL;
  102.    result |= ADCH<<8;
  103.    result = 1126400L / result; // Back-calculate Vcc in mV
  104.    ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power
  105.    return result;
  106. }
  107. //########################################################################################################################
  108.  
  109. void setup() {
  110.  
  111. //  pinMode(BMP085_POWER, OUTPUT); // set power pin for BMP085 to output
  112. //  digitalWrite(BMP085_POWER, HIGH); // turn BMP085 sensor on
  113.   Sleepy::loseSomeTime(50);
  114.   psensor.getCalibData();
  115.  
  116.   rf12_initialize(myNodeID,freq,network); // Initialize RFM12 with settings defined above
  117.   rf12_sleep(0);                          // Put the RFM12 to sleep
  118.    
  119.   PRR = bit(PRTIM1); // only keep timer 0 going
  120.  
  121.   ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power
  122.  
  123. }
  124.  
  125. void loop() {
  126.    
  127.   // Get raw temperature reading
  128.   psensor.startMeas(BMP085::TEMP);
  129.   Sleepy::loseSomeTime(16);
  130.   int32_t traw = psensor.getResult(BMP085::TEMP);
  131.  
  132.   // Get raw pressure reading
  133.   psensor.startMeas(BMP085::PRES);
  134.   Sleepy::loseSomeTime(32);
  135.   int32_t praw = psensor.getResult(BMP085::PRES);
  136.  
  137.   // Calculate actual temperature and pressure
  138.   int32_t press;
  139.   psensor.calculate(tinytx.temp, press);
  140.   tinytx.pres = (press * 0.01);
  141.  
  142.   tinytx.supplyV = readVcc(); // Get supply voltage
  143.  
  144.   rfwrite(); // Send data via RF
  145.  
  146.   Sleepy::loseSomeTime(60000); //JeeLabs power save function: enter low power mode for 60 seconds (valid range 16-65000 ms)
  147.  
  148. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement