thumbnail

几年前闲的蛋疼购买了一块esp8266开发板,还买了面包板和一块屏幕还有一堆led灯珠开关杜邦线啥的,但是很快就失去兴趣了,最近天天在b站刷到各种桌面小摆件,于是又来了兴趣。

在某宝逛了半天,发现一款紫色的esp32s3uno,我当时还寻思这种样式的开发板很不错,不需要面包板就能很不错的连接其它模块,刚好在下方推荐中发现一块可以直插r3uno的2.4寸ILI9341屏幕,然后我就想买这两个再把他们对插起来,这样刚好可以很方便的使用,一根线都不需要接了,还买了一个r3uno亚克力外壳,把他俩包起来。还看了不少这种样式的开发板扩展模块,甚至还有一分二的扩展板,于是全部收藏起来,以后可能需要。

还没到货的时候我就在提前准备,妈的我才开始考虑这个引脚的问题,屏幕是给r3 uno用的,引脚虽然长得一样但是io数都不一样,甚至买的亚克力外壳都是给官方r3uno的,我傻了,看了一晚上引脚相关的教程,凌晨三点睡觉。

第二天我怕买来都不能用,于是就考虑买个一分二扩展板,结果那个扩展版一分二只是接线方便,一个口还是只能用一次,于是立刻转头考虑买r3uno,刷到源地的unor4,搜了搜发现r4和r3接口很兼容,而且性能也高,看到他家的开发板都不错,又顺便买了块esp32s3开发板。

由于uno的开发板接了屏幕后剩余接口不多,于是我就买了面包板和许多跳线,ST7789屏幕,INMP441全向麦克风,SHT30温湿度传感器,MAX98357音频放大器和一个小喇叭,这样可以把那款esp32s3uno只用来接屏幕,这些模块用来做一个桌面摆件,可以显示时间当前温湿度,也可以对话。

果真如我所料,那款接口一样的esp32s3uno直接插上屏幕后无法正常使用,使用tft_espi库配置好引脚后也不能用,于是寻求各路大神帮助,经过各种短接rst,修改多次库文件等各种操作,仍然不可用,屏幕测试程序运行后屏幕白屏,但是程序已经正常运行了,持续好几天,由于这款开发板网上没有任何资料,只有店铺扔出的引脚图片,最后我怀疑是引脚就是错误的,但是写了个程序测试了每个引脚,发现gpio47和gpio48接反了,而且gpio48和gnd短接了,但是这两个问题与屏幕没任何关联,于是也放弃不管,垃圾某宝卖家买的什么垃圾玩意。在网上搜到esp32s3文档中表面有的io口有特殊作用。gpio3与gpio46均为Strapping管脚,于是怀疑是不是这两个引脚的问题,搜索许多也没作用。

9月16号今天没上班,上午又在看,直接开干,不对插直接改变接线,用杜邦线重新连接,把gpio3与gpio46换成了gpio8和gpio9,屏幕显示正常,我立刻把8改回3发现还是正常,于是怀疑是gpio46的原因,就在我回去修改tft_espi配置文件的时候,妈的突然发现引脚定义配置旁边注释写着一条只能用gpio0-gpio31妈的我直接傻了,看了半天也没看到注释,于是我尝试修改gpio46到gpio8,尝试短接这两个端口后仍能正常刷入和开机使用,于是立刻将两个引脚背面焊了起来,现在一切正常。

翻箱倒柜找出来之前买的esp8266,把温湿度传感器接上了,让8266连接wifi后发送温湿度信息到局域网,然后再用esp32来接收。

#include <WiFi.h>
#include <WiFiUdp.h>
#include <TFT_eSPI.h>
#include <NTPClient.h>
#include <TimeLib.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>


const char* ssid = "SSID";
const char* password = "PASSWORD";
bool connectionSuccess;
const char* ntpServer = "NTPSERVER";
const int listenPort = PORT;
const long gmtOffset_sec = 28800;
const int daylightOffset_sec = 0;
unsigned long previousWeatherMillis = 0;
unsigned long lastReceiveTime = 0;
const unsigned long receiveInterval = 30000;
const unsigned long timeoutInterval = 300000;
unsigned long currentMillis = millis();
const long weatherInterval = 300000;
String url = "APIURL";
char timeStr[9];
char dateStr[11];
String temperature = "N/A";
String humidity = "N/A";
String textDay;
String high;
String low;
String humidity2;
String windy;
String precip;
String rainfall;
float precip_num = precip.toFloat();
int precip_percentage = static_cast<int>(precip_num * 100);
String precip_print = String(precip_percentage);

WiFiUDP udp;
WiFiUDP ntpUDP;
HTTPClient http;
NTPClient timeClient(ntpUDP, ntpServer, gmtOffset_sec, 60000);
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite sprite = TFT_eSprite(&tft);

void setup() {
  Serial.begin(115200);
  tft.init();
  tft.setRotation(3);
  sprite.createSprite(tft.width(), tft.height());
  sprite.fillRect(0, 0, 320, 240, TFT_BLACK);
  connectToWifi();
  timeClient.begin();
  getDateTime();
  udp.begin(listenPort);
  getUdpPacket();
  getWeather();
}

void loop() {
  sprite.fillRect(0, 0, 320, 240, TFT_BLACK);
  getDateTime();
  getUdpPacket();
  if (currentMillis - previousWeatherMillis >= weatherInterval) {
    previousWeatherMillis = currentMillis;
    getWeather();
  }
  if (millis() - lastReceiveTime > timeoutInterval) {
    temperature = "N/A";
    humidity = "N/A";
  }
  sprite.setTextColor(TFT_WHITE);
  sprite.setTextSize(3);
  sprite.setCursor(10, 20);
  sprite.print("Time:");
  sprite.print(timeStr);
  sprite.setTextSize(2);
  sprite.setCursor(10, 60);
  sprite.print("Date:");
  sprite.print(dateStr);
  sprite.setCursor(10, 90);
  sprite.print("Temperature:" + temperature);
  sprite.setCursor(10, 120);
  sprite.print("Humidity:" + humidity);
  sprite.setCursor(10, 150);
  sprite.print("Weather:" + textDay);
  sprite.setCursor(10, 180);
  sprite.print(low + "C~" + high + "C," + humidity2 + "%RH," + windy + "km/h");
  sprite.setCursor(10, 210);
  sprite.print(rainfall + "mm,Chance:" + precip_print + "%");
  sprite.pushSprite(0, 0);
  delay(1000);
}
void connectToWifi() {
    int attemptCount = 0;

    while (true) {
        sprite.fillRect(0, 0, 320, 240, TFT_BLACK);
        sprite.setTextColor(TFT_WHITE);
        sprite.setTextSize(3);
        sprite.setCursor(10, 80);
        sprite.print("Connecting...");
        sprite.pushSprite(0, 0);

        WiFi.begin(ssid, password);
        
        int cursorPosition = 10;
        attemptCount = 0;

        while (attemptCount < 5) {
            while (WiFi.status() != WL_CONNECTED) {
                sprite.setCursor(cursorPosition, 120);
                sprite.print(".");
                sprite.pushSprite(0, 0);
                cursorPosition += 20;
                if (cursorPosition > 80) {
                    cursorPosition = 10;
                }
                delay(1000);
            }

            if (WiFi.status() == WL_CONNECTED) {
                sprite.fillRect(0, 0, 320, 240, TFT_BLACK);
                sprite.setTextColor(TFT_WHITE);
                sprite.setTextSize(3);
                sprite.setCursor(10, 80);
                sprite.print("Connected!");
                sprite.pushSprite(0, 0);
                delay(3000);
                return;
            }

            attemptCount++;
        }

        sprite.fillRect(0, 0, 320, 240, TFT_BLACK);
        sprite.setTextColor(TFT_WHITE);
        sprite.setTextSize(3);
        sprite.setCursor(10, 80);
        sprite.print("Connection Failed!");
        sprite.setCursor(10, 120);
        sprite.print("Waiting 5 mins...");
        sprite.pushSprite(0, 0);
        delay(300000);
    }
}
void getDateTime() {
  timeClient.update();
  unsigned long epochTime = timeClient.getEpochTime();
  setTime(epochTime);
  sprintf(dateStr, "%04d-%02d-%02d", year(), month(), day());
  sprintf(timeStr, "%02d:%02d:%02d", hour(), minute(), second());
}
void getUdpPacket() {
  int packetSize = udp.parsePacket();
  if (packetSize) {
    String receivedData = "";
    while (udp.available()) {
      receivedData += (char)udp.read();
    }

    int tempIndex = receivedData.indexOf("Temperature:");
    int humidIndex = receivedData.indexOf("Humidity:");

    if (tempIndex != -1 && humidIndex != -1) {
      temperature = receivedData.substring(tempIndex + 12, receivedData.indexOf(",", tempIndex));
      humidity = receivedData.substring(humidIndex + 9);
      lastReceiveTime = millis();
    }
  }
}
void getWeather() {
  http.begin(url);
  int httpCode = http.GET();
  if (httpCode == 200) {
    String payload = http.getString();
    DynamicJsonDocument doc(2048);
    DeserializationError error = deserializeJson(doc, payload);
    if (error) {
            String textDay = "N/A";
            String high = "N/A";
            String low = "N/A";
            String windy = "N/A";
            String precip_print = "N/A";
            String rainfall = "N/A";
            http.end();
            return;
        }
    textDay = doc["results"][0]["daily"][1]["text_day"].as<String>();
    high = doc["results"][0]["daily"][1]["high"].as<String>();
    low = doc["results"][0]["daily"][1]["low"].as<String>();
    humidity2 = doc["results"][0]["daily"][1]["humidity"].as<String>();
    windy = doc["results"][0]["daily"][1]["wind_speed"].as<String>();
    precip = doc["results"][0]["daily"][1]["precip"].as<String>();
    rainfall = doc["results"][0]["daily"][1]["rainfall"].as<String>();
    http.end();
  }
}

改来改去不知道还能不能编译成功,闲置了,兴趣转瞬即逝了。