玩转Arduino(4)-天气预报

硬件 ESP32 开发板 0.96寸OLED 128*64 思路 ESP32 开发板自带WIFI和蓝牙 Step1 使用开发板连接家里的WIFI热点 注意修改代码中的WIFI SSID和password Step2 使用和风天气API,获取天气信息 和风天气的API默认访问https://devapi.qweather.com 需要使用SSL,对单片机开发非常麻烦,我重新封装代理了对应接口,简化了调用过程。 可使用 http://qweather.vearne.com/v7/weather/3d?location=101010100&lang=en&key=xxx 访问和风天气API,注意修改秘钥key 代码库为vearne/simpleQweather Step3 解析Response,将天气信息显示在OLED显示屏幕上 代码 完整代码 weather #include <WiFi.h> #include <HTTPClient.h> #include <Arduino.h> #include <Arduino_JSON.h> #include <SPI.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include "BitmapData.h" #define LOGO_HEIGHT 16 #define LOGO_WIDTH 16 #define WEATHER_X 50 const char *ssid = "vearne-Guest"; // Change this to your WiFi SSID const char *password = "xxxx"; // Change this to your WiFi password // Change key to your api key // https://dev.qweather.com/docs/configuration/project-and-key/ const char *url = "http://qweather.vearne.com/v7/weather/3d?location=101010100&lang=en&key=xxx"; #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) #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); void setup() { Serial.begin(115200); while (!Serial) { delay(100); } // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F("SSD1306 allocation failed")); for (;;) ; // Don't proceed, loop forever } // We start by connecting to a WiFi network Serial.println(); Serial.println("******************************************************"); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void loop() { if (WiFi.status() == WL_CONNECTED) { HTTPClient http; // 开始请求 // http.addHeader(const String &name, const String &value) http.begin(url); // 发送 GET 请求 int httpCode = http.GET(); // 如果请求成功 if (httpCode > 0) { // 读取响应 String payload = http.getString(); Serial.println("响应内容:"); Serial.println(payload); // 结束请求 http.end(); JSONVar weatherData = JSON.parse(payload); if (JSON.typeof(weatherData) == "undefined") { Serial.println("Parsing input failed!"); return; } // 获取第一天的天气信息 JSONVar firstDay = weatherData["daily"][0]; String tempMax = (const char *)firstDay["tempMax"]; String tempMin = (const char *)firstDay["tempMin"]; String windScale = (const char *)firstDay["windScaleDay"]; String fxDate = (const char *)firstDay["fxDate"]; String iconDay = (const char *)firstDay["iconDay"]; switch (iconDay.toInt()) { case 100: drawOLED(sun, fxDate, tempMin, tempMax, windScale); break; case 101: drawOLED(cloudy, fxDate, tempMin, tempMax, windScale); break; case 102: drawOLED(cloud, fxDate, tempMin, tempMax, windScale); default: drawOLED(rain, fxDate, tempMin, tempMax, windScale); break; } } else { Serial.println("WiFi 未连接"); } delay(1000 * 300); // 等待 5min } } void drawOLED(const uint8_t *bitmap, String dateStr, String tempMin, String tempMax, String windScale) { display.clearDisplay(); // weather icon display.drawBitmap( 10, 10, bitmap, LOGO_WIDTH, LOGO_HEIGHT, 1); // temp & wind display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(WHITE); // Draw white text display.setCursor(WEATHER_X, 10); display.print("temp: "); String s = ""; s.concat(tempMin); s.concat("~"); s.concat(tempMax); display.println(s); display.setCursor(WEATHER_X, 25); display.print("wind: "); display.println(windScale); // line display.drawLine(0, 45, display.width() - 1, 45, WHITE); // date display.setTextSize(2); // Normal 1:1 pixel scale display.setTextColor(WHITE); // Draw white text display.setCursor(5, 50); // Start at top-left corner display.println(dateStr); display.display(); delay(1000); } 库依赖 1.Adafruit_SSD1306 2.Arduino_JSON 3.ArduinoHttpClient 4.WiFi ...

November 23, 2024 · 3 min

玩转Arduino(3)-感应式垃圾桶

思路 arduino接红外线传感器, 舵机、灯,红外线传感器被触发后,红灯亮起,舵机转动一定的角度,垃圾桶盖被打开,等待3秒后,舵机转回初始位置,垃圾桶盖关闭。 代码 #include <Servo.h> int infraredPin = 2; int lightPin = 6; int steerPin = 9; int closeAngle = 0; int openAngle = 80; Servo servo; void setup() { pinMode(infraredPin, INPUT); pinMode(steerPin, OUTPUT); pinMode(lightPin, OUTPUT); servo.attach(steerPin); // 初始状态: 垃圾桶盖子是关闭的 servo.write(closeAngle); } void loop() { if (digitalRead(infraredPin) == 0) { //检测到障碍物,输出低电平 digitalWrite(lightPin, HIGH); //亮灯 // 垃圾桶开盖 servo.write(openAngle); delay(3000); // 等待3秒 // clear digitalWrite(lightPin, LOW); // 灭灯 servo.write(closeAngle); } delay(200); } 演示视频 B站 ...

November 1, 2024 · 1 min

玩转Arduino(2)-按钮控制小灯

思路 按钮按下输出为低电平,按钮抬起时为高电平。 萌叔希望达到的效果是按一下按钮,小灯亮起,再按一次,小灯熄灭 需要捕获电位从 低电位 -> 高电位 的这个变化 代码 #define legPinIn 10 #define legPinOut 5 bool isLightOn = false; int preMode = HIGH; int currMode = HIGH; void setup() { Serial.begin(9600); pinMode(legPinIn, INPUT); pinMode(legPinOut, OUTPUT); } void loop() { isLightOn = getLightState(); if (isLightOn) { digitalWrite(legPinOut, HIGH); } else { digitalWrite(legPinOut, LOW); } delay(100); } bool getLightState() { if (digitalRead(legPinIn) != currMode) { preMode = currMode; currMode = digitalRead(legPinIn); if (preMode == LOW && currMode == HIGH) { isLightOn = !isLightOn; Serial.print("isLightOn: "); Serial.println(isLightOn); } } return isLightOn; } 演示视频 B站 ...

October 20, 2024 · 1 min

玩转Arduino(1)-自制温度湿度计

思路 从温湿度传感器读取温度和湿度信息,然后在LCD显示器上展示 代码 #include <DHT11.h> #include <Bonezegei_LCD1602_I2C.h> DHT11 dht11(2); Bonezegei_LCD1602_I2C lcd(0x27); void setup() { // Initialize serial communication to allow debugging and data readout. // Using a baud rate of 9600 bps. Serial.begin(9600); lcd.begin(); } void loop() { int temperature = 0; int humidity = 0; // Attempt to read the temperature and humidity values from the DHT11 sensor. int result = dht11.readTemperatureHumidity(temperature, humidity); // Check the results of the readings. // If the reading is successful, print the temperature and humidity values. // If there are errors, print the appropriate error messages. if (result == 0) { Serial.print("Temperature: "); Serial.print(temperature); Serial.print(" °C\tHumidity: "); Serial.print(humidity); Serial.println(" %"); String str = String("Temperat: ") + temperature + String(" C"); lcd.setPosition(0, 0); lcd.print(str.c_str()); lcd.setPosition(0, 1); str = str = String("Humidity: ") + humidity + String(" %"); lcd.print(str.c_str()); } else { // Print error message based on the error code. Serial.println(DHT11::getErrorString(result)); } delay(10000); } 参考资料 1.DHT11驱动 2.LCD1602驱动 ...

October 20, 2024 · 1 min