simple esp8266 weather display

A simple dot matrix display showing weather data directly from openweathermap.org

This is not a clock but i has its place right under the tv , it has no buttons no controls whatsoever and it just shows you current weather forecast

yeah yeah , i know , nothing new here , yet another one weather thingy. But its something new for me and my first device that uses an esp board , hooollyy shit im ecstatic as fuck! So much memory , wifi on board , so much info and the good thing is that you can use it in arduino IDE

The project only uses 2 parts. A board containing 4 dot matrix displays driven by 4x MAX7219 display drivers and an ESP8266 (ESP-12E Module) board . The only connections made on the board is connecting the power between the 3v3 pin of the esp to the vcc of the display , the grounds and for data transfer D5 goes to CLK , D7 goes to DATA and D8 goes to CS.. Thats it!

So the connections are the following:

  • 3v3 -> VCC
  • Gnd -> Gnd
  • D5 -> CLK
  • D7 -> DATA
  • D8 -> CS

 

 

 

For the software the`re some that must be done to use the ESP with the arduino. I will not go into this , theres a shitload of examples out there showing exactly how is done. So lets assume this is done there are some libraries that must be installed . Those are  the ArduinoJson.h  and the MD_MAX72xx.h.  Those can be installed through arduino IDE (you can google how) .The other libraries seen in the project are probably already included if you installed the boards correctly.

The outer shell was 3d printed using PLA , the external body was made using natural PLA and the interal was made using blue PLA. I always liked how the internal frame looks like through the semitransparent outer skin

The stl can be found in thingiverse here  without printing its backplate because i wanted to use the onboard usb cable to power the device. It was christmas so i just wanted to chill , watch movies and stuff instead of making a psu for this.

here you can see it in action:

 

The software , once again , its nothing extreme as you will find or anything new. There where some ideas taken from other examples i`ve found out there (didnt save the links though..) At the beginning i tried to make it work as a wifi hotspot and server so i could dial my wifi credentials. Then i found out that there are some wifi manager libraries o could use ,but there were a ton of problems (for some reason it wouldn`t compile at all , even the examples didnt work for some reason) so i tried once again to set my small server. This obviously didnt work very well so i got quickly bored and said “the fuck with that, i will just make it to work for me”. Eh  may be some day , who knows..

So here it is


#include 
#include         // JSON decoding library
#include   // http web access library
#include 
#include     

#define DEFAULT_BRIGHTNESS 3

#define MAX_DEVICES 4

#define CLK_PIN   D5 // or SCK
#define DATA_PIN  D7 // or MOSI
#define CS_PIN    D8 // or SS
#define DELAYTIME  50 //for scrolling
#define CHAR_SPACING  1 // pixels between characters
#define BUF_SIZE  75

int br_addr = 0;//address for brightness
int brightness = 0;
const char *ssid     = "your ssid";
const char *password = "your code";

//weather data
float temp, feeltemp, pressure, wind_speed, rain_1h;
int humidity, wind_degree, clouds;
String description, dayOfTheWeek, currentDateTime;
int state = 0;

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

void scrollUp(){
  for (uint8_t i = 0; i < 8; i++) {
    mx.transform(MD_MAX72XX::TSU); delay(DELAYTIME-10);
    delay(DELAYTIME);
  }
}

void scrollDown(){
  for (uint8_t i = 0; i < 8; i++) {
    mx.transform(MD_MAX72XX::TSD); delay(DELAYTIME-10);
    delay(DELAYTIME);
  }
}


void scrollLeft(){                                             
  for (uint8_t i = 0; i < 32; i++) {
    mx.transform(MD_MAX72XX::TSL); delay(DELAYTIME-35);
    delay(DELAYTIME);
  }
}

void scrollText(String input_text){
  uint8_t charWidth;
  uint8_t cBuf[8];
  const char *p;
  int descsize = input_text.length() + 1;
  char descbuff[descsize];
  input_text.toCharArray(descbuff , descsize);
  p = descbuff;
  
  mx.clear();
  while (*p != '\0')
  {
    charWidth = mx.getChar(*p++, sizeof(cBuf) / sizeof(cBuf[0]), cBuf);

    for (uint8_t i=0; i<=charWidth; i++)  // allow space between characters
    {
      mx.transform(MD_MAX72XX::TSL);
      if (i < charWidth)
        mx.setColumn(0, cBuf[i]);
        delay(DELAYTIME);
    }
  }
}

void printText(int leftpad,uint8_t modStart, uint8_t modEnd, char *pMsg){
  uint8_t   state = 0;
  uint8_t   curLen;
  uint16_t  showLen;
  uint8_t   cBuf[8];
  int16_t   col = ((modEnd + 1) * COL_SIZE) - leftpad;
 
  mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::OFF);
  do   
  {
    switch(state)
    {
      case 0: 
        if (*pMsg == '\0')
        {
          showLen = col - (modEnd * COL_SIZE);  // padding characters
          state = 2;
          break;
        }
        showLen = mx.getChar(*pMsg++, sizeof(cBuf)/sizeof(cBuf[0]), cBuf);
        curLen = 0;
        state++;
      case 1:
        mx.setColumn(col--, cBuf[curLen++]);
        if (curLen == showLen)
        {
          showLen = CHAR_SPACING;
          state = 2;
        }
        break;
      case 2:
        curLen = 0;
        state++;
      case 3:
        mx.setColumn(col--, 0);
        curLen++;
        if (curLen == showLen)
          state = 0;
        break;
      default:
        col = -1;   // this definitely ends the do loop
    }
  } while (col >= (modStart * COL_SIZE));
  mx.control(modStart, modEnd, MD_MAX72XX::UPDATE, MD_MAX72XX::ON);
}

void setup() {
  Serial.begin(115200);
  mx.begin();
  mx.control(MD_MAX72XX::INTENSITY, DEFAULT_BRIGHTNESS);

  WiFi.begin(ssid, password);
  delay(5000);
}

void getWeatherData(){
  // WEATHER DATA =======================================================
  HTTPClient http;
  http.begin("http://api.openweathermap.org/data/2.5/weather?q=Ilion,gr&APPID=a9284b0f9cf23773a8d2d3f4406169c9");
  int httpCode = http.GET();
 
  if (httpCode > 0) {
    String payload = http.getString();
    DynamicJsonBuffer jsonBuffer(512);
    
    JsonObject& root = jsonBuffer.parseObject(payload);
    if (!root.success()) {
      Serial.println(F("Parsing failed!"));
      return;
    }
    //update weather data
    temp = (float)(root["main"]["temp"]) - 273.15;        // get temperature
    feeltemp = (float)(root["main"]["feels_like"]) - 273.15;        // get temperature
    humidity = root["main"]["humidity"];                  // get humidity
    pressure = (float)(root["main"]["pressure"]) / 1000;  // get pressure
    wind_speed = root["wind"]["speed"];                   // get wind speed
    wind_degree = root["wind"]["deg"];
    rain_1h = root["rain"]["1h"];
    clouds = root["clouds"]["all"];
    description = root["weather"][0]["description"].as();  
    }

  http.end();   //Close connection
  
  state = 1;
}


void displayWeatherData(){

  char t[30];
  
  scrollText("Current weather");
  scrollLeft();
  scrollText(description);
  scrollLeft();
  
  scrollText("Outside Temperature");
  scrollUp();
  dtostrf(temp, 1, 1, t);
  strcat(t,"C");
  printText(1,0,MAX_DEVICES-1,t);
  delay(5000);
  scrollLeft();
  
  scrollText("Feels like temp");
  scrollDown();
  dtostrf(feeltemp, 1, 1, t);
  strcat(t,"C");
  printText(1,0,MAX_DEVICES-1,t);
  delay(5000);
  scrollLeft();

  scrollText("Outside Humidity %");
  scrollUp();
  itoa(humidity,t,10);
  strcat(t,"%");
  printText(1,0,MAX_DEVICES-1,t);
  delay(5000);
  scrollLeft();

  scrollText("Atmospheric Pressure");
  scrollDown();
  dtostrf(pressure, 1, 3, t);
  strcat(t," b");
  printText(1,0,MAX_DEVICES-1,t);
  delay(5000);
  scrollLeft();

  scrollText("Wind Speed m/s");
  scrollUp();
  dtostrf(wind_speed, 1, 1, t);
  strcat(t,"ms");
  printText(1,0,MAX_DEVICES-1,t);
  delay(5000);
  scrollLeft();

  scrollText("Wind Direction");
  scrollDown();
  itoa(wind_degree,t,10);
  strcat(t,"dg");
  printText(1,0,MAX_DEVICES-1,t);
  delay(5000);
  scrollLeft();

  scrollText("Rain height mm/h");
  scrollUp();
  dtostrf(rain_1h, 1, 1, t);
  strcat(t,"mm");
  printText(1,0,MAX_DEVICES-1,t);
  delay(5000);
  scrollLeft();

  scrollText("Cloud Coverage %");
  scrollDown();
  itoa(clouds,t,10);
  strcat(t,"%");
  printText(1,0,MAX_DEVICES-1,t);
  delay(5000);
  scrollLeft();

  state = 0;
}

void getDateTimeData(){
  // DATE TIME =======================================================
  HTTPClient http_time;
  http_time.begin("http://worldclockapi.com/api/json/utc/now");
  int httpCode_time = http_time.GET();  // send the request
 
  if (httpCode_time > 0) {
    String payload_time = http_time.getString();
    DynamicJsonBuffer jsonBuffer_time(512);

    JsonObject& root_time = jsonBuffer_time.parseObject(payload_time);
    if (!root_time.success()) {
        scrollText("Time parsing failed");
        scrollLeft();
      return;
    } else {
      dayOfTheWeek = root_time["dayOfTheWeek"].as();
      currentDateTime = root_time["currentDateTime"].as();
    }
  }
  http_time.end();
}

void displayDateTime(){
  currentDateTime.replace("T"," ");
  currentDateTime.replace("Z","");
  scrollText(currentDateTime+" "+dayOfTheWeek);
  scrollLeft();
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
      
      if(state == 0){
        getWeatherData();
        getDateTimeData();//the state is returning to 1 after this ends
      }

      if(state == 1){
        displayDateTime();
        displayWeatherData();//the state is returning to 0 after this ends
      }
  } else {
    scrollText("Connecting to wifi");
    scrollLeft();
  }
}