Difference between revisions of "X10 / Arduino"
Eagle00789 (talk | contribs) |
m (project stalled (probably)) |
||
(17 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
{{Project | {{Project | ||
− | |State= | + | |Featured=No |
− | |Members= | + | |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. | ||
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 | 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 == | == Hardware == | ||
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]]) |
− | *LCD Shield van SparkFun ([[http://www.sparkfun.com/products/9363 | + | *Arduino Mega Proto Shield ([[http://www.iprototype.nl/products/arduino/shields/megaproto]]) |
− | *Ethernet Shield | + | *LCD Shield van SparkFun ([[http://www.sparkfun.com/products/9363]]) |
− | *XM10 TTL/CMOS interface ([[http://www.elekhomica.nl/product_info.php?products_id=31| | + | *Ethernet Shield van sparkfun ([[http://www.sparkfun.com/products/9026]]) |
+ | *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]]) | ||
+ | |||
+ | == 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. | ||
+ | <gallery> | ||
+ | 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|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-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. | ||
+ | File:X10-4.jpg | ||
+ | File:X10-2.jpg|Hierboven zie je een lampmodule van mijn X10 systeem. Deze lampmodule is dimbaar :) | ||
+ | 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-7.jpg | ||
+ | </gallery> | ||
+ | |||
+ | == BRONCODE == | ||
+ | Hieronder de volledige broncode van de X10 controller in zijn huidige staat: | ||
+ | <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 | |
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); } }