Here is my entry for Open Arduino theme. And before I forget belated Happy Birthday Project14 and Arudino ! and also big thanks to tariq.ahmad and team at element14 for hosting Project14 and sending out the awesome Arduino Uno board. I have been wanting to make smaller version of Upcycled Clock which was part of the Upcycle it Design Challenge last year, so it is easy to replicate at home or at your local maker space, if you can get your hands on a 3D printer. And since this is an Arduino theme meant that I had to use Arduino MKR1000, the original idea was to use and Arduino Uno and an Ethernet shield which I thought I handy in my part bin, but I realized I had given it to a friend of mine, who has not yet returned it ...
I am calling the project – Weather Cloud Clock, but if you come up with a better name leave a comment below. The idea here is to 3D print parts to diffuse Neopixels which will depict the weather outside, which I plan to get form openweathermap.org , and also display the time on quad alphanumeric display as you see in the picture below. But, you can also re-purpose the display to show temperature and humidity.
The Arduino board used is the - Arduino MKR1000, which is based on the Atmel ATSAMW25 SoC (System on Chip), that is part of the SmartConnect family of Atmel Wireless devices, specifically designed for IoT projects and devices. For getting stared and more info check out -https://www.arduino.cc/en/Guide/MKR1000.
https://www.arduino.cc/en/Guide/MKR1000.
Update May 02 2018 .....
Here is a picture of the circuit diagram on the breadboard
- Neopixel is connected to pin#6 (PWM) on the Arduino, for the test I am using a NeoPixel ring
- The data and clock pin on the Quad Alphanumeric Display with a I2C Backpack is connected to Arduino MKR1000 SDA (pin#11) and SCL (pin#12)
Here are some pictures of the 3D printed parts
{gallery} 3D printed parts |
---|
Quick test using the Arduino MKR1000, Neopixel ring and Quad Alphanumeric Display with a I2C Backpack
Update on May 12 2018 ..
So.. today is Arduino day 2018, which meant I had to post an update to the project before heading out.
To get the components in the 3D printed enclosure I had to move from a neo-pixel ring to a neo-pixel strip and also move my wiring on the bread boarding wire.And I also painted the 'sun' area on the 3D printed part yellow with a paint pen.
And then uploaded code to the Arduino MKR1000, and also used hot glue to secure the components.Finally punched a nail in the wall to hang the Weather Cloud clock ..
{gallery} Adding the electronics to 3D printed parts |
---|
Added electronic components to the 3D printed part |
Panting the Sun... |
Testing the code - it is raining outside.. |
Weather Cloud clock Nailed to the wall |
Weather clock cloud - a better picture,was struggling to get a picture with the blue color, manually updated code to set Neo-Pixels to red. |
Before uploading the code to the Arduino MKR1000, create an account on https://openweathermap.org/ and then generate and make a note of the API key.
In addition, you will also have to update the following variables in the Arduino code below
- WiFi Router SSID
- WiFi Router password
- APIKEY from the screenshot above from openweathermap
- CityID for the place you live in
- Time Zone offset from GMT
//05/12/2-18 Code created for Weather Clock Project using the Arduino MKR1000 #incude <adafruit_gfx.h> //https://github.com/adafruit/Adafruit_LED_Backpack #include <adafruit_ledbackpack.h> #include <adafruit_neopixel.h> //https://github.com/adafruit/Adafruit_NeoPixel #include #include #include #include #include #include #include //Download Arduino Json from - https://github.com/bblanchon/ArduinoJson #define PIN 6 Adafruit_AlphaNum4 alpha4 = Adafruit_AlphaNum4(); int hours, mins; const long timeZoneOffs = 25200L;//-ve offset for PST time- https://www.epochconverter.com/timezones /// LED backpack connection UNO connection Data - A4 clck -A5, but on the mkr100 SDA 11 SCL 12 String timeDisplay =""; char timeArray[5]={' ', ' ', ' ', ' ',' '}; Adafruit_NeoPixel strip = Adafruit_NeoPixel(8, PIN, NEO_GRB + NEO_KHZ800); //Update the details for your Wifi router setup at home char ssid[] = "XXXXXXXXXXXXX"; //your network SSID char pass[] = "XXXXXXXX"; //your network password unsigned int localPort = 2390;// local port to listen for UDP packets IPAddress timeServerIP; // time.nist.gov NTP server address const char* ntpServerName = "time.nist.gov"; const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets WiFiUDP udp; //required for openweathermap.org API WiFiClient client; char servername[]="api.openweathermap.org"; String APIKEY = "XXXXXXXXXXX"; //update your API key from openweathermap String CityID = "XXXXXX"; //in my case Los Angeles,CA,USA //change this to your city id- http://openweathermap.org/help/city_list.txt String result; int counter = 60; String weatherDescription =""; String weatherLocation = ""; String Country; float Temperature; float Humidity; float Pressure; void setup() { Serial.begin(115200); Serial.println(); Serial.println(); //connecting to a WiFi network Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); Serial.println("Starting UDP"); udp.begin(localPort); alpha4.begin(0x70); // pass in the address alpha4.clear(); alpha4.writeDigitAscii(0, 'P'); alpha4.writeDigitAscii(1, 'R'); alpha4.writeDigitAscii(2, '1'); alpha4.writeDigitAscii(3, '4'); alpha4.writeDisplay(); // Initialize all Neo-Pixels strip.begin(); strip.show(); } void loop() { colorWipe(strip.Color(0, 255, 0), 100); // green //get a random server from the pool WiFi.hostByName(ntpServerName, timeServerIP); sendNTPpacket(timeServerIP); // send an NTP packet to a time server //wait to see if a reply is available delay(10000); int cb = udp.parsePacket(); if (!cb) { Serial.println("no packet yet"); } else { Serial.print("packet received, length="); Serial.println(cb); // We've received a packet, read the data from it udp.read(packetBuffer, NTP_PACKET_SIZE); //the timestamp starts at byte 40 of the received packet and is four bytes, // or two words, long. First, esxtract the two words: unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); // combine the four bytes (two words) into a long integer // this is NTP time (seconds since Jan 1 1900): unsigned long secsSince1900 = highWord << 16 | lowWord; Serial.print("Seconds since Jan 1 1900 = " ); Serial.println(secsSince1900); // now convert NTP time into everyday time: Serial.print("Unix time = "); // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: const unsigned long seventyYears = 2208988800UL; // subtract seventy years: unsigned long epoch = secsSince1900 - seventyYears - timeZoneOffs; //this is with a -ve offset to GMT, for the east of GMT set+ve offset // print Unix time: Serial.println(epoch); // print the hour, minute and second: Serial.print("The time is ::"); if(((epoch % 86400L) / 3600) < 10){ Serial.print('0'); timeDisplay = '0'; } Serial.print((epoch % 86400L) / 3600); // print the hour hours = (epoch % 86400L) / 3600; timeDisplay = timeDisplay+ String(hours); Serial.print(':'); if ( ((epoch % 3600) / 60) < 10 ) { // In the first 10 minutes of each hour, we'll want a leading '0' Serial.print('0'); timeDisplay = timeDisplay+'0'; } Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute) mins = (epoch % 3600) / 60; timeDisplay = timeDisplay+ String(mins); Serial.println(" The time to display on sevengement: " + timeDisplay); /*//No space to show seconds on the alpha numeric display Serial.print(':'); if ( (epoch % 60) < 10 ) { // In the first 10 seconds of each minute, we'll want a leading '0' Serial.print('0'); } Serial.println(epoch % 60); // print the second */ } //Testing the NeoPixel Strip //colorWipe(strip.Color(0, 0, 255), 1000); // Blue //colorWipe(strip.Color(255, 255, 255), 100); // white // colorWipe(strip.Color(255, 255, 0), 1000); // yellow // colorWipe(strip.Color(255, 0, 0), 2000); // red //colorWipe(strip.Color(255, 100, 200), 1000); // red //rainbow(20); //Get weather data from Openweathermap Serial.println("Write to the seven segment.."); timeDisplay.toCharArray(timeArray,5); // set every digit to the buffer alpha4.writeDigitAscii(0, timeArray[0]); alpha4.writeDigitAscii(1, timeArray[1]); alpha4.writeDigitAscii(2, timeArray[2]); alpha4.writeDigitAscii(3, timeArray[3]); // write it out! alpha4.writeDisplay(); delay(2000); //getWeatherData(); Serial.println("The weather is :" + weatherDescription ); Serial.println(" weatherLocation: " + weatherLocation ); //https://openweathermap.org/weather-conditions#Weather-Condition-Codes-213 Serial.println(" Temp: " + String(Temperature) ); Serial.println(" Humidity: " + String(Humidity) ); //for weather condition check out https://openweathermap.org/weather-conditions if(Temperature > 30) //temperature in C { colorWipe(strip.Color(255, 0, 0), 40); // red Serial.println(" Temp Red..." ); } if(weatherDescription == "rain" || weatherDescription == "thunderstorm"){ colorWipe(strip.Color(0, 0, 255), 40); //blue } if(weatherDescription == "few clouds" || weatherDescription == "overcast clouds"){ colorWipe(strip.Color(255, 255, 255), 40); //white } if(weatherDescription == "clear sky" ){ colorWipe(strip.Color(255, 255, 0), 40); //yellow } // there are more weather condition that you can add based on the aread you live in, like white for snow instead of clouds // wait ten seconds before asking for the time again delay(10000); } // Fill the dots one after the other with a color void colorWipe(uint32_t c, uint8_t wait) { for(uint16_t i=0; i<strip.numpixels(); i++)="" {<br=""> strip.setPixelColor(i, c); strip.show(); delay(wait); } } void rainbow(uint8_t wait) { uint16_t i, j; for(j=0; j<256; j++) { for(i=0; i<strip.numpixels(); i++)="" {<br=""> strip.setPixelColor(i, Wheel((i+j) & 255)); } strip.show(); delay(wait); } } // Input a value 0 to 255 to get a color value. // The colours are a transition r - g - b - back to r. uint32_t Wheel(byte WheelPos) { WheelPos = 255 - WheelPos; if(WheelPos < 85) { return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); } if(WheelPos < 170) { WheelPos -= 85; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); } WheelPos -= 170; return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); } // send an NTP request to the time server at the given address unsigned long sendNTPpacket(IPAddress& address) { Serial.println("sending NTP packet..."); // set all bytes in the buffer to 0 memset(packetBuffer, 0, NTP_PACKET_SIZE); // Initialize values needed to form NTP request // (see URL above for details on the packets) 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 // 8 bytes of zero for Root Delay & Root Dispersion packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; // all NTP fields have been given values, now // you can send a packet requesting a timestamp: udp.beginPacket(address, 123); //NTP requests are to port 123 udp.write(packetBuffer, NTP_PACKET_SIZE); udp.endPacket(); } //Get weather data from the Openweathermap API void getWeatherData() { if (client.connect(servername, 80)) { //starts client connection, dont forget to update you API key at the top client.println("GET /data/2.5/weather?id="+CityID+"&units=metric&APPID="+APIKEY); client.println("Host: api.openweathermap.org"); client.println("User-Agent: ArduinoWiFi/1.1"); client.println("Connection: close"); client.println(); } else { Serial.println("connection failed"); //error message if no client connect Serial.println(); } while(client.connected() && !client.available()) delay(1); //waits for data while (client.connected() || client.available()) { //connected or data available char c = client.read(); //gets byte from ethernet buffer result = result+c; } client.stop(); //stop client result.replace('[', ' '); result.replace(']', ' '); Serial.println(result); char jsonArray [result.length()+1]; result.toCharArray(jsonArray,sizeof(jsonArray)); jsonArray[result.length() + 1] = '\0'; StaticJsonBuffer<1024> json_buf; JsonObject &root = json_buf.parseObject(jsonArray); if (!root.success()) { Serial.println("parseObject() failed"); } String location = root["name"]; String country = root["sys"]["country"]; float temperature = root["main"]["temp"]; float humidity = root["main"]["humidity"]; String weather = root["weather"]["main"]; String description = root["weather"]["description"]; float pressure = root["main"]["pressure"]; weatherDescription = description; weatherLocation = location; Country = country; Temperature = temperature; Humidity = humidity; Pressure = pressure; }
Here is a quick video demo of the weather cloud clock in action ...
Top Comments