mbed Weather Station for Weatherduino on mbeduino http://mbed.org/users/okini3939/notebook/weatherduino-on-mbed/
Revision 0:6e444b317905, committed 2010-09-27
- Comitter:
- okini3939
- Date:
- Mon Sep 27 15:52:09 2010 +0000
- Child:
- 1:23400c328a71
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BMP085/.meta Mon Sep 27 15:52:09 2010 +0000 @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<root> + <global/> + <data> + <created_ts>1284884707</created_ts> + <last_mod_ts>1284884707</last_mod_ts> + <is_archive>0</is_archive> + <is_published>0</is_published> + <is_svn>0</is_svn> + <is_module>0</is_module> + <is_lib>1</is_lib> + <path>/Weather/BMP085</path> + <lines>40</lines> + <enable_beta_0006>true</enable_beta_0006> + <compiler_version>1.3.0.13</compiler_version> + <rmchars>4979</rmchars> + <duration>1288</duration> + <chars>470</chars> + </data> +</root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BMP085/BMP085.cpp Mon Sep 27 15:52:09 2010 +0000 @@ -0,0 +1,133 @@ +/* + * mbed library to use a Bosch Sensortec BMP085 sensor + * Copyright (c) 2010 Hiroshi Suga + * Released under the MIT License: http://mbed.org/license/mit + */ + +#include "mbed.h" +#include "BMP085.h" + +#define WEATHER_BMP085 0xee +#define xpow(x, y) ((long)1 << y) + + +BMP085::BMP085 (PinName p_sda, PinName p_scl, BMP085_oss p_oss) : i2c(p_sda, p_scl) { + init(p_oss); +} + +BMP085::BMP085 (I2C& p_i2c, BMP085_oss p_oss) : i2c(p_i2c) { + init(p_oss); +} + +float BMP085::get_temperature() { + return temperature; +} + +float BMP085::get_pressure() { + return pressure; +} + +void BMP085::update () { + long t, p, ut, up, x1, x2, x3, b3, b5, b6; + unsigned long b4, b7; + + twi_writechar(WEATHER_BMP085, 0xf4, 0x2e); + wait(0.01); + ut = twi_readshort(WEATHER_BMP085, 0xf6); + + twi_writechar(WEATHER_BMP085, 0xf4, 0x34 | (oss << 6)); + wait(0.05); + up = twi_readlong(WEATHER_BMP085, 0xf6) >> (8 - oss); + + x1 = (ut - ac6) * ac5 / xpow(2, 15); + x2 = (long)mc * xpow(2, 11) / (x1 + md); + b5 = x1 + x2; + t = (b5 + 8) / xpow(2, 4); + temperature = (float)t / 10.0; + + b6 = b5 - 4000; + x1 = (b2 * (b6 * b6 / xpow(2, 12))) / xpow(2, 11); + x2 = ac2 * b6 / xpow(2, 11); + x3 = x1 + x2; + b3 = ((((unsigned long)ac1 * 4 + x3) << oss) + 2) / 4; + x1 = ac3 * b6 / xpow(2, 13); + x2 = (b1 * (b6 * b6 / xpow(2, 12))) / xpow(2, 16); + x3 = ((x1 + x2) + 2) / xpow(2, 2); + b4 = ac4 * (unsigned long)(x3 + 32768) / xpow(2, 15); + b7 = ((unsigned long)up - b3) * (50000 >> oss); + if (b7 < (unsigned long)0x80000000) { + p = (b7 * 2) / b4; + } else { + p = (b7 / b4) * 2; + } + x1 = (p / xpow(2, 8)) * (p / xpow(2, 8)); + x1 = (x1 * 3038) / xpow(2, 16); + x2 = (-7357 * p) / xpow(2, 16); + p = p + (x1 + x2 + 3791) / xpow(2, 4); + pressure = (float)p / 100.0; +} + +void BMP085::init (BMP085_oss p_oss) { + ac1 = twi_readshort(WEATHER_BMP085, 0xaa); + ac2 = twi_readshort(WEATHER_BMP085, 0xac); + ac3 = twi_readshort(WEATHER_BMP085, 0xae); + ac4 = twi_readshort(WEATHER_BMP085, 0xb0); + ac5 = twi_readshort(WEATHER_BMP085, 0xb2); + ac6 = twi_readshort(WEATHER_BMP085, 0xb4); + b1 = twi_readshort(WEATHER_BMP085, 0xb6); + b2 = twi_readshort(WEATHER_BMP085, 0xb8); + mb = twi_readshort(WEATHER_BMP085, 0xba); + mc = twi_readshort(WEATHER_BMP085, 0xbc); + md = twi_readshort(WEATHER_BMP085, 0xbe); + oss = p_oss; +} + +unsigned short BMP085::twi_readshort (int id, int addr) { + + i2c.start(); + i2c.write(id); + i2c.write(addr); + + i2c.start(); + unsigned short i; + + i2c.start(); + i2c.write(id); + i2c.write(addr); + + i2c.start(); + i2c.write(id | 1); + i = i2c.read(1) << 8; + i |= i2c.read(0); + i2c.stop(); + + return i; +} + +unsigned long BMP085::twi_readlong (int id, int addr) { + unsigned long i; + + i2c.start(); + i2c.write(id); + i2c.write(addr); + + i2c.start(); + i2c.write(id | 1); + i = i2c.read(1) << 16; + i |= i2c.read(1) << 8; + i |= i2c.read(0); + i2c.stop(); + + return i; +} + +char BMP085::twi_writechar (int id, int addr, int dat) { + + i2c.start(); + i2c.write(id); + i2c.write(addr); + i2c.write(dat); + i2c.stop(); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BMP085/BMP085.h Mon Sep 27 15:52:09 2010 +0000 @@ -0,0 +1,44 @@ +/* + * mbed library to use a Bosch Sensortec BMP085 sensor + * Copyright (c) 2010 Hiroshi Suga + * Released under the MIT License: http://mbed.org/license/mit + */ + +#ifndef BMP085_H +#define BMP085_H + +#include "mbed.h" + +enum BMP085_oss { + BMP085_oss1 = 0, + BMP085_oss2 = 1, + BMP085_oss4 = 2, + BMP085_oss8 = 3 +}; + +class BMP085 : public Base { +public: + BMP085(PinName p_sda, PinName p_scl, BMP085_oss p_oss = BMP085_oss1); + BMP085(I2C& p_i2c, BMP085_oss p_oss = BMP085_oss1); + + float get_temperature(); + float get_pressure(); + void update(); + +protected: + void init(BMP085_oss); + unsigned short twi_readshort (int, int); + unsigned long twi_readlong (int, int); + char twi_writechar (int, int, int); + + I2C i2c; + float temperature; + float pressure; + +private: + + short ac1, ac2, ac3, b1, b2, mb, mc, md, oss; + unsigned short ac4, ac5, ac6; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SHT_v1/.meta Mon Sep 27 15:52:09 2010 +0000 @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<root> + <global/> + <data> + <created_ts>1284884416</created_ts> + <last_mod_ts>1284989117</last_mod_ts> + <is_archive>0</is_archive> + <is_published>0</is_published> + <is_svn>0</is_svn> + <is_module>0</is_module> + <is_lib>1</is_lib> + <url>http://mbed.org/users/roselea/programs/SHT_v1</url> + <url_full>http://mbed.org/users/roselea/programs/SHT_v1/5ye5b</url_full> + <rev>5ye5b</rev> + </data> +</root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SHT_v1/SHT.cpp Mon Sep 27 15:52:09 2010 +0000 @@ -0,0 +1,224 @@ +/* mbed module to use a Sensirion SHT1x /SHT7x sensor + * Copyright (c) 2007-2009 Stephen McGarry + * Released under the MIT License: http://mbed.org/license/mit + */ + +#include "SHT.h" + +#include "mbed.h" + +SHT::SHT(PinName p_sclk, PinName p_data, SHT_acc p_accuracy) : sclk(p_sclk), data(p_data), accuracy(p_accuracy) { + sclk=0; + data=0; // data pin will be used as open collector pin + data.mode(PullUp); // with the pull up internally active + data.input(); // with line released to go high + temperature = humidity = dewpoint=0.0f; + printf("constructor\n"); +} + +char SHT::write_byte(byte value) +//---------------------------------------------------------------------------------- +// writes a byte on the Sensibus and checks the acknowledge +{ + int i; + char error=0; + + for (i=0x80;i>0;i/=2) { //shift bit for masking + if (i & value) data.input(); //masking value with i , write to SENSI-BUS + else data.output(); + wait_us(1); //ensure sclk is low for min time + sclk=1; //clk for SENSI-BUS + wait_us(1); //pulsewith approx. 2 us + sclk=0; + } + data.input(); //release DATA-line + wait_us(1); //ensure sclk is low for min time + sclk=1; //clk #9 for ack + error=data; //check ack (DATA will be pulled down by SHT11) + wait_us(1); + sclk=0; + return error; //error=1 in case of no acknowledge +} + +byte SHT::read_byte(bool send_ack) +//---------------------------------------------------------------------------------- +// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1" +{ + byte i,val=0; + data.input(); //release DATA-line + for (i=0x80;i>0;i/=2) { //shift bit for masking + wait_us(1); + sclk=1; //clk for SENSI-BUS + if (data) val=(val | i); //read bit + wait_us(1); + sclk=0; + } + wait_us(1); + if (send_ack) data.output(); // if ack needed then drive data low + sclk=1; //clk #9 for ack + wait_us(1); + sclk=0; + data.input(); //release DATA-line + return val; +} + +void SHT::trans_start(void) +//---------------------------------------------------------------------------------- +// generates a transmission start +// _____ ________ +// DATA: |_______| +// ___ ___ +// SCK : ___| |___| |______ +{ + data.input(); + sclk=0; //Initial state + wait_us(1); + sclk=1; + wait_us(1); + data.output(); // data low + wait_us(1); + sclk=0; + wait_us(1); + sclk=1; + wait_us(1); + data.input(); // allow data to high + wait_us(1); + sclk=0; + wait_us(1); +} + +void SHT::connection_reset(void) +//---------------------------------------------------------------------------------- +// communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart +// _____________________________________________________ ________ +// DATA: |_______| +// _ _ _ _ _ _ _ _ _ ___ ___ +// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |______ +{ + int i; + data.input(); // allow data high + sclk=0; // and clk low + for (i=0;i<9;i++) { // 9 SCK cycles + wait_us(1); + sclk=1; + wait_us(1); + sclk=0; + } +} +char SHT::soft_reset(void) +//---------------------------------------------------------------------------------- +// resets the sensor by a softreset +{ + char error=0; + SHT::connection_reset(); //reset communication + trans_start(); + error+=write_byte(com_reset); //send RESET-command to sensor + return error; //error=1 in case of no response form the sensor +} + +char SHT::read_status(byte &value) +//---------------------------------------------------------------------------------- +// reads the status register with checksum (8-bit) +{ + //byte checksum; + + char error=0; + trans_start(); //transmission start + error=write_byte(com_read_status_reg); //send command to sensor + value=read_byte(send_ack); //read status register (8-bit) + /* checksum= */ + (void)read_byte(no_ack); //read checksum (8-bit) + // check the checksum ?? + return error; //error=1 in case of no response form the sensor +} + +char SHT::write_status(byte value) +//---------------------------------------------------------------------------------- +// writes the status register (8-bit) +{ + char error=0; + trans_start(); //transmission start + error+=write_byte(com_write_status_reg); //send command to sensor + error+=write_byte(value); //send value of status register + return error; //error>=1 in case of no response form the sensor +} + +char SHT::measure(int &value, byte command) +//---------------------------------------------------------------------------------- +// makes a measurement (humidity/temperature) with checksum +{ + unsigned int i; + byte msb; + // byte checksum; + + trans_start(); //transmission start + if (write_byte(command)) return 1; // if command fails return + + for (i=10000;i;i--) { //wait until sensor has finished the measurement + wait_us(100); + if (data==0) break; + } + if (data) return 1; // or timeout (~1 sec.) is reached !! + msb = read_byte(send_ack); //read the first byte (MSB) + value = msb*256 + read_byte(send_ack); //read the second byte (LSB) + /* checksum= */ + (void)read_byte(no_ack); //read checksum + return 0; +} + +void SHT::calculate() +//---------------------------------------------------------------------------------------- +// calculates temperature [°C] and humidity [%RH] +// input : hum [Ticks] (12 bit) +// temp [Ticks] (14 bit) +// output: humidity [%RH] +// temperature [°C] +{ + const float C1=-4.0; // for 12 Bit + const float C2=+0.0405; // for 12 Bit + const float C3=-0.0000028; // for 12 Bit + //const float T1=+0.01; // for 14 Bit @ 5V + //const float T2=+0.00008; // for 14 Bit @ 5V + + float rh; // rh: Humidity [Ticks] 12 Bit + float t; // t: Temperature [Ticks] 14 Bit + //float rh_lin; // rh_lin: Humidity linear + if (accuracy==SHT_low) { + rh=hum*16; // rescale to high accuracy values - 8 to 12 bits + t=temp*4; // and 12 to 14 bits + } else { + rh=hum; + t=temp; + } + + temperature=t*0.01 - 40; //calc. temperature from ticks to [°C] + humidity=C3*rh*rh + C2*rh + C1; //calc. humidity from ticks to [%RH] + // =(temperature-25)*(T1+T2*rh)+rh_lin; //calc. temperature compensated humidity [%RH] (ignore as never >0.25%) + if (humidity>100)humidity=100; //cut if the value is outside of + if (humidity<0.1)humidity=0.1; //the physical possible range +} + +float SHT::get_temperature() { // get the most recent temp reading + return temperature; +} + +float SHT::get_humidity() { // get the most recent humidity reading + return humidity; +} + +float SHT::get_dewpoint() { // get the most recent dewpoint value + return dewpoint; +} + +void SHT::update(SHT_acc acc) { // update stored values from sensor + int error=0; + connection_reset(); + if (acc!=accuracy) { + accuracy=acc; + error+=write_status((acc==SHT_low)?0x01:0x00); //set the status reg to high or low accuarcy + } + error+=measure(temp,com_measure_temp); + error+=measure(hum,com_measure_humid); + if (!error) calculate(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SHT_v1/SHT.h Mon Sep 27 15:52:09 2010 +0000 @@ -0,0 +1,66 @@ +/* mbed module to use a Sensirion SHT1x /SHT7x sensor + * Copyright (c) 2007-2009 Stephen McGarry + * Released under the MIT License: http://mbed.org/license/mit + */ +#ifndef SHT_H +#define SHT_H + +#include "mbed.h" + +enum SHT_acc { + SHT_low=0, + SHT_high=1 +}; + +typedef unsigned char byte; + +class SHT : public Base { +public: + /* Constructor: SHT + * Creates an SHT interface connected to specific pins. + * + */ + SHT(PinName p_sclk, PinName p_data, SHT_acc p_accuracy); + + /* Functions + */ + float get_temperature(); // get the most recent temp reading + float get_humidity(); // get the most recent humidity reading + float get_dewpoint(); // get the most recent dewpoint value + void update(SHT_acc accuracy); // update stored values from sensor + +protected: + byte read_byte(bool send_ack); + char write_byte(byte value); + void trans_start(void); + void connection_reset(void); + char soft_reset(); + char read_status(byte &value); + char write_status(byte value); + char measure(int &value, byte mode); + void calculate(); + + DigitalOut sclk; + DigitalInOut data; + SHT_acc accuracy; // will we use high or low accuracy mode on the sensor + + float temperature; // calculated from sensor reading + float humidity; + float dewpoint; + int temp,hum; // integer values from sensor before conversion + + enum commands { + com_read_status_reg=0x06, + com_write_status_reg=0x07, + com_measure_temp=0x03, + com_measure_humid=0x05, + com_reset=0x1E + }; + + enum acks { + no_ack=0, + send_ack=1 + }; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WeatherMeters/.meta Mon Sep 27 15:52:09 2010 +0000 @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<root> + <global/> + <data> + <created_ts>1285492351</created_ts> + <last_mod_ts>1285492351</last_mod_ts> + <is_archive>0</is_archive> + <is_published>0</is_published> + <is_svn>0</is_svn> + <is_module>0</is_module> + <is_lib>1</is_lib> + <path>/Weather/WeatherMeters</path> + <chars>1478</chars> + <enable_beta_0006>true</enable_beta_0006> + <compiler_version>1.3.0.13</compiler_version> + <lines>99</lines> + <duration>2492</duration> + <rmchars>2730</rmchars> + </data> +</root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WeatherMeters/WeatherMeters.cpp Mon Sep 27 15:52:09 2010 +0000 @@ -0,0 +1,109 @@ +/* + * mbed library to use a Sparkfun Weather Meters + * Copyright (c) 2010 Hiroshi Suga + * Released under the MIT License: http://mbed.org/license/mit + */ + +#include "mbed.h" +#include "WeatherMeters.h" + +#define WEATHER_VREF 3.3 + +const float tbl_windvane[16][2] = { + {0.0, 33000}, {22.5, 6570}, {45.0, 8200}, {67.5, 891}, + {90.0, 1000}, {112.5, 688}, {135.0, 2200}, {157.5, 1410}, + {180.0, 3900}, {202.5, 3140}, {225.0, 16000}, {247.5, 14120}, + {270.0, 120000}, {292.5, 42120}, {315.0, 64900}, {337.5, 21880} +}; + +WeatherMeters::WeatherMeters (PinName p_anemometer, PinName p_windvane, PinName p_raingauge, Weather_mode w_mode) : int01(p_anemometer), int02(p_raingauge), ain01(p_windvane) { + int i; + + windspeed = 0; windvane = 0; raingauge = 0; + count_anemo = 0; count_rain = 0; time_anemo = 0; time_rain = 0; + for (i = 0; i < 12; i ++) { + buf_anemo[i] = 0; + buf_rain[i] = 0; + } + + mode = w_mode; + int01.fall(this, &WeatherMeters::int_anemometer); + int02.fall(this, &WeatherMeters::int_raingauge); + ticker01.attach(this, &WeatherMeters::int_timer, 0.25); +} + +float WeatherMeters::get_windspeed() { + float s; + + if (mode == Weather_auto) { + s = (float)windspeed * 0.667 / 3.0; // 0.667m/s/Hz (/3s) + windspeed = 0; + } else { + s = (float)count_anemo * 0.667 / ((float)time_anemo / 4.0); // 0.667m/s/Hz + time_anemo = 0; + count_anemo = 0; + } + return s; +} + +float WeatherMeters::get_windvane() { + int i; + float v; + + if (windspeed == 0) windvane = ain01; + v = windvane * WEATHER_VREF; // V + v = v / ((WEATHER_VREF - v) / 10000.0); // ohm + for (i = 0; i < 16; i ++) { + if (v > tbl_windvane[i][1] * 0.9 && v < tbl_windvane[i][1] * 1.1) { + return tbl_windvane[i][0]; + } + } + return 0; +} + +float WeatherMeters::get_raingauge() { + return (float)raingauge * 0.2794; // 0.2794mm/Hz +} + +void WeatherMeters::int_anemometer () { + count_anemo ++; +} + +void WeatherMeters::int_raingauge () { + count_rain ++; +} + +void WeatherMeters::int_timer () { + int i, n; + + if (mode == Weather_auto) { + n = 0; + for (i = 11; i > 0; i --) { + buf_anemo[i] = buf_anemo[i - 1]; + n = n + buf_anemo[i]; + } + buf_anemo[0] = count_anemo; + n = n + buf_anemo[0]; + count_anemo = 0; + if (n > windspeed) { + windspeed = n; + windvane = ain01; + } + } else { + time_anemo ++; + } + + time_rain ++; + if (time_rain >= 4 * 300) { + n = 0; + for (i = 11; i > 0; i --) { + buf_rain[i] = buf_rain[i - 1]; + n = n + buf_rain[i]; + } + buf_rain[0] = count_rain; + n = n + buf_rain[0]; + count_rain = 0; + time_rain = 0; + raingauge = n; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WeatherMeters/WeatherMeters.h Mon Sep 27 15:52:09 2010 +0000 @@ -0,0 +1,44 @@ +/* + * mbed library to use a Sparkfun Weather Meters + * Copyright (c) 2010 Hiroshi Suga + * Released under the MIT License: http://mbed.org/license/mit + */ + +#ifndef WeatherMeters_H +#define WeatherMeters_H + +#include "mbed.h" + +enum Weather_mode { + Weather_manual = 0, + Weather_auto = 1 +}; + +class WeatherMeters : public Base { +public: + WeatherMeters(PinName p_anemometer, PinName p_windvane, PinName p_raingauge, Weather_mode w_mode = Weather_auto); + + float get_windspeed(); + float get_windvane(); + float get_raingauge(); + void update(); + +protected: + void int_anemometer (); + void int_raingauge (); + void int_timer (); + + InterruptIn int01, int02; + AnalogIn ain01; + Ticker ticker01; + int windspeed, raingauge; + float windvane; + int mode; + +private: + + int count_anemo, count_rain, time_anemo, time_rain; + int buf_anemo[12], buf_rain[12]; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Sep 27 15:52:09 2010 +0000 @@ -0,0 +1,30 @@ +#include "mbed.h" +#include "BMP085.h" +#include "SHT.h" +#include "WeatherMeters.h" + +I2C i2c(p9, p10); + +BMP085 bmp085(i2c, BMP085_oss4); +SHT sht11(p24, p12, SHT_high); // sclock, data +WeatherMeters wmeters(p30, p17, p21); // anemo, vane, rain + +DigitalOut myled(LED1); +Serial pc(USBTX, USBRX); + +int main() { + while(1) { + myled = 1; + + bmp085.update(); + pc.printf("p:%6.2f hPa / t:%6.2f C\n", bmp085.get_pressure(), bmp085.get_temperature()); + + sht11.update(SHT_high); + pc.printf("t:%6.2f C / h:%6.2f %%\n", sht11.get_temperature(), sht11.get_humidity()); + + pc.printf("a:%6.2f m/s / v:%6.2f / r:%6.2f mm\n", wmeters.get_windspeed(), wmeters.get_windvane(), wmeters.get_raingauge()); + + myled = 0; + wait(10); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Sep 27 15:52:09 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e