--- /dev/null
+//
+// greenhouse monitoring and control program
+// copyright 2010 by Bdale Garbee <bdale@gag.com> GPLv2
+//
+// data logging and fan+heat control for a greenhouse for arduino duemilanove
+//
+// temperature sensor analog 0
+// light sensor analog 1
+// humidity sensor analog 2
+//
+// i2c bus analog 4,5
+// DS1307 real time clock
+// 24AA1025 128x8 EEPROM
+//
+// spi digital 10,11,12,13
+// TeleDongle
+// http://www.arduino.cc/playground/Code/Spi
+//
+// 4 relays for 120VAC digital 2,3,4,5
+//
+
+#include <Wire.h> // needed for i2c bus
+
+// analog inputs
+#define TEMPERATURE 0 // temperature sensor
+#define LIGHT 1 // light sensor
+#define HUMIDITY 2 // humidity sensor
+
+// i2c bus
+#define AA1025_ADDRESS 0x50
+#define DS1307_ADDRESS 0x68
+
+// spi bus
+
+// digital outputs
+#define RELAY_0 2
+#define RELAY_1 3
+#define RELAY_2 4
+#define RELAY_3 5
+#define LED 9
+
+// data layout in EEPROM
+#define LAST_WRITE_ADDR_MSB 0x00
+#define LAST_WRITE_ADDR_LSB 0x01
+#define MIN_WRITE_ADDR 0x02
+#define MAX_WRITE_ADDR 0xFFFF
+
+// timing values
+//#define READ_INTERVAL 900000
+#define READ_INTERVAL 3000
+#define SERIAL_WAIT_DELAY 20
+
+long last_write_addr;
+long next_read_time;
+boolean out_of_space;
+int val;
+
+void setup() {
+
+// // setup the pins
+ pinMode(LED, OUTPUT);
+ digitalWrite(LED, LOW);
+// pinMode(WARNING_LED, OUTPUT);
+// digitalWrite(WARNING_LED, LOW);
+
+// pinMode(DOWNLOAD_PIN, INPUT); // set pin to input
+// digitalWrite(DOWNLOAD_PIN, HIGH); // turn on pullup resistors
+
+
+ // configure i2c
+ Wire.begin();
+ delay(50); // allow some settling time
+
+ // restore last_write_addr from eeprom
+ last_write_addr = i2c_eeprom_read_byte( AA1025_ADDRESS, LAST_WRITE_ADDR_MSB) << 8;
+ last_write_addr += i2c_eeprom_read_byte( AA1025_ADDRESS, LAST_WRITE_ADDR_LSB);
+
+ // configure async console
+ Serial.begin(19200);
+
+ status();
+
+ next_read_time = 0;
+ out_of_space = 0;
+
+ Serial.println("Initialization complete");
+}
+
+void loop() {
+
+ // find out if the user requests calibrations or not
+ readSerial();
+
+ // see if we need to save a new value
+ if (millis() > next_read_time) {
+ digitalWrite(LED, HIGH);
+
+ next_read_time += READ_INTERVAL;
+
+
+ if (last_write_addr + 5 < MAX_WRITE_ADDR) {
+ last_write_addr += 4;
+
+ // get the temperature
+ val = analogRead(TEMPERATURE);
+Serial.print(val);
+Serial.print(",");
+ // save into the next available space
+ i2c_eeprom_write_byte( AA1025_ADDRESS, last_write_addr, val >> 8);
+ i2c_eeprom_write_byte( AA1025_ADDRESS, last_write_addr+1, val & 0xFF);
+
+ // get the photo sensor value
+ val = analogRead(LIGHT);
+Serial.println(val);
+ // save into the next available space
+ i2c_eeprom_write_byte( AA1025_ADDRESS, last_write_addr+2, val >> 8);
+ i2c_eeprom_write_byte( AA1025_ADDRESS, last_write_addr+3, val & 0xFF);
+
+ // save the last write address to the eeprom in case we lose power
+ i2c_eeprom_write_byte( AA1025_ADDRESS, LAST_WRITE_ADDR_MSB, last_write_addr >> 8);
+ i2c_eeprom_write_byte( AA1025_ADDRESS, LAST_WRITE_ADDR_LSB, last_write_addr & 0xFF);
+
+
+ }
+ else {
+ Serial.println("Out of space to log values");
+ // flash the status LED
+ out_of_space = 1;
+ }
+ digitalWrite(LED, LOW);
+ }
+ // do something if out_of_space?
+
+}
+
+void readSerial() {
+ // listen for serial data
+ if (Serial.available()) {
+ // ensure all the data has been buffered
+ delay(SERIAL_WAIT_DELAY);
+
+ // read current command
+ val = Serial.read();
+ // clear the rest of the current serial buffer
+ Serial.flush();
+
+ if (val == 'd' || val == 'D') {
+ // dump data over serial
+ sendData();
+ }
+ else if (val == 'r' || val == 'R') {
+ // reset
+ reset();
+ }
+ else if (val == 's' || val == 'S') {
+ // status
+ status();
+ }
+ else {
+ // inappropriate command received
+ Serial.println("Inappropriate serial command received");
+ Serial.println("Send 'r' to reset write pointer");
+ Serial.println("Send 'd' to download all data via serial");
+ return;
+ }
+
+ }
+}
+
+void status() {
+ long l, l2;
+
+ Serial.println("");
+ Serial.println("");
+ Serial.println("Garbee Greenhouse Controller");
+
+ Serial.println("");
+
+ l = (last_write_addr - MIN_WRITE_ADDR) / 2;
+ l2 = (MAX_WRITE_ADDR - MIN_WRITE_ADDR) / 2;
+ Serial.print("Existing records: ");
+ Serial.print(l);
+ Serial.print(" / ");
+ Serial.print(l2);
+ Serial.print(" (");
+ Serial.print(((float)l / (float)l2) * 100.0);
+ Serial.println("%)");
+
+ Serial.print("Read interval: " );
+ Serial.print(READ_INTERVAL);
+ Serial.println("ms");
+
+}
+
+void reset() {
+ Serial.print("Resetting write address to ");
+ Serial.println((int) MIN_WRITE_ADDR);
+
+ i2c_eeprom_write_byte ( AA1025_ADDRESS, LAST_WRITE_ADDR_MSB, 0x00 );
+ i2c_eeprom_write_byte ( AA1025_ADDRESS, LAST_WRITE_ADDR_LSB, MIN_WRITE_ADDR );
+ last_write_addr = MIN_WRITE_ADDR;
+}
+
+void sendData() {
+ delay(50);
+
+ long count;
+
+ // send data to serial
+ Serial.println("\nTemperature,Light:");
+ count = 0;
+ for (long addr = MIN_WRITE_ADDR; addr < last_write_addr; addr += 4){
+
+ val = i2c_eeprom_read_byte( AA1025_ADDRESS, addr ) << 8;
+ val += i2c_eeprom_read_byte( AA1025_ADDRESS, addr+1 );
+
+ Serial.print(val);
+ Serial.print(',');
+
+ val = i2c_eeprom_read_byte( AA1025_ADDRESS, addr+2 ) << 8;
+ val += i2c_eeprom_read_byte( AA1025_ADDRESS, addr+3 );
+
+ Serial.println(val);
+
+
+ count ++;
+ if (count % 250 == 0) {
+ Serial.print(count);
+ Serial.print('/');
+ Serial.print((last_write_addr - MIN_WRITE_ADDR) / 4);
+ Serial.print(",");
+ }
+ }
+
+ Serial.println("Download complete.");
+ Serial.print("Sent ");
+ Serial.print((last_write_addr - MIN_WRITE_ADDR) / 4);
+ Serial.println(" records");
+
+}
+
+
+static void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
+ delay(5);
+
+ int rdata = data;
+ Wire.beginTransmission(deviceaddress);
+ Wire.send((int)(eeaddress >> 8)); // MSB
+ Wire.send((int)(eeaddress & 0xFF)); // LSB
+ Wire.send(rdata);
+ Wire.endTransmission();
+}
+
+static byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
+ delay(5);
+ byte rdata = 0xFF;
+ Wire.beginTransmission(deviceaddress);
+ Wire.send((int)(eeaddress >> 8)); // MSB
+ Wire.send((int)(eeaddress & 0xFF)); // LSB
+ Wire.endTransmission();
+ Wire.requestFrom(deviceaddress,1);
+
+ if (Wire.available()) rdata = Wire.receive();
+ return rdata;
+}