This week, we had to demonstrate a communication between a microcontroller and another device. I decided I wanted to use the government’s weather API, and I was thinking of ways to use the output devices we have in stock. I then decided to use my LED strip after realizing I really liked working with it a few weeks ago! I decided to depict a week’s forecast with 7 of the pixels on the LED strip.
At first I thought about translating sunny/cloudy/rainy/snowy into pixels, but I wanted to interact with a range of colors instead, so I used the temperature in Fahrenheit. So for temperatures between 70 and 80, for instance, it would show an orangish color, whereas a temperature in between 30 and 40 would be a purplish blue. I used a LAN connection to allow my computer to interact with the microcontroller. I created 5 different city options, and, when clicked on my IP address site, the LED strip would display the city color code and 7 days worth of temperatures.
I think it turned out well! There were some huge obstacles to overcome, and I found myself constantly debugging. But it all worked out in the end, and I’m happy with the result. I've attached the code below.
#include <WiFi.h> #include <HTTPClient.h> #include <ArduinoJson.h> #include <Adafruit_NeoPixel.h> // Set up LED strip #define PIN 14 #define NUMPIXELS 9 Adafruit_NeoPixel strip(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); const char* ssid = "MYWIFINAME"; const char* password = "MYWIFIPASS"; const String endpoint = "https://api.weather.gov/gridpoints/"; WiFiServer server(80); void setup() { Serial.begin(115200); // Set up LED strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) strip.show(); // Turn OFF all pixels ASAP strip.setBrightness(10); // Set BRIGHTNESS low to reduce draw (max = 255) // Set up wifi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi.."); } Serial.println("Connected to the WiFi network"); Serial.println(WiFi.localIP()); server.begin(); } int value = 0; void loop(){ WiFiClient client = server.available(); // listen for incoming clients if (client) { // if you get a client, Serial.println("New Client."); // print a message out the serial port String currentLine = ""; // make a String to hold incoming data from the client while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println(); // the content of the HTTP response follows the header: client.print("Click <a href=\"/NYC\">here</a> to show the weather forecast for New York City.<br>"); client.print("Click <a href=\"/LA\">here</a> to show the weather forecast for Los Angeles.<br>"); client.print("Click <a href=\"/CAM\">here</a> to show the weather forecast for Cambridge.<br>"); client.print("Click <a href=\"/MIA\">here</a> to show the weather forecast for Miami.<br>"); client.print("Click <a href=\"/CHI\">here</a> to show the weather forecast for Chicago.<br>"); // The HTTP response ends with another blank line: client.println(); // break out of the while loop: break; } else { // if you got a newline, then clear currentLine: currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } if (currentLine.endsWith("GET /NYC")) { strip.clear(); strip.setPixelColor(1, strip.Color(0, 0, 255)); const String location = "OKX/33,36/forecast"; getWeather(location); } if (currentLine.endsWith("GET /LA")) { strip.clear(); strip.setPixelColor(1, strip.Color(252, 254, 2)); const String location = "LOX/152,44/forecast"; getWeather(location); } if (currentLine.endsWith("GET /CAM")) { strip.clear(); strip.setPixelColor(1, strip.Color(164, 22, 2)); const String location = "BOX/68,76/forecast"; getWeather(location); } if (currentLine.endsWith("GET /MIA")) { strip.clear(); strip.setPixelColor(1, strip.Color(255,165,0)); const String location = "MFL/108,50/forecast"; getWeather(location); } if (currentLine.endsWith("GET /CHI")) { strip.clear(); strip.setPixelColor(1, strip.Color(0,128,0)); const String location = "LOT/75,72/forecast"; getWeather(location); } } } // close the connection: client.stop(); Serial.println("Client Disconnected."); } } void getWeather(const String location) { if ((WiFi.status() == WL_CONNECTED)) { //Check the current connection status HTTPClient http; const String url = endpoint + location; http.begin(url); //Specify the URL int httpResponseCode = http.GET(); // Make the GET request if (httpResponseCode > 0) { // Execute if we get a good response String payload = http.getString(); Serial.println(httpResponseCode); // Serial.println(payload); // Uncomment to view the entire payload DynamicJsonDocument doc(15000); // Create a buffer of 10000 bytes // Deserialize the JSON document DeserializationError error = deserializeJson(doc, payload); // Test if parsing succeeds. if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.c_str()); return; } // Navigate through JSON document, extracting some values const int day1 = doc["properties"]["periods"][0]["temperature"]; const int day2 = doc["properties"]["periods"][2]["temperature"]; const int day3 = doc["properties"]["periods"][4]["temperature"]; const int day4 = doc["properties"]["periods"][6]["temperature"]; const int day5 = doc["properties"]["periods"][8]["temperature"]; const int day6 = doc["properties"]["periods"][10]["temperature"]; const int day7 = doc["properties"]["periods"][12]["temperature"]; findColor(day1, 2); findColor(day2, 3); findColor(day3, 4); findColor(day4, 5); findColor(day5, 6); findColor(day6, 7); findColor(day7, 8); strip.show(); http.end(); // Close the connection } } } void findColor(int daytemp, int pixel) { if (daytemp << 10) { strip.setPixelColor(pixel, strip.Color(0, 0, 255)); strip.show(); }; if (daytemp >= 10 && daytemp < 20) { strip.setPixelColor(pixel, strip.Color(3, 140, 184)); strip.show(); }; if (daytemp >= 20 && daytemp < 30) { strip.setPixelColor(pixel, strip.Color(3, 110, 253)); strip.show(); }; if (daytemp >= 30 && daytemp < 40) { strip.setPixelColor(pixel, strip.Color(3, 9, 253)); strip.show(); }; if (daytemp >= 40 && daytemp < 50) { strip.setPixelColor(pixel, strip.Color(103, 9, 236)); strip.show(); }; if (daytemp >= 50 && daytemp < 60) { strip.setPixelColor(pixel, strip.Color(138, 2, 224)); strip.show(); }; if (daytemp >= 60 && daytemp < 70) { strip.setPixelColor(pixel, strip.Color(208, 75, 202)); strip.show(); }; if (daytemp >= 70 && daytemp < 80) { strip.setPixelColor(pixel, strip.Color(208, 75, 111)); strip.show(); }; if (daytemp >= 80 && daytemp < 90) { strip.setPixelColor(pixel, strip.Color(230, 75, 69)); strip.show(); }; if (daytemp >= 90 && daytemp < 100) { strip.setPixelColor(pixel, strip.Color(230, 37, 19)); strip.show(); }; if (daytemp >= 100) { strip.setPixelColor(pixel, strip.Color(225, 0, 0)); strip.show(); }; }