hub8735
Published © GPL3+

Forecast Automatic weather Device

The purpose of this project is to HUB5168+Combine Stackable Circuit Modules SHT30 Temperature and humidity sensing SSD1306 OLED Display info

BeginnerFull instructions provided1 hour94
Forecast Automatic weather Device

Things used in this project

Hardware components

HUB-5168
×1
Grove - OLED Display 0.66" (SSD1306)- IIC - 3.3V/5V
Seeed Studio Grove - OLED Display 0.66" (SSD1306)- IIC - 3.3V/5V
×1

Software apps and online services

MQTT
MQTT

Story

Read more

Custom parts and enclosures

readme manual

step by step build project

Schematics

HUB 5168+Footprints

HUB5168+ useRTL8720DN(Wi-Fi+Bluetooth+BLE)Chip,
As Brand new design Beyond, exist PIN foot compatible in old model DSI5168, and attach 8bits QI/O.
When using separate boards, By back sheet flexible cable connection( Available I2C or UART to control, the right board is 8-bit I/O).

Code

library

Arduino
code library
Binary file (code library)

hub5168p.h

Arduino
head file
/* Analog pin mapping */
#define A0                                    	4 // PB_1 3.3V    CH4 
#define A1                                    	5 // PB_2 3.3V    CH5 
#define A2                                      6 // PB_3 3.3V    CH6

/* LED pin mapping */
#define LED_G                                   3 // AMB_D10  Green
#undef  LED_R                                  
#define LED_B                                   9 // AMB_D11  Blue
#define LED_BUILTIN                             LED_G   // AMB_D11  Green

#define SDA     4
#define SCL     7

ntp_dht11_i2cOLED_20221113.ino

Arduino
arduino ino file
#include <Arduino.h>
#include <ArduinoJson.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#include <PubSubClient.h>
#include "hub5168p.h"
#include <U8g2lib.h>
#include <TimeLib.h>
#include <HttpClient.h>
#include <DHT.h>
#include <Wire.h>
#include "SHT31.h"

#define DHTPIN 4
#define DHTTYPE DHT11   // DHT 11
DHT dht(DHTPIN, DHTTYPE);

#define U8X8_HAVE_HW_I2C

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

SHT31 sht;
uint32_t start;
uint32_t stop;

// WPA/WPA2 SSID and password
char ssid2[] = "Pos";      // your network SSID (name)
char pass2[] = "0222435183";  // your network password
char ssid1[] = "EricYangIoT";      // your network SSID (name)
char pass1[] = "66666666";  // your network password
int status  = WL_IDLE_STATUS;   // the Wifi radio's status

char mqttServer[]     = "broker.emqx.io";         // new ideaschain dashboard MQTT server
int mqttPort          = 1883;
char clientId[]       = "DSI5168Testxxx";         // MQTT client ID. it's better to use unique id,xxx the last 3 digits of the phone number
char username[]       = "1234";                   // device access token(存取權杖)
char password[]       = "";                       // no need password

char subscribeTopic[] = "HUB5168Sensor/xxx";       // xxx It is the last 3 digits of the phone number, or use all of phone number
char publishTopic[]   = "HUB5168Sensor/xxx";       // xxx It is the last 3 digits of the phone number, or use all of phone number

#define MQTT_RECONNECT_INTERVAL 100                   // millisecond
#define MQTT_LOOP_INTERVAL      50                    // millisecond
//----------------------------- openweathermap----------------------------------
//open weather map api key
String apiKey = "b3a1fd4de2403e47a564135a5be59821";
//the city you want the weather for
String location = "Taichung,TW";
char server[] = "api.openweathermap.org";

//-------------------------------- NTP Server setup---------------------------------------------------------
int keyIndex = 0;                                   // your network key Index number (needed only for WEP)
char timeServer[] = "time.stdtime.gov.tw";
const int timeZone = 8;                             // Taipei Time
// A UDP instance to let us send and receive packets over UDP
WiFiUDP Udp;
unsigned int localPort = 2390;                      // local port to listen for UDP packets
time_t getNtpTime();
void sendNTPpacket(IPAddress &address);
//------------------------------------MQTT Setup---------------------------------
void mqtt_callback(char* topic, byte* payload, unsigned int msgLength);  // MQTT Callback function header
WiFiClient wifiClient;
PubSubClient mqttClient(mqttServer, mqttPort, mqtt_callback, wifiClient);
//PubSubClient client(wifiClient);
unsigned long startTime, quarkStartTime, nowTime;   // Program start time and current time
unsigned long WifiConnectingTimeout; //Connection timeout

unsigned long weatherTimeoutStart;
int weatherTimeoutCounter = 0;
char *weekdayStr[7] = {"sun.", "mon.", "tue,", "wed.", "thu.", "fri.", "sat."};
String weatherStr, nowTemp, maxTemp, minTemp, humidity;
int getLoop = 0;


//------------------------------json6 object-------------------------------------------------------------
DynamicJsonDocument doc(3000);
char json_output[150];
long lastTime = 0;

boolean mqtt_nonblock_reconnect() {
  boolean doConn = false;

  if (! mqttClient.connected()) {
    // attempts to reconnect every [MQTT_RECONNECT_INTERVAL] milliseconds without blocking the main loop.
    long currTime = millis();
    if (currTime - lastTime > MQTT_RECONNECT_INTERVAL) {
      lastTime = currTime;
      doConn = true;
      //boolean isConn = mqttClient.connect(clientId);
      boolean isConn = mqttClient.connect(clientId, username, password);
      char logConnected[100];
      sprintf(logConnected, "MQTT System [%s] Connect %s !", clientId, (isConn ? "Successful" : "Failed"));
      Serial.println(logConnected);

      if (isConn) {

        mqttClient.subscribe(subscribeTopic);

      }
    }
  }

}

void mqtt_callback(char* topic, byte* payload, unsigned int msgLength) {

  char temp[80];
  sprintf(temp , "Message arrived with Topic [%s]\n  Data Length: [%d], Payload: [", topic, msgLength);
  Serial.print(temp);
  Serial.write(payload, msgLength);
  Serial.println("]");

  /*if (strcmp(subscribeTopic, topic) == 0) {                 // Topic: [HomeDevice/Button]

      String aresStr  = "";
      for (int i = 0; i < msgLength; i++) {
        aresStr += (char)payload[i];
      }      //  Payload: [On]


    }*/
}

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);


void setup() {

  pinMode(LED_G, OUTPUT);
  digitalWrite(LED_G, HIGH);
  Serial.begin(115200);
  digitalWrite(LED_G, LOW);
  
  Wire.begin();
  sht.begin(0x45);    //Sensor I2C Address
  Wire.setClock(100000);
  uint16_t stat = sht.readStatus();
  Serial.print(stat, HEX);
  Serial.println();

  u8g2.begin();
  u8g2.enableUTF8Print();

  u8g2.setFont(u8g2_font_unifont_t_chinese1); //Use our fonts
  u8g2.clearBuffer();
  u8g2.setCursor(0, 30);
  u8g2.print("Connecting, please wait...");
  u8g2.sendBuffer();
  
  WifiConn();
  if ( WiFi.status() == WL_CONNECTED ) {

    Serial.println("waiting for sync");
    Udp.begin(localPort);

  }
  else
    Serial.println("no network !!   ");
  digitalWrite(LED_G, HIGH);
  dht.begin();

  u8g2.begin();
  u8g2.enableUTF8Print();
  u8g2.setFont(u8g2_font_unifont_t_chinese1); //使用我們做好的字型
  Serial.println(WiFi.localIP());

  if (WiFi.status() == WL_CONNECTED )
  {
    u8g2.setCursor(30, 50);
    u8g2.print("Connection successful");
    u8g2.sendBuffer();
    setSyncProvider(getNtpTime);
    setSyncInterval(120);
  }
  u8g2.setFont(u8g2_font_ncenB08_tr);
  mqttClient.setServer(mqttServer, mqttPort);
  mqttClient.setCallback(mqtt_callback);

  delay(1000);
  getNtpTime();
  getWeather();
  while ( nowTemp.toInt() == 0 )
  {
    ++getLoop ;
    getWeather();
    if ( getLoop > 5)
    {
      Serial.println("getWeather error!!");
      break ;
    }
  }
  startTime =  millis();
}

void loop() {
  
  mqtt_nonblock_reconnect();
  
  sht.read();

  Serial.print("Temperature:");
  Serial.print(sht.getTemperature(), 1);
  Serial.print("\t");
  Serial.print("Humidity:");
  Serial.println(sht.getHumidity(), 1);
  
  
  if(minute()%30 == 0 && second()== 0 )
     getWeather();
 
  
  // display OLED
  u8g2.setFont(u8g2_font_ncenB08_tr);
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.drawStr(35,30,(String(hour()) + ":" + String(minute())+ ":" + String(second())).c_str());
  u8g2.drawStr(35, 64, ((String)"Humi: " + String(round(sht.getHumidity())) + (String)"%").c_str());
  u8g2.drawStr(35, 53, ((String)"Temp: " + String(round(sht.getTemperature())) + (String)" C").c_str());
  u8g2.drawStr(35, 42, (String(minTemp.toInt()) + "-" + String(maxTemp.toInt()) + (String)" C").c_str());
  u8g2.setFont(u8g2_font_unifont_t_chinese1);
  u8g2.setCursor(80, 35);
  u8g2.print(String( *(weekdayStr+weekday()-1) )); 
  u8g2.sendBuffer();                 // transfer internal memory to the display   */

  String Buff   ;
  
  DynamicJsonDocument json_doc(150);
  

  Serial.print("nowTemp: ");
  Serial.println(nowTemp);
  Serial.print("maxTemp: ");
  Serial.println(maxTemp);
  Serial.print("minTemp: ");
  Serial.println(minTemp);

  Buff += nowTemp ;                //The value is converted to String
  json_doc["NowTemp"] = Buff;

  Buff = "";
  Buff += humidity ;
  json_doc["Humi"] = Buff;
  
  Buff = "";
  Buff += weatherStr;
  json_doc["Weather"] = Buff;

  Buff = "";
  Buff += String(round(sht.getTemperature()));
  json_doc["RealTemp"] = Buff;

  Buff = "";
  Buff += String(round(sht.getHumidity()));
  json_doc["RealHumi"] = Buff;

  serializeJson(json_doc, json_output);
  Serial.print("JSON Str: ");
  Serial.println(json_output);
  digitalWrite(LED_G, LOW);
  delay(1000);
  if( second()% 10 == 0)
    mqttClient.publish(publishTopic, json_output);
  digitalWrite(LED_G, HIGH);
  mqttClient.loop();
  delay(MQTT_LOOP_INTERVAL);
}

/*-------- NTP code ----------*/
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets

time_t getNtpTime()
{
  Serial.println("Transmit NTP Request");
  //Udp.setRecvTimeout(1500);
  sendNTPpacket();
  if ( Udp.read(packetBuffer, NTP_PACKET_SIZE) > 0 ) {
    unsigned long secsSince1900;
    // convert four bytes starting at location 40 to a long integer
    secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
    secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
    secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
    secsSince1900 |= (unsigned long)packetBuffer[43];
    return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
  } else {
    // Unable to obtain NTP, try to connect to the Internet again to keep the network connected at all times; if the network is idle for 2-3 minutes, it will enter power saving or sleep mode, which will result in the inability to connect to the Internet, although WL_CONNECTED == True
    Serial.println("No NTP Response :-(");
    return 0; // return 0 if unable to get the time
  }
}

// send an NTP request to the time server at the given address
void sendNTPpacket()
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  Udp.beginPacket(timeServer, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

time_t getWeather() {

  String jsonTmp ;
  wifiClient.stop();
  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (wifiClient.connect(server, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    wifiClient.print("GET /data/2.5/weather?");
    wifiClient.print("q=" + location);
    wifiClient.print("&appid=" + apiKey);
    wifiClient.print("&cnt=3");
    wifiClient.println("&units=metric");
    wifiClient.println("Host: api.openweathermap.org");
    wifiClient.println("Connection: close");
    wifiClient.println();
    wifiClient.flush();
  } else {
    Serial.println("unable to connect");
  }

  delay(500);
  while (wifiClient.available())
  {
    String jsonData = wifiClient.readStringUntil('\r');  //Read column by column
    Serial.println(jsonData);
    DeserializationError error = deserializeJson(doc, jsonData);

    // Test if parsing succeeds.
    if (error) {
      Serial.print(F("deserializeJson() failed: "));
      Serial.println(error.c_str());
      //return;
    }
    //JsonArray array = doc.as<JsonArray>();
    String Str1 = doc["main"]["temp"];
    String Str2 = doc["main"]["temp_min"];
    String Str3 = doc["main"]["temp_max"];
    String Str4 = doc["weather"][0]["main"];
    String Str5 = doc["main"]["humidity"];

    nowTemp = Str1;
    minTemp = Str2;
    maxTemp = Str3;
    weatherStr = Str4;
    humidity = Str5;


    Serial.print("current temperature: ");
    Serial.println(nowTemp);
    Serial.print("lowest temperature: ");
    Serial.println(minTemp);  //Display temperature value
    Serial.print("maximum temperature: ");
    Serial.println(maxTemp);  //Display temperature value
    Serial.print("weather conditions: ");
    Serial.println(weatherStr);
    Serial.print("humidity: ");
    Serial.println(humidity);
  }
}

void WifiConn()
{
  Serial.print("Connecting to ");
  Serial.println(ssid1);

  WiFi.begin(ssid1, pass1);
  WifiConnectingTimeout = millis();
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid1);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    //WiFi.begin(ssid1, pass1);
    if ((millis() - WifiConnectingTimeout) > 10000) //wait 10 sec
      break;
    delay(500);
    Serial.print(".");
  }
  if (WiFi.status() != WL_CONNECTED)
  {
    WifiConnectingTimeout = millis();
    WiFi.begin(ssid2, pass2);
    while (WiFi.status() != WL_CONNECTED) {
      Serial.print("Attempting to connect to SSID: ");
      Serial.println(ssid2);
      // Connect to WPA/WPA2 network. Change this line if using open or WEP network:

      if ((millis() - WifiConnectingTimeout) > 10000) //wait 10 sec
        break;
      delay(500);
      Serial.print(".");
    }
  }

}

Credits

hub8735
5 projects • 79 followers
Contact

Comments

Please log in or sign up to comment.