Initializing TM repository

This commit is contained in:
Nathanaël Restori 2012-09-05 20:01:37 +02:00
commit d4f1f57a01
19 changed files with 3139 additions and 0 deletions

View File

@ -0,0 +1,290 @@
/***************************************************
This is a library for the BMP085 Barometric Pressure & Temp Sensor
Designed specifically to work with the Adafruit BMP085 Breakout
----> https://www.adafruit.com/products/391
These displays use I2C to communicate, 2 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#include "BMP085.h"
#include <util/delay.h>
BMP085::BMP085() {
}
void BMP085::begin(uint8_t mode) {
if (mode > BMP085_ULTRAHIGHRES)
mode = BMP085_ULTRAHIGHRES;
oversampling = mode;
Wire.begin();
/* read calibration data */
ac1 = read16(BMP085_CAL_AC1);
ac2 = read16(BMP085_CAL_AC2);
ac3 = read16(BMP085_CAL_AC3);
ac4 = read16(BMP085_CAL_AC4);
ac5 = read16(BMP085_CAL_AC5);
ac6 = read16(BMP085_CAL_AC6);
b1 = read16(BMP085_CAL_B1);
b2 = read16(BMP085_CAL_B2);
mb = read16(BMP085_CAL_MB);
mc = read16(BMP085_CAL_MC);
md = read16(BMP085_CAL_MD);
#if (BMP085_DEBUG == 1)
Serial.print("ac1 = "); Serial.println(ac1, DEC);
Serial.print("ac2 = "); Serial.println(ac2, DEC);
Serial.print("ac3 = "); Serial.println(ac3, DEC);
Serial.print("ac4 = "); Serial.println(ac4, DEC);
Serial.print("ac5 = "); Serial.println(ac5, DEC);
Serial.print("ac6 = "); Serial.println(ac6, DEC);
Serial.print("b1 = "); Serial.println(b1, DEC);
Serial.print("b2 = "); Serial.println(b2, DEC);
Serial.print("mb = "); Serial.println(mb, DEC);
Serial.print("mc = "); Serial.println(mc, DEC);
Serial.print("md = "); Serial.println(md, DEC);
#endif
}
uint16_t BMP085::readRawTemperature(void) {
write8(BMP085_CONTROL, BMP085_READTEMPCMD);
_delay_ms(5);
#if BMP085_DEBUG == 1
Serial.print("Raw temp: "); Serial.println(read16(BMP085_TEMPDATA));
#endif
return read16(BMP085_TEMPDATA);
}
uint32_t BMP085::readRawPressure(void) {
uint32_t raw;
write8(BMP085_CONTROL, BMP085_READPRESSURECMD + (oversampling << 6));
if (oversampling == BMP085_ULTRALOWPOWER)
_delay_ms(5);
else if (oversampling == BMP085_STANDARD)
_delay_ms(8);
else if (oversampling == BMP085_HIGHRES)
_delay_ms(14);
else
_delay_ms(26);
raw = read16(BMP085_PRESSUREDATA);
raw <<= 8;
raw |= read8(BMP085_PRESSUREDATA+2);
raw >>= (8 - oversampling);
/* this pull broke stuff, look at it later?
if (oversampling==0) {
raw <<= 8;
raw |= read8(BMP085_PRESSUREDATA+2);
raw >>= (8 - oversampling);
}
*/
#if BMP085_DEBUG == 1
Serial.print("Raw pressure: "); Serial.println(raw);
#endif
return raw;
}
int32_t BMP085::readPressure(void) {
int32_t UT, UP, B3, B5, B6, X1, X2, X3, p;
uint32_t B4, B7;
UT = readRawTemperature();
UP = readRawPressure();
#if BMP085_DEBUG == 1
// use datasheet numbers!
UT = 27898;
UP = 23843;
ac6 = 23153;
ac5 = 32757;
mc = -8711;
md = 2868;
b1 = 6190;
b2 = 4;
ac3 = -14383;
ac2 = -72;
ac1 = 408;
ac4 = 32741;
oversampling = 0;
#endif
// do temperature calculations
X1 = ((UT - (int32_t)ac6) * (int32_t)ac5) >> 15;
X2 = ((int32_t)mc << 11) - (X1 + md)/2; // round up
X2 /= (X1 + md);
B5 = X1 + X2;
#if BMP085_DEBUG == 1
Serial.print("X1 = "); Serial.println(X1);
Serial.print("X2 = "); Serial.println(X2);
Serial.print("B5 = "); Serial.println(B5);
#endif
// do pressure calcs
B6 = B5 - 4000;
X1 = ((int32_t)b2 * ( (B6 * B6)>>12 )) >> 11;
X2 = ((int32_t)ac2 * B6) >> 11;
X3 = X1 + X2;
B3 = ((((int32_t)ac1*4 + X3) << oversampling) + 2) / 4;
#if BMP085_DEBUG == 1
Serial.print("B6 = "); Serial.println(B6);
Serial.print("X1 = "); Serial.println(X1);
Serial.print("X2 = "); Serial.println(X2);
Serial.print("B3 = "); Serial.println(B3);
#endif
X1 = ((int32_t)ac3 * B6) >> 13;
X2 = ((int32_t)b1 * ((B6 * B6) >> 12)) >> 16;
X3 = ((X1 + X2) + 2) >> 2;
B4 = ((uint32_t)ac4 * (uint32_t)(X3 + 32768)) >> 15;
B7 = ((uint32_t)UP - B3) * (uint32_t)( 50000UL >> oversampling );
#if BMP085_DEBUG == 1
Serial.print("X1 = "); Serial.println(X1);
Serial.print("X2 = "); Serial.println(X2);
Serial.print("B4 = "); Serial.println(B4);
Serial.print("B7 = "); Serial.println(B7);
#endif
if (B7 < 0x80000000) {
p = (B7 * 2) / B4;
} else {
p = (B7 / B4) * 2;
}
X1 = (p >> 8) * (p >> 8);
X1 = (X1 * 3038) >> 16;
X2 = (-7357 * p) >> 16;
#if BMP085_DEBUG == 1
Serial.print("p = "); Serial.println(p);
Serial.print("X1 = "); Serial.println(X1);
Serial.print("X2 = "); Serial.println(X2);
#endif
p = p + ((X1 + X2 + (int32_t)3791)>>4);
#if BMP085_DEBUG == 1
Serial.print("p = "); Serial.println(p);
#endif
return p;
}
float BMP085::readTemperature(void) {
int32_t UT, X1, X2, B5; // following ds convention
float temp;
UT = readRawTemperature();
#if BMP085_DEBUG == 1
// use datasheet numbers!
UT = 27898;
ac6 = 23153;
ac5 = 32757;
mc = -8711;
md = 2868;
#endif
// step 1
X1 = ((UT - (int32_t)ac6) * (int32_t)ac5) >> 15;
X2 = ((int32_t)mc << 11) / (X1 + (int32_t)md);
B5 = X1 + X2;
temp = (B5 + 8) >> 4;
temp /= 10;
return temp;
}
float BMP085::readAltitude(float sealevelPressure) {
float altitude;
float pressure = readPressure();
altitude = 44330 * (1.0 - pow(pressure /sealevelPressure,0.1903));
return altitude;
}
/*********************************************************************/
uint8_t BMP085::read8(uint8_t a) {
uint8_t ret;
Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device
#if (ARDUINO >= 100)
Wire.write(a); // sends register address to read from
#else
Wire.send(a); // sends register address to read from
#endif
Wire.endTransmission(); // end transmission
Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device
Wire.requestFrom(BMP085_I2CADDR, 1);// send data n-bytes read
#if (ARDUINO >= 100)
ret = Wire.read(); // receive DATA
#else
ret = Wire.receive(); // receive DATA
#endif
Wire.endTransmission(); // end transmission
return ret;
}
uint16_t BMP085::read16(uint8_t a) {
uint16_t ret;
Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device
#if (ARDUINO >= 100)
Wire.write(a); // sends register address to read from
#else
Wire.send(a); // sends register address to read from
#endif
Wire.endTransmission(); // end transmission
Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device
Wire.requestFrom(BMP085_I2CADDR, 2);// send data n-bytes read
#if (ARDUINO >= 100)
ret = Wire.read(); // receive DATA
ret <<= 8;
ret |= Wire.read(); // receive DATA
#else
ret = Wire.receive(); // receive DATA
ret <<= 8;
ret |= Wire.receive(); // receive DATA
#endif
Wire.endTransmission(); // end transmission
return ret;
}
void BMP085::write8(uint8_t a, uint8_t d) {
Wire.beginTransmission(BMP085_I2CADDR); // start transmission to device
#if (ARDUINO >= 100)
Wire.write(a); // sends register address to read from
Wire.write(d); // write data
#else
Wire.send(a); // sends register address to read from
Wire.send(d); // write data
#endif
Wire.endTransmission(); // end transmission
}

View File

@ -0,0 +1,71 @@
/***************************************************
This is a library for the BMP085 Barometric Pressure & Temp Sensor
Designed specifically to work with the Adafruit BMP085 Breakout
----> https://www.adafruit.com/products/391
These displays use I2C to communicate, 2 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "Wire.h"
#define BMP085_DEBUG 0
#define BMP085_I2CADDR 0x77
#define BMP085_ULTRALOWPOWER 0
#define BMP085_STANDARD 1
#define BMP085_HIGHRES 2
#define BMP085_ULTRAHIGHRES 3
#define BMP085_CAL_AC1 0xAA // R Calibration data (16 bits)
#define BMP085_CAL_AC2 0xAC // R Calibration data (16 bits)
#define BMP085_CAL_AC3 0xAE // R Calibration data (16 bits)
#define BMP085_CAL_AC4 0xB0 // R Calibration data (16 bits)
#define BMP085_CAL_AC5 0xB2 // R Calibration data (16 bits)
#define BMP085_CAL_AC6 0xB4 // R Calibration data (16 bits)
#define BMP085_CAL_B1 0xB6 // R Calibration data (16 bits)
#define BMP085_CAL_B2 0xB8 // R Calibration data (16 bits)
#define BMP085_CAL_MB 0xBA // R Calibration data (16 bits)
#define BMP085_CAL_MC 0xBC // R Calibration data (16 bits)
#define BMP085_CAL_MD 0xBE // R Calibration data (16 bits)
#define BMP085_CONTROL 0xF4
#define BMP085_TEMPDATA 0xF6
#define BMP085_PRESSUREDATA 0xF6
#define BMP085_READTEMPCMD 0x2E
#define BMP085_READPRESSURECMD 0x34
class BMP085 {
public:
BMP085();
void begin(uint8_t mode = BMP085_ULTRAHIGHRES); // by default go highres
float readTemperature(void);
int32_t readPressure(void);
float readAltitude(float sealevelPressure = 101325); // std atmosphere
uint16_t readRawTemperature(void);
uint32_t readRawPressure(void);
private:
uint8_t read8(uint8_t addr);
uint16_t read16(uint8_t addr);
void write8(uint8_t addr, uint8_t data);
uint8_t oversampling;
int16_t ac1, ac2, ac3, b1, b2, mb, mc, md;
uint16_t ac4, ac5, ac6;
};

View File

@ -0,0 +1,263 @@
// Code by JeeLabs http://news.jeelabs.org/code/
// Released to the public domain! Enjoy!
//
// Modified for Chronodot / DS3132 with
// temperature data by Stephanie Maks
// http://planetstephanie.net/
#include <Wire.h>
#include <avr/pgmspace.h>
#include "Chronodot.h"
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#define CHRONODOT_ADDRESS 0x68
#define SECONDS_PER_DAY 86400L
#define SECONDS_FROM_1970_TO_2000 946684800
////////////////////////////////////////////////////////////////////////////////
// utility code, some of this could be exposed in the DateTime API if needed
static uint8_t daysInMonth [] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 };
// number of days since 2000/01/01, valid for 2001..2099
static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) {
if (y >= 2000)
y -= 2000;
uint16_t days = d;
for (uint8_t i = 1; i < m; ++i)
days += pgm_read_byte(daysInMonth + i - 1);
if (m > 2 && y % 4 == 0)
++days;
return days + 365 * y + (y + 3) / 4 - 1;
}
static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) {
return ((days * 24L + h) * 60 + m) * 60 + s;
}
////////////////////////////////////////////////////////////////////////////////
// DateTime implementation - ignores time zones and DST changes
// NOTE: also ignores leap seconds, see http://en.wikipedia.org/wiki/Leap_second
DateTime::DateTime (uint32_t t) {
t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970
ss = t % 60;
t /= 60;
mm = t % 60;
t /= 60;
hh = t % 24;
uint16_t days = t / 24;
uint8_t leap;
for (yOff = 0; ; ++yOff) {
leap = yOff % 4 == 0;
if (days < 365 + leap)
break;
days -= 365 + leap;
}
for (m = 1; ; ++m) {
uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1);
if (leap && m == 2)
++daysPerMonth;
if (days < daysPerMonth)
break;
days -= daysPerMonth;
}
d = days + 1;
}
DateTime::DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec, int tempF, float tempC) {
if (year >= 2000)
year -= 2000;
yOff = year;
m = month;
d = day;
hh = hour;
mm = min;
ss = sec;
ttf = tempF;
ttc = tempC;
}
static uint8_t conv2d(const char* p) {
uint8_t v = 0;
if ('0' <= *p && *p <= '9')
v = *p - '0';
return 10 * v + *++p - '0';
}
// A convenient constructor for using "the compiler's time":
// DateTime now (__DATE__, __TIME__);
// NOTE: using PSTR would further reduce the RAM footprint
DateTime::DateTime (const char* date, const char* time) {
// sample input: date = "Dec 26 2009", time = "12:34:56"
yOff = conv2d(date + 9);
// Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
switch (date[0]) {
case 'J': m = date[1] == 'a' ? 1 : m = date[2] == 'n' ? 6 : 7; break;
case 'F': m = 2; break;
case 'A': m = date[2] == 'r' ? 4 : 8; break;
case 'M': m = date[2] == 'r' ? 3 : 5; break;
case 'S': m = 9; break;
case 'O': m = 10; break;
case 'N': m = 11; break;
case 'D': m = 12; break;
}
d = conv2d(date + 4);
hh = conv2d(time);
mm = conv2d(time + 3);
ss = conv2d(time + 6);
}
uint8_t DateTime::dayOfWeek() const {
uint16_t day = date2days(yOff, m, d);
return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6
}
long DateTime::secondstime(void) const {
long t;
uint16_t days = date2days(yOff, m, d);
t = time2long(days, hh, mm, ss);
return t;
}
uint32_t DateTime::unixtime(void) const {
uint32_t t;
uint16_t days = date2days(yOff, m, d);
t = time2long(days, hh, mm, ss);
t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000
return t;
}
////////////////////////////////////////////////////////////////////////////////
// RTC_DS3231 implementation
static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
uint8_t Chronodot::begin(void) {
return 1;
}
uint8_t Chronodot::isrunning(void) {
Wire.beginTransmission(CHRONODOT_ADDRESS);
#if ARDUINO >= 100
Wire.write((byte)0x0F);
#else
Wire.send(0x0F);
#endif
Wire.endTransmission();
Wire.requestFrom(CHRONODOT_ADDRESS, 1);
#if ARDUINO >= 100
uint8_t ss = Wire.read();
#else
uint8_t ss = Wire.receive();
#endif
return !(ss>>7);
}
void Chronodot::adjust(const DateTime& dt) {
// send new date & time to chronodot
Wire.beginTransmission(CHRONODOT_ADDRESS);
#if ARDUINO >= 100
Wire.write((byte)0); // memory address
Wire.write(bin2bcd(dt.second())); // byte 0
Wire.write(bin2bcd(dt.minute())); // byte 1
Wire.write(bin2bcd(dt.hour())); // byte 2
Wire.write(bin2bcd(0)); // byte 3
Wire.write(bin2bcd(dt.day())); // byte 4
Wire.write(bin2bcd(dt.month())); // byte 5
Wire.write(bin2bcd(dt.year() - 2000)); // byte 6
#else
Wire.send(0);
Wire.send(bin2bcd(dt.second()));
Wire.send(bin2bcd(dt.minute()));
Wire.send(bin2bcd(dt.hour()));
Wire.send(bin2bcd(0));
Wire.send(bin2bcd(dt.day()));
Wire.send(bin2bcd(dt.month()));
Wire.send(bin2bcd(dt.year() - 2000));
#endif
Wire.endTransmission();
// now get the control byte - we need to set bit 7 to zero
Wire.beginTransmission(CHRONODOT_ADDRESS);
#if ARDUINO >= 100
Wire.write((byte)0x0F);
#else
Wire.send(0x0F);
#endif
Wire.endTransmission();
Wire.requestFrom(CHRONODOT_ADDRESS, 1);
#if ARDUINO >= 100
uint8_t ss = Wire.read();
#else
uint8_t ss = Wire.receive();
#endif
ss &= ~(1 << 7); // clear OSF bit
Wire.beginTransmission(CHRONODOT_ADDRESS);
#if ARDUINO >= 100
Wire.write((byte)0x0F);
Wire.write((byte)ss);
#else
Wire.send(0x0F);
Wire.send(ss);
#endif
Wire.endTransmission();
}
DateTime Chronodot::now() {
Wire.beginTransmission(CHRONODOT_ADDRESS);
#if ARDUINO >= 100
Wire.write((byte)0);
#else
Wire.send(0);
#endif
Wire.endTransmission();
Wire.requestFrom(CHRONODOT_ADDRESS, 19);
byte blah[20];
int i;
for(i=0; i<20; i++) {
#if ARDUINO >= 100
blah[i] = Wire.read();
#else
blah[i] = Wire.receive();
#endif
}
uint8_t ss = bcd2bin(blah[0] & 0x7F);
uint8_t mm = bcd2bin(blah[1]);
uint8_t hh = bcd2bin(blah[2]);
uint8_t d = bcd2bin(blah[4]);
uint8_t m = bcd2bin(blah[5]);
uint16_t y = bcd2bin(blah[6]) + 2000;
float ttc = (float)(int)blah[17];
byte portion = blah[18];
if(portion == 0b01000000) ttc += 0.25;
if(portion == 0b10000000) ttc += 0.5;
if(portion == 0b11000000) ttc += 0.75;
float degF = (((ttc * 9.0) / 5.0) + 32.5);
int ttf = (int)degF;
return DateTime (y, m, d, hh, mm, ss, ttf, ttc);
}
////////////////////////////////////////////////////////////////////////////////
// RTC_Millis implementation
long RTC_Millis::offset = 0;
void RTC_Millis::adjust(const DateTime& dt) {
offset = dt.unixtime() - millis() / 1000;
}
DateTime RTC_Millis::now() {
return (uint32_t)(offset + millis() / 1000);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,60 @@
// Code by JeeLabs http://news.jeelabs.org/code/
// Released to the public domain! Enjoy!
//
// Modified for Chronodot / DS3132 with
// temperature data by Stephanie Maks
// http://planetstephanie.net/
#ifndef CHRONODOT_H
#define CHRONODOT_H
// Simple general-purpose date/time class (no TZ / DST / leap second handling!)
class DateTime {
public:
DateTime (uint32_t t =0);
DateTime (uint16_t year, uint8_t month, uint8_t day,
uint8_t hour =0, uint8_t min =0, uint8_t sec =0, int tempF =0, float tempC = 0.0);
DateTime (const char* date, const char* time);
uint16_t year() const { return 2000 + yOff; }
uint8_t month() const { return m; }
uint8_t day() const { return d; }
uint8_t hour() const { return hh; }
uint8_t minute() const { return mm; }
uint8_t second() const { return ss; }
int tempF() const { return ttf; }
float tempC() const { return ttc; }
uint8_t dayOfWeek() const;
// 32-bit times as seconds since 1/1/2000
long secondstime() const;
// 32-bit times as seconds since 1/1/1970
uint32_t unixtime(void) const;
protected:
uint8_t yOff, m, d, hh, mm, ss;
int ttf;
float ttc;
};
// Chronodot based on the DS3231 chip connected via I2C and the Wire library
class Chronodot {
public:
static uint8_t begin(void);
static void adjust(const DateTime& dt);
uint8_t isrunning(void);
static DateTime now();
};
// RTC using the internal millis() clock, has to be initialized before use
// NOTE: this clock won't be correct once the millis() timer rolls over (>49d?)
class RTC_Millis {
public:
static void begin(const DateTime& dt) { adjust(dt); }
static void adjust(const DateTime& dt);
static DateTime now();
protected:
static long offset;
};
#endif CHRONODOT_H

View File

@ -0,0 +1,160 @@
/* DHT library
MIT license
written by Adafruit Industries
*/
#include "DHT.h"
DHT::DHT(uint8_t pin, uint8_t type) {
_pin = pin;
_type = type;
firstreading = true;
}
void DHT::begin(void) {
// set up the pins!
pinMode(_pin, INPUT);
digitalWrite(_pin, HIGH);
_lastreadtime = 0;
}
//boolean S == Scale. True == Farenheit; False == Celcius
float DHT::readTemperature(bool S) {
float f;
if (read()) {
switch (_type) {
case DHT11:
f = data[2];
if(S)
f = convertCtoF(f);
return f;
case DHT22:
case DHT21:
f = data[2] & 0x7F;
f *= 256;
f += data[3];
f /= 10;
if (data[2] & 0x80)
f *= -1;
if(S)
f = convertCtoF(f);
return f;
}
}
Serial.print("Read fail");
return NAN;
}
float DHT::convertCtoF(float c) {
return c * 9 / 5 + 32;
}
float DHT::readHumidity(void) {
float f;
if (read()) {
switch (_type) {
case DHT11:
f = data[0];
return f;
case DHT22:
case DHT21:
f = data[0];
f *= 256;
f += data[1];
f /= 10;
return f;
}
}
Serial.print("Read fail");
return NAN;
}
boolean DHT::read(void) {
uint8_t laststate = HIGH;
uint8_t counter = 0;
uint8_t j = 0, i;
unsigned long currenttime;
// pull the pin high and wait 250 milliseconds
digitalWrite(_pin, HIGH);
delay(250);
currenttime = millis();
if (currenttime < _lastreadtime) {
// ie there was a rollover
_lastreadtime = 0;
}
if (!firstreading && ((currenttime - _lastreadtime) < 2000)) {
return true; // return last correct measurement
//delay(2000 - (currenttime - _lastreadtime));
}
firstreading = false;
/*
Serial.print("Currtime: "); Serial.print(currenttime);
Serial.print(" Lasttime: "); Serial.print(_lastreadtime);
*/
_lastreadtime = millis();
data[0] = data[1] = data[2] = data[3] = data[4] = 0;
// now pull it low for ~20 milliseconds
pinMode(_pin, OUTPUT);
digitalWrite(_pin, LOW);
delay(20);
cli();
digitalWrite(_pin, HIGH);
delayMicroseconds(40);
pinMode(_pin, INPUT);
// read in timings
for ( i=0; i< MAXTIMINGS; i++) {
counter = 0;
while (digitalRead(_pin) == laststate) {
counter++;
delayMicroseconds(1);
if (counter == 255) {
break;
}
}
laststate = digitalRead(_pin);
if (counter == 255) break;
// ignore first 3 transitions
if ((i >= 4) && (i%2 == 0)) {
// shove each bit into the storage bytes
data[j/8] <<= 1;
if (counter > 6)
data[j/8] |= 1;
j++;
}
}
sei();
/*
Serial.println(j, DEC);
Serial.print(data[0], HEX); Serial.print(", ");
Serial.print(data[1], HEX); Serial.print(", ");
Serial.print(data[2], HEX); Serial.print(", ");
Serial.print(data[3], HEX); Serial.print(", ");
Serial.print(data[4], HEX); Serial.print(" =? ");
Serial.println(data[0] + data[1] + data[2] + data[3], HEX);
*/
// check we read 40 bits and that the checksum matches
if ((j >= 40) &&
(data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) ) {
return true;
}
return false;
}

View File

@ -0,0 +1,36 @@
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
/* DHT library
MIT license
written by Adafruit Industries
*/
// how many timing transitions we need to keep track of. 2 * number bits + extra
#define MAXTIMINGS 85
#define DHT11 11
#define DHT22 22
#define DHT21 21
#define AM2301 21
class DHT {
private:
uint8_t data[6];
uint8_t _pin, _type;
boolean read(void);
unsigned long _lastreadtime;
boolean firstreading;
public:
DHT(uint8_t pin, uint8_t type);
void begin(void);
float readTemperature(bool S=false);
float convertCtoF(float);
float readHumidity(void);
};

View File

@ -0,0 +1,298 @@
/**************************************************************************/
/*!
@file tsl2561.c
@author K. Townsend (microBuilder.eu / adafruit.com)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2010, microBuilder SARL, Adafruit Industries
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>
#include "TSL2561.h"
TSL2561::TSL2561(uint8_t addr) {
_addr = addr;
_initialized = false;
_integration = TSL2561_INTEGRATIONTIME_13MS;
_gain = TSL2561_GAIN_16X;
// we cant do wire initialization till later, because we havent loaded Wire yet
}
boolean TSL2561::begin(void) {
Wire.begin();
// Initialise I2C
Wire.beginTransmission(_addr);
#if ARDUINO >= 100
Wire.write(TSL2561_REGISTER_ID);
#else
Wire.send(TSL2561_REGISTER_ID);
#endif
Wire.endTransmission();
Wire.requestFrom(_addr, 1);
#if ARDUINO >= 100
int x = Wire.read();
#else
int x = Wire.receive();
#endif
//Serial.print("0x"); Serial.println(x, HEX);
if (x & 0x0A ) {
//Serial.println("Found TSL2561");
} else {
return false;
}
_initialized = true;
// Set default integration time and gain
setTiming(_integration);
setGain(_gain);
// Note: by default, the device is in power down mode on bootup
disable();
return true;
}
void TSL2561::enable(void)
{
if (!_initialized) begin();
// Enable the device by setting the control bit to 0x03
write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON);
}
void TSL2561::disable(void)
{
if (!_initialized) begin();
// Disable the device by setting the control bit to 0x03
write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF);
}
void TSL2561::setGain(tsl2561Gain_t gain) {
if (!_initialized) begin();
enable();
_gain = gain;
write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, _integration | _gain);
disable();
}
void TSL2561::setTiming(tsl2561IntegrationTime_t integration)
{
if (!_initialized) begin();
enable();
_integration = integration;
write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, _integration | _gain);
disable();
}
uint32_t TSL2561::calculateLux(uint16_t ch0, uint16_t ch1)
{
unsigned long chScale;
unsigned long channel1;
unsigned long channel0;
switch (_integration)
{
case TSL2561_INTEGRATIONTIME_13MS:
chScale = TSL2561_LUX_CHSCALE_TINT0;
break;
case TSL2561_INTEGRATIONTIME_101MS:
chScale = TSL2561_LUX_CHSCALE_TINT1;
break;
default: // No scaling ... integration time = 402ms
chScale = (1 << TSL2561_LUX_CHSCALE);
break;
}
// Scale for gain (1x or 16x)
if (!_gain) chScale = chScale << 4;
// scale the channel values
channel0 = (ch0 * chScale) >> TSL2561_LUX_CHSCALE;
channel1 = (ch1 * chScale) >> TSL2561_LUX_CHSCALE;
// find the ratio of the channel values (Channel1/Channel0)
unsigned long ratio1 = 0;
if (channel0 != 0) ratio1 = (channel1 << (TSL2561_LUX_RATIOSCALE+1)) / channel0;
// round the ratio value
unsigned long ratio = (ratio1 + 1) >> 1;
unsigned int b, m;
#ifdef TSL2561_PACKAGE_CS
if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1C))
{b=TSL2561_LUX_B1C; m=TSL2561_LUX_M1C;}
else if (ratio <= TSL2561_LUX_K2C)
{b=TSL2561_LUX_B2C; m=TSL2561_LUX_M2C;}
else if (ratio <= TSL2561_LUX_K3C)
{b=TSL2561_LUX_B3C; m=TSL2561_LUX_M3C;}
else if (ratio <= TSL2561_LUX_K4C)
{b=TSL2561_LUX_B4C; m=TSL2561_LUX_M4C;}
else if (ratio <= TSL2561_LUX_K5C)
{b=TSL2561_LUX_B5C; m=TSL2561_LUX_M5C;}
else if (ratio <= TSL2561_LUX_K6C)
{b=TSL2561_LUX_B6C; m=TSL2561_LUX_M6C;}
else if (ratio <= TSL2561_LUX_K7C)
{b=TSL2561_LUX_B7C; m=TSL2561_LUX_M7C;}
else if (ratio > TSL2561_LUX_K8C)
{b=TSL2561_LUX_B8C; m=TSL2561_LUX_M8C;}
#else
if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1T))
{b=TSL2561_LUX_B1T; m=TSL2561_LUX_M1T;}
else if (ratio <= TSL2561_LUX_K2T)
{b=TSL2561_LUX_B2T; m=TSL2561_LUX_M2T;}
else if (ratio <= TSL2561_LUX_K3T)
{b=TSL2561_LUX_B3T; m=TSL2561_LUX_M3T;}
else if (ratio <= TSL2561_LUX_K4T)
{b=TSL2561_LUX_B4T; m=TSL2561_LUX_M4T;}
else if (ratio <= TSL2561_LUX_K5T)
{b=TSL2561_LUX_B5T; m=TSL2561_LUX_M5T;}
else if (ratio <= TSL2561_LUX_K6T)
{b=TSL2561_LUX_B6T; m=TSL2561_LUX_M6T;}
else if (ratio <= TSL2561_LUX_K7T)
{b=TSL2561_LUX_B7T; m=TSL2561_LUX_M7T;}
else if (ratio > TSL2561_LUX_K8T)
{b=TSL2561_LUX_B8T; m=TSL2561_LUX_M8T;}
#endif
unsigned long temp;
temp = ((channel0 * b) - (channel1 * m));
// do not allow negative lux value
if (temp < 0) temp = 0;
// round lsb (2^(LUX_SCALE-1))
temp += (1 << (TSL2561_LUX_LUXSCALE-1));
// strip off fractional portion
uint32_t lux = temp >> TSL2561_LUX_LUXSCALE;
// Signal I2C had no errors
return lux;
}
uint32_t TSL2561::getFullLuminosity (void)
{
if (!_initialized) begin();
// Enable the device by setting the control bit to 0x03
enable();
// Wait x ms for ADC to complete
switch (_integration)
{
case TSL2561_INTEGRATIONTIME_13MS:
delay(14);
break;
case TSL2561_INTEGRATIONTIME_101MS:
delay(102);
break;
default:
delay(400);
break;
}
uint32_t x;
x = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW);
x <<= 16;
x |= read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW);
disable();
return x;
}
uint16_t TSL2561::getLuminosity (uint8_t channel) {
uint32_t x = getFullLuminosity();
if (channel == 0) {
// Reads two byte value from channel 0 (visible + infrared)
return (x & 0xFFFF);
} else if (channel == 1) {
// Reads two byte value from channel 1 (infrared)
return (x >> 16);
} else if (channel == 2) {
// Reads all and subtracts out just the visible!
return ( (x & 0xFFFF) - (x >> 16));
}
// unknown channel!
return 0;
}
uint16_t TSL2561::read16(uint8_t reg)
{
uint16_t x; uint16_t t;
Wire.beginTransmission(_addr);
#if ARDUINO >= 100
Wire.write(reg);
#else
Wire.send(reg);
#endif
Wire.endTransmission();
Wire.requestFrom(_addr, 2);
#if ARDUINO >= 100
t = Wire.read();
x = Wire.read();
#else
t = Wire.receive();
x = Wire.receive();
#endif
x <<= 8;
x |= t;
return x;
}
void TSL2561::write8 (uint8_t reg, uint8_t value)
{
Wire.beginTransmission(_addr);
#if ARDUINO >= 100
Wire.write(reg);
Wire.write(value);
#else
Wire.send(reg);
Wire.send(value);
#endif
Wire.endTransmission();
}

View File

@ -0,0 +1,184 @@
/**************************************************************************/
/*!
@file tsl2561.h
@author K. Townsend (microBuilder.eu)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2010, microBuilder SARL
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
#ifndef _TSL2561_H_
#define _TSL2561_H_
#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#include <Wire.h>
#define TSL2561_VISIBLE 2 // channel 0 - channel 1
#define TSL2561_INFRARED 1 // channel 1
#define TSL2561_FULLSPECTRUM 0 // channel 0
// 3 i2c address options!
#define TSL2561_ADDR_LOW 0x29
#define TSL2561_ADDR_FLOAT 0x39
#define TSL2561_ADDR_HIGH 0x49
// Lux calculations differ slightly for CS package
//#define TSL2561_PACKAGE_CS
#define TSL2561_PACKAGE_T_FN_CL
#define TSL2561_READBIT (0x01)
#define TSL2561_COMMAND_BIT (0x80) // Must be 1
#define TSL2561_CLEAR_BIT (0x40) // Clears any pending interrupt (write 1 to clear)
#define TSL2561_WORD_BIT (0x20) // 1 = read/write word (rather than byte)
#define TSL2561_BLOCK_BIT (0x10) // 1 = using block read/write
#define TSL2561_CONTROL_POWERON (0x03)
#define TSL2561_CONTROL_POWEROFF (0x00)
#define TSL2561_LUX_LUXSCALE (14) // Scale by 2^14
#define TSL2561_LUX_RATIOSCALE (9) // Scale ratio by 2^9
#define TSL2561_LUX_CHSCALE (10) // Scale channel values by 2^10
#define TSL2561_LUX_CHSCALE_TINT0 (0x7517) // 322/11 * 2^TSL2561_LUX_CHSCALE
#define TSL2561_LUX_CHSCALE_TINT1 (0x0FE7) // 322/81 * 2^TSL2561_LUX_CHSCALE
// T, FN and CL package values
#define TSL2561_LUX_K1T (0x0040) // 0.125 * 2^RATIO_SCALE
#define TSL2561_LUX_B1T (0x01f2) // 0.0304 * 2^LUX_SCALE
#define TSL2561_LUX_M1T (0x01be) // 0.0272 * 2^LUX_SCALE
#define TSL2561_LUX_K2T (0x0080) // 0.250 * 2^RATIO_SCALE
#define TSL2561_LUX_B2T (0x0214) // 0.0325 * 2^LUX_SCALE
#define TSL2561_LUX_M2T (0x02d1) // 0.0440 * 2^LUX_SCALE
#define TSL2561_LUX_K3T (0x00c0) // 0.375 * 2^RATIO_SCALE
#define TSL2561_LUX_B3T (0x023f) // 0.0351 * 2^LUX_SCALE
#define TSL2561_LUX_M3T (0x037b) // 0.0544 * 2^LUX_SCALE
#define TSL2561_LUX_K4T (0x0100) // 0.50 * 2^RATIO_SCALE
#define TSL2561_LUX_B4T (0x0270) // 0.0381 * 2^LUX_SCALE
#define TSL2561_LUX_M4T (0x03fe) // 0.0624 * 2^LUX_SCALE
#define TSL2561_LUX_K5T (0x0138) // 0.61 * 2^RATIO_SCALE
#define TSL2561_LUX_B5T (0x016f) // 0.0224 * 2^LUX_SCALE
#define TSL2561_LUX_M5T (0x01fc) // 0.0310 * 2^LUX_SCALE
#define TSL2561_LUX_K6T (0x019a) // 0.80 * 2^RATIO_SCALE
#define TSL2561_LUX_B6T (0x00d2) // 0.0128 * 2^LUX_SCALE
#define TSL2561_LUX_M6T (0x00fb) // 0.0153 * 2^LUX_SCALE
#define TSL2561_LUX_K7T (0x029a) // 1.3 * 2^RATIO_SCALE
#define TSL2561_LUX_B7T (0x0018) // 0.00146 * 2^LUX_SCALE
#define TSL2561_LUX_M7T (0x0012) // 0.00112 * 2^LUX_SCALE
#define TSL2561_LUX_K8T (0x029a) // 1.3 * 2^RATIO_SCALE
#define TSL2561_LUX_B8T (0x0000) // 0.000 * 2^LUX_SCALE
#define TSL2561_LUX_M8T (0x0000) // 0.000 * 2^LUX_SCALE
// CS package values
#define TSL2561_LUX_K1C (0x0043) // 0.130 * 2^RATIO_SCALE
#define TSL2561_LUX_B1C (0x0204) // 0.0315 * 2^LUX_SCALE
#define TSL2561_LUX_M1C (0x01ad) // 0.0262 * 2^LUX_SCALE
#define TSL2561_LUX_K2C (0x0085) // 0.260 * 2^RATIO_SCALE
#define TSL2561_LUX_B2C (0x0228) // 0.0337 * 2^LUX_SCALE
#define TSL2561_LUX_M2C (0x02c1) // 0.0430 * 2^LUX_SCALE
#define TSL2561_LUX_K3C (0x00c8) // 0.390 * 2^RATIO_SCALE
#define TSL2561_LUX_B3C (0x0253) // 0.0363 * 2^LUX_SCALE
#define TSL2561_LUX_M3C (0x0363) // 0.0529 * 2^LUX_SCALE
#define TSL2561_LUX_K4C (0x010a) // 0.520 * 2^RATIO_SCALE
#define TSL2561_LUX_B4C (0x0282) // 0.0392 * 2^LUX_SCALE
#define TSL2561_LUX_M4C (0x03df) // 0.0605 * 2^LUX_SCALE
#define TSL2561_LUX_K5C (0x014d) // 0.65 * 2^RATIO_SCALE
#define TSL2561_LUX_B5C (0x0177) // 0.0229 * 2^LUX_SCALE
#define TSL2561_LUX_M5C (0x01dd) // 0.0291 * 2^LUX_SCALE
#define TSL2561_LUX_K6C (0x019a) // 0.80 * 2^RATIO_SCALE
#define TSL2561_LUX_B6C (0x0101) // 0.0157 * 2^LUX_SCALE
#define TSL2561_LUX_M6C (0x0127) // 0.0180 * 2^LUX_SCALE
#define TSL2561_LUX_K7C (0x029a) // 1.3 * 2^RATIO_SCALE
#define TSL2561_LUX_B7C (0x0037) // 0.00338 * 2^LUX_SCALE
#define TSL2561_LUX_M7C (0x002b) // 0.00260 * 2^LUX_SCALE
#define TSL2561_LUX_K8C (0x029a) // 1.3 * 2^RATIO_SCALE
#define TSL2561_LUX_B8C (0x0000) // 0.000 * 2^LUX_SCALE
#define TSL2561_LUX_M8C (0x0000) // 0.000 * 2^LUX_SCALE
enum
{
TSL2561_REGISTER_CONTROL = 0x00,
TSL2561_REGISTER_TIMING = 0x01,
TSL2561_REGISTER_THRESHHOLDL_LOW = 0x02,
TSL2561_REGISTER_THRESHHOLDL_HIGH = 0x03,
TSL2561_REGISTER_THRESHHOLDH_LOW = 0x04,
TSL2561_REGISTER_THRESHHOLDH_HIGH = 0x05,
TSL2561_REGISTER_INTERRUPT = 0x06,
TSL2561_REGISTER_CRC = 0x08,
TSL2561_REGISTER_ID = 0x0A,
TSL2561_REGISTER_CHAN0_LOW = 0x0C,
TSL2561_REGISTER_CHAN0_HIGH = 0x0D,
TSL2561_REGISTER_CHAN1_LOW = 0x0E,
TSL2561_REGISTER_CHAN1_HIGH = 0x0F
};
typedef enum
{
TSL2561_INTEGRATIONTIME_13MS = 0x00, // 13.7ms
TSL2561_INTEGRATIONTIME_101MS = 0x01, // 101ms
TSL2561_INTEGRATIONTIME_402MS = 0x02 // 402ms
}
tsl2561IntegrationTime_t;
typedef enum
{
TSL2561_GAIN_0X = 0x00, // No gain
TSL2561_GAIN_16X = 0x10, // 16x gain
}
tsl2561Gain_t;
class TSL2561 {
public:
TSL2561(uint8_t addr);
boolean begin(void);
void enable(void);
void disable(void);
void write8(uint8_t r, uint8_t v);
uint16_t read16(uint8_t reg);
uint32_t calculateLux(uint16_t ch0, uint16_t ch1);
void setTiming(tsl2561IntegrationTime_t integration);
void setGain(tsl2561Gain_t gain);
uint16_t getLuminosity (uint8_t channel);
uint32_t getFullLuminosity ();
private:
int8_t _addr;
tsl2561IntegrationTime_t _integration;
tsl2561Gain_t _gain;
boolean _initialized;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,93 @@
#include <SD.h>
#include <Wire.h>
#include "BMP085.h"
#include "DHT.h"
#include "TSL2561.h"
#include "Chronodot.h"
#define TIMING 1000 // milliseconds
#define DHTPIN 2
#define DHTTYPE DHT22
#define SDPIN 4
BMP085 bmp;
DHT dht(DHTPIN, DHTTYPE);
TSL2561 tsl(TSL2561_ADDR_FLOAT);
Chronodot chronodot;
File file;
void setup() {
Serial.begin(9600);
//----- SD Card
Serial.println("INIT SD Card");
if (!SD.begin(4)) {
Serial.println("FAILED");
return;
}
Serial.println("DONE");
//----- Sensors
Serial.println("INIT Sensors");
bmp.begin();
dht.begin();
tsl.begin();
chronodot.begin();
// You can change the gain on the fly, to adapt to brighter/dimmer light situations
//tsl.setGain(TSL2561_GAIN_0X); // set no gain (for bright situtations)
tsl.setGain(TSL2561_GAIN_16X); // set 16x gain (for dim situations)
// Changing the integration time gives you a longer time over which to sense light
// longer timelines are slower, but are good in very low light situtations!
tsl.setTiming(TSL2561_INTEGRATIONTIME_13MS); // shortest integration time (bright light)
//tsl.setTiming(TSL2561_INTEGRATIONTIME_101MS); // medium integration time (medium light)
//tsl.setTiming(TSL2561_INTEGRATIONTIME_402MS); // longest integration time (dim light)
if (!SD.exists("data.tsv")) {
file = SD.open("data.tsv", FILE_WRITE);
if (file) {
Serial.print("Creating data.tsv");
file.println("#Time\t\tT [°C]\tP [Pa]\tAlt [m]\tHr [%]\tLx [lux]");
file.close();
Serial.println("DONE");
} else {
Serial.println("Error opening data.tsv");
}
}
}
void loop() {
float temperature = bmp.readTemperature();
int32_t pressure = bmp.readPressure();
float altitude = bmp.readAltitude();
float humidity = dht.readHumidity();
uint32_t lum = tsl.getFullLuminosity();
uint16_t lightIr = lum >> 16;
uint16_t lightFull = lum & 0xFFFF;
DateTime time = chronodot.now();
file = SD.open("data.tsv", FILE_WRITE);
if (file) {
Serial.print("Writing to data.tsv...");
file.print(time.year()); file.print("-"); file.print(time.month()); file.print("-"); file.print(time.day()); file.print(" "); file.print(time.hour()); file.print(":"); file.print(time.minute()); file.print(":"); file.print(time.second()); file.print("\t");
file.print(temperature); file.print("\t");
file.print(pressure); file.print("\t");
file.print(altitude); file.print("\t");
file.print(humidity); file.print("\t");
file.println(tsl.calculateLux(lightFull, lightIr));
file.close();
Serial.println("DONE");
} else {
Serial.println("Error opening data.tsv");
}
delay(TIMING);
}

View File

@ -0,0 +1,113 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Station Météo</title>
<style>
html, body {
background: #000;
color: #fff;
}
body {
font-family: 'DejaVu Sans', Verdana, Arial, sans-serif;
font-size: 100%;
margin: 0;
padding: 0;
}
#home {
background: #000;
color: #fff;
margin: 1em;
padding: 0;
}
#home h1 {
color: #f7c000;
font-size: 2em;
margin: 1em;
text-align: center;
}
#home p {
background: #111;
border: 1px solid #444;
font-size: 1.5em;
list-style-type: none;
padding: 0;
width: 100%;
text-align: center;
}
#home table {
background: #111;
border: 1px solid #444;
font-size: 1.5em;
list-style-type: none;
padding: 0;
width: 100%;
text-align: center;
}
#home ul#links li {
font-weight: bold;
margin: 0;
padding: 0.8em;
text-align: center;
}
#footer {
background: #000;
color: #888;
font-size: 0.8em;
margin: 1em;
text-align: center;
padding: 0;
}
</style>
</head>
<body>
<div id='home'>
<h1>Station Météo</h1>
<table><tr><th>Temps</th><th>T [°C]</th><th>P [Pa]</th><th>Alt [m]</th><th>Hr [%]</th><th>Lx [lux]</th></tr>
<tr><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td></tr></table>
<p><label>Intervale de mise à jour (en secondes) : </label><input id='interval' type='number' value=2 /></p>
</div>
<div id='footer'>
par Nathanaël Restori
</div>
<script>
function updateInfo() {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/sensors.json');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var response = JSON.parse(xhr.responseText);
var rows = document.getElementsByTagName('tr');
var cell = rows[1].firstChild;
var index = 0;
while (cell) {
cell.firstChild.nodeValue = response.sensors[index].data;
cell = cell.nextSibling;
index++;
}
}
};
xhr.send(null);
}
updateInfo();
var updateID = setInterval(updateInfo, 2000);
var interval = document.getElementById('interval');
interval.addEventListener('change', function(e) {
clearInterval(updateID);
updateID = setInterval(updateInfo, e.target.value*1000);
}, true);
</script>
</body>
</html>

View File

@ -0,0 +1,158 @@
#include <Wire.h>
#include <SPI.h>
#include <Ethernet.h>
#include "WebServer.h"
#include "BMP085.h"
#include "DHT.h"
#include "TSL2561.h"
#include "Chronodot.h"
#define TIMEZONE 7200 // 2 hours
#define DHTPIN 2
#define DHTTYPE DHT22
#define PREFIX ""
#define NTP_PACKET_SIZE 48
static uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
static IPAddress ip = IPAddress(192, 168, 1, 210);
static IPAddress timeserver = IPAddress(192, 43, 244, 18);
P(indexHtml) = "<!DOCTYPE html><html><head><meta charset='utf-8' /><title>Station Météo</title>"
"<style>html, body{background: #000;color: #fff;}body{font-family: 'DejaVu Sans', Verdana, Arial, sans-serif;font-size: 100%;margin: 0;padding: 0;}#home{background: #000;color: #fff;margin: 1em;padding: 0;}#home h1{color: #f7c000;font-size: 2em;margin: 1em;text-align: center;}#home p{background: #111;border: 1px solid #444;font-size: 1.5em;list-style-type: none;padding: 0;width: 100%;text-align: center;}#home table{background: #111;border: 1px solid #444;font-size: 1.5em;list-style-type: none;padding: 0;width: 100%;text-align: center;}#home ul#links li{font-weight: bold;margin: 0;padding: 0.8em;text-align: center;}#footer{background: #000;color: #888;font-size: 0.8em;margin: 1em;text-align: center;padding: 0;}</style>"
"</head><body>"
"<div id='home'><h1>Station Météo</h1>"
"<table><tr><th>Temps</th><th>T [°C]</th><th>P [Pa]</th><th>Alt [m]</th><th>Hr [%]</th><th>Lx [lux]</th></tr>"
"<tr><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td></tr></table>"
"<p><label>Intervale de mise à jour (en secondes) : </label><input id='interval' type='number' value=2 /></p></div><div id='footer'>par Nathanal Restori</div>"
"<script>function updateInfo(){var xhr=new XMLHttpRequest();xhr.open('GET', '/sensors.json');xhr.onreadystatechange=function(){if (xhr.readyState==4 && xhr.status==200){var response=JSON.parse(xhr.responseText);var rows=document.getElementsByTagName('tr');var cell=rows[1].firstChild;var index=0;while (cell){cell.firstChild.nodeValue=response.sensors[index].data;cell=cell.nextSibling;index++;}}};xhr.send(null);}updateInfo();var updateID=setInterval(updateInfo, 2000);var interval=document.getElementById('interval');interval.addEventListener('change', function(e){clearInterval(updateID);updateID=setInterval(updateInfo, e.target.value*1000);}, true);</script>"
"</body></html>";
// no-cost stream operator as described at
// http://sundial.org/arduino/?page_id=119
template<class T>
inline Print &operator <<(Print &obj, T arg)
{ obj.print(arg); return obj; }
BMP085 bmp;
DHT dht(DHTPIN, DHTTYPE);
TSL2561 tsl(TSL2561_ADDR_FLOAT);
Chronodot chronodot;
WebServer webserver(PREFIX, 80);
byte packetBuffer[ NTP_PACKET_SIZE];
EthernetUDP Udp;
void defaultCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete) {
server.httpSuccess();
server.printP(indexHtml);
}
void sensorsJsonCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete) {
float temperature = bmp.readTemperature();
int32_t pressure = bmp.readPressure();
float altitude = bmp.readAltitude();
float humidity = dht.readHumidity();
uint32_t lum = tsl.getFullLuminosity();
uint16_t lightIr = lum >> 16;
uint16_t lightFull = lum & 0xFFFF;
DateTime time = chronodot.now();
server.httpSuccess("application/json");
server << "{ \"sensors\": ["
<< "{\"data\":\"" << time.hour() << ":" << time.minute() << ":" << time.second() << " " << time.day() << "/" << time.month() << "/" << time.year() << "\"},"
<< "{\"data\":" << temperature << "},"
<< "{\"data\":" << pressure << "},"
<< "{\"data\":" << altitude << "},"
<< "{\"data\":" << humidity << "},"
<< "{\"data\":" << tsl.calculateLux(lightFull, lightIr) << "}"
<< "] }";
}
void sendNTPpacket(IPAddress& address) {
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer,NTP_PACKET_SIZE);
Udp.endPacket();
Serial.println("Sending ntp packet");
delay(1000);
if ( Udp.parsePacket() ) {
// We've received a packet, read the data from it
Udp.read(packetBuffer,NTP_PACKET_SIZE); // read the packet into the buffer
//the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, esxtract the two words:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
unsigned long epoch = secsSince1900 - seventyYears + TIMEZONE;
Serial.println("Adjusting time");
chronodot.adjust(DateTime(epoch));
}
}
void setup() {
Serial.begin(9600);
//----- Ethernet/WebServer
Serial.println("INIT Ethernet");
Ethernet.begin(mac, ip);
webserver.begin();
webserver.setDefaultCommand(&defaultCmd);
webserver.addCommand("sensors.json", &sensorsJsonCmd);
//----- Sensors
Serial.println("INIT Sensors");
bmp.begin();
dht.begin();
tsl.begin();
chronodot.begin();
// You can change the gain on the fly, to adapt to brighter/dimmer light situations
//tsl.setGain(TSL2561_GAIN_0X); // set no gain (for bright situtations)
tsl.setGain(TSL2561_GAIN_16X); // set 16x gain (for dim situations)
// Changing the integration time gives you a longer time over which to sense light
// longer timelines are slower, but are good in very low light situtations!
tsl.setTiming(TSL2561_INTEGRATIONTIME_13MS); // shortest integration time (bright light)
//tsl.setTiming(TSL2561_INTEGRATIONTIME_101MS); // medium integration time (medium light)
//tsl.setTiming(TSL2561_INTEGRATIONTIME_402MS); // longest integration time (dim light)
Udp.begin(8888);
sendNTPpacket(timeserver);
}
void loop() {
webserver.processConnection();
delay(500);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

91
latex/TM.tex Normal file
View File

@ -0,0 +1,91 @@
\documentclass{scrreprt}
\usepackage{fontspec}
\usepackage{xunicode}
\usepackage{polyglossia}
\usepackage{csquotes}
\usepackage[citestyle=verbose-trad2]{biblatex}
\usepackage[hidelinks]{hyperref}
\usepackage[acronym,toc,xindy]{glossaries}
\setmainlanguage{french}
\title{La lumière s'éteint-elle dans le frigo ?}
\subtitle{ou bla bli blu}
\author{Nathanaël \textsc{Restori}}
\date{\today}
\bibliography{bibliographie.bib}
\renewcommand*{\glstextformat}{\textbf}
\makeglossaries
\input{glossaire.tex}
\begin{document}
\input{couverture.tex}
\chapter*{Remerciements}
\thispagestyle{empty}
Je remercie bla bla bla...
\vfill
Image de couverture par \enquote{oomlout}, sous licence Creative Commons Attribution-Share like 2.0 Generic (CC BY-SA 2.0)
\tableofcontents
\chapter{Introduction}
\section{Motivations}
J'ai décidé de faire mon travaille de maturité sur ce sujet car je suis passionné de robotique depuis tout petit. J'ai commencé en participant à un atelier de soudures à la Maison Picson\footnote{Établissement servant de cantine proposant aussi des activités à Blonay}. Je suis aussi allé à la première édition du Festival de Robotique à l'EPFL en 2008 et ai participé à deux ateliers (introduction à la programmation de microcontrôleur et soudure d'un robot DIDEL).
Je suis aussi passionné par l'informatique en général, la programmation ainsi que les logiciels libres.
\section{Présentation du travail}
TODO
\section{Les principes du logiciel libre}
Un logiciel libre est un logiciel qui respecte quatre libertés fondamentales~:
\begin{enumerate}
\item la liberté d'utiliser le logiciel
\item la liberté de copier le logiciel
\item la liberté d'étudier le logiciel
\item la liberté de modifier le logiciel et de redistribuer les versions modifiées
\end{enumerate}
Les deux dernière libertés demandent la mise à disposition du \gls{code source}. On parle souvent de \emph{copyleft}, par opposition au copyright.
On retrouve aussi le terme \enquote{\emph{open source}}, mais celui-ci est ambigu : celui-ci pouvant désigner un logiciel des les sources sont disponibles mais non réutilisables ou redistribuable ou désigner un logiciel libre (comme définit par \gls{OSI}).
Les sources du logiciels sont soumis à des licences spécifiques garantissant ces libertés. Les plus connues sont la \gls{GPL}, la \gls{BSD} ou la MIT.
Quelques logiciels libres connus sont Firefox et Thunderbird, Linux ou OpenOffice.org/LibreOffice.
\section{Conventions d'écriture}
Les mots en \textbf{gras} sont des mots expliqués dans le glossaire ou des acronymes.
Les textes écrits avec \verb|cette police d'écriture| sont des extraits de code.
\chapter{Le matériel}
\section{Le choix de la plate-forme}
Il existe de nombreuse \gls{plate-forme} en robotique~: par exemple, le Boe-Bot de Parallax, utilisé dans les cours facultatifs de robotique de M. \textsc{Gardon}. J'ai fait le choix d'un Arduino car cette un plate-forme de plus en plus répandue, peu chère (20 € pour une carte programmable) et puissante. On trouve de nombreux exemples de \gls{DIY}, elle est programmable en \gls{C++} (donc il est possible d'utiliser des \glspl{bibliotheque}) et c'est du \gls{materiel libre}.
\section{Les capteurs}
Il a été décidé de faire une station météo. Nous avons donc besoin d'un thermomètre, d'un hygromètre, d'un baromètre et d'un capteur de luminosité. J'ai ajouté une horloge qui nous permettra d'avoir l'heure à laquelle les mesures ont été prises. Tous les capteurs ont été commandé sur le site d'Adafruit. L'hygromètre ne se connecte malheureusement pas en I²C, aucun capteur de ce type n'étant disponible% TODO : ajouter images/figures
\section{Les limitations}
J'ai vite été confronté a quelque limitations : la mémoire de l'Arduino ne peux contenir seulement 32256 octets de code compilé. Il ne peux donc pas contenir en même temps les \glspl{bibliotheque} pour utiliser les capteurs en I²C, utiliser le port RJ45 et utiliser la carte SD. La solution a été de couper le programme en deux : il y a donc un code pour afficher les mesures en direct à travers un navigateur web et un code pour prendre des mesures de manière régulière et les enregistrer.
%\listoffigures
\glsadd{DIYg}
\printglossary[type=\acronymtype,title=Acronymes,toctitle=Acronymes]
\newpage
\printglossary[type=main,title=Glossaire,toctitle=Glossaire]
%\chapter{Bibliographie}
\nocite{*}
%\printbibliography[heading=none]
\printbibliography
\appendix
%\appendixpage
%\addappheadtotoc
\end{document}

9
latex/bibliographie.bib Normal file
View File

@ -0,0 +1,9 @@
@Article{ref,
author={Durand, Patrick AND Durand, René},
journal={Le beau journal},
title={Les tomates tueuses},
year={2007},
month={jan},
pages={24},
notes={sympatique},
}

34
latex/couverture.tex Normal file
View File

@ -0,0 +1,34 @@
\begin{titlepage}
\makeatletter
\begin{center}
\textsc{\LARGE Gymnase de Burier}\\[4cm]
\textbf{\huge \@title\\[0.5em]
\large \@subtitle}
\vfill
\begin{figure}[htp]
\centering
\includegraphics[scale=1.0]{Arduino_Ethernet_Board_.jpg}
\end{figure}
\vfill
\begin{minipage}{0.59\textwidth}
\begin{flushleft}
Blonay, le \@date
\end{flushleft}
\end{minipage}
\begin{minipage}{0.4\textwidth}
\begin{flushright}
\@author, 2M6\\
\end{flushright}
\end{minipage}
\end{center}
\setcounter{page}{0}
\makeatother
\end{titlepage}

41
latex/glossaire.tex Normal file
View File

@ -0,0 +1,41 @@
\newglossaryentry{code source}
{
name=code source,
description={bla}
}
\newglossaryentry{DIYg}
{
name=DIY,
description={littéralement, \enquote{faites-le vous-même}. S'assimile à du bricolage}
}
\newglossaryentry{C++}
{
name=C++,
description={langage de programmation ancien et répandu}
}
\newglossaryentry{bibliotheque}
{
name=bibliothèque,
plural=bilbiothèques,
description={ensemble de fonctions permettant de manipuler un capteur, un objet, une puce (etc.) plus facilement}
}
\newglossaryentry{materiel libre}
{
name=matériel libre,
description={matériel dont les plans sont publics. Tout le monde peux les modifier, fabriquer, redistribuer et utiliser. Pendant matériel du logiciel libre}
}
\newglossaryentry{plate-forme}
{
name=plate-forme,
description={en informatique, une base de travail à partir de laquelle on peut écrire, lire, utiliser, développer un ensemble de logiciels\footnote{tiré de Wikipédia}}
}
\newacronym{BSD}{BSD}{Berkeley Software Distribution}
\newglossaryentry{DIY}{type=\acronymtype, name={DIY}, description={Do It Yourself}, first={Do It Yourself (DIY)}, see=[Glossaire :]{DIYg}}
\newacronym{GPL}{GPL}{GNU General Public License}
\newacronym{OSI}{OSI}{Open Source Initiative}

11
latex/latexmkrc Normal file
View File

@ -0,0 +1,11 @@
$pdflatex = "xelatex";
$pdf_mode = "1";
push @generated_exts, 'glo', 'gls', 'glg';
push @generated_exts, 'acn', 'acr', 'alg';
$clean_ext .= ' %R.bbl %R-blx.bib %R.ist %R.nav %R.run.xml %R.snm %R.xdy';
add_cus_dep( 'glo', 'gls', 0, 'makeglossaries' );
sub makeglossaries {
system( "makeglossaries \"$_[0]\"" );
}

52
latex/presentation.tex Normal file
View File

@ -0,0 +1,52 @@
%\pdfminorversion=4
\documentclass{beamer}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[francais]{babel}
\title{La lumière s'éteint-elle dans le frigo ?}
\subtitle{ou bla bli blu}
\author{Nathanaël \bsc{Restori}}
\date{\today}
\institute{Gymnase de Burier}
\usetheme{Warsaw}
\begin{document}
\begin{frame}
\titlepage
\end{frame}
\begin{frame}
\tableofcontents[pausesections]
\end{frame}
\section{Section 1}
\subsection{Sous section 1 de la Section 1}
\begin{frame}
Ma première page !
\end{frame}
\subsection{Sous section 2 de la Section 1}
\begin{frame}
Et maintenant ma deuxième page !
\end{frame}
\section{Section 2}
\subsection{Sous section 1 de la Section 2}
\begin{frame}
Voici ma troisième page, elle appartient à ma deuxième section ! :)
\end{frame}
\subsection{Sous section 2 de la Section 2}
\begin{frame}
Et celle là c'est la deuxième page, mais de ma deuxième section.
\end{frame}
\end{document}