Difference between revisions of "X10 / Arduino"

From Hackerspace ACKspace
Jump to: navigation, search
(Hardware)
m (project stalled (probably))
 
(11 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
{{Project
 
{{Project
|State=Active
+
|Featured=No
|Members=eagle00789
+
|State=Stalled
 +
|Members=Eagle00789
 
|Description=Let Arduino control my X10 Controllers
 
|Description=Let Arduino control my X10 Controllers
 +
|Picture=X10-1.jpg
 
}}
 
}}
 
Make Arduino control any X10 appliance in a single home.
 
Make Arduino control any X10 appliance in a single home.
Line 10: Line 12:
 
De benodigde hardware hiervoor is inmiddels binnen.
 
De benodigde hardware hiervoor is inmiddels binnen.
 
De hardware bestaat uit:
 
De hardware bestaat uit:
*Arduino Mega 2560
+
*Arduino Mega 2560 ([[http://www.iprototype.nl/products/arduino/boards/mega2560]])
 +
*Arduino Mega Proto Shield ([[http://www.iprototype.nl/products/arduino/shields/megaproto]])
 
*LCD Shield van SparkFun ([[http://www.sparkfun.com/products/9363]])
 
*LCD Shield van SparkFun ([[http://www.sparkfun.com/products/9363]])
*Ethernet Shield
+
*Ethernet Shield van sparkfun ([[http://www.sparkfun.com/products/9026]])
 
*XM10 TTL/CMOS interface ([[http://www.elekhomica.nl/product_info.php?products_id=31]])
 
*XM10 TTL/CMOS interface ([[http://www.elekhomica.nl/product_info.php?products_id=31]])
 +
*RF Receiver - 434MHz ([http://www.iprototype.nl/products/arduino/modules-adapters/rf-receiver-434mhz])
 
*DS1307 RTC van Sparkfun ([[http://www.sparkfun.com/products/99]])
 
*DS1307 RTC van Sparkfun ([[http://www.sparkfun.com/products/99]])
  
 
== Huidige status ==
 
== Huidige status ==
Het ethernetshield werkt zonder problemen. Het lcd shield heeft echter problemen met de library. Hierdoor ben ik nu al veel tijd kwijt met het omprogrammeren van deze library
+
Het ethernetshield werkt zonder problemen. Het lcd shield heeft echter problemen met de library. Hierdoor ben ik nu al veel tijd kwijt met het omprogrammeren van deze library.
 +
Deze library werkt inmiddels zonder problemen verder.
 +
De DS1307 werkt naar behoren.
 +
Het Ethernet shield wordt nu alleen gebruikt als NTP client.
 +
Op het LCD shield is inmiddels een compleet werkend menu te vinden.
 +
De X10 interface werkt inmiddels ook zonder problemen.
 +
 
 +
== Toekomstige acties ==
 +
De NTP gegevens worden straks alleen gebruikt om de RTC te updaten.
 +
Mogelijkheid tot het presenteren van een webpagina waarop de X10 modules kunnen worden afgelezen en bestuurd.
 +
De RF receiver moet nog getuned worden en aangesloten worden. Ook moeten de ontvangen signalen nog worden omgezet naar X10.
  
 
== Foto's ==
 
== Foto's ==
 
Hieronder een paar foto's van de apparatuur die tot nu toe gebruikt wordt voor dit project.
 
Hieronder een paar foto's van de apparatuur die tot nu toe gebruikt wordt voor dit project.
[[File:X10-1.jpg|250px|thumb|center]]
+
<gallery>
Van onder naar boven zie je hier de Arduino Mega 2560, Arduino Mega Proto Shield, Ethernet Shield, LCD Shield. Op de Proto Shield zie je een RJ12 contra stekker voor de verbinding naar de TTL/CMOS controller
+
File:X10-1.jpg|Van onder naar boven zie je hier de Arduino Mega 2560, Arduino Mega Proto Shield, Ethernet Shield, LCD Shield. Op de Proto Shield zie je een RJ12 contra stekker voor de verbinding naar de TTL/CMOS controller
[[File:X10.jpg|250px|thumb|center]]
+
File:X10.jpg|Een andere hoek van dezelfde toren.
Een andere hoek van dezelfde toren.
+
File:X10-5.jpg|Het werkende menu met de tijd er op die wordt opgehaald middels NTP
[[File:X10-5.jpg|250px|thumb|center]]
+
File:X10-3.jpg|Boven en onder zie je de voor en achterkant van een KAKU (Klik Aan Klik Uit) wand module die ik nog had liggen en ook in dit systeem wil gaan gebruiken.
Het werkende menu met de tijd er op die wordt opgehaald middels NTP
+
File:X10-4.jpg
[[File:X10-3.jpg|250px|thumb|center]]
+
File:X10-2.jpg|Hierboven zie je een lampmodule van mijn X10 systeem. Deze lampmodule is dimbaar :)
Boven en onder zie je de voor en achterkant van een KAKU (Klik Aan Klik Uit) wand module die ik nog had liggen en ook in dit systeem wil gaan gebruiken.
+
File:X10-6.jpg|Boven en onder zie je de TTL/CMOS module van mijn X10 systeem. Deze module zorgt er voor dat de signalen die de Arduino verstuurt aan de TTL/CMOS module, worden vertaald naar X10
[[File:X10-4.jpg|250px|thumb|center]]
+
File:X10-7.jpg
[[File:X10-2.jpg|250px|thumb|center]]
+
</gallery>
Hierboven zie je een lampmodule van mijn X10 systeem. Deze lampmodule is dimbaar :)
+
 
[[File:X10-6.jpg|250px|thumb|center]]
+
== BRONCODE ==
Boven en onder zie je de TTL/CMOS module van mijn X10 systeem. Deze module zorgt er voor dat de signalen die de Arduino verstuurt aan de TTL/CMOS module, worden vertaald naar X10
+
Hieronder de volledige broncode van de X10 controller in zijn huidige staat:
[[File:X10-7.jpg|250px|thumb|center]]
+
<pre>#include <Time.h>
 +
#include <x10.h>
 +
#include <x10constants.h>
 +
#include "LCD_driver.h"
 +
#include <string.h>
 +
#include <stdlib.h>
 +
#include <stdio.h>
 +
#include <SPI.h>       
 +
#include <Ethernet.h>
 +
#include <Udp.h>
 +
#include <WProgram.h>
 +
#include <Wire.h>
 +
#include <DS1307.h>
 +
 
 +
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
 +
//byte ip[] = { 192,168,0,177 }; //thuis
 +
//byte gw[] = { 192,168,0,1}; //thuis
 +
byte ip[] = { 10,0,30,177 }; //ACKspace
 +
byte gw[] = { 10,0,30,254}; //ACKspace
 +
byte netmask[] = { 255,255,255,0 };
 +
 
 +
byte timeServer[] = {
 +
  85, 12, 35, 12}; // nl.pool.ntp.org NTP server
 +
 
 +
unsigned int localPort = 8888;      // local port to listen for UDP packets
 +
 
 +
const int NTP_PACKET_SIZE= 48;
 +
 
 +
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
 +
 
 +
char *strHour;
 +
char *strMin;
 +
char *strSec;
 +
 
 +
#define MENUITEMS 5
 +
#define MAXSUBMENUITEMS 8
 +
 
 +
int activeMenu;
 +
int activeSubMenu;
 +
int activeMenuType;
 +
char *menu[MENUITEMS][MAXSUBMENUITEMS];
 +
 
 +
#define zcPin 24
 +
#define rxPin 25
 +
#define txPin 28
 +
#define HOUSE HOUSE_D
 +
#define BRIGHTLEVEL0  0
 +
#define BRIGHTLEVEL25  3
 +
#define BRIGHTLEVEL50  6
 +
#define BRIGHTLEVEL75  8
 +
#define BRIGHTLEVEL100 11
 +
 
 +
x10 myHouse =  x10(zcPin, txPin, rxPin);
 +
 
 +
void setup()
 +
{
 +
  //Serial.begin(9600);
 +
  activeMenu = 0;
 +
  activeSubMenu = 1;
 +
  activeMenuType = 0;
 +
  LCDInit();     //Initialize the LCD
 +
  LCDContrast(44);
 +
  menu[0][0] = "Enable module";
 +
  menu[0][1] = "TV Light";
 +
  menu[0][2] = "Wall Light";
 +
  menu[0][3] = "Standing Light";
 +
  menu[0][4] = "Cabinet Light";
 +
  menu[0][5] = "Bedroom Light";
 +
  menu[0][6] = "Stable Light";
 +
  menu[0][7] = "<< Back >>";
 +
  menu[1][0] = "Disable module";
 +
  menu[1][1] = "TV Light";
 +
  menu[1][2] = "Wall Light";
 +
  menu[1][3] = "Standing Light";
 +
  menu[1][4] = "Cabinet Light";
 +
  menu[1][5] = "Bedroom Light";
 +
  menu[1][6] = "Stable Light";
 +
  menu[1][7] = "<< Back >>";
 +
  menu[2][0] = "Control shutters";
 +
  menu[2][1] = "Block sun";
 +
  menu[2][2] = "100%";
 +
  menu[2][3] = " 75%";
 +
  menu[2][4] = " 50%";
 +
  menu[2][5] = " 25%";
 +
  menu[2][6] = "  0%";
 +
  menu[2][7] = "<<  Back >>";
 +
  menu[3][0] = "All modules on";
 +
  menu[4][0] = "All modules off";
 +
  PrintMenu(0);
 +
  Ethernet.begin(mac,ip,gw,netmask);
 +
  Udp.begin(localPort);
 +
  setSyncProvider(UpdateTime);
 +
//  RTC.stop();
 +
//  RTC.set(DS1307_SEC,30);        //set the seconds
 +
//  RTC.set(DS1307_MIN,6);    //set the minutes
 +
//  RTC.set(DS1307_HR,16);      //set the hours
 +
//  RTC.set(DS1307_DOW,3);      //set the day of the week
 +
//  RTC.set(DS1307_DATE,5);      //set the date
 +
//  RTC.set(DS1307_MTH,10);        //set the month
 +
//  RTC.set(DS1307_YR,11);        //set the year
 +
//  RTC.start();
 +
}
 +
 
 +
void loop()
 +
{
 +
  char CurrentTime[8];
 +
  sprintf(CurrentTime, "%02d:%02d:%02d",RTC.get(DS1307_HR,true),RTC.get(DS1307_MIN,false),RTC.get(DS1307_SEC,false));
 +
  LCDPutStr(CurrentTime, 0, 63, GREEN, WHITE);
 +
  MenuButtons();
 +
  if(timeStatus() == timeSet)
 +
  {
 +
    UpdateTimeDisplay();
 +
  }
 +
}
 +
 
 +
void UpdateTimeDisplay()
 +
{
 +
  char CurrentTime[8];
 +
  int DSTAdjust;
 +
  if (month() < 3 || month() > 11)
 +
  {
 +
    DSTAdjust = 0;
 +
  }
 +
  if (month() > 3 && month() < 11)
 +
  {
 +
    DSTAdjust = 1;
 +
    int previousSunday = day() - weekday();
 +
    if (month() == 3 && previousSunday >= 8)
 +
    {
 +
      DSTAdjust = 1;
 +
    }
 +
    if (month() == 10 && previousSunday <= 0)
 +
    {
 +
      DSTAdjust = 0;
 +
    }
 +
  }
 +
  sprintf(CurrentTime, "%02d:%02d:%02d",hour()+DSTAdjust+1,minute(),second());
 +
  if (activeMenuType == 0)
 +
  {
 +
    LCDPutStr(CurrentTime, 0, 63, GREEN, WHITE);
 +
  }
 +
}
 +
 
 +
unsigned long UpdateTime()
 +
{
 +
  sendNTPpacket(timeServer); // send an NTP packet to a time server
 +
  delay(1000);
 +
  if ( Udp.available() ) { 
 +
    Udp.readPacket(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer
 +
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
 +
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); 
 +
    unsigned long secsSince1900 = highWord << 16 | lowWord; 
 +
    const unsigned long seventyYears = 2208988800UL;   
 +
    unsigned long epoch = secsSince1900 - seventyYears; 
 +
    return epoch;
 +
  }
 +
  return 0;
 +
}
 +
 
 +
unsigned long sendNTPpacket(byte *address)
 +
{
 +
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
 +
  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
 +
  packetBuffer[12]  = 49;
 +
  packetBuffer[13]  = 0x4E;
 +
  packetBuffer[14]  = 49;
 +
  packetBuffer[15]  = 52;
 +
  Udp.sendPacket( packetBuffer,NTP_PACKET_SIZE,  address, 123); //NTP requests are to port 123
 +
}
 +
 
 +
void  MenuButtons()
 +
{
 +
  int s1, s2, s3;
 +
  s1 = !digitalRead(kSwitch1_PIN);
 +
  s2 = !digitalRead(kSwitch2_PIN);
 +
  s3 = !digitalRead(kSwitch3_PIN);
 +
 
 +
  if (s1)
 +
  {
 +
    ButtonDown();
 +
  }
 +
  else if (s2)
 +
  {
 +
    ButtonSelect();
 +
  }
 +
  else if (s3)
 +
  {
 +
    ButtonUp();
 +
  }
 +
  s1 = 0;
 +
  s2 = 0;
 +
  s3 = 0;
 +
  delay(150);
 +
}
 +
 
 +
void  ButtonUp()
 +
{
 +
  if (activeMenuType == 0)
 +
  {
 +
    int tmpMenuPos = (activeMenu * 16) + 16;
 +
    PrintMenuItem(menu[activeMenu][0], 0, tmpMenuPos);
 +
    activeMenu--;
 +
    if (activeMenu < 0)
 +
    {
 +
      activeMenu = MENUITEMS - 1;
 +
    }
 +
    tmpMenuPos = (activeMenu * 16) + 16;
 +
    PrintMenuItem(menu[activeMenu][0], 1, tmpMenuPos);
 +
  }
 +
  else
 +
  {
 +
    int tmpMenuPos = ((activeSubMenu - 1) * 16) + 16;
 +
    PrintMenuItem(menu[activeMenu][activeSubMenu], 0, tmpMenuPos);
 +
    activeSubMenu--;
 +
    if (activeSubMenu < 1)
 +
    {
 +
      activeSubMenu = MAXSUBMENUITEMS - 1;
 +
    }
 +
    tmpMenuPos = ((activeSubMenu - 1) * 16) + 16;
 +
    PrintMenuItem(menu[activeMenu][activeSubMenu], 1, tmpMenuPos);
 +
  }
 +
}
 +
 
 +
void  ButtonSelect()
 +
{
 +
  switch (activeMenu)
 +
  {
 +
    case 0:
 +
      if (activeMenuType == 0)
 +
      {
 +
        activeMenuType = 1;
 +
        PrintSubMenu(activeMenu);
 +
        break;
 +
      }
 +
      else
 +
      {
 +
        switch (activeSubMenu)
 +
        {
 +
          case 1:
 +
            TurnLightOn(UNIT_9);
 +
            break;
 +
          case 2:
 +
            TurnLightOn(UNIT_10);
 +
            break;
 +
          case 3:
 +
            TurnLightOn(UNIT_11);
 +
            break;
 +
          case 4:
 +
            TurnLightOn(UNIT_12);
 +
            break;
 +
          case 5:
 +
            TurnLightOn(UNIT_13);
 +
            break;
 +
          case 6:
 +
            TurnLightOn(UNIT_5);
 +
            break;
 +
          case 7:
 +
            activeMenuType = 0;
 +
            PrintMenu(0);
 +
            break;
 +
        }
 +
      }
 +
      break;
 +
    case 1:
 +
      if (activeMenuType == 0)
 +
      {
 +
        activeMenuType = 1;
 +
        PrintSubMenu(activeMenu);
 +
        break;
 +
      }
 +
      else
 +
      {
 +
        switch (activeSubMenu)
 +
        {
 +
          case 1:
 +
            TurnLightOff(UNIT_9);
 +
            break;
 +
          case 2:
 +
            TurnLightOff(UNIT_10);
 +
            break;
 +
          case 3:
 +
            TurnLightOff(UNIT_11);
 +
            break;
 +
          case 4:
 +
            TurnLightOff(UNIT_12);
 +
            break;
 +
          case 5:
 +
            TurnLightOff(UNIT_13);
 +
            break;
 +
          case 6:
 +
            TurnLightOff(UNIT_5);
 +
            break;
 +
          case 7:
 +
            activeMenuType = 0;
 +
            PrintMenu(1);
 +
            break;
 +
        }
 +
      }
 +
      break;
 +
    case 2:
 +
      if (activeMenuType == 0)
 +
      {
 +
        activeMenuType = 1;
 +
        PrintSubMenu(activeMenu);
 +
        break;
 +
      }
 +
      else
 +
      {
 +
        switch (activeSubMenu)
 +
        {
 +
          case 1:
 +
            SetLightLevel(UNIT_14, BRIGHTLEVEL25);
 +
            break;
 +
          case 2:
 +
            SetLightLevel(UNIT_14, BRIGHTLEVEL100);
 +
            break;
 +
          case 3:
 +
            SetLightLevel(UNIT_14, BRIGHTLEVEL75);
 +
            break;
 +
          case 4:
 +
            SetLightLevel(UNIT_14, BRIGHTLEVEL50);
 +
            break;
 +
          case 5:
 +
            SetLightLevel(UNIT_14, BRIGHTLEVEL25);
 +
            break;
 +
          case 6:
 +
            //SetLightLevel(UNIT_14, BRIGHTLEVEL0);
 +
            TurnLightOff(UNIT_14);
 +
            break;
 +
          case 7:
 +
            activeMenuType = 0;
 +
            PrintMenu(2);
 +
            break;
 +
        }
 +
      }
 +
      break;
 +
    case 3:
 +
      TurnLightOn(UNIT_9);
 +
      TurnLightOn(UNIT_10);
 +
      TurnLightOn(UNIT_11);
 +
      TurnLightOn(UNIT_12);
 +
      break;
 +
    case 4:
 +
      TurnLightOff(UNIT_9);
 +
      TurnLightOff(UNIT_10);
 +
      TurnLightOff(UNIT_11);
 +
      delay(150000);
 +
      TurnLightOff(UNIT_12);
 +
      break;
 +
  }
 +
}
 +
 
 +
void  ButtonDown()
 +
{
 +
  if (activeMenuType == 0)
 +
  {
 +
    int tmpMenuPos = (activeMenu * 16) + 16;
 +
    PrintMenuItem(menu[activeMenu][0], 0, tmpMenuPos);
 +
    activeMenu++;
 +
    if (activeMenu >= MENUITEMS)
 +
    {
 +
      activeMenu = 0;
 +
    }
 +
    tmpMenuPos = (activeMenu * 16) + 16;
 +
    PrintMenuItem(menu[activeMenu][0], 1, tmpMenuPos);
 +
  }
 +
  else
 +
  {
 +
    int tmpMenuPos = ((activeSubMenu - 1) * 16) + 16;
 +
    PrintMenuItem(menu[activeMenu][activeSubMenu], 0, tmpMenuPos);
 +
    activeSubMenu++;
 +
    if (activeSubMenu >= MAXSUBMENUITEMS)
 +
    {
 +
      activeSubMenu = 1;
 +
    }
 +
    tmpMenuPos = ((activeSubMenu - 1) * 16) + 16;
 +
    PrintMenuItem(menu[activeMenu][activeSubMenu], 1, tmpMenuPos);
 +
  }
 +
}
 +
 
 +
void  TurnLightOn(int Unit)
 +
{
 +
  myHouse.write(HOUSE, Unit, 1);
 +
  myHouse.write(HOUSE, ON, 1);
 +
}
 +
 
 +
void  TurnLightOff(int Unit)
 +
{
 +
  myHouse.write(HOUSE, Unit, 1);
 +
  myHouse.write(HOUSE, OFF, 1);
 +
}
 +
 
 +
void  SwitchLight(int Unit)
 +
{
 +
  //
 +
}
 +
 
 +
void  SetLightLevel(int Unit, int Level)
 +
{
 +
  myHouse.write(HOUSE, Unit, 1);
 +
  myHouse.write(HOUSE, BRIGHT, 1);
 +
}
 +
 
 +
void  PrintMenu(int ActiveMainMenu)
 +
{
 +
  LCDClear(WHITE);
 +
  PrintMenuTitle("MENU");
 +
  int row, col, line;
 +
  line = 16;
 +
  for (row = 0; row < MENUITEMS; row++)
 +
  {
 +
    if (row == ActiveMainMenu)
 +
    {
 +
      PrintMenuItem(menu[row][0], 1, line);
 +
    }
 +
    else
 +
    {
 +
      PrintMenuItem(menu[row][0], 0, line);
 +
    }
 +
    line += 16;
 +
  }
 +
}
 +
 
 +
void  PrintSubMenu(int ActiveMainMenu)
 +
{
 +
  activeSubMenu = 1;
 +
  LCDClear(WHITE);
 +
  PrintMenuTitle(menu[ActiveMainMenu][0]);
 +
  int row, col, line;
 +
  line = 16;
 +
  for (row = 1; row < MAXSUBMENUITEMS; row++)
 +
  {
 +
    if (row == 1)
 +
    {
 +
      PrintMenuItem(menu[ActiveMainMenu][row], 1, line);
 +
    }
 +
    else
 +
    {
 +
      PrintMenuItem(menu[ActiveMainMenu][row], 0, line);
 +
    }
 +
    line += 16;
 +
  }
 +
}
 +
 
 +
void  PrintMenuTitle(char *menuString)
 +
{
 +
  LCDPutStr(menuString, 0, 0, RED, WHITE);
 +
}
 +
 
 +
void  PrintMenuItem(char *menuString, int Active, int x)
 +
{
 +
  if (Active == 1)
 +
  {
 +
    LCDPutStr(menuString, x, 1, BLUE, WHITE);
 +
  }
 +
  else
 +
  {
 +
    LCDPutStr(menuString, x, 1, BLACK, WHITE);
 +
  }
 +
}
 +
</pre>
 +
[[Category:Arduino]]

Latest revision as of 14:24, 23 May 2017

Project: X10 / Arduino
Featured: No
State Stalled
Members Eagle00789
GitHub No GitHub project defined. Add your project here.
Description Let Arduino control my X10 Controllers
Picture
X10-1.jpg

Make Arduino control any X10 appliance in a single home. It would be the most fun to make the arduino available via a web-interface and control the X10 appliances via the webinterface using the arduino

Hardware

De benodigde hardware hiervoor is inmiddels binnen. De hardware bestaat uit:

  • Arduino Mega 2560 ([[1]])
  • Arduino Mega Proto Shield ([[2]])
  • LCD Shield van SparkFun ([[3]])
  • Ethernet Shield van sparkfun ([[4]])
  • XM10 TTL/CMOS interface ([[5]])
  • RF Receiver - 434MHz ([6])
  • DS1307 RTC van Sparkfun ([[7]])

Huidige status

Het ethernetshield werkt zonder problemen. Het lcd shield heeft echter problemen met de library. Hierdoor ben ik nu al veel tijd kwijt met het omprogrammeren van deze library. Deze library werkt inmiddels zonder problemen verder. De DS1307 werkt naar behoren. Het Ethernet shield wordt nu alleen gebruikt als NTP client. Op het LCD shield is inmiddels een compleet werkend menu te vinden. De X10 interface werkt inmiddels ook zonder problemen.

Toekomstige acties

De NTP gegevens worden straks alleen gebruikt om de RTC te updaten. Mogelijkheid tot het presenteren van een webpagina waarop de X10 modules kunnen worden afgelezen en bestuurd. De RF receiver moet nog getuned worden en aangesloten worden. Ook moeten de ontvangen signalen nog worden omgezet naar X10.

Foto's

Hieronder een paar foto's van de apparatuur die tot nu toe gebruikt wordt voor dit project.

BRONCODE

Hieronder de volledige broncode van de X10 controller in zijn huidige staat:

#include <Time.h>
#include <x10.h>
#include <x10constants.h>
#include "LCD_driver.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <SPI.h>         
#include <Ethernet.h>
#include <Udp.h>
#include <WProgram.h>
#include <Wire.h>
#include <DS1307.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
//byte ip[] = { 192,168,0,177 }; //thuis
//byte gw[] = { 192,168,0,1}; //thuis
byte ip[] = { 10,0,30,177 }; //ACKspace
byte gw[] = { 10,0,30,254}; //ACKspace
byte netmask[] = { 255,255,255,0 };

byte timeServer[] = { 
  85, 12, 35, 12}; // nl.pool.ntp.org NTP server

unsigned int localPort = 8888;      // local port to listen for UDP packets

const int NTP_PACKET_SIZE= 48;

byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 

char *strHour;
char *strMin;
char *strSec;

#define MENUITEMS 5
#define MAXSUBMENUITEMS 8

int activeMenu;
int activeSubMenu;
int activeMenuType;
char *menu[MENUITEMS][MAXSUBMENUITEMS];

#define zcPin 24
#define rxPin 25
#define txPin 28
#define HOUSE HOUSE_D
#define BRIGHTLEVEL0   0
#define BRIGHTLEVEL25  3
#define BRIGHTLEVEL50  6
#define BRIGHTLEVEL75  8
#define BRIGHTLEVEL100 11

x10 myHouse =  x10(zcPin, txPin, rxPin);

void	setup()
{
  //Serial.begin(9600);
  activeMenu = 0;
  activeSubMenu = 1;
  activeMenuType = 0;
  LCDInit();	    //Initialize the LCD
  LCDContrast(44);
  menu[0][0] = "Enable module";
  menu[0][1] = "TV Light";
  menu[0][2] = "Wall Light";
  menu[0][3] = "Standing Light";
  menu[0][4] = "Cabinet Light";
  menu[0][5] = "Bedroom Light";
  menu[0][6] = "Stable Light";
  menu[0][7] = "<< Back >>";
  menu[1][0] = "Disable module";
  menu[1][1] = "TV Light";
  menu[1][2] = "Wall Light";
  menu[1][3] = "Standing Light";
  menu[1][4] = "Cabinet Light";
  menu[1][5] = "Bedroom Light";
  menu[1][6] = "Stable Light";
  menu[1][7] = "<< Back >>";
  menu[2][0] = "Control shutters";
  menu[2][1] = "Block sun";
  menu[2][2] = "100%";
  menu[2][3] = " 75%";
  menu[2][4] = " 50%";
  menu[2][5] = " 25%";
  menu[2][6] = "  0%";
  menu[2][7] = "<<  Back >>";
  menu[3][0] = "All modules on";
  menu[4][0] = "All modules off";
  PrintMenu(0);
  Ethernet.begin(mac,ip,gw,netmask);
  Udp.begin(localPort);
  setSyncProvider(UpdateTime);
//  RTC.stop();
//  RTC.set(DS1307_SEC,30);        //set the seconds
//  RTC.set(DS1307_MIN,6);     //set the minutes
//  RTC.set(DS1307_HR,16);       //set the hours
//  RTC.set(DS1307_DOW,3);       //set the day of the week
//  RTC.set(DS1307_DATE,5);       //set the date
//  RTC.set(DS1307_MTH,10);        //set the month
//  RTC.set(DS1307_YR,11);         //set the year
//  RTC.start();
}

void	loop()
{
  char CurrentTime[8];
  sprintf(CurrentTime, "%02d:%02d:%02d",RTC.get(DS1307_HR,true),RTC.get(DS1307_MIN,false),RTC.get(DS1307_SEC,false));
  LCDPutStr(CurrentTime, 0, 63, GREEN, WHITE);
  MenuButtons();
  if(timeStatus() == timeSet)
  {
    UpdateTimeDisplay();
  }
}

void UpdateTimeDisplay()
{
  char CurrentTime[8];
  int DSTAdjust;
  if (month() < 3 || month() > 11)
  {
    DSTAdjust = 0;
  }
  if (month() > 3 && month() < 11)
  {
    DSTAdjust = 1;
    int previousSunday = day() - weekday();
    if (month() == 3 && previousSunday >= 8)
    {
      DSTAdjust = 1;
    }
    if (month() == 10 && previousSunday <= 0)
    {
      DSTAdjust = 0;
    }
  }
  sprintf(CurrentTime, "%02d:%02d:%02d",hour()+DSTAdjust+1,minute(),second());
  if (activeMenuType == 0)
  {
    LCDPutStr(CurrentTime, 0, 63, GREEN, WHITE);
  }
}

unsigned long UpdateTime()
{
  sendNTPpacket(timeServer); // send an NTP packet to a time server
  delay(1000);
  if ( Udp.available() ) {  
    Udp.readPacket(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
    unsigned long secsSince1900 = highWord << 16 | lowWord;  
    const unsigned long seventyYears = 2208988800UL;     
    unsigned long epoch = secsSince1900 - seventyYears;  
    return epoch;
  }
  return 0;
}

unsigned long sendNTPpacket(byte *address)
{
  memset(packetBuffer, 0, NTP_PACKET_SIZE); 
  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
  packetBuffer[12]  = 49; 
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  Udp.sendPacket( packetBuffer,NTP_PACKET_SIZE,  address, 123); //NTP requests are to port 123
}

void   MenuButtons()
{
  int	s1, s2, s3;
  s1	=	!digitalRead(kSwitch1_PIN);
  s2	=	!digitalRead(kSwitch2_PIN);
  s3	=	!digitalRead(kSwitch3_PIN);

  if (s1)
  {
    ButtonDown();
  }
  else if (s2)
  {
    ButtonSelect();
  }
  else if (s3)
  {
    ButtonUp();
  }
  s1 = 0;
  s2 = 0;
  s3 = 0;
  delay(150);
}

void   ButtonUp()
{
  if (activeMenuType == 0)
  {
    int tmpMenuPos = (activeMenu * 16) + 16;
    PrintMenuItem(menu[activeMenu][0], 0, tmpMenuPos);
    activeMenu--;
    if (activeMenu < 0)
    {
      activeMenu = MENUITEMS - 1;
    }
    tmpMenuPos = (activeMenu * 16) + 16;
    PrintMenuItem(menu[activeMenu][0], 1, tmpMenuPos);
  }
  else
  {
    int tmpMenuPos = ((activeSubMenu - 1) * 16) + 16;
    PrintMenuItem(menu[activeMenu][activeSubMenu], 0, tmpMenuPos);
    activeSubMenu--;
    if (activeSubMenu < 1)
    {
      activeSubMenu = MAXSUBMENUITEMS - 1;
    }
    tmpMenuPos = ((activeSubMenu - 1) * 16) + 16;
    PrintMenuItem(menu[activeMenu][activeSubMenu], 1, tmpMenuPos);
  }
}

void   ButtonSelect()
{
  switch (activeMenu)
  {
    case 0:
      if (activeMenuType == 0)
      {
        activeMenuType = 1;
        PrintSubMenu(activeMenu);
        break;
      }
      else
      {
        switch (activeSubMenu)
        {
          case 1:
            TurnLightOn(UNIT_9);
            break;
          case 2:
            TurnLightOn(UNIT_10);
            break;
          case 3:
            TurnLightOn(UNIT_11);
            break;
          case 4:
            TurnLightOn(UNIT_12);
            break;
          case 5:
            TurnLightOn(UNIT_13);
            break;
          case 6:
            TurnLightOn(UNIT_5);
            break;
          case 7:
            activeMenuType = 0;
            PrintMenu(0);
            break;
        }
      }
      break;
    case 1:
      if (activeMenuType == 0)
      {
        activeMenuType = 1;
        PrintSubMenu(activeMenu);
        break;
      }
      else
      {
        switch (activeSubMenu)
        {
          case 1:
            TurnLightOff(UNIT_9);
            break;
          case 2:
            TurnLightOff(UNIT_10);
            break;
          case 3:
            TurnLightOff(UNIT_11);
            break;
          case 4:
            TurnLightOff(UNIT_12);
            break;
          case 5:
            TurnLightOff(UNIT_13);
            break;
          case 6:
            TurnLightOff(UNIT_5);
            break;
          case 7:
            activeMenuType = 0;
            PrintMenu(1);
            break;
        }
      }
      break;
    case 2:
      if (activeMenuType == 0)
      {
        activeMenuType = 1;
        PrintSubMenu(activeMenu);
        break;
      }
      else
      {
        switch (activeSubMenu)
        {
          case 1:
            SetLightLevel(UNIT_14, BRIGHTLEVEL25);
            break;
          case 2:
            SetLightLevel(UNIT_14, BRIGHTLEVEL100);
            break;
          case 3:
            SetLightLevel(UNIT_14, BRIGHTLEVEL75);
            break;
          case 4:
            SetLightLevel(UNIT_14, BRIGHTLEVEL50);
            break;
          case 5:
            SetLightLevel(UNIT_14, BRIGHTLEVEL25);
            break;
          case 6:
            //SetLightLevel(UNIT_14, BRIGHTLEVEL0);
            TurnLightOff(UNIT_14);
            break;
          case 7:
            activeMenuType = 0;
            PrintMenu(2);
            break;
        }
      }
      break;
    case 3:
      TurnLightOn(UNIT_9);
      TurnLightOn(UNIT_10);
      TurnLightOn(UNIT_11);
      TurnLightOn(UNIT_12);
      break;
    case 4:
      TurnLightOff(UNIT_9);
      TurnLightOff(UNIT_10);
      TurnLightOff(UNIT_11);
      delay(150000);
      TurnLightOff(UNIT_12);
      break;
  }
}

void   ButtonDown()
{
  if (activeMenuType == 0)
  {
    int tmpMenuPos = (activeMenu * 16) + 16;
    PrintMenuItem(menu[activeMenu][0], 0, tmpMenuPos);
    activeMenu++;
    if (activeMenu >= MENUITEMS)
    {
      activeMenu = 0;
    }
    tmpMenuPos = (activeMenu * 16) + 16;
    PrintMenuItem(menu[activeMenu][0], 1, tmpMenuPos);
  }
  else
  {
    int tmpMenuPos = ((activeSubMenu - 1) * 16) + 16;
    PrintMenuItem(menu[activeMenu][activeSubMenu], 0, tmpMenuPos);
    activeSubMenu++;
    if (activeSubMenu >= MAXSUBMENUITEMS)
    {
      activeSubMenu = 1;
    }
    tmpMenuPos = ((activeSubMenu - 1) * 16) + 16;
    PrintMenuItem(menu[activeMenu][activeSubMenu], 1, tmpMenuPos);
  }
}

void   TurnLightOn(int Unit)
{
  myHouse.write(HOUSE, Unit, 1);
  myHouse.write(HOUSE, ON, 1);
}

void   TurnLightOff(int Unit)
{
  myHouse.write(HOUSE, Unit, 1);
  myHouse.write(HOUSE, OFF, 1);
}

void   SwitchLight(int Unit)
{
  //
}

void   SetLightLevel(int Unit, int Level)
{
  myHouse.write(HOUSE, Unit, 1);
  myHouse.write(HOUSE, BRIGHT, 1);
}

void   PrintMenu(int ActiveMainMenu)
{
  LCDClear(WHITE);
  PrintMenuTitle("MENU");
  int row, col, line;
  line = 16;
  for (row = 0; row < MENUITEMS; row++)
  {
    if (row == ActiveMainMenu)
    {
      PrintMenuItem(menu[row][0], 1, line);
    }
    else
    {
      PrintMenuItem(menu[row][0], 0, line);
    }
    line += 16;
  }
}

void   PrintSubMenu(int ActiveMainMenu)
{
  activeSubMenu = 1;
  LCDClear(WHITE);
  PrintMenuTitle(menu[ActiveMainMenu][0]);
  int row, col, line;
  line = 16;
  for (row = 1; row < MAXSUBMENUITEMS; row++)
  {
    if (row == 1)
    {
      PrintMenuItem(menu[ActiveMainMenu][row], 1, line);
    }
    else
    {
      PrintMenuItem(menu[ActiveMainMenu][row], 0, line);
    }
    line += 16;
  }
}

void   PrintMenuTitle(char *menuString)
{
  LCDPutStr(menuString, 0, 0, RED, WHITE);
}

void  PrintMenuItem(char *menuString, int Active, int x)
{
  if (Active == 1)
  {
    LCDPutStr(menuString, x, 1, BLUE, WHITE);
  }
  else
  {
    LCDPutStr(menuString, x, 1, BLACK, WHITE);
  }
}