#include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> // http web access library #include <ArduinoJson.h> // JSON decoding library // Libraries for SSD1306 OLED display #include <Wire.h> // include wire library (for I2C devices such as the SSD1306 display) #include <Adafruit_GFX.h> // include Adafruit graphics library #include <Adafruit_SSD1306.h> // include Adafruit SSD1306 OLED display driver #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) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); const char* ssid = "xxxxxxxxxxxxxxxxxxx"; const char* password = "yyyyyyyyyyyyyy"; // set location and API key //String Location = "City Name, Country Code"; //String API_Key = "Your API Key"; String Location = "Rieti, it"; String API_Key = "zzzzzzzzzzzzzzzzzzzzzzzzzzzz"; void setup(void) { Serial.begin(9600); delay(1000); //Wire.begin(4, 0); // set I2C pins [SDA = GPIO4 (D2), SCL = GPIO0 (D3)], default clock is 100kHz // by default, we'll generate the high voltage from the 3.3v line internally! (neat!) display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64) // init done Wire.setClock(400000L); // set I2C clock to 400kHz display.clearDisplay(); // clear the display buffer display.setTextColor(WHITE, BLACK); display.setTextSize(1); display.setCursor(0, 0); display.println(" Internet Weather"); display.print(" Station - RIETI"); display.display(); WiFi.begin(ssid, password); Serial.print("Connecting."); display.setCursor(0, 24); display.println("Connecting..."); display.display(); while ( WiFi.status() != WL_CONNECTED ) { delay(500); Serial.print("."); } Serial.println("connected"); display.print("connected"); display.display(); delay(1000); } void loop() { if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status { HTTPClient http; //Declare an object of class HTTPClient // specify request destination http.begin("http://api.openweathermap.org/data/2.5/weather?q=" + Location + "&APPID=" + API_Key); // !! int httpCode = http.GET(); // send the request if (httpCode > 0) // check the returning code { String payload = http.getString(); //Get the request response payload DynamicJsonBuffer jsonBuffer(512); // Parse JSON object JsonObject& root = jsonBuffer.parseObject(payload); if (!root.success()) { Serial.println(F("Parsing failed!")); return; } //float temp = (float)(root["main"]["temp"]) - 273.15; // get temperature in °C int temp = root["main"]["temp"]; // get temperature in °C int humidity = root["main"]["humidity"]; // get humidity in % float pressure = (float)(root["main"]["pressure"]) / 1000; // get pressure in bar float wind_speed = root["wind"]["speed"]; // get wind speed in m/s int wind_degree = root["wind"]["deg"]; // get wind degree in ° // print data Serial.printf("Temperature = %.2f°C\r\n", temp); Serial.printf("Humidity = %d %%\r\n", humidity); Serial.printf("Pressure = %.3f bar\r\n", pressure); Serial.printf("Wind speed = %.1f m/s\r\n", wind_speed); Serial.printf("Wind degree = %d°\r\n\r\n", wind_degree); display.setCursor(0, 24); display.printf("Temperature: %5.2f C\r\n", temp); //display.printf("Temperature: %d C\r\n", temp); display.printf("Humidity : %d %%\r\n", humidity); display.printf("Pressure : %.3fbar\r\n", pressure); display.printf("Wind speed : %.1f m/s\r\n", wind_speed); display.printf("Wind degree: %d", wind_degree); display.drawRect(109, 24, 3, 3, WHITE); // put degree symbol ( ° ) display.drawRect(97, 56, 3, 3, WHITE); display.display(); } http.end(); //Close connection } delay(20000); // wait 1 minute } // End of code.
Hi Rui, I tried to run this code to get data from the API. But I got on the OLED as follows:
Temperature : %.2f °C
Humidity : 30%
Pressure: %.3fbar
Wind speed: %.1f m/s
Wind degree: 230°
It seems that rows 1st,3rd and 4st are not correct; have you any ideas?
thanks, Domenico
Hi Domenico.
Try to convert those variables to string before printing them on the OLED display.
Regards,
Sara
Do you get the right values on the serial monitor?
On the code you’re sharing, you’re getting the temperature and humidity as int variables.
So, you just need to use the String() method: for example
String tempString;
tempString = String (temp);
To convert float to string you can use the dtostrf() method. For example:
char buffer[10];
String tempString = dtostrf(temp, 5, 2, buffer);
Regards,
Sara
I guess unfortunately no.
Below find the serial monitor log:
—————————- Serial Monitor ———————-
Connecting………connected
Temperature = %.2f°C
Humidity = 24 %
Pressure = %.3f bar
Wind speed = %.1f m/s
Wind degree = 250°
Temperature = %.2f°C
Humidity = 24 %
Pressure = %.3f bar
Wind speed = %.1f m/s
Wind degree = 250°
Temperature = %.2f°C
Humidity = 24 %
Pressure = %.3f bar
Wind speed = %.1f m/s
Wind degree = 250°
Temperature = %.2f°C
Humidity = 24 %
Pressure = %.3f bar
Wind speed = %.1f m/s
Wind degree = 250°
Hi Domenico.
I’m sorry for taking so long to get back to you again.
When you convert your variables to strings, then, you need to modify the printf specifiers to match the type of variable you want to display.
So, after converting the variables to strings, you print them on the serial monitor using the %s specifier (for string), for example:
Serial.printf("Temperature = %s°C\r\n", temp);
I think the same applies for the OLED display.
Can you show me how you’re trying to display the information on the display now?
Regards,
Sara
Hi Sara, thanks for your answer.
But I am not able to integrate your suggestions into the code, because of the compilation error.
Can you please try to do by yourself ? Then, I can run the code directly, thanks.
Hi again.
I’ve just uploaded your code with my API-KEY to an ESP8266 with OLED and it is working fine.
I just replaced the following line
Wire.setClock(400000L); // set I2C clock to 400kHz
with
Wire.setClock(400000); // set I2C clock to 400kHz
And uncommented the temperature to get the conversion from Kelvin to Celsius:
//float temp = (float)(root["main"]["temp"]) - 273.15; // get temperature in °C
Everything was working fine.
See my pictures below
Try again and see if it works now.
What version of the OLED library are you using? Mine is 1.3.0
Regards,
Sara
Hi Sara, excellent!
Can you PLEASE post the complete sketch to me , thanks ? So that I can run the same you run fine!
ps. OLED library version is : 1.2.9
Hi Sara, in the meantime I wait your kind answer, I say you as follows.
- I run the original code I posted few days ago and it doesn’t work fine;
- I attach the version about the IDE and libraries:
Arduino IDE ver : 1.8.9 ArduinoJson.h : 5.13.5 Adafruit_GFX.h : 1.1.5 Adafruit_SSD1306.h : 2.1.0
ps. I post the link of the project
Hi.
I run the code that you shared. But here it is, if you want: https://pastebin.com/YG2aAtmi
These are the library versions I have installed:
- Arduino IDE: 1.8.10
- ArduinoJson: 5.13.5 (the same as yours)
- Adafruit_GFX: 1.5.6
- Adafruit_ SSD1306: 1.3.0
You can try using the same library versions I’m using and see what you get.
Your code works perfectly fine for me.
Regards,
Sara
Dear Sara,
nothing to do !
I tried to update everything (excepted for the IDE) but it doesn’t work to me 🙁
Very strange………any idea?
And the Serial Monitor? What do you see?
Does it connect well to the internet?
My guess is that you might not be able to get the values from the API.
Can you go directly to the API link and see what you get?
Here’s what I see when I access the API link with my API KEY
Same than display! Connection is perfect !!
{"coord":{"lon":12.86,"lat":42.41},"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03d"}],"base":"stations","main":{"temp":285.44,"feels_like":284.9,"temp_min":281.48,"temp_max":289.82,"pressure":1010,"humidity":81},"visibility":6000,"wind":{"speed":0.5},"clouds":{"all":40},"dt":1586872553,"sys":{"type":1,"id":6772,"country":"IT","sunrise":1586838510,"sunset":1586886514},"timezone":7200,"id":3169412,"name":"Rieti","cod":200}
Hi again.
I’m out of ideas of what might be the issue :/
What board are you using? I’m using a NodeMCU 12-E like this: https://makeradvisor.com/tools/esp8266-esp-12e-nodemcu-wi-fi-development-board/
The project is working perfectly fine on my side as I’ve shown you previously.
Do you still get the error even in the Serial Monitor?
HI Sara, yes I use the same NodeMCU 12-E like.
Yes, I get exactly the same error even into the Serial Monitor. Very strange!
ps. I don’t think to be a OLED issue, but could be rfelated to the “parse” function with float istruction.
I don’t know.
It is very strange.
The only different is the Arduino IDE version, which shouldn’t be an issue.
But, in any case, do you want to upgrade for the 1.8.10 version?
I don’t know what else can be wrong 🙁
Dear Sara,
thanks again for your kind answer.
By the way, I didn’t have success in those further tests, but I tried another solution.
Now it seems to me working fine, but very honestly I changed some part of the code to take it running as expected. I attach it for your reference and eventually your kind comments.
One further question I hope:
I’d like to “print” on the OLED some parameters not exactly “numeric” like, pressure, temp, etc etc.
For instance like these:
String tmp0 = root[“city”][“name”];
String tmp1 = root[“list”][“weather”][“main”];
String tmp2 = root[“list”][“weather”][“description”];
Question is: how can I modify the “display.print(.)” instruction to get to display a “description” value?
Thanks. Domenico
// —————— quote
float temp = (float)(root[“main”][“temp”]) – 273.15; // get temperature in °C
float humidity = root[“main”][“humidity”]; // get humidity in %
float pressure = root[“main”][“pressure”]; // get pressure in bar
float wind_speed = root[“wind”][“speed”]; // get wind speed in m/s
float wind_degree = root[“wind”][“deg”]; // get wind degree in °
// print data
Serial.printf(“Temperature = %.2f°C\r\n”, temp);
Serial.printf(“Humidity = %d %%\r\n”, humidity);
Serial.printf(“Pressure = %.3f bar\r\n”, pressure);
Serial.printf(“Wind speed = %.1f m/s\r\n”, wind_speed);
Serial.printf(“Wind degree = %d°\r\n\r\n”, wind_degree);
//display.clearDisplay();
display.fillRoundRect(1, 20, 126, 40, 2, BLACK);
display.drawRoundRect(0, 0, 128, 64, 1, WHITE);
display.setTextSize(1);
display.setCursor(2, 20);
display.print(“Temperature:”);
display.setCursor(85, 20);
display.print(temp,2);
display.setCursor(2, 29);
display.print(“Humidity:”);
display.setCursor(85, 29);
display.print(humidity,0);
display.setCursor(2, 37);
display.print(“Pressure:”);
display.setCursor(85, 37);
display.print(pressure,0);
display.setCursor(2, 46);
display.print(“Wind speed:”);
display.setCursor(85, 46);
display.print(wind_speed,1);
display.display();
}
http.end(); //Close connection
}
delay(20000); // wait 1 minute
}
// —————— un-quote
Hi Domenico.
If your values are strings like the:
String tmp0 = root[“city”][“name”];
You can simply pass the variables as argument to the display.print() function:
display.print(tmp0);
I hope this helps.
Regards,
Sara
Dear Sara, it works fine, thanks. One further question if possible.
This herebelow is the API, but I am not able to get the “weather” parameters using this instruction maybe due to some syntax error; others work perfect. Any ideas? ps. I guess some bracket issue!
String tmp1 = root[“weather”][“main”];
String tmp2 = root[“weather”][“description”];
—————– quote
{
“coord” :{“lon”:12.86,”lat”:42.41},
“weather” :[{“id”:802,
“main”: “Clouds”,
“description”:”scattered clouds”,
“icon”:”03d”}],
“base” :”stations”,
“main” :{“temp”:284.67,
“feels_like”:283.86,
“temp_min”:281.48,
“temp_max”:288.71,
“pressure”:1010,
“humidity”:87},
“visibility”:6000,
“wind” :{“speed”:1},
“clouds” :{“all”:40},
“dt” :1586869978,
“sys” :{“type”:1,
“id”:6772,
“country”:”IT”,
“sunrise”:1586838510,
“sunset”:1586886514},
“timezone” :7200,
“id” :3169412,
“name”: “Rieti”,
“cod” :200
}
—————– un-quote
Hi Domenico.
Because there’s a [] in the weather, you need to do something like this:
String tmp1 = root["weather"][0]["main"];
String tmp2 = root["weather"][0]["description"];
It works for me.
Let me know if it works for you.
Regards,
Sara