MQTT TRV based on a EQ3

Hi just wanted to share my latest project with you. MQTT trv based on the very cheep non Bluetooth EQ3 trv.

So let’s first tare one down



the original control board was replaced with a Wemos D1 mini. Since the motor is only 2 wire a L298N was used to control direction and a max471 used to sense motor stall current as the motor does not have a limit switch.

A few picks of the components used

Arduino code to follow in the next post

4 Likes
#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>



#define LED             2                      //wemos D1 led pin
#define Motorforward    4                     // H bridge motor forrward 
pin
#define Motorbackward   5                     // H bridge motor 
backwards pin
#define max471In        A0                     // input for max471 
current mon pin


#define MQTT_CLIENT     "mqtt_trv_1"          // mqtt client_id (Must be 
unique for each TRV)
#define MQTT_SERVER     "SERVER IP"                      // mqtt server
#define MQTT_PORT       1883                                 // mqtt port
#define MQTT_TOPIC      "home/trv_1"          // mqtt topic (Must be 
unique for each TRV)
#define MQTT_USER       "*******"                               // mqtt 
user
#define MQTT_PASS       "********" // mqtt password

#define WIFI_SSID       "******"                           // wifi ssid
#define WIFI_PASS       "*****"                           // wifi password

#define VERSION    "\n\n------------------  MQTT TRV v1.0 
------------------"

bool rememberMotorState = true;                              // If 
'true' remembers the state of the Motor before power loss.
bool sendStatus = false;                                     // (Do not 
Change)
bool requestRestart = false;                                 // (Do not 
Change)

int kUpdFreq = 1;                                            // Update 
frequency in Mintes to check for mqtt connection
int kRetries = 10;                                           // WiFi 
retry count. Increase if not connecting to router.
int lastMotorState;                                          // (Do not 
Change)

int RawValue= 0;                                             // (Do not 
Change)
float Current = 0;                                           // (Do not 
Change)

unsigned long TTasks;                                        // (Do not 
Change)
unsigned long count = 0;                                     // (Do not 
Change)

extern "C" {
   #include "user_interface.h"
}

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient, MQTT_SERVER, MQTT_PORT);


void callback(const MQTT::Publish& pub) {
   if (pub.payload_string() == "stat") {
   }
   else if (pub.payload_string() == "on") {
     digitalWrite(LED, LOW);
     trv_on();


   }
   else if (pub.payload_string() == "off") {
     digitalWrite(LED, HIGH);
     trv_off();

   }
   else if (pub.payload_string() == "reset") {
     requestRestart = true;
   }
   sendStatus = true;
}



void setup() {
   pinMode(max471In, INPUT);
   pinMode(Motorforward, OUTPUT);
   pinMode(Motorbackward, OUTPUT);
   pinMode(LED, OUTPUT);


   digitalWrite(LED, HIGH);
   analogWrite(Motorforward, 0);
   analogWrite(Motorbackward, 0);
   Serial.begin(115200);
   EEPROM.begin(8);
   lastMotorState = EEPROM.read(0);
   if (rememberMotorState && lastMotorState == 1) {
     digitalWrite(LED, LOW);
     trv_on();
   }
   if (rememberMotorState && lastMotorState == 0) {
     digitalWrite(LED, HIGH);
     trv_off();
   }


   mqttClient.set_callback(callback);
   WiFi.mode(WIFI_STA);
   WiFi.begin(WIFI_SSID, WIFI_PASS);
   Serial.println(VERSION);
   Serial.print("\nUnit ID: ");
   Serial.print("esp8266-");
   Serial.print(ESP.getChipId(), HEX);
   Serial.print("\nConnecting to "); Serial.print(WIFI_SSID); 
Serial.print(" Wifi");
   while ((WiFi.status() != WL_CONNECTED) && kRetries --) {
     delay(500);
     Serial.print(" .");
   }
   if (WiFi.status() == WL_CONNECTED) {
     Serial.println(" DONE");
     Serial.print("IP Address is: "); Serial.println(WiFi.localIP());
     Serial.print("Connecting to 
");Serial.print(MQTT_SERVER);Serial.print(" Broker . .");
     delay(500);
     while 
(!mqttClient.connect(MQTT::Connect(MQTT_CLIENT).set_keepalive(90).set_auth(MQTT_USER, 
MQTT_PASS)) && kRetries --) {
       Serial.print(" .");
       delay(1000);
     }
     if(mqttClient.connected()) {
       Serial.println(" DONE");
       Serial.println("\n----------------------------  Logs 
----------------------------");
       Serial.println();
       mqttClient.subscribe(MQTT_TOPIC);
       blinkLED(LED, 40, 8);

     }
     else {
       Serial.println(" FAILED!");
Serial.println("\n
"); 

       Serial.println();
     }
   }
   else {
     Serial.println(" WiFi FAILED!");
Serial.println("\n
"); 

     Serial.println();
   }
}

void loop() {
   mqttClient.loop();
   timedTasks();
   checkStatus();

}

void get_current() {
        RawValue = analogRead(max471In);
        Current = (RawValue * 5.0 )/ 1024.0;
        Serial.print("Current = ");                                  // 
shows the voltage measured
Serial.print(Current,3);                                     //3 digits 
after decimal point
        Serial.println(" amps DC");                                  //3 
digits after decimal point

}

void trv_on(){
        get_current();
        while(Current < 0.150){
          Serial.println("motorr moving backwads");
          analogWrite(Motorforward, 0);
          analogWrite(Motorbackward, 1023);
          delay(1000);
        get_current();
        if(Current > 0.150){
         analogWrite(Motorforward, 0);
         analogWrite(Motorbackward, 0);
         Serial.println("motor stop");
        }
        }
}

void trv_off(){
        get_current();
        while(Current < 0.150){
          Serial.println("motorr moving forwad");
          analogWrite(Motorforward, 1023);
          analogWrite(Motorbackward, 0);
          delay(1000);
        get_current();
        if(Current > 0.150){
         analogWrite(Motorforward, 0);
         analogWrite(Motorbackward, 0);
         Serial.println("motor stop");
        }
        }
}
void blinkLED(int pin, int duration, int n) {
   for(int i=0; i<n; i++)  {
     digitalWrite(pin, HIGH);
     delay(duration);
     digitalWrite(pin, LOW);
     delay(duration);
   }
}



void checkConnection() {
   if (WiFi.status() == WL_CONNECTED)  {
     if (mqttClient.connected()) {
       Serial.println("mqtt broker connection . . . . . . . . . . OK");
     }
     else {
       Serial.println("mqtt broker connection . . . . . . . . . . LOST");
       requestRestart = true;
     }
   }
   else {
     Serial.println("WiFi connection . . . . . . . . . . LOST");
     requestRestart = true;
   }
}

void checkStatus() {
   if (sendStatus) {
     if(digitalRead(LED) == LOW)  {
       if (rememberMotorState) {
         EEPROM.write(0, 1);
       }
       mqttClient.publish(MQTT::Publish(MQTT_TOPIC"/stat", 
"on").set_retain().set_qos(1));
       Serial.println("TRV . . . . . . . . . . . . . . . . . . ON");
       trv_on();
     } else {
       if (rememberMotorState) {
         EEPROM.write(0, 0);
       }
       mqttClient.publish(MQTT::Publish(MQTT_TOPIC"/stat", 
"off").set_retain().set_qos(1));
       Serial.println("TRV . . . . . . . . . . . . . . . . . . OFF");
       trv_off();
     }
     if (rememberMotorState) {
       EEPROM.commit();
     }
     sendStatus = false;
   }
   if (requestRestart) {
     blinkLED(LED, 400, 4);
     ESP.restart();
   }
}

void timedTasks() {
   if ((millis() > TTasks + (kUpdFreq*60000)) || (millis() < TTasks)) {
     TTasks = millis();
     checkConnection();
   }
}

1 Like

The next plan is to add oled screen to replace the LCD. Just waiting on the parts to arrive. Plan is to display current room temp and valve status

2 Likes

hove you got any further with this? i am intrigued i was hoping to do something similar and add dht22 for room temps

I bought this TRV to play with too.

I had 2 ideas :

  1. Remove the PCB and do a new one with an ESP
  2. Reprogram the STM and add a UART between an added ESP and the STM

Did you made some improvements ?

the old is a good idea too ! I’ll have a look. Do you have a reference ?

I am wondering if you are still using it 2 years later or you moved to something else. I am looking for smart TRV that can be locally controlled only but apparently I cannot find anything - all is closed source and cloud only and expensive as well. Let me know if you are still there please :wink:

The eq3 can be locally controlled by Bluetooth with no need for the phone app nor to be modified. Many of us have been struggling to get them to work past 2 months due to changes in HA. I have them working using Bluetooth on TASMOTA on esp32.

Thx, I was thinking about putting ESP there instead of the original board - this way ESPhome and no issues, right? or even DIY code in Arduino or so

Back in the day, I was dabbling a bit with building a battery powered ESP8266 temperature wensor. My takeaway was: I could get a battery life of a few months even with a very efficient power regulator and wake up from deep sleep every 10 minutes.

What I am saying: if you plug in a D1 mini, the battery life will be much shorter than the originally advertised 1 or 2 years :slight_smile: