Homeyduino display

Just thought that I could share the Arduino code for my small Homeyduino display project. It is based on a small Wemos D1 mini and its tft 2.4 touch screen display, (found here https://www.aliexpress.com/item/32919729730.html). Not much soldering (just the pins on the Wemos). To be able to trigger a Homey flow by touching the screen you first have to touch the screen once and then create the device flow card. The code is substantially based on code by maxxie01 from the Homeyduino channel on Slack.

!
!
!

Here’s the code (some hardcoded degree symbols and a custom font from http://oleddisplay.squix.ch/ but other than that you can just start using it). When you have uploaded the code to the board you can log in to the wifi of the device and set up SSID and so on.

/*
   Homey Arduino library
   Usage example for use with ESP8266

   Most of the code in this file comes from the ethernet usage examples included with Arduino
   Also the code at https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay has been included to
   show you how to read sensors and emit triggers without using the delay function.

*/

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiManager.h>
#include <Homey.h>
#include <SPI.h>                //I2C interface for OLED display
#include <Wire.h>               //I2C interface for OLED display
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <XPT2046_Touchscreen.h>
#include <Fonts\URW_Gothic_L_Demi_20.h> // custom fonts, see http://oleddisplay.squix.ch/#/home
#include <Fonts\URW_Gothic_L_Demi_70.h>


//Wifi manager starts as AccessPoint if there is no wifi connection
WiFiManager wifiManager;

//OLED config
#define TFT_CS D0  //for D1 mini or TFT I2C Connector Shield (V1.1.0 or later)
#define TFT_DC D8  //for D1 mini or TFT I2C Connector Shield (V1.1.0 or later)
#define TFT_RST -1 //for D1 mini or TFT I2C Connector Shield (V1.1.0 or later)
#define TS_CS D3   //for D1 mini or TFT I2C Connector Shield (V1.1.0 or later)

//Global variables used for the blink without delay example
unsigned long previousMillis = 0;
const unsigned long interval = 5000; //Interval in milliseconds

//put text received from Homey into this
//if number of rows are changed, change this
String textRow[] = {"","","","","","","","",""};
String receivedHomey;

IPAddress ip;
bool isFirst = true;
byte t = 0; //wait 
String textWait[] = {"-","\\","/"};
bool success;

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
XPT2046_Touchscreen ts(TS_CS);

//Arduino functions
void setup() {
  //Enable serial port
  Serial.begin(115200);
  Serial.println("Setup start");

  //init OLED display
  tft.begin();
  delay(500);

  // init touch
  ts.begin();
  ts.setRotation(1);
  
  //Connect to network
  String deviceName = "OLED-" + String(ESP.getChipId()); //Generate device name based on ID
  Serial.print("wifiManager...");
  Serial.println(deviceName);
  wifiManager.autoConnect(deviceName.c_str(), ""); //Start wifiManager
  Serial.println("  Connected!");
  ip = WiFi.localIP();
  Serial.print(" IP address: ");
  Serial.println(ip.toString());
  
  showText(3, "IP number", false);
  showText(3, ip.toString(), true);
    
  //Start Homey library
  Homey.begin("arduinodisplay");
  Homey.setClass("sensor");

  Homey.addAction("Row1", onArduinoReceivedText1);   
  Homey.addAction("Row2", onArduinoReceivedText2);   
  Homey.addAction("Row3", onArduinoReceivedText3);   
  Homey.addAction("Row4", onArduinoReceivedText4);   
  Homey.addAction("Row5", onArduinoReceivedText5);   
  Homey.addAction("Row6", onArduinoReceivedText6);
  Homey.addAction("Row7", onArduinoReceivedText7);
  Homey.addAction("Row8", onArduinoReceivedText8);     
  Homey.addAction("Background", onArduinoReceivedBackground);

  Serial.println("Setup completed");
}

void loop() {

  // touch trigger to Homey
  // run the trigger once, then it appears as a device flow card

  if (ts.touched())
  {

    Homey.trigger("touch", "touch");
    Serial.println("touch");
    
  }
  
  //Handle incoming connections
  Homey.loop();
  /* Note:
      The Homey.loop(); function needs to be called as often as possible.
      Failing to do so will cause connection problems and instability.
      Avoid using the delay function at all times. Instead please use the
      method explaind on the following page on the Arduino website:
      https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
  */

  //This is the 'blink without delay' code
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    //(This code will be executed every <interval> milliseconds.)
    
    if (isFirst){
      Homey.trigger("IPnumber", ip.toString());
      isFirst = false;
    }
    
    //Emit a trigger to Homey
    //bool success = Homey.trigger("mytrigger", "Hello world");
    /* Note:
     *  The first argument to the emit function is the name of the trigger  
     *  this name has to match the name used in the flow editor
     *  
     *  The second argument to the emit function is the argument.
     *  An argument can be one of the following:
     *     - a string
     *     - an integer (int)
     *     - a floating point number (float or double),
     *     - a boolean (bool)
     *     - nothing (void)
     *  
     *  Make sure to select the right type of flow card to match the type
     *  of argument sent to Homey.
     *  For a string argument the "text" flowcard is used.
     *  For an integer or floating point number the "number" flowcard is used.
     *  For the boolean argument the "boolean" flowcard is used.
     *  And when no argument is supplied the flowcard without argument is used.
     *  
     */

  }
}

  /* Note:
   *  
   *  The argument will always be received as a String.
   *  If you sent a number or boolean from homey then you can convert
   *  the value into the type you want as follows:
   *  
   *   - Integer number: "int value = Homey.value.toInt();"
   *   - Floating point number: "float value = Homey.value.toFloat();"
   *   - Boolean: "bool value = Homey.value.toInt();"
   *   - String: "String value = Homey.value;"
   *  
   * In case something goes wrong while executing your action
   * you can return an error to the Homey flow by calling
   * Homey.returnError("<message>");
   */

void onArduinoReceivedText1(){showText(1, Homey.value, true);}
void onArduinoReceivedText2(){showText(2, Homey.value, true);}
void onArduinoReceivedText3(){showText(3, Homey.value, true);}
void onArduinoReceivedText4(){showText(4, Homey.value, true);}
void onArduinoReceivedText5(){showText(5, Homey.value, true);}
void onArduinoReceivedText6(){showText(6, Homey.value, true);}
void onArduinoReceivedText7(){showText(7, Homey.value, true);}
void onArduinoReceivedText8(){showText(8, Homey.value, true);}

void onArduinoReceivedBackground(){tft.fillScreen(Homey.value.toFloat());

float tmpHomey = Homey.value.toFloat();
Serial.println("homey send: " + String(tmpHomey));
 }


void showText(byte row, String text, boolean show){
  Serial.print("row: ");
  Serial.print(row);
  Serial.print(", text: ");
  Serial.print(text);
  Serial.print(", show: ");
  Serial.print(show);
  textRow[row] = text;
  Serial.print(", textRow[row]: ");
  Serial.println(textRow[row]);

  
  
  if(show){
    //tft.fillScreen(ILI9341_BLACK);
    
    tft.fillCircle(175,33,5,65535);
    tft.fillCircle(175,103,5,65535);
    tft.setFont(&URW_Gothic_L_Demi_70);
    tft.setTextSize(1);
    tft.setTextColor(ILI9341_WHITE);
    tft.setCursor(10,80);
    tft.print(textRow[1]);
    tft.setCursor(175,80);
    tft.println("C");
    tft.setCursor(10,150);
    tft.print(textRow[2]);
    tft.setCursor(175,150);
    tft.println("C");
    tft.setFont(&URW_Gothic_L_Demi_20);
    tft.setCursor(10,198);
    tft.println(textRow[3]);
    tft.setCursor(10,220);
    tft.println(textRow[4]);
    tft.setCursor(10,242);
    tft.println(textRow[5]);
    tft.setCursor(10,264);
    tft.println(textRow[6]);
    tft.setCursor(10,286);
    tft.println(textRow[7]);
    tft.setCursor(10,308);
    tft.println(textRow[8]);
  }
}
8 Likes

Excellent… well done… thanks for sharing everything!

Interested to know what’s next

Thanks! Hm, next project is to build a small enclosure box out of plywood. (3D printing feels sooo 2019, hehe).

And then build some more sensors (the Senseair sunrise CO2 sensor, and Sensirion SPS30 particulate matter sensor) and then update my outdoor air quality sensor with measuring NO2 and O3 and then a power meter, hehe!

Nice! Do you have a special reason to use the SenseAir sunrise? Which sensor(s) are you using for temp/hum/VOC? Obviously sensors are outside display part. Why is that?

No, real reason why to use the sunrise sensor. I already have one Senseair S8, so I thought it was nice with the newest Senseair sensor, and it was a discount. Still expensive, though. Hehe.

The reason why there’re no sensors attached is because the display shows an average of the other sensors. The outdoor temperature shows a group sensor (the lowest of one aqara sensor, one 433mhz sensor and the heating outdoor sensor catched through Rest API), the indoor temperature is the average of eight indoor sensors, mostly aqara but also some netatmo healthy home coaches and one airthings wave plus. The CO2 is the average of the netatmos, one homeyduino senseair s8 and the airthings (which is a senseair sunrise). VOC is also the airthings sensor (with its BME680 sensor).

What did you pay for the sunrise sensor? I have seen some “cheap” S8’s on Aliexpress (+/-€ 25,00) but I wonder whether they are fake. Good idea to take the average of multiple sensors because no sensor/location is alike. I read somewhere that the Netatmo CO2 sensors are not that reliable, what’s your experience?

Paid around 50 euro, so it wasn’t cheap, but still. Bought if from the source, or at least a guy working close to the company. https://firstbyte.shop/products/s11

Regarding the netatmo CO2 sensors my experience is that they’re pretty on spot around 400-1000ppm but that they show too high values above that? But it is just a feeling. Can compare with my airthings which is easy to move around. (The senseair autocalibrates every 8th day, but only if it has been powered the whole time, I think.).

According to this source (https://orbit.dtu.dk/en/publications/accuracy-and-air-temperature-dependency-of-commercial-low-cost-nd) the netatmo works fine when the temperature is the same as when calibrated. “Calibration of cloud-based sensors is essential to obtain credible results. The CO2 sensors in the Netatmo modules were highly dependent on the air temperature. In the Netatmo modules it was found that accuracy of CO2 concentration measurements was high if the value of air temperature under investigation was close to the air temperature in which the manual calibration occurred.”


The comparison between the airthings wave plus (senseair sunrise) and netatmo healthy home coach. Pretty similar. Just like I thought the netatmo show slightly higher values when the values are high.

@rindler hello. Would you please give me more info about this project? Which software and hardware did u used? I need display as u link above and what else?
I think this one:
LOLIN D1 Mini V3.1.0 - WEMOS ESP8266 4MB MicroPython Nodemcu Arduino Compatible
LOLIN D1 Mini V3.1.0 WEMOS WIFI Internet of Things Board based ESP8266 4MB MicroPython Nodemcu Arduino Compatible|d1 mini|wemos d1 miniwemos d1 - AliExpress ? … And what else?

Yes, the only hardware you need is that wemos you posted in the link, and then the display in the first post. You don’t need no dupont cables or similar, since the display is a shield which can be connected straight to the wemos. But you need a soldering iron to fasten the pins.

Then you connect the wemos to a computer with a usb cable and upload the firmware with Arduino IDE, https://www.arduino.cc/en/software. And you need that Homeyduino app from Homey app store.

Have flows which update the display every 10th minute with actions like this.

2 Likes

Thanks for your introduction on how to make this. I have got it working (almost)!!

Update: Working!!! Thanx!

I use it to monitor how much energy I get from the grid or are pushing energy back to the grid with my solar panels. Energey measurement is done with a Smile P1.

Voorkant

1 Like

Hi!
Should both rows of connections on the WeMOS be connected to the display? Hard to see on the picture.

Best regards Anders

Hi, Yes. Maybe these 2 pictures help.

20220204_144045.jpg

Perfect, thanks for the info.

@rindler This is perfect!

Thanks!

I have a project coming that need som Arduino/Homeyduino magic so hope I can ask you some advice when the time comes.

Meanwhile, this was a fun little project, think I need to add this to my list

1 Like

Hi!
I have it up and running now.
I have two questions:

  1. When sending new text to abrow it is written over the current text. How do I remove the old text? How do I make a row empty again?
    I guess I need to repaint the whole display?

  2. What values to send for background colour? Is it RGB as HEX ffffff?

  1. Just uncomment the line about the background.
 if(show){
    tft.fillScreen(ILI9341_BLACK);
    
    tft.fillCircle(175,33,5,65535);
    tft.fillCircle(175,103,5,65535);

I ended up setting the background from Homey, with the line tft.fillScreen(background);. Then you have to set background (black) in the beginning of the code float background = 0; and add void onArduinoReceivedBackground(){background = (Homey.value.toFloat()); among the other void onArduinoReceived lines.

  1. Think you can use the RGB565 values from here RGB565 Color Picker - Barth Development Maybe you need to convert the hexadecimal value to decimal value afterwards.

Hi!
Thanks. I tought so.
Think I will set variable background from the onArduinoReceivedBackground() like this

float background = 0;

…

onArduinoReceivedBackground(){
{
background = Homey.value.toFloat();
tft.fillScreen(background);
}

And use that in showText.

How do you mount your display?
I am think of using a photo frame, but do you have better tips?