Final Project for 4180 Nixie Tube IoT Clock
Dependencies: 4DGL-uLCD-SE NixieTube MBed_Adafruit-GPS-Library NetServices wave_player mbed spxml
Final Project for ECE 4180
Diff: main.cpp
- Revision:
- 2:714d63ea1eef
- Parent:
- 1:a6fbd8341289
- Child:
- 3:d62bb9ee0aa0
--- a/main.cpp Sun Dec 11 17:19:29 2016 +0000 +++ b/main.cpp Wed Dec 14 03:55:23 2016 +0000 @@ -6,7 +6,6 @@ // Includes Files #include "mbed.h" -#include "rtos.h" #include <string> #include "uLCD_4DGL.h" #include "wave_player.h" @@ -14,33 +13,69 @@ #include "spdomparser.hpp" /// Parseing Weather #include "spxmlnode.hpp" /// Parseing Weather #include "spxmlhandle.hpp" /// Parseing Weather -#include <TimeUtilities.h> // Used for Clock - #include "EthernetNetIf.h" #include "HTTPClient.h" #include <string> +#include "NTPClient.h" +/////////////////////// +#define TUBE_1_LED 0x00800 +#define TUBE_2_LED 0x01000 +#define TUBE_3_LED 0x02000 +#define TUBE_4_LED 0x04000 +#define TUBE_5_LED 0x08000 +#define TUBE_6_LED 0x10000 + +#define TUBE_1_CATH 0x20000 +#define TUBE_2_CATH 0x40000 +#define TUBE_3_CATH 0x80000 +#define TUBE_4_CATH 0x100000 +#define TUBE_5_CATH 0x200000 +#define TUBE_6_CATH 0x400000 -#include "NixieTube.h" -NixieTube test(p23,p24,p25,p26); -/* -int main() { - test.start_nixie(); - test.update_nixie_tube(1,2); - test.set_dim(1.0,200); -} -*/ +void nixie_shiftout(); +int nixie_id_convert(int digit); +void send_nixie_shiftreg(int cathode_id, int led_bitfield, int tube_bitfield); + + +DigitalOut myled1(LED1); +DigitalOut myled2(LED2); + + +DigitalOut sdi(p24); +DigitalOut scl(p23); +DigitalOut rcl(p22); +PwmOut cen(p21); + +Ticker shifter; + +int curr_tube = 1; + +volatile int digit1 = 1; +volatile int digit2 = 2; +volatile int digit3 = 3; +volatile int digit4 = 4; + + +uint32_t delay1 = 0.0005; +uint32_t delay2 = 0.0045; + +float brightness = 0; - +///////////////////////// +Serial pc(USBTX, USBRX); EthernetNetIf eth; HTTPClient http; HTTPResult result; +NTPClient ntp; + + LocalFileSystem local("local"); // Create the local filesystem under the name "local" AnalogOut DACout(p18); // DAC for producing sound wave_player waver(&DACout); // wavplayer object Serial * gps_Serial; // GPS Interface -uLCD_4DGL uLCD(p9,p10,p11); // serial tx, serial rx, reset pin; +uLCD_4DGL uLCD(p13,p14,p15); // serial tx, serial rx, reset pin; //LCD Files Needs to be local to the ulcd screen @@ -55,29 +90,73 @@ // Confirm Bluetoth link? display bluetooth decal when connected? Or just Letter B in Blue just as good // Declarations - +bool completed = false; // Used for HTTP Request bool pressPlay = false;//default on pause (song select mode) int volume = 0; -/// Functions will follow here -void display_screen_debug() { +int weather(); +bool gps_setup(); +void display_screen_debug(),request_callback(),parseWeather(),system_setup(),display_weather(),sound_alarm(); + +int main() { + //sound_alarm(1); + //display_weather(0); + pc.baud(9600); + pc.printf("\r\nintializing hardware,...v14\r\n"); + eth.init(); //Use DHCP +sendGETRequest: + EthernetErr ethErr = eth.setup(60000); + int retry = 0; + if (ethErr) { + pc.printf("Error in setup trying again %d",retry); + retry++; + goto sendGETRequest; } + pc.printf("net ok testing weather\r\n"); + weather(); -void system_setup () { - - } -bool completed = false; + cen.period_us(10000); + cen.write(1.0); + shifter.attach(&nixie_shiftout, 0.001); + time_t ctTime; + ctTime = time(NULL); + + Host server(IpAddr(), 123, "0.us.pool.ntp.org"); + ntp.setTime(server); -void display_weather(int code){ - uLCD.flush_media(); - uLCD.cls(); - uLCD.media_init(); - //uLCD.printf("\n\nAn SD card is needed for image and video data"); - uLCD.set_sector_address(0x0000,(code*65)); - uLCD.display_image(0,0); - uLCD.cls(); - } + char hString[3]; + char mString[3]; + int offset = 5; + while(1) { + ctTime = time(NULL) - 3600 * offset; + strftime(hString, 3, "%I", localtime(&ctTime)); + strftime(mString, 3, "%M", localtime(&ctTime)); + + //pc.printf("hour: %s \n min: %s\n", hString, mString); + + int hour = std::atoi(hString); + int min = std::atoi(mString); + + int digit1 = hour / 10; + int digit2 = hour % 10; + + int digit3 = min / 10; + int digit4 = min % 10; + + pc. printf("\n %d, %d, %d, %d", digit1, digit2, digit3, digit4); + wait(5); + //ctTime = time(NULL); + //pc.printf("\nTime is now (UTC): %s\n", ctime(&ctTime)); + } + + return 0; + + + + //eth.disconnect(); + } + // Used for obtaining weather Information void request_callback(HTTPResult r) { result = r; @@ -90,220 +169,14 @@ SP_XmlHandle handle(node); SP_XmlElementNode * condition = handle.getChild( "item" ).getChild("yweather:condition").toElement(); //display Weather conditions - display_weather((int)condition->getAttrValue("code")); + pc.printf("%d:\r\n", (int)condition->getAttrValue("code")); // Print the name of the city - uLCD.locate(0,1); - uLCD.printf("%s:", loc); + pc.printf("%s:\r\n", loc); //Print the weather conditions - uLCD.locate(0,2); - uLCD.printf("%s",condition->getAttrValue("text")); - //Print the termperature (in degrees Celcius) - uLCD.locate(0,3); - uLCD.printf("%sF",condition->getAttrValue("temp")); -} -// Need To update so that this takes lat longitude gives it to a website to find local time and or time zone -void parseWhereAmI(SP_XmlElementNode *node, string loc) -{ - //extracts current weather XML data fields for LCD - SP_XmlHandle handle(node); - SP_XmlElementNode * condition = handle.getChild( "item" ).getChild("yweather:condition").toElement(); - //display Weather conditions - display_weather((int)condition->getAttrValue("code")); - // Print the name of the city - uLCD.locate(0,1); - uLCD.printf("%s:", loc); - //Print the weather conditions - uLCD.locate(0,2); - uLCD.printf("%s",condition->getAttrValue("text")); + pc.printf("%s\r\n",condition->getAttrValue("text")); //Print the termperature (in degrees Celcius) - uLCD.locate(0,3); - uLCD.printf("%sF",condition->getAttrValue("temp")); - -} - -// Query Term for Weather -// select+*+from+weather.forecast+where+woeid+in+(SELECT+woeid+FROM+geo.places+WHERE+text%3D%22(33.7490%2C-84.3880)%22) -// Query Website https://developer.yahoo.com/yql/console/#h=select+*+from+weather.forecast+where+woeid+in+(SELECT+woeid+FROM+geo.places+WHERE+text%3D%22(33.7490%2C-84.3880)%22) -//asuming that outputformat of lattitude and logitude is - for west + for east and does not use chars for directionals as that would be dumb -//"https://query.yahooapis.com/v1/public/yql?q=select+*+from+weather.forecast+where+woeid+in+(SELECT+woeid+FROM+geo.places+WHERE+text%3D%22(33.7490%2C-84.3880)%22)", &stream, request_callback); -// "https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20%28SELECT%20woeid%20FROM%20geo.places%20WHERE%20text%3D%22(33.7490%2C-84.3880)%22)"(lat log) &stream, request_callback) - -// Variable Version -// "https://query.yahooapis.com/v1/public/yql?q=select+*+from+weather.forecast+where+woeid+in+(SELECT+woeid+FROM+geo.places+WHERE+text%3D%22(lat%2Clong)%22)", &stream, request_callback); -// "https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20%28SELECT%20woeid%20FROM%20geo.places%20WHERE%20text%3D%22(%.6f%2C%.6f)%22)"(lat log) &stream, request_callback) - -int weather() -{ - completed = false; - SP_XmlDomParser parser; - HTTPStream stream; - char buffer [240]; - int n; - float lat = 33.7490; - float log = -84.3880; - n=sprintf(buffer, "https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20%28SELECT%20woeid%20FROM%20geo.places%20WHERE%20text%3D%22(%.6f%2C%.6f)%22)", lat, log); - char BigBuf[512 + 1] = {0}; - uLCD.printf(buffer); - stream.readNext((byte*)BigBuf, 512); //Point to buffer for the first read - //Yahoo! weather API for selected city - get XML document for parsing - HTTPResult r = http.get(buffer, &stream, request_callback); // This is wehre the http query for the local weather occurs - while (!completed) { - Net::poll(); //Polls the Networking stack - if (stream.readable()) { - BigBuf[stream.readLen()] = 0; //Transform this buffer in a zero-terminated char* string - parser.append( BigBuf, strlen(BigBuf)); // stream current buffer data to the XML parser - stream.readNext((byte*)BigBuf, 512); //Buffer has been read, now we can put more data in it - } - } - uLCD.locate(0,6); - if (result == HTTP_OK) { - uLCD.printf("Weather complete"); - } else { - uLCD. printf("Weather Error %d", result); - return -1; - } - - SP_XmlHandle rootHandle( parser.getDocument()->getRootElement() ); - SP_XmlElementNode * child2 = rootHandle.getChild( "results" ).getChild( "channel" ).toElement(); - - //uLCD.printf(BigBuf); - - if ( child2 ) { - parseWeather(child2, "Atlanta"); //parses XML "current-conditions" info - } - - if ( NULL != parser.getError() ) { - uLCD.printf( "\n error: %s\n", parser.getError() ); - } - return 0; + pc.printf("%sF\r\n",condition->getAttrValue("temp")); } - - -// Need to update so that if it failes to get a GPS fix after say 10 tries it defaults lat and longitude values and time is found thought another method. -bool gps_setup(){ - Timer refresh_Timer; //sets up a timer for use in loop; how often do we print GPS info? - const int refresh_Time = 2000; //refresh time in ms - bool gps_off = true; - char c; - gps_Serial = new Serial(p9,p10); //serial object for use w/ GPS tx rx - Adafruit_GPS myGPS(gps_Serial); //object of Adafruit's GPS class - myGPS.begin(9600); //sets baud rate for GPS communication; note this may be changed via Adafruit_GPS::sendCommand(char *) - myGPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); //these commands are defined in MBed_Adafruit_GPS.h; a link is provided there for command creation - myGPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); - myGPS.sendCommand(PGCMD_ANTENNA); - refresh_Timer.start(); //starts the clock on the timer - uLCD.printf("Starting Up\n"); - while(gps_off){ - uLCD.cls(); - c = myGPS.read(); //queries the GPS - if (c) { uLCD.printf("%c", c); } //this line will echo the GPS data if not paused - //check if we recieved a new message from GPS, if so, attempt to parse it, - if ( myGPS.newNMEAreceived() ) { - if ( !myGPS.parse(myGPS.lastNMEA()) ) { - continue; - } - } - //check if enough time has passed to warrant printing GPS info to screen - //note if refresh_Time is too low or pc.baud is too low, GPS data may be lost during printing - if (refresh_Timer.read_ms() >= refresh_Time) { - refresh_Timer.reset(); - uLCD.printf("Fix: %d\n", (int) myGPS.fix); - uLCD.printf("Quality: %d\n", (int) myGPS.fixquality); - if (myGPS.fix) { - uLCD.printf("Time: %d:%d:%d.%u\n", myGPS.hour, myGPS.minute, myGPS.seconds, myGPS.milliseconds); - uLCD.printf("Date: %d/%d/20%d\n", myGPS.day, myGPS.month, myGPS.year); - uLCD.printf("Location: %5.2f%c, %5.2f%c\n", myGPS.latitude, myGPS.lat, myGPS.longitude, myGPS.lon); - uLCD.printf("Speed: %5.2f knots\n", myGPS.speed); - uLCD.printf("Angle: %5.2f\n", myGPS.angle); - uLCD.printf("Altitude: %5.2f\n", myGPS.altitude); - uLCD.printf("Satellites: %d\n", myGPS.satellites); - gps_off = false; - } - } - } - return true; -} - -void sound_alarm(int volume) { - pressPlay = true; - FILE *wave_file = fopen("/local/alarm.wav","r"); - waver.play(wave_file,&pressPlay, &volume); //play(FILE *wavefile,bool *pressPlay, int *volume); - pressPlay = false; - fclose(wave_file); - } - -RealTimeClock rtc; - - void main_test() { - bool success; - char TimeTest[] = "05/29/2011 14:15:18 (-6:00)"; - char buf[50]; - success = rtc.SetTime(TimeTest); - rtc.GetTimeString(buf); - uLCD.printf("success: %i, time: %s\n", success, buf); - } - -int main() { - //sound_alarm(1); - //display_weather(0); - - - } - - - - //////////////////////////////////////////////// - - #include "mbed.h" -#include "EthernetNetIf.h" -#include "HTTPClient.h" -#include "spdomparser.hpp" -#include "spxmlnode.hpp" -#include "spxmlhandle.hpp" -#include <string> -EthernetNetIf eth; -Serial pc(USBTX, USBRX); -HTTPClient http; -HTTPResult result; - -bool completed = false; -void request_callback(HTTPResult r) -{ - result = r; - completed = true; -} - -void parseWeather(SP_XmlElementNode *node, string loc) -{ - //extracts current weather XML data fields for LCD - SP_XmlHandle handle(node); - SP_XmlElementNode * condition = handle.getChild( "item" ).getChild("yweather:condition").toElement(); - //display Weather conditions - pc.printf("%d:", (int)condition->getAttrValue("code")); - // Print the name of the city - pc.printf("%s:", loc); - //Print the weather conditions - pc.printf("%s",condition->getAttrValue("text")); - //Print the termperature (in degrees Celcius) - pc.printf("%sF",condition->getAttrValue("temp")); -} -// Need To update so that this takes lat longitude gives it to a website to find local time and or time zone -void parseWhereAmI(SP_XmlElementNode *node, string loc) -{ - //extracts current weather XML data fields for LCD - SP_XmlHandle handle(node); - SP_XmlElementNode * condition = handle.getChild( "item" ).getChild("yweather:condition").toElement(); - //display Weather conditions - pc.printf("%d:", (int)condition->getAttrValue("code")); - // Print the name of the city - pc.printf("%s:", loc); - //Print the weather conditions - pc.printf("%s",condition->getAttrValue("text")); - //Print the termperature (in degrees Celcius) - pc.printf("%sF",condition->getAttrValue("temp")); - -} - // Query Term for Weather // select+*+from+weather.forecast+where+woeid+in+(SELECT+woeid+FROM+geo.places+WHERE+text%3D%22(33.7490%2C-84.3880)%22) // Query Website https://developer.yahoo.com/yql/console/#h=select+*+from+weather.forecast+where+woeid+in+(SELECT+woeid+FROM+geo.places+WHERE+text%3D%22(33.7490%2C-84.3880)%22) @@ -376,23 +249,127 @@ } -int main() -{ - pc.baud(9600); - pc.printf("\r\nintializing hardware,...v14\r\n"); - eth.init(); //Use DHCP -sendGETRequest: - EthernetErr ethErr = eth.setup(60000); - int retry = 0; - if (ethErr) { - pc.printf("Error in setup trying again %d",retry); - retry++; - goto sendGETRequest; + +/// Functions will follow here +void display_screen_debug() { + } + +void system_setup () { + + } + +void display_weather(int code){ + uLCD.flush_media(); + uLCD.cls(); + uLCD.media_init(); + //uLCD.printf("\n\nAn SD card is needed for image and video data"); + uLCD.set_sector_address(0x0000,(code*65)); + uLCD.display_image(0,0); + uLCD.cls(); + } + +// Need to update so that if it failes to get a GPS fix after say 10 tries it defaults lat and longitude values and time is found thought another method. +bool gps_setup(){ + Timer refresh_Timer; //sets up a timer for use in loop; how often do we print GPS info? + const int refresh_Time = 2000; //refresh time in ms + bool gps_off = true; + char c; + gps_Serial = new Serial(p9,p10); //serial object for use w/ GPS tx rx + Adafruit_GPS myGPS(gps_Serial); //object of Adafruit's GPS class + myGPS.begin(9600); //sets baud rate for GPS communication; note this may be changed via Adafruit_GPS::sendCommand(char *) + myGPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); //these commands are defined in MBed_Adafruit_GPS.h; a link is provided there for command creation + myGPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); + myGPS.sendCommand(PGCMD_ANTENNA); + refresh_Timer.start(); //starts the clock on the timer + uLCD.printf("Starting Up\n"); + while(gps_off){ + uLCD.cls(); + c = myGPS.read(); //queries the GPS + if (c) { uLCD.printf("%c", c); } //this line will echo the GPS data if not paused + //check if we recieved a new message from GPS, if so, attempt to parse it, + if ( myGPS.newNMEAreceived() ) { + if ( !myGPS.parse(myGPS.lastNMEA()) ) { + continue; + } + } + //check if enough time has passed to warrant printing GPS info to screen + //note if refresh_Time is too low or pc.baud is too low, GPS data may be lost during printing + if (refresh_Timer.read_ms() >= refresh_Time) { + refresh_Timer.reset(); + uLCD.printf("Fix: %d\n", (int) myGPS.fix); + uLCD.printf("Quality: %d\n", (int) myGPS.fixquality); + if (myGPS.fix) { + uLCD.printf("Time: %d:%d:%d.%u\n", myGPS.hour, myGPS.minute, myGPS.seconds, myGPS.milliseconds); + uLCD.printf("Date: %d/%d/20%d\n", myGPS.day, myGPS.month, myGPS.year); + uLCD.printf("Location: %5.2f%c, %5.2f%c\n", myGPS.latitude, myGPS.lat, myGPS.longitude, myGPS.lon); + uLCD.printf("Speed: %5.2f knots\n", myGPS.speed); + uLCD.printf("Angle: %5.2f\n", myGPS.angle); + uLCD.printf("Altitude: %5.2f\n", myGPS.altitude); + uLCD.printf("Satellites: %d\n", myGPS.satellites); + gps_off = false; + } + } } - pc.printf("net ok testing weather\r\n"); - weather(); - //eth.disconnect(); + return true; +} + +void sound_alarm(int volume) { + pressPlay = true; + FILE *wave_file = fopen("/local/alarm.wav","r"); + waver.play(wave_file,&pressPlay, &volume); //play(FILE *wavefile,bool *pressPlay, int *volume); + pressPlay = false; + fclose(wave_file); + } +void nixie_shiftout() { + + + switch (curr_tube) { + case 1: + send_nixie_shiftreg(nixie_id_convert(digit1), 0, TUBE_1_CATH); + break; + case 2: + send_nixie_shiftreg(nixie_id_convert(digit2), 0, TUBE_2_CATH); + break; + case 3: + send_nixie_shiftreg(nixie_id_convert(digit3), 0, TUBE_3_CATH); + break; + case 4: + send_nixie_shiftreg(nixie_id_convert(digit4), 0, TUBE_4_CATH); + break; + default: + curr_tube = 1; + } + curr_tube++; + if (curr_tube == 5) { + curr_tube = 1; + } } - - + +int nixie_id_convert(int digit) { + if (digit == 0 || digit == -1) { + return digit + 1; + } + if (digit < 10) { + return 11 - digit; + } + if (digit == 10) { + return 11; + } + return 0; +} + +void send_nixie_shiftreg(int cathode_id, int led_bitfield, int tube_bitfield) { + + int buffer = 0; + buffer = 1 << (cathode_id-1) | led_bitfield | tube_bitfield; + + for (int i=23; i >= 0; i--) { + sdi = buffer & (1 << i); + scl = 1; + scl = 0; + } + rcl = 1; + rcl = 0; + +}