Open Arduino

Enter Your Project for a chance to win a grand prize for the most innovative use of Arduino or a $200 shopping cart! The Birthday Special: Arduino Projects for Arduino Day!

Back to The Project14 homepage

Project14 Home
Monthly Themes
Monthly Theme Poll

 

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 ...