Introduction: Indoor Grow Space Automation Part 1

Disclaimer: The author assumes no liability for any incidental, consequential or other liability from the use of this information. All risks and damages, incidental or otherwise, arising from the use or misuse of the information contained herein are entirely the responsibility of the user. Although careful precaution has been taken in the preparation of this material, we assume no responsibility for omissions or errors.

This will form Part 1 of a series to achieve an automated indoor grow space.

What I'll cover in this instructable:
1) A Relay that switches a light on and off on a timer.
2) The use of a Light Dependent Resistor.
3) 3 x DS18B20 temperature sensors daisy-chained.
4) 2 x Moisture sensors.
5) The arduino sketch.
6) C# program, Serial interface, MySQL API.

Project Mission: Create a solution that will automate indoor plant growth, be safe and remotely manageable. Maybe include some external weather information. All aimed at learning new tools.

Project End Goals (What I ultimately want to achieve):
1) Measure temperature and light in the grow space, my room and outside, mostly because the data should be interesting and defines the environment in and around the grow space. Values to be saved in a database (MySQL in this case) and be graphed through MS Excel through an odbc connection. The light and temperature will also be used as control to ensure the light mentioned in point 2 below, does actually switch on.
2) Switch a 220volt light system on and off on a configurable timetable.
3) Measure soil moisture. I'm going to measure the moisture content in two pots and may even look into setting up checks for possible water overflow or leaks, as a control measure.
4) Switch a 220volt water pump on for a period of time to water the plants, when moisture levels drop below a certain threshold.
5) Control the temperature with the use of a fan/extractor fan.
6) Video Cam to remotely monitor. Website for remote access and control.

Warning: When working with water and electricity, place all plugs, connectors, relays, etc, higher than your plants and lights. Run cable's down. Insolate properly. Use common sense. Watch your humidity and condensation.

Step 1: Component List

You can scale your own project up or down, depending on your design needs.

Software used:
1) Arduino IDE. Refer to Arduino website on where to buy and how to setup your Arduino. I got my kit from Earthshine Design.
2) Microsoft Visual C# 2008 Express Edition.
3) MySQL. Many sources. Try http://sourceforge.net/projects/phpdev5/ Note this will install a host of other software that we might use in later parts of this series.
4) MySQL/Net 5.2.  I struggled a bit to get this API working in C#. Your luck may vary. This provides you with these definitions on the forms code:
using MySql.Data;
using MySql.Data.MySqlClient;
5) Microsoft Excel.
6) MySQL Connector/ODBC 5.1. For MS Excel to connect to MySQL through ODBC.
7) SendEmail
8) Fritzing
9) HeidiSQL

- I will not spend time explaining the installation of these. If there is enough interest I'll consider covering some in a later series, but most of the above is well documented already.

Hardware used:
1) Arduino Duemilanove
2) 1 x TIP-120 NPN Transistor
3) HFS41
4) 3 x DS18B20
5) 1 x 1N4001 Diode or others
6) 4 x Galvanized Nails
7) Some Cable (I like to use UTP Cat5 cable)
8) 1 x Light Dependent Resistor
9) A breadboard
10) PC or laptop
11) A grow light of sorts
12) Some Jumper Wire
13) Pots and plants.
14) 1 x 1.5Kohm resisor
15) 4 x 4.7Kohm resistor (Does not have to be exact)

Step 2: Light Control

Objective: Switch the plant grow light on and off at set times of the day.

Component considerations:
- Lights:

Plants need the right kind of light to grow. Human visible light does not necessarily mean that it has the right light wavelengths required for plant growth. Choices can be:
MH - Pros: Very strong light with much of the light spectrum necessary for plant growth. Cons: This kind of light gives off a lot of heat, so you will have to invest heavily in cooling your environment. Heat can cause fire. Setup can be expensive.

HPS - pretty much the same as above in my opinion. The Light spectrum differs from MH.
CFL's - This is my current choice of light. Pros: They can be bought colour tempered, meaning they can either emit warm (red) or cold (blue) light. Much cooler and therefore you will have less trouble with controlling heat. The light can be very close to your plant canopy without burning your plants and the plants will get much more light. Cons: Not as well tested as the above two. Might not have enough light to take plants through a flowering stage. I opted for two 125w .5 amp CFL's. One red and the other blue.

LED's - Pros: Good light spectrum for plant growth. Very cool. Cons: Untested. You will need a lot of led's to match the wattage of other forms of light. This will drive up costs and due to the amount of LEDs, you might even end up having heat issues, purely because of the number of LED's necessary. (I will do some tests in the future.)

Plasma Lights - In my opinion the future of lights!!! Very new but also very expensive. See:
http://www.nlites.co.uk/sulphur-plasma.htm
http://www.treehugger.com/files/2008/04/luxim-plasma-lifi-light-bulb-led-cfl.php

For more on light see:
http://www.sunmastergrowlamps.com/SunmLightandPlants.html
http://www.littlegreenhouse.com/guide3.shtml
http://www.cheapvegetablegardener.com/2008/12/effects-of-colors-on-plant-growth.html

- Relay: I used a zero crossing HFS41 solid state relay, rated 5amp output at 220-240volt. Depending on the light solution you choose, you might need a bigger and better relay to switch your lights. Be sure what you're doing here. Lights are conductive and the wrong relays can either reduce the lifespan of your devices or at worst, a fire. Ask someone that knows if you don't.

From RS Components UK.
http://uk.rs-online.com/web/search/searchBrowseAction.html?method=getProduct&R=0476652

- Transistor: For those that don't know how a standard relay works- The relay has 2 inputs and 2 output legs (other combinations exist).  Some relays are closed and some open when there is no power running over the input legs. I suggest closed, since it is safer, but you might want it to be open (on) even if your arduino is not switched on. The arduino can only push 40ma out of one digital pin. The HFS41 needs between 3 and 15volt at at least 40ma to switch on. From this you might think you can simply connect the relay input pins directly to one of the arduino pins. I've asked around on forums and everyone I spoke to suggested it would be safer to do the switching with a transistor. So the pin will switch on the transistor. I also want to mention that if you're going to use relays and motors etc. its best to have the arduino power supply connected to the arduino because it will give the arduino more ma's to work with. The USB is only good to provide power to smaller setups. I have both connected, since I need the USB for communication to the computer.

- Cable: UTP cat 5. Long enough to reach your grow space.

Step 3: Light Sensor

Objective: This will be used to tell me if the light has really switched on or not. The kids could have switched it off at the plug. So if the light is switched on, the light sensor should pick it up. If not, it must sms or email me.

Note: This sensor is still on my breadboard and not in the grow space. No email/sms alerts for this is configured yet.

- Light Dependant resistor.

- 1 x 4.7Kohm resistor.

Step 4: Temperature Sensors

Objective: I want to record the temperature at many places. I guess you could get away with only one temp sensor in your grow area, but the sensor I use makes taking the temperature at multiple locations easy and fun. The Temperature sensor will also ultimately be used to switch a fan/ extractor fan on to control the temperature. Depending on what you want to grow, you'll need to regulate the temperature. Without any temperature control, my grow space never reached above 30'C with my two 125watt CFL's. So temp control was not high on my list.

- DS18B20: This temp sensor is amazing. The DS18B20 digital thermometer provides 9-bit to 12-bit Celsius temperature measurements and has an alarm function with nonvolatile user-programmable upper and lower trigger points. The DS18B20 communicates over a 1-Wire bus that by definition requires only one data line (and ground) for communication with a central microprocessor. It has an operating temperature range of -55°C to +125°C and is accurate to ±0.5°C over the range of -10°C to +85°C. In addition, the DS18B20 can derive power directly from the data line ("parasite power"), eliminating the need for an external power supply. Each DS18B20 has a unique 64-bit serial code, which allows multiple DS18B20s to function on the same 1-Wire bus. Thus, it is simple to use one microprocessor to control many DS18B20s distributed over a large area. One thing to note is that it takes a bit of time to read this sensor and this will be the only place I use delays in my sketch. I hate those and tried my best to avoid delays wherever I could. More on delays later. From RS Components UK.

- 3 x 4.7Kohm.

Step 5: Moisture Sensors

Objective: Measure the moisture levels in the soil to trigger an event that will water the plants.

- 2 x Galvanized Nails: Basically they're stuck into two ends of your pot and we measure the current across them. The wetter the soil, the better the current flow. This sounds very basic and it is. One has to calibrate your readings which could be challenging. The lower limit in dry soil for me is below 300 and in wet soil above 800. The analogue input of the arduino can read the voltage on a scale of 0 for 0 volts to 1023 for 5 volts.

- 2 x 4.7Kohm resistor.

Step 6: Electrical Layout

Download project.zip for a high resolution image.

Step 7: Arduino Sketch

Objective: All attempts are made to keep this as simple as possible. The arduino should really not do anything, but wait for an instruction and then execute the corresponding code. Therefore a computer is permanently necessary for this project. When I'm done developing and everything is working well, I'll connect it up to a spare old Laptop I have and place it closer to my grow area, as it's currently connected to my desktop computer.

The TakeDS function was adapted from the sketch on the arduino site. All credit to them!  

Download code.txt attached below.

Attachments

Step 8: C# Program & MySQL

Objective: The program must control the arduino via the USB serial port. The code to address the port was derived from http://csharp.simpleserial.com/ . All credit to the developer.

Todo:
- Create the MySQL database and tables. Code listed below C# code or see Garden2.zip.
- You must set your MySQL database username and password in the code.
- Also set you email details in the emailStatus function.

// ---------------------------------------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using MySql.Data;               // For MySQL
using MySql.Data.MySqlClient;   // For MySQL
using System.Diagnostics;       // To do emailStatus()


namespace Garden
{
    public partial class Form1 : Form
    {
        string RxString, testS, tempS, light, Temp1, Temp2, Temp3, moist1, moist2 = "";
        double workD, tmp1, tmp2, tmp3, m1, m2 = 0;
        char call = '0';
        char[] buff = new char[1];
        char[] conv = new char[70];
        int l1, c2, lightOnH, lightOnM, lightOffH, lightOffM = 0;
        int count = 0;
        bool state = false;

        public Form1()
        {
            InitializeComponent();
            // Hide some buttons and textboxes. I wanted to create a separate form to set variables
            // ie. light on time. I couldn't figure out how to pass variables between forms in c#.
            // This will be on my wish list for later versions. For now I hide things to create more
            // space on the form.
            label3.Visible = false;
            label4.Visible = false;
            label5.Visible = false;
            label6.Visible = false;
            lonhBOX.Visible = false;
            lonmBOX.Visible = false;
            loffhBOX.Visible = false;
            loffmBOX.Visible = false;
            saveBUT.Visible = false;
            CancelBUT.Visible = false;
        }


        private void buttonStart_Click(object sender, EventArgs e) // Lets start things.
        {                                                   // All intervals needs to be save in "settings" table. Todo.
            timer1.Interval = 10000;                        // Timer for 10 seconds. I display values on the from every
                                                            // 10 seconds.
            timer1.Enabled = true;                          // Start the timer.
            timer1.Tick += new EventHandler(timer1_Tick);   // Setup the event handler for the timer.
            timer2.Interval = 500;                          // This happens every .5 second to update the date/time
                                                            // field on the form.
            timer2.Enabled = true;
            timer2.Tick += new EventHandler(timer2_Tick);
            timer3.Interval = 3600000;                      // Interval at which to email status to owner.
            timer3.Enabled = true;
            timer3.Tick += new EventHandler(timer3_Tick);
            serialPort1.PortName = "COM3";                  // USB serial port number.
                                                            // Need to make this changeable through setting settings.
                                                            // To save in the database in the "settings" table.
            serialPort1.BaudRate = 9600;                    // Serial port speed.
                                                            // Sometimes I need to reset the arduino via button on the board
                                                            // to get things going at start-up. Not sure why the serial
                                                            // communication does not always work straight away. Once reset and
                                                            // working it keeps working, so it doesn't bug me too much. FYI.
            serialPort1.Open();                             // Open serial port for communication.
            if (serialPort1.IsOpen)
            {
                buttonStart.Enabled = false;
                buttonStop.Enabled = true;
            }
            ReadMyData();                                   // Get settings from "settings" table.
            CallA();                                        // Send char "a" to the arduino to get values.
        }

        private void emailStatus()
        {
            Process myProc;
            // Start the process.
            // Get SendEmail here: http://caspian.dotconf.net/menu/Software/SendEmail/
            myProc = Process.Start("c:\\email\\sendEmail.exe", "-f your@email.com -t your@email.com -u Status -m " + l1 + "," + tmp1 + "," + tmp2 + "," + tmp3 + "," + m1 + "," + m2 + "; -s your.smtp.com -xu username -xp password");
            // Stop the process.
            myProc.CloseMainWindow();
        }


        private void buttonStop_Click(object sender, EventArgs e) // Stop everything.
        {
            if (serialPort1.IsOpen)
            {
                timer1.Enabled = false;         // Stop the timers.
                timer2.Enabled = false;
                timer3.Enabled = false;
                serialPort1.Close();            // Close the serial port.
                buttonStart.Enabled = true;    
                buttonStop.Enabled = false;
             }

        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {

            if (serialPort1.IsOpen) serialPort1.Close();        // Close to port if we leave.
        }

        private void DisplayText(object sender, EventArgs e)    // Display form values. You can look here for the
                                                                // forms text names.
        {

            lightBox.Text = light;                      // Display values in textboxes.
            m1Box.Text = moist1;
            m2Box.Text = moist2;
            workD = Convert.ToDouble(Temp1) / 10000;    // Get our decimal places back.
            tmp1 = workD;                               // Save for Database save.
            tempS = workD.ToString("N2");
            tempBox1.Text = tempS;
            workD = Convert.ToDouble(Temp2) / 10000;
            tmp2 = workD;
            tempS = workD.ToString("N2");
            tempBox2.Text = tempS;
            workD = Convert.ToDouble(Temp3) / 10000;
            tmp3 = workD;
            tempS = workD.ToString("N2");
            tempBox3.Text = tempS;

            if (state)
            {
                stateTextBox.Text = "On";
            }
            else
            {
                stateTextBox.Text = "Off";
            }
            c2 = c2 + 1;

            if (c2 == 6)                        // Every 6 10 seconds save to database. This is quite allot of data points.
            {
                l1 = Convert.ToInt16(light);    // Convert values to save in the databse.
                m1 = Convert.ToInt16(moist1);
                m2 = Convert.ToInt16(moist2);
                c2 = 0;
                // Setup connection string.
                MySqlConnection MyCon = new MySqlConnection("SERVER=localhost;" + "DATABASE=garden2;" + "UID=root;" + "PASSWORD=password;");
                // Open connection.
                MyCon.Open();
                // Setup the SQL string.
                MySqlCommand command = new MySqlCommand("insert into readings values (null, null," + l1 + "," + tmp1 + "," + tmp2 + "," + tmp3 + "," + m1 + "," + m2 + ")", MyCon);
                // Execute the SQL string on the database.
                command.ExecuteNonQuery();
                // Close Database connection.
                MyCon.Close();

                // Do some logic to determine whether to switch the light on or off. This could probably be done in a separate timer event.
                if (DateTime.Now.Hour >= lightOnH)
                {
                    if (DateTime.Now.Hour >= lightOffH)
                    {
                        if (DateTime.Now.Minute >= lightOffM)
                        {
                            CallC(); // Light off.
                        }
                    }
                    else
                    {
                        if (DateTime.Now.Minute >= lightOnM)
                        {
                            CallB(); //Light on.
                        }
                    }

                }
                else
                {
                    CallC(); // Light off.
                }
            }
         }

        private void Sort(object sender, EventArgs e)   // Dissect the string we got from the arduino.
        {
            testS = "~";            // The value break char.
            light = "";             // Clear all values.
            Temp1 = "";
            Temp2 = "";
            Temp3 = "";
            moist1 = "";
            moist2 = "";
            count = 0;
            while (RxString[count] != testS[0])     // Check first char for break value(~). Repeat till found.
            {
                light = light + RxString[count];    // If not add the char to new string(light).
                count += 1;                         // Goto next char.
            }
            count += 1;                             // Lets go on to the next char via (count).
            while (RxString[count] != testS[0])
            {
                Temp1 = Temp1 + RxString[count];
                count += 1;
            }
            count += 1;
            while (RxString[count] != testS[0])
            {
                Temp2 = Temp2 + RxString[count];
                count += 1;
            }
            count += 1;
            while (RxString[count] != testS[0])
            {
                Temp3 = Temp3 + RxString[count];
                count += 1;
            }
            count += 1;
            while (RxString[count] != testS[0])
            {
                moist1 = moist1 + RxString[count];
                count += 1;
            }
            count += 1;
            while (RxString[count] != testS[0])
            {
                moist2 = moist2 + RxString[count];
                count += 1;
            }
            // Add more while statements for extra values from arduino.
        }

        public void ReadMyData()            // Read "settings" table.
        {
            // SQL query string.
            string mySelectQuery = "SELECT LOnH, LOnM, LOffH, LOffM FROM settings";
            // Database connection string.
            MySqlConnection myConnection = new MySqlConnection("SERVER=localhost;" + "DATABASE=garden2;" + "UID=root;" + "PASSWORD=password;");
            MySqlCommand myCommand = new MySqlCommand(mySelectQuery, myConnection);
            // Open database connection.
            myConnection.Open();
            MySqlDataReader myReader;
            // Execute query string.
            myReader = myCommand.ExecuteReader();
            // Always call Read before accessing data.
            while (myReader.Read())
            {
                lightOnH = myReader.GetInt16(0);
                lightOnM = myReader.GetInt16(1);
                lightOffH = myReader.GetInt16(2);
                lightOffM = myReader.GetInt16(3);
            }
            // Always call Close when done reading.
            myReader.Close();
            // Close the connection when done with it.
            myConnection.Close();
        }    

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) // We have data at the port.
        {
            System.Threading.Thread.Sleep(50);      // A delay to make sure all the data is received at the port.
            switch (call)
            {
                case 'a':                                       // We called a "a".
                    RxString = "";                              // Clear the recieve string.
                    RxString = serialPort1.ReadExisting();      // Get the data from the port.
                    this.Invoke(new EventHandler(Sort));        // Dissect the string into individual values.
                    this.Invoke(new EventHandler(DisplayText)); // Display the values on the form.
                break;
                case 'c':       // We called a "c". Future use.
                break;
                case 'd':       // We called a "d". Future use.
                break;
                case 'e':       // We called a "e". Future use.
                break;
           }
        }

        private void CallA()                    // Send char "a" to serial port.
        {
            if (!serialPort1.IsOpen) return;
            buff[0] = 'a';
            call = 'a';                         // Used to see what call we made to the arduino.
            serialPort1.Write(buff, 0, 1);
        }

        private void CallB()                    // Send char "b" to serial port.
        {
            if (!state)
            {
                if (!serialPort1.IsOpen) return;
                buff[0] = 'b';
                call = 'b';
                serialPort1.Write(buff, 0, 1);
                state = true;
            }
        }

        private void CallC()                    // Send char "c" to serial port.
        {
            if (state) {
            if (!serialPort1.IsOpen) return;
            buff[0] = 'c';
            call = 'c';
            serialPort1.Write(buff, 0, 1);
            state = false;
            }
        }

        private void wtime()        // Writes date/time to forms textbox.
        {
            DateBox.Text = Convert.ToString(DateTime.Now);
        }

        private void timer1_Tick(object sender, System.EventArgs e)  // Timer event.
        {
            CallA();        // Send "a". Get values.
         }

        private void timer2_Tick(object sender, System.EventArgs e)
        {
            wtime();        // Call wtime function.
        }

        private void timer3_Tick(object sender, System.EventArgs e)
        {
            emailStatus();  // Call emailStatus function.
        }

        private void lightOn_Click(object sender, EventArgs e)  // Send light on commend to arduino. Char "b".
        {
            if (!serialPort1.IsOpen) return;
            buff[0] = 'b';
            call = 'b';
            serialPort1.Write(buff, 0, 1);
            state = true;
        }

        private void lightOff_Click(object sender, EventArgs e) // Send light off commend to arduino. Char "c".
        {
            if (!serialPort1.IsOpen) return;
            buff[0] = 'c';
            call = 'c';
            serialPort1.Write(buff, 0, 1);
            state = false;
        }

        private void settingsBUT_Click(object sender, EventArgs e) // Let's enter new settings.
        {
            ReadMyData();                   // Get the data from the "settings" table.
            stateTextBox.Visible = false;
            lightOn.Visible = false;
            lightOff.Visible = false;
            label3.Visible = true;
            label4.Visible = true;
            label5.Visible = true;
            label6.Visible = true;
            lonhBOX.Visible = true;
            lonmBOX.Visible = true;
            loffhBOX.Visible = true;
            loffmBOX.Visible = true;
            saveBUT.Visible = true;
            CancelBUT.Visible = true;
            lonhBOX.Text = Convert.ToString(lightOnH);
            lonmBOX.Text = Convert.ToString(lightOnM);
            loffhBOX.Text = Convert.ToString(lightOffH);
            loffmBOX.Text = Convert.ToString(lightOffM);
        }

        private void CancelBUT_Click(object sender, EventArgs e)    // Cancel. No change saved to table.
        {
            label3.Visible = false;
            label4.Visible = false;
            label5.Visible = false;
            label6.Visible = false;
            lonhBOX.Visible = false;
            lonmBOX.Visible = false;
            loffhBOX.Visible = false;
            loffmBOX.Visible = false;
            saveBUT.Visible = false;
            CancelBUT.Visible = false;
            stateTextBox.Visible = true;
            lightOn.Visible = true;
            lightOff.Visible = true;
        }

        private void saveBUT_Click(object sender, EventArgs e)  // Save settings changes to "settings" table.
        {
            lightOnH = Convert.ToInt16(lonhBOX.Text);       // Convert textbox strings to integers.
            lightOnM = Convert.ToInt16(lonmBOX.Text);
            lightOffH = Convert.ToInt16(loffhBOX.Text);
            lightOffM = Convert.ToInt16(loffmBOX.Text);  
            // Open Database connection.
            MySqlConnection MyCon = new MySqlConnection("SERVER=localhost;" + "DATABASE=garden2;" + "UID=root;" + "PASSWORD=password;");
            MyCon.Open();
            // Update table SQL string.
            MySqlCommand command = new MySqlCommand("update settings set LOnH=" + lightOnH + ", LOnM =" + lightOnM + ", LOffH=" + lightOffH + ", LOffM=" + lightOffM, MyCon);
            command.ExecuteNonQuery();
            // Close Database connection.
            MyCon.Close();
            // Fix the form.
            label3.Visible = false;
            label4.Visible = false;
            label5.Visible = false;
            label6.Visible = false;
            lonhBOX.Visible = false;
            lonmBOX.Visible = false;
            loffhBOX.Visible = false;
            loffmBOX.Visible = false;
            saveBUT.Visible = false;
            CancelBUT.Visible = false;
            stateTextBox.Visible = true;
            lightOn.Visible = true;
            lightOff.Visible = true;
        }
    }
}

// ---------------------------------------------------------------------------------------------------------------------------------

# HeidiSQL Dump
#
# --------------------------------------------------------
# Host:                         127.0.0.1
# Database:                     garden2
# Server version:               5.1.39-community
# Server OS:                    Win32
# Target compatibility:         ANSI SQL
# HeidiSQL version:             4.0
# Date/time:                    2009-11-14 15:57:31
# --------------------------------------------------------

/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ANSI,NO_BACKSLASH_ESCAPES';*/
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;*/


#
# Database structure for database 'garden2'
#

CREATE DATABASE /*!32312 IF NOT EXISTS*/ "garden2" /*!40100 DEFAULT CHARACTER SET utf8 */;

USE "garden2";


#
# Table structure for table 'readings'
#

CREATE TABLE /*!32312 IF NOT EXISTS*/ "readings" (
  "Id" bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  "dtime" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  "light" int(10) DEFAULT NULL,
  "temp1" double DEFAULT NULL,
  "temp2" double DEFAULT NULL,
  "temp3" double DEFAULT NULL,
  "m1" int(10) DEFAULT NULL,
  "m2" int(10) DEFAULT NULL,
  PRIMARY KEY ("Id"),
  UNIQUE KEY "Id" ("Id"),
  KEY "Id_2" ("Id")
);



#
# Table structure for table 'settings'
#

CREATE TABLE /*!32312 IF NOT EXISTS*/ "settings" (
  "LOnH" tinyint(2) unsigned NOT NULL,
  "LOnM" tinyint(2) unsigned NOT NULL,
  "LOffH" tinyint(2) unsigned NOT NULL,
  "LOffM" tinyint(2) unsigned NOT NULL
);

/*!40101 SET SQL_MODE=@OLD_SQL_MODE;*/
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;*/

Step 9: Conclusion

The project will probably always be considered 'in process' because the possibilities for further development are endless. I hope you enjoyed this instructable, I certainly enjoyed creating it! Please vote for me on the Arduino contest!

Arduino Contest

Runner Up in the
Arduino Contest