/************************************************************************** This is an example for our Monochrome OLEDs based on SSD1306 drivers Pick one up today in the adafruit shop! ------> http://www.adafruit.com/category/63_98 This example is for a 128x64 pixel display using I2C to communicate 3 pins are required to interface (two I2C and one reset). Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Written by Limor Fried/Ladyada for Adafruit Industries, with contributions from the open source community. BSD license, check license.txt for more information All text above, and the splash screen below must be included in any redistribution. **************************************************************************/ /* Simple demo, should work with any driver board Connect STEP, DIR as indicated Copyright (C)2015-2017 Laurentiu Badea This file may be redistributed under the terms of the MIT license. A copy of this license has been included with this distribution in the file LICENSE. */ /* Author: Emmanuel Odunlade Complete Project Details http://randomnerdtutorials.com */ //Changes made: // API call query 4 timepoints // Added some debug Serial Print statements to find out what was going on // Changed output to be moire what I desire (simple yes/no if any of the timepoints show bad weather) // NeoPixelTest // This example will cycle between showing four pixels as Red, Green, Blue, White // and then showing those pixels as Black. // // Included but commented out are examples of configuring a NeoPixelBus for // different color order including an extra white channel, different data speeds, and // for Esp8266 different methods to send the data. // NOTE: You will need to make sure to pick the one for your platform // // // There is serial output of the current state so you can confirm and follow along. // //Mashup of codes above! #include #include #include #include #include #include "BasicStepperDriver.h" #include #include #include #include //ALL PIN DEFINITIONS HERE: //BUTTON Pins: #define REFERENCESWITCH 13 //D1 Mini: D3 (Arduino: 0) #define BUTTON 0 //D1 Mini: D7 (Arduino: 13) //#define BUTTON 0 //set to 0 for testing with the same button as the reference switch! //MOTOR Pins: // All the wires needed for full functionality #define DIR 14 //D1 Mini: D5 (Arduino: 14) #define STEP 12 //D1 Mini: D6 (Arduino: 12) #define SLEEP 16 //D1 Mini: D0 (Arduino: 16) //Fixed Pins (actually dont need defines, just for expliciteness): #define LEDPIN 2 //D1 Mini: D4/TXD1 (Arduino: 2), cannot be cchanged and will always be ignored! #define SCL 5 //D1 Mini: D1 (Arduino: 5) #define SDA 4 //D1 Mini: D2 (Arduino: 4) const uint16_t PixelCount = 6; // this example assumes 4 pixels, making it smaller will cause a failure const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 #define colorSaturation 20 // four element pixels, GRBW NeoPixelBus strip(PixelCount, PixelPin); RgbColor red(colorSaturation, 0, 0); RgbColor green(0, colorSaturation, 0); RgbColor blue(0, 0, colorSaturation); RgbColor white(colorSaturation); RgbColor black(0); HslColor hslRed(red); HslColor hslGreen(green); HslColor hslBlue(blue); HslColor hslWhite(white); HslColor hslBlack(black); // Replace with your SSID and password details //char ssid[] = "FRITZ!Box 3490"; //char pass[] = "25908836372315102355"; //char ssid[] = "Galaxy S203614"; //char pass[] = "eutc2742"; char ssid1[] = "Galaxy S203614"; char pass1[] = "eutc2742"; char ssid2[] = "FRITZ!Box 3490"; char pass2[] = "25908836372315102355"; int wifiTimeOut = 10000; int wifiTimeOutStart = 0; WiFiClient client; // Open Weather Map API server name const char server[] = "api.openweathermap.org"; // Replace the next line to match your city and 2 letter country code String nameOfCity = "Kleve,DE"; // How your nameOfCity variable would look like for Lagos on Nigeria //String nameOfCity = "Lagos,NG"; // Replace the next line with your API Key String apiKey = "2a7c53ed47121cac7ce0ecc6302201c2"; String text; int jsonend = 0; boolean startJson = false; int status = WL_IDLE_STATUS; #define JSON_BUFF_DIMENSION 2500 unsigned long lastConnectionTime = 10 * 60 * 1000; // last time you connected to the server, in milliseconds const unsigned long postInterval = 10 * 60 * 1000; // posting interval of 10 minutes (10L * 1000L; 10 seconds delay for testing) String dtNow = "1970-01-01 01:23:45"; float tempNow = 12.34; float humidityNow = 56.78; String weatherNow = "rainbows"; String dtLater = dtNow; float tempLater = tempNow; float humidityLater = humidityNow; String weatherLater = weatherNow; String dtLaterer = dtNow; float tempLaterer = tempNow; float humidityLaterer = humidityNow; String weatherLaterer = weatherNow; String dtLatererer = dtNow; float tempLatererer = tempNow; float humidityLatererer = humidityNow; String weatherLatererer = weatherNow; // Motor steps per revolution. Most steppers are 200 steps or 1.8 degrees/step #define MOTOR_STEPS 50 #define RPM 30 // Since microstepping is set externally, make sure this matches the selected mode // If it doesn't, the motor will move at a different RPM than chosen // 1=full step, 2=half step etc. #define MICROSTEPS 2 // 2-wire basic config, microstepping is hardwired on the driver //BasicStepperDriver stepper(MOTOR_STEPS, DIR, STEP); //Uncomment line to use enable/disable functionality BasicStepperDriver stepper(MOTOR_STEPS, DIR, STEP, SLEEP); #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) // The pins for I2C are defined by the Wire-library. // On an arduino UNO: A4(SDA), A5(SCL) // On an arduino MEGA 2560: 20(SDA), 21(SCL) // On an arduino LEONARDO: 2(SDA), 3(SCL), ... #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) #define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); #define NUMFLAKES 10 // Number of snowflakes in the animation example #define LOGO_HEIGHT 16 #define LOGO_WIDTH 16 static const unsigned char PROGMEM logo_bmp[] = { 0b00000000, 0b11000000, 0b00000001, 0b11000000, 0b00000001, 0b11000000, 0b00000011, 0b11100000, 0b11110011, 0b11100000, 0b11111110, 0b11111000, 0b01111110, 0b11111111, 0b00110011, 0b10011111, 0b00011111, 0b11111100, 0b00001101, 0b01110000, 0b00011011, 0b10100000, 0b00111111, 0b11100000, 0b00111111, 0b11110000, 0b01111100, 0b11110000, 0b01110000, 0b01110000, 0b00000000, 0b00110000 }; //int maxSwing = 10 * MICROSTEPS; //maximum swing of the indicator in steps (multiplied by the number of microsteps/step to get steps to move) int maxSwing = 18; //18 so 3 steps of 6 can be done reuslting in 4 positions: 0-6-12-18 //turns on 1 LED per step as given here: float degreePerLed = 5; void setup() { pinMode(REFERENCESWITCH, INPUT_PULLUP); pinMode(BUTTON, INPUT_PULLUP); // this resets all the neopixels to an off state strip.Begin(); strip.Show(); delay(1000); //neoPixelBlink(); // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1306 allocation failed")); for (;;); // Don't proceed, loop forever } // Show initial display buffer contents on the screen -- // the library initializes this with an Adafruit splash screen. display.display(); Serial.begin(9600); //neoPixelBlink(); text.reserve(JSON_BUFF_DIMENSION); WiFi.begin(ssid1, pass1); Serial.println("connecting to " + String(ssid1)); display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.println("connecting to " + String(ssid1)); display.display(); wifiTimeOutStart = millis(); while (WiFi.status() != WL_CONNECTED) { delay(500); //Serial.print("."); display.print("."); display.display(); if((millis()-wifiTimeOutStart) > wifiTimeOut){ display.println("timeout!"); display.println(); WiFi.begin(ssid2, pass2); break; } } if(WiFi.status() != WL_CONNECTED){ display.println("connecting to " + String(ssid2)); display.display(); while (WiFi.status() != WL_CONNECTED) { delay(500); //Serial.print("."); display.print("."); display.display(); if(wifiTimeOut > millis()-wifiTimeOutStart){ display.print("timeout!"); break; } } } Serial.println("WiFi Connected"); display.println("WiFi Connected"); display.display(); printWiFiStatus(); testdrawconnectionstatus(); delay(1000); stepper.begin(RPM, MICROSTEPS); // if using enable/disable on ENABLE pin (active LOW) instead of SLEEP uncomment next line stepper.setEnableActiveState(LOW); //Fake reference drive stepper.enable(); while(digitalRead(REFERENCESWITCH)){ drawReferenceDrive(); stepper.move(-1); delay(500); } drawReferenceDriveFinished(); stepper.move(4); stepper.disable(); stepper.enable(); stepper.disable(); delay(2000); } void loop() { //OWM requires 10mins between request intervals //check if 10mins has passed then connect again and pull if (millis() - lastConnectionTime > postInterval) { // note the time that the connection was made: lastConnectionTime = millis(); makehttpRequest(); } //drawButtonState(5000); //testdrawconnectionstatus(); //delay(1000); stepper.disable(); testdrawweathertext(); //delay(5000); if(digitalRead(BUTTON) == LOW){ neoPixelTemp(tempNow); // energize coils - the motor will hold position stepper.enable(); /* Moving motor one full revolution using the degree notation */ /*strip.SetPixelColor(0, red); strip.SetPixelColor(1, green); strip.SetPixelColor(2, blue); strip.SetPixelColor(3, white); // the following line demonstrates rgbw color support // if the NeoPixels are rgbw types the following line will compile // if the NeoPixels are anything else, the following line will give an error strip.SetPixelColor(3, RgbwColor(colorSaturation)); strip.Show(); */ testdrawcw(); //stepper.move(-maxSwing); for(int i = 0; i<3; i++){ stepper.move(maxSwing/3); delay(2500); } /* Moving motor to original position using steps */ //delay(2000); /* // turn off the pixels strip.SetPixelColor(0, black); strip.SetPixelColor(1, black); strip.SetPixelColor(2, black); strip.SetPixelColor(3, black); strip.Show(); */ testdrawccw(); stepper.move(-maxSwing); // pause and allow the motor to be moved by hand // stepper.disable(); delay(2000); } } void drawReferenceDriveFinished(){ display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.println("Reference drive finished!"); display.println("Zero established!"); display.display(); } void drawReferenceDrive(){ display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.println("Reference drive in progress..."); display.println("Going CCW..."); display.display(); } void drawButtonState(int duration){ int start = millis(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font while((millis()-start) < duration){ display.clearDisplay(); display.setCursor(0, 0); // Start at top-left corner display.println("Button state:"); /* if(digitalRead(REFERENCESWITCH)==HIGH){ display.println("HIGH"); } else { display.println("LOW"); }*/ display.print(digitalRead(REFERENCESWITCH)); display.display(); } } void testdrawchar(void) { display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font // Not all the characters will fit on the display. This is normal. // Library will draw what it can and the rest will be clipped. for (int16_t i = 0; i < 256; i++) { if (i == '\n') display.write(' '); else display.write(i); } display.display(); delay(2000); } void testdrawweathertext(void) { display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.println(dtNow.substring(11) + ": " + tempNow + " " + ((char)248) + "C, " + humidityNow + "% rH," + weatherNow); display.println(dtLater.substring(11) + ": " + tempLater + " " + ((char)248) + "C, " + humidityLater + "% rH," + weatherLater); display.println(dtLaterer.substring(11) + ": " + tempLaterer + " " + ((char)248) + "C, " + humidityLaterer + "% rH," + weatherLaterer); display.println(dtLatererer.substring(11) + ": " + tempLatererer + " " + ((char)248) + "C, " + humidityLatererer + "%rH, " + weatherLatererer); display.display(); //delay(2000); } void testdrawcw(void) { display.clearDisplay(); display.setTextSize(2); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.println("CW\nrotation!"); display.display(); } void testdrawccw(void) { display.clearDisplay(); display.setTextSize(2); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.println("CCW\nrotation!"); display.display(); } void testdrawconnectionstatus(void) { display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font // print the SSID of the network you're attached to: display.println("SSID: "); display.print(" "); display.println(WiFi.SSID()); // print your WiFi shield's IP address: IPAddress ip = WiFi.localIP(); display.println("IP Address: "); display.print(" "); display.println(ip); // print the received signal strength: long rssi = WiFi.RSSI(); display.println("signal strength (RSSI):"); display.print(" "); display.print(rssi); display.println(" dBm"); display.display(); } // print Wifi status void printWiFiStatus() { // print the SSID of the network you're attached to: Serial.print("SSID: "); Serial.println(WiFi.SSID()); // print your WiFi shield's IP address: IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip); // print the received signal strength: long rssi = WiFi.RSSI(); Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm"); } // to request data from OWM void makehttpRequest() { // close any connection before send a new request to allow client make connection to server client.stop(); // if there's a successful connection: if (client.connect(server, 80)) { Serial.println("connecting..."); // send the HTTP PUT request: Serial.println("GET /data/2.5/forecast?q=" + nameOfCity + "&APPID=" + apiKey + "&mode=json&units=metric&cnt=4 HTTP/1.1"); client.println("GET /data/2.5/forecast?q=" + nameOfCity + "&APPID=" + apiKey + "&mode=json&units=metric&cnt=4 HTTP/1.1"); client.println("Host: api.openweathermap.org"); client.println("User-Agent: ArduinoWiFi/1.1"); client.println("Connection: close"); client.println(); Serial.println("closed..."); unsigned long timeout = millis(); while (client.available() == 0) { if (millis() - timeout > 5000) { Serial.println(">>> Client Timeout !"); client.stop(); return; } } Serial.println("no timeout..."); Serial.println("printing server answer:"); char c = 0; while (client.available()) { c = client.read(); // since json contains equal number of open and close curly brackets, this means we can determine when a json is completely received by counting // the open and close occurences, Serial.print(c); if (c == '{') { startJson = true; // set startJson true to indicate json message has started jsonend++; Serial.println(">>> Opening bracket..."); } if (c == '}') { jsonend--; Serial.println(">>> Closing bracket..."); } if (startJson == true) { text += c; } // if jsonend = 0 then we have have received equal number of curly braces if (jsonend == 0 && startJson == true) { Serial.println(">>> Starting parse..."); parseJson(text.c_str()); // parse c string text in parseJson function Serial.println(">>> Parsed..."); text = ""; // clear text string for the next time startJson = false; // set startJson to false to indicate that a new message has not yet started } } } else { // if no connction was made: Serial.println("connection failed"); return; } } //to parse json data recieved from OWM void parseJson(const char * jsonString) { //StaticJsonBuffer<4000> jsonBuffer; const size_t bufferSize = 2 * JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(2) + 4 * JSON_OBJECT_SIZE(1) + 3 * JSON_OBJECT_SIZE(2) + 3 * JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + 2 * JSON_OBJECT_SIZE(7) + 2 * JSON_OBJECT_SIZE(8) + 720; DynamicJsonBuffer jsonBuffer(bufferSize); // FIND FIELDS IN JSON TREE JsonObject& root = jsonBuffer.parseObject(jsonString); if (!root.success()) { Serial.println("parseObject() failed"); return; } JsonArray& list = root["list"]; JsonObject& nowT = list[0]; JsonObject& later = list[1]; JsonObject& laterer = list[2]; JsonObject& latererer = list[3]; // including temperature and humidity for those who may wish to hack it in String city = root["city"]["name"]; dtNow = String(nowT["dt_txt"]); tempNow = nowT["main"]["temp"]; humidityNow = nowT["main"]["humidity"]; weatherNow = String(nowT["weather"][0]["description"]); dtLater = String(later["dt_txt"]); tempLater = later["main"]["temp"]; humidityLater = later["main"]["humidity"]; weatherLater = String(later["weather"][0]["description"]); dtLaterer = String(laterer["dt_txt"]); tempLaterer = laterer["main"]["temp"]; humidityLaterer = laterer["main"]["humidity"]; weatherLaterer = String(laterer["weather"][0]["description"]); dtLatererer = String(latererer["dt_txt"]); tempLatererer = latererer["main"]["temp"]; humidityLatererer = latererer["main"]["humidity"]; weatherLatererer = String(latererer["weather"][0]["description"]); Serial.println("Parsed values:"); Serial.println(city + ":"); Serial.print(dtNow + ": "); Serial.print(String(tempNow) + "°C, "); Serial.print(String(humidityNow) + "%rH, "); Serial.println(weatherNow); Serial.print(dtLater + ": "); Serial.print(String(tempLater) + "°C, "); Serial.print(String(humidityLater) + "%rH, "); Serial.println(weatherLater); Serial.print(dtLaterer + ": "); Serial.print(String(tempLaterer) + "°C, "); Serial.print(String(humidityLaterer) + "%rH, "); Serial.println(weatherLaterer); Serial.print(dtLatererer + ": "); Serial.print(String(tempLatererer) + "°C, "); Serial.print(String(humidityLatererer) + "%rH, "); Serial.println(weatherLatererer); Serial.println(); weatherDataAction(weatherNow, weatherLater, weatherLaterer, weatherLatererer); } void weatherDataAction(String nowT, String later, String laterer, String latererer) { display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font //check for "rain" in JSON of all 4 timepoints String weatherType = "rain"; int indexNow = nowT.indexOf(weatherType); int indexLater = later.indexOf(weatherType); int indexLaterer = laterer.indexOf(weatherType); int indexLatererer = latererer.indexOf(weatherType); if (max(max(max(indexNow, indexLater), indexLaterer), indexLatererer) > 0) { Serial.println("There's going to be rain!"); } else { Serial.println("No rain for the next 9 hours!"); } } void neoPixelBlink(){ strip.SetPixelColor(0, red); strip.SetPixelColor(1, green); strip.SetPixelColor(2, blue); strip.SetPixelColor(3, white); // the following line demonstrates rgbw color support // if the NeoPixels are rgbw types the following line will compile // if the NeoPixels are anything else, the following line will give an error strip.SetPixelColor(3, RgbwColor(colorSaturation)); strip.Show(); delay(1000); // turn off the pixels strip.SetPixelColor(0, black); strip.SetPixelColor(1, black); strip.SetPixelColor(2, black); strip.SetPixelColor(3, black); strip.Show(); delay(1000); } void neoPixelTemp(float temperature){ for(int i = 0; i < PixelCount; i++){ if(temperature >= (i+1)*degreePerLed) strip.SetPixelColor(i, red); } // the following line demonstrates rgbw color support // if the NeoPixels are rgbw types the following line will compile // if the NeoPixels are anything else, the following line will give an error //strip.SetPixelColor(3, RgbwColor(colorSaturation)); strip.Show(); }