cano64 / ATTiny85-ATTiny84-BMP085-Arduino-Library-FastAltitude

ATTiny BMP085 Arduino Library is designed for ATTiny85 and ATTtiny84 microcontrollers using super fast and tiny calculation of altitude without pow and math library
11 stars 3 forks source link

readPressure issue with ATTiny84 #1

Closed exsertus closed 11 years ago

exsertus commented 11 years ago

Hi, just started using this great port for an ATTiny84 / XBee / BMP085 sensor module. I've modded the TinyWireM.h and .cpp files to cater for my ATTiny84 running at 8MHz and I can successfully call the the bmp.readTemperature10C(); function.

However, when I call readPressure() I get a value of around -30055. This suggests that the I2C calls are working between the MCU and BMP085.

I'm in London, so I'd expect the pressure value to be around 1000-1020 Hpa

Here's the code (apologies its quite verbose!). I've also tried this without all the WDT and sleep modes to see if it was those that we messing with the I2C comms. Also my linker is the 8K, so it compiles fine (around 7K)

/*============================================================ Name : XBeeBMP085Sensor Author : exsertus.com (Steve Bowerman)

Summary Generic Xbee sensor program.

Version : 2.0

Credits

============================================================*/

include

include <avr/power.h>

include <avr/sleep.h>

include <avr/wdt.h>

include

include

// Setup 85 and 84 Specifics

if defined (AVR_ATtiny24) || defined(AVR_ATtiny44) || defined(AVR_ATtiny84)

define TX 7

define RX 8

define SLEEP 10

define SENSPWR 9

define DIO1 1

define DIO2 2

define DIO3 5

define AIO1 1

define AIO2 2

define AIO3 5

elif defined (AVR_ATtiny25) || defined(AVR_ATtiny45) || defined(AVR_ATtiny85)

define TX 4

define RX 3

define SLEEP 1

define SENSPWR 0

define D1 2

define A1 1

endif

define INTERVAL 60

define CACHESIZE 1

define DATASETS 1

ifndef cbi

define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))

endif

ifndef sbi

define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

endif

struct LogType { char dataset; int val; int vcc; int offset; };

// Globals

SoftwareSerial XBee (RX, TX); long Vcc = 0; String XBeeAddress = ""; LogType logs[CACHESIZE*DATASETS]; int logcount = 0; int offset = 0;

tinyBMP085 bmp;

ISR(WDT_vect) { // Don't do anything here but we must include this // block of code otherwise the interrupt calls an // uninitialized interrupt handler. }

/*---------------------------------------------------------- Function : setup_watchdog Inputs : li Return : None Globals : None

Summary Sets watchdog interupt up Watchdog timeout values 0=16ms, 1=32ms, 2=64ms, 3=128ms, 4=250ms, 5=500ms 6=1sec, 7=2sec, 8=4sec, 9=8sec Caters for different names for WDT between ATTiny84 and ATTiny85 ----------------------------------------------------------*/

void setup_watchdog(int ii) {
// The prescale value is held in bits 5,2,1,0 // This block moves ii itno these bits byte bb; if (ii > 9 ) ii=9; bb=ii & 7; if (ii > 7) bb|= (1<<5); bb|= (1<<WDCE);

// Reset the watchdog reset flag MCUSR &= ~(1<<WDRF);

if defined (AVR_ATtiny24) || defined(AVR_ATtiny44) || defined(AVR_ATtiny84)

  // Start timed sequence
  WDTCSR |= (1<<WDCE) | (1<<WDE);
  // Set new watchdog timeout value
  WDTCSR = bb;
  // Enable interrupts instead of reset
  WDTCSR |= _BV(WDIE);

elif defined (__AVR_ATtiny25__) || defined(AVR_ATtiny45) || defined(AVR_ATtiny85)

  // Start timed sequence
  WDTCR |= (1<<WDCE) | (1<<WDE);
  // Set new watchdog timeout value
  WDTCR = bb;
  // Enable interrupts instead of reset
  WDTCR |= _BV(WDIE);

endif

}

/*---------------------------------------------------------- Function : deepsleep Inputs : waitTime Return : None Globals : None

Summary Puts Attiny into sleep mode (consumes around 10uA)

----------------------------------------------------------*/

void deepsleep(int waitTime) { // Calculate the delay time waitTime = waitTime / 4; int waitCounter = 0; while (waitCounter != waitTime) { set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode sleep_mode(); // System sleeps here waitCounter++; } }

/*----------------------------------------------------------

Function : setup Inputs : None Return : None Globals : Vcc, XBee, SLEEP, SENSPWR

Summary Sets up program, called once when the circuit is powered up. Sets pins, creates software serial object, watchdog and gets XBee Address

----------------------------------------------------------*/

void setup() {
pinMode(SENSPWR,OUTPUT); pinMode(SLEEP,OUTPUT);

XBee.begin(9600);

getXBeeAddress(); setup_watchdog(8);

}

/*----------------------------------------------------------

Function : loop Inputs : None Return : None Globals : Vcc, XBee, XBeeAddress, INTERVAL, SENSPWR, SLEEP

Summary Main loop routine. Wakes up Xbee, takes reading, sends reading, puts XBee back to sleep, then finally puts ATTIny into sleep mode. Avg awake consumption = 20mAh, sleep consumption = 10uAh

----------------------------------------------------------*/

void loop() { /*

 Take sensor readings and store results in memory

*/

digitalWrite(SENSPWR, HIGH);

// Enable ADC ADCSRA |= (1 << ADEN); ADCSRA |= (1 << ADSC);

delay(1000); bmp.begin(); int32_t readAltitudemm(int32_t sealevelPressure = 101325);

logs[logcount].dataset = 'T'; logs[logcount].val = bmp.readTemperature10C(); //bmp.readPressure(); logs[logcount].vcc = readVcc(); logs[logcount].offset = INTERVAL*(CACHESIZE-offset-1); logcount++;

offset++;

// Disable ADC
ACSR |= _BV(ACD);
ADCSRA &= ~_BV(ADEN);

digitalWrite(SENSPWR, LOW);

/* Upload readings to server

*/

if (logcount >= (DATASETS*CACHESIZE)) { // Wake up Xbee from sleep digitalWrite(SLEEP,LOW); delay(1000);

 // Iterate through log array and upload to server

 for (int i=0; i<logcount; i++) {
   XBee.print(logs[i].dataset);
   XBee.print(",");
   if (logs[i].dataset == 'M' || logs[i].dataset == 'P') {
     XBee.print(logs[i].val);
   } else {
     XBee.print(logs[i].val/10);
     XBee.print(".");
     XBee.print(logs[i].val%10);
   }
   XBee.print(",");
   XBee.print(logs[i].vcc);
   XBee.print(",");
   XBee.print(XBeeAddress);
   XBee.print(",");
   XBee.print(logs[i].offset);
   XBee.print("\n");
   delay(500);
   // clear down array item
   logs[i] = (LogType){' ',0,0,0};
 } 

 logcount = 0;
 offset = 0;

 // Put XBee back to sleep, wait first to allow all remaining data to be sent
 delay(500);   

 digitalWrite(SLEEP,HIGH);

}

// Go back to sleep deepsleep(INTERVAL);

}

/*----------------------------------------------------------

Function : readVcc Inputs : None Return : None Globals : Vcc

Summary Sets the Vcc global variable with the current supply voltage to the Attiny. Works by reading 1.1V reference against AVcc set the reference to Vcc and the measurement to the internal 1.1V reference

----------------------------------------------------------*/

long readVcc() {

if defined (AVR_ATtiny24) || defined(AVR_ATtiny44) || defined(AVR_ATtiny84)

ADMUX = _BV(MUX5) | _BV(MUX0);

elif defined (__AVR_ATtiny25__) || defined(AVR_ATtiny45) || defined(AVR_ATtiny85)

ADMUX = _BV(MUX3) | _BV(MUX2);

endif

delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversion while (bit_is_set(ADCSRA,ADSC)); // measuring

uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both

long result = (high<<8) | low;

result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1_1023_1000 return result; // Vcc in millivolts }

/*----------------------------------------------------------

Function : getXBeeAddress Inputs : None Return : None Globals : XBee, XBeeAddress

Summary Gets the low part of the XBee 64 bit address using the AT command mode persists XBeeAddress in global variable. Only called once during setup.

----------------------------------------------------------*/

void getXBeeAddress() { int inByte; XBeeAddress = "";

digitalWrite(SLEEP,LOW); // wake up XBee delay(1000);

XBee.print("+++"); delay(2000); XBee.flush();

XBee.print("ATSL\r"); delay(500); while (XBee.available() > 0) { inByte = XBee.read(); if (inByte != '\n' && inByte != '\r') XBeeAddress += (char)inByte; }

XBee.print("ATCN\r"); XBee.flush(); delay(1000);

digitalWrite(SLEEP,HIGH); // Put XBee back to sleep

}

cano64 commented 11 years ago

Hi, I believe you are overflowing, see your log structure struct LogType { char dataset; int val; int vcc; int offset; }; int is only 16 bit, values above 32767 won't fix. Your pressure would be about 100000 though. try to use int32_t instead

exsertus commented 11 years ago

Gah!, schoolboy error!. Yup, worked a charm. Just took the value and divided by 100 before writing it to my struct, as I'm interested in HPa rather than Pa.

Brilliant lib, thanks for the quick response.

Steve