2 // greenhouse monitoring and control program
3 // copyright 2010 by Bdale Garbee <bdale@gag.com> GPLv2
5 // data logging and fan+heat control for a greenhouse for arduino duemilanove
7 // temperature sensor analog 0
8 // light sensor analog 1
9 // humidity sensor analog 2
12 // DS1307 real time clock
13 // 24AA1025 128x8 EEPROM
15 // spi digital 10,11,12,13
17 // http://www.arduino.cc/playground/Code/Spi
19 // 4 relays for 120VAC digital 2,3,4,5
22 #include <Wire.h> // needed for i2c bus
25 #define TEMPERATURE 0 // temperature sensor
26 #define LIGHT 1 // light sensor
27 #define HUMIDITY 2 // humidity sensor
30 #define AA1025_ADDRESS 0x50
31 #define DS1307_ADDRESS 0x68
42 // data layout in EEPROM
43 #define LAST_WRITE_ADDR_MSB 0x00
44 #define LAST_WRITE_ADDR_LSB 0x01
45 #define MIN_WRITE_ADDR 0x02
46 #define MAX_WRITE_ADDR 0xFFFF
49 //#define READ_INTERVAL 900000
50 #define READ_INTERVAL 3000
51 #define SERIAL_WAIT_DELAY 20
62 digitalWrite(LED, LOW);
63 // pinMode(WARNING_LED, OUTPUT);
64 // digitalWrite(WARNING_LED, LOW);
66 // pinMode(DOWNLOAD_PIN, INPUT); // set pin to input
67 // digitalWrite(DOWNLOAD_PIN, HIGH); // turn on pullup resistors
72 delay(50); // allow some settling time
74 // restore last_write_addr from eeprom
75 last_write_addr = i2c_eeprom_read_byte( AA1025_ADDRESS, LAST_WRITE_ADDR_MSB) << 8;
76 last_write_addr += i2c_eeprom_read_byte( AA1025_ADDRESS, LAST_WRITE_ADDR_LSB);
78 // configure async console
86 Serial.println("Initialization complete");
91 // find out if the user requests calibrations or not
94 // see if we need to save a new value
95 if (millis() > next_read_time) {
96 digitalWrite(LED, HIGH);
98 next_read_time += READ_INTERVAL;
101 if (last_write_addr + 5 < MAX_WRITE_ADDR) {
102 last_write_addr += 4;
104 // get the temperature
105 val = analogRead(TEMPERATURE);
108 // save into the next available space
109 i2c_eeprom_write_byte( AA1025_ADDRESS, last_write_addr, val >> 8);
110 i2c_eeprom_write_byte( AA1025_ADDRESS, last_write_addr+1, val & 0xFF);
112 // get the photo sensor value
113 val = analogRead(LIGHT);
115 // save into the next available space
116 i2c_eeprom_write_byte( AA1025_ADDRESS, last_write_addr+2, val >> 8);
117 i2c_eeprom_write_byte( AA1025_ADDRESS, last_write_addr+3, val & 0xFF);
119 // save the last write address to the eeprom in case we lose power
120 i2c_eeprom_write_byte( AA1025_ADDRESS, LAST_WRITE_ADDR_MSB, last_write_addr >> 8);
121 i2c_eeprom_write_byte( AA1025_ADDRESS, LAST_WRITE_ADDR_LSB, last_write_addr & 0xFF);
126 Serial.println("Out of space to log values");
127 // flash the status LED
130 digitalWrite(LED, LOW);
132 // do something if out_of_space?
137 // listen for serial data
138 if (Serial.available()) {
139 // ensure all the data has been buffered
140 delay(SERIAL_WAIT_DELAY);
142 // read current command
144 // clear the rest of the current serial buffer
147 if (val == 'd' || val == 'D') {
148 // dump data over serial
151 else if (val == 'r' || val == 'R') {
155 else if (val == 's' || val == 'S') {
160 // inappropriate command received
161 Serial.println("Inappropriate serial command received");
162 Serial.println("Send 'r' to reset write pointer");
163 Serial.println("Send 'd' to download all data via serial");
175 Serial.println("Garbee Greenhouse Controller");
179 l = (last_write_addr - MIN_WRITE_ADDR) / 2;
180 l2 = (MAX_WRITE_ADDR - MIN_WRITE_ADDR) / 2;
181 Serial.print("Existing records: ");
186 Serial.print(((float)l / (float)l2) * 100.0);
187 Serial.println("%)");
189 Serial.print("Read interval: " );
190 Serial.print(READ_INTERVAL);
191 Serial.println("ms");
196 Serial.print("Resetting write address to ");
197 Serial.println((int) MIN_WRITE_ADDR);
199 i2c_eeprom_write_byte ( AA1025_ADDRESS, LAST_WRITE_ADDR_MSB, 0x00 );
200 i2c_eeprom_write_byte ( AA1025_ADDRESS, LAST_WRITE_ADDR_LSB, MIN_WRITE_ADDR );
201 last_write_addr = MIN_WRITE_ADDR;
209 // send data to serial
210 Serial.println("\nTemperature,Light:");
212 for (long addr = MIN_WRITE_ADDR; addr < last_write_addr; addr += 4){
214 val = i2c_eeprom_read_byte( AA1025_ADDRESS, addr ) << 8;
215 val += i2c_eeprom_read_byte( AA1025_ADDRESS, addr+1 );
220 val = i2c_eeprom_read_byte( AA1025_ADDRESS, addr+2 ) << 8;
221 val += i2c_eeprom_read_byte( AA1025_ADDRESS, addr+3 );
227 if (count % 250 == 0) {
230 Serial.print((last_write_addr - MIN_WRITE_ADDR) / 4);
235 Serial.println("Download complete.");
236 Serial.print("Sent ");
237 Serial.print((last_write_addr - MIN_WRITE_ADDR) / 4);
238 Serial.println(" records");
243 static void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
247 Wire.beginTransmission(deviceaddress);
248 Wire.write((int)(eeaddress >> 8)); // MSB
249 Wire.write((int)(eeaddress & 0xFF)); // LSB
251 Wire.endTransmission();
254 static byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
257 Wire.beginTransmission(deviceaddress);
258 Wire.write((int)(eeaddress >> 8)); // MSB
259 Wire.write((int)(eeaddress & 0xFF)); // LSB
260 Wire.endTransmission();
261 Wire.requestFrom(deviceaddress,1);
263 if (Wire.available()) rdata = Wire.read();