Geekzone: technology news, blogs, forums
Guest
Welcome Guest.
You haven't logged in yet. If you don't have an account you can register now.




406 posts

Ultimate Geek


#195424 19-Apr-2016 20:47
Send private message

Been working on this code to work with HRV home recovery ventilation system, happy to share the code... basically utilises an Arduino Uno REV3 + Ethernet shield.  It connects into the HRV Control Panel and grabs TTL serial data, interprets it and sends the HRV Roof and House Temperatures (and control panel temperature settings + fan speed, if you want to edit code and send that too) to an MQTT Broker (which I have running on OpenHAB)  The ribbon cable from roof to HRV control panel has 6 wires, the outside 2 wires (1 and 6) are 5V power, the next two wires in (2 and 5) are GND and the middle two wires (3 and 4) are TTL serial RX/TX (which it both sends and receives on the same wire)  Put an RJ11 splitter between HRV control panel and ribbon cable from roof controller, then make your own ribbon cable into the split port.  You only need to split one of each wire (1 x 5V, 1 x GND and 1 x data)  Run 5V into Arduino 5V (be aware, this will power the Arduino but is not recommended, best to put a diode in - I take no responsibility if you fry your Arduino) then run GND to GND then run one of the data lines into GPIO pin 7.

 

Assumes you have OpenHAB and MQTT broker already setup.  Change your IP in MQTT broker to suit your setup.

 

No doubt pasting will lose indentation..., can't use BBCode coz I have array declared in code!

 

 

 

//
// Reads HRV serial data and sends to MQTT broker
// Author: chimera
// Date: 19 April 2016
//
// RX/TX native generates an err02 in HRV control panel
// Credit to: http://www.hexperiments.com/?page_id=47 for data structure
// Credit to: https://github.com/benrugg/Arduino-Hex-Decimal-Conversion for Dec/Hex conversion
//

 

#include <PubSubClient.h>
#include <Ethernet.h>
#include <SoftwareSerial.h>

 

// HRV
#define MSGSTARTSTOP 0x7E
#define HRVROOF 0x30
#define HRVHOUSE 0x31

 

// MQTT subs
#define OPENHABHRVSUBHOUSE "openhab/hrv/housetemp"
#define OPENHABHRVSUBROOF "openhab/hrv/rooftemp"

 

// TTL Serial on GPIO ports (HRV does not like RX/TX ports!)
SoftwareSerial hrvSerial(7, 8); // RX, TX

 

// MQTT Broker
IPAddress MQTT_SERVER(192, 168, 222, 254);

 

// The IP address of the Arduino
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

 

// Define message buffer and publish string
char message_buff[10];
String pubString;

 

// TTL serial data indicators
bool bStarted = false;
bool bEnded = false;

 

// Temperature from Roof or House?
char eTempLoc;

 

// TTL Serial data array, bIndex, bIndex of checksum and temperature
byte inData[10];
byte bIndex;
byte bChecksum;
float fHRVTemp;

 

// Ethernet Initalization
EthernetClient ethClient;

 

// Callback to Arduino from MQTT (inbound message arrives for a subscription)
void callback(char* topic, byte* payload, unsigned int length) {

 

// Messaging inbound from MQTT broker
int iChar = 0;
for(iChar=0; iChar<length; iChar++) {
message_buff[iChar] = payload[iChar];
}
message_buff[iChar] = '\0';

 

// This can be used in a future revision to control the HRV control panel

 

}

 

// Define Publish / Subscribe client (must be defined after callback function above)
PubSubClient mqttClient(MQTT_SERVER, 1883, callback, ethClient);

 


void setup()
{
// Start HRV serial
hrvSerial.begin(1200);

 

// Start Network (replace with 'Ethernet.begin(mac, ip);' for fixed IP)
while (Ethernet.begin(mac) == 0) {
Serial.println("Could not obtain DHCP lease");
delay(5000);
}

 

// Let network have a chance to start up
delay(1500);

 

// Debug USB serial
Serial.begin(1200);

 

// Initialize defaults
bIndex = 0;
bChecksum = 0;

 

// Show the IP address
printIPAddress();

}

 


void loop()
{

 

// If not MQTT connected, try connecting
if (!mqttClient.connected()) {

 

// Connect to MQTT broker on the openhab server, retry constantly
while (mqttClient.connect("hrv") != 1) {
Serial.println("Error connecting to MQTT (State:" + String(mqttClient.state()) + ")");
delay(1000);
}

}

 

// Flush stale data
hrvSerial.flush();

// Only if we're plugged in...
while (hrvSerial.available() > 0)
{

// Read serial data
int inChar = hrvSerial.read();

 

// Start/Stop marker, which is it? Wait til next loop
if (inChar == MSGSTARTSTOP)
{
// Start if first time we've got the message
if (bIndex == 0)
{
bStarted = true;
}
else
{
bChecksum = bIndex-1;
bEnded = true;
break;
}

 

}

 

// Grab data
if (bStarted == true)
{

// Double check we actually got something
if (sizeof(inChar) > 0)
{

 

//Serial.print(inChar, HEX);
//Serial.print(",");
inData[bIndex] = inChar;
bIndex++;
}

}

}

 

// Validate data, or if not enough data will fail
if (bStarted && bEnded && bChecksum > 0)
{
int iChar;
int iLess;

 

// Checks
byte bCalc;
String sCalc;
byte bCheck;
String sCheck;

 

// Subtract from zero
iChar = 0;

// Subtract each byte in ID and data
for (int iPos=1; iPos < bChecksum; iPos++)
{
iLess = inData[iPos];
iChar = iChar - iLess;
}

// Convert calculations
bCalc = (byte) (iChar % 0x100);
sCalc = decToHex(bCalc, 2);
bCheck = (byte) inData[bChecksum];
sCheck = decToHex(bCheck, 2);

// Mod result by 256 and compare to checksum, or not enough data
if (sCalc != sCheck || bIndex <6)
{
// Checksum failed, reset
bStarted = false;
bEnded = false;
bIndex = 0;

// Need to flush, maybe getting the end marker
hrvSerial.flush();
}

// Reset checksum
bChecksum = 0;

}

 

// We got both start and end messages, process the data
if (bStarted && bEnded)
{

 

// Only process if we got enough data, minimum 6 characters
if (bIndex > 5)
{

String sHexPartOne;
String sHexPartTwo;
String hrvSetTemp;
int iPos;

// Pull data out of the array, position 0 is 0x7E (start and end of message)
for (int iPos=1; iPos <= bIndex; iPos++)
{

// Position 1 defines house or roof temperature
if (iPos==1) { eTempLoc = (char) inData[iPos]; }

 

// Position 2 and 3 are actual temperature, convert to hex
if (iPos == 2) { sHexPartOne = decToHex(inData[iPos], 2); }
if (iPos == 3) { sHexPartTwo = decToHex(inData[iPos], 2); }

 

if (eTempLoc == HRVHOUSE && iPos == 4)
{
// Fan full speed
if (inData[iPos] == 100 )
{
Serial.println("Fan speed: FULL");
}
else
{
Serial.print("Fan speed: ");
Serial.println(inData[iPos]);
}

}

// If message is from control panel
if (eTempLoc == HRVHOUSE && iPos == 5)
{
hrvSetTemp = inData[iPos];
Serial.print("Control Panel: ");
Serial.println(hrvSetTemp);
}

}

// Concatenate first and second hex, convert back to decimal, 1/16th of dec + rounding
// Note: rounding is weird - it varies between roof and house, so below is rough - its accurate 99% of the time!
fHRVTemp = hexToDec(sHexPartOne + sHexPartTwo);
fHRVTemp = (fHRVTemp * 0.0625) + 0.66;

 

// Cast back to integer
fHRVTemp = (int) fHRVTemp;

 

// Send data to MQTT broker
SendMQTTMessage();

 

}

// Chill a bit, sometimes we'll time the data, sometimes not
delay(2000);

 

// Reset defaults for processing
bStarted = false;
bEnded = false;
bIndex = 0;

}
else
{
// Wait for serial to come alive
delay(2000);
}

 

mqttClient.loop();

}

 


String decToHex(byte decValue, byte desiredStringLength)
{

String hexString = String(decValue, HEX);
while (hexString.length() < desiredStringLength) hexString = "0" + hexString;

return hexString;
}

 

 

 

unsigned int hexToDec(String hexString)
{

unsigned int decValue = 0;
int nextInt;

for (int i = 0; i < hexString.length(); i++) {

nextInt = int(hexString.charAt(i));
if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9);
if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15);
if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15);
nextInt = constrain(nextInt, 0, 15);

decValue = (decValue * 16) + nextInt;
}

return decValue;
}

 

 

 

// Send data to MQTT broker
void SendMQTTMessage()
{

 

// Define and send message about door state
pubString = String(fHRVTemp);
pubString.toCharArray(message_buff, pubString.length()+1);
if (eTempLoc == HRVHOUSE)
{
Serial.print("House ");
Serial.println(message_buff);
mqttClient.publish(OPENHABHRVSUBHOUSE, message_buff);
}
else if (eTempLoc == HRVROOF)
{
Serial.print("Roof ");
Serial.println(message_buff);
mqttClient.publish(OPENHABHRVSUBROOF, message_buff);
}
else
{
Serial.println("Undefined");
}

}

 

 

 


// Print IP for debugging, can be removed if needed
void printIPAddress()
{
Serial.print("My IP address: ");

for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
Serial.print(Ethernet.localIP()[thisByte], DEC);
Serial.print(".");
}

 

Serial.println();
}

 

 

 

 





 

 


View this topic in a long page with up to 500 replies per page Create new topic
 1 | 2
5 posts

Wannabe Geek


  #1544569 30-Apr-2016 17:56
Send private message

Hi, thanks a lot for sharing! I'm keen to do something with my HRV too as the built-in controller is way to basic for what I want it to do.

 

I wonder if it is possible to also control HRV (such as change fan speed) using Arduino? 




406 posts

Ultimate Geek


  #1544705 1-May-2016 08:14
Send private message

Hey,

No problems glad it can help. Be aware the code may need tweaking still around getting the exact temperature it works most of the time however as I eluded too above I haven't quite worked out how they do their rounding.

RX and TX are on the same wire so I guess it would be a matter of just constructing the right packet and doing an hrvSerial.write();

See the "credit too" URL link at the top of the code to a web site that outlines the data structure

Cheers




 

 


 
 
 
 




406 posts

Ultimate Geek


  #1546423 4-May-2016 01:08
Send private message

Phew, got this working with an ESP8266 12E board NodeMCU (with WiFi)

 

It has a considerably smaller footprint than an Arduino UNO board, with the NodeMCU able to fit in the wall behind the HRV control panel.

 

I'll edit the first post and update it to a link to the Arduino code tomorrow (there are a couple small coding bugs fixed too)

 

All you need is one of these http://www.trademe.co.nz/electronics-photography/other-electronics/electronic-components/other/auction-1079437602.htm

 

It must be the 12E version or better though, as these dev boards can take a 5V VIN, so you can use power from HRV system to power the ESP.

 

A little more testing first...





 

 




406 posts

Ultimate Geek


  #1548834 9-May-2016 18:19
Send private message

Link to better code here  

 

Connections...

 

- 5V from HRV to VIN on NodeMCU (probably good to throw a diode in prior to 5V VIN on NodeMCU too, awaiting a schottky diode to help minimize voltage drop)

 

- GND from HRV to both GND on NodeMCU and GND on HIGH side of TTL converter

 

- Data from HRV to HV1 on TTL converter

 

- 3.3V out from NodeMCU to LV on TTL converter

 

- GND from NodeMCU to GND on TTL converter

 

- LV1 from TTL converter to GPIO pin 2 on NodeMCU (note: in code, "pin 4" for NodeMCU, refers to physical GPIO pin 2)

 

Will post a photo later of connections.

 

I'm waiting for some 100uF capacitors to arrive to see if they resolve the random WDT errors and NodeMCU reboots...

 

TBA on cap testing...

 

If anyone happens to test themselves, please reply with your own findings.

 

Cheers

 

 





 

 




406 posts

Ultimate Geek


  #1551947 13-May-2016 09:07
Send private message

I have optimized the code now which has helped on either WIFI or MQTT broker disconnections (it recovers from these nicely now) - uploaded to same link in post above.

 

I've also added a schottky diode and 10uF capacitor to VCC/GND of the NodeMCU to help smooth the power out.

 

I updated the firmware on the NodeMCU as well which appears to have helped with intermittent exception errors (cause 2: bootcode 3,6 issues) - at least, its run a lot longer without failing.

 

The issue I still have, is very randomly the HRV control panel itself will "restart" - it will beep a few times as it powers off/on.  Something to do with the NodeMCU being plugged in - I'm thinking that possibly the control panel is not getting enough Volts/Amps (as I'm using the 5V supply from the HRV to also power the NodeMCU and TTL logic converter) so am testing now with the 5V unplugged and using 5V USB power supply (plus lets me debug in the serial window)

 

Any ideas???

 

Here are some images of it on the breadboard:

 

 





 

 


1724 posts

Uber Geek

Subscriber

  #1551949 13-May-2016 09:12
Send private message

@chimera - probably a bit late in the piece to be suggesting a new framework but have you checked out Homie (https://github.com/marvinroger/homie-esp8266)? It is a great way to WIFI/MQTT-enable your NodeMCU board and handles all the reconnection stuff automatically. It also supports OTA updates (and myself and another chap have written a simple python based OTA server to make managing your firmwares much easier - https://github.com/jpmens/homie-ota). This means once the device is hidden away behind the wall you can still upgrade the firmware without touching it.

 

Might be worth a look as it will simplify all your WIFI and MQTT connection handling code.


1724 posts

Uber Geek

Subscriber

  #1551950 13-May-2016 09:14
Send private message

Here are some example sketches using Homie... https://github.com/IntranetOfThings

 

 


 
 
 
 




406 posts

Ultimate Geek


  #1552200 13-May-2016 14:04
Send private message

Thanks, but the code isn't the issue any longer. It's "electronic component" related problem which I'm now getting out of my depth to resolve (but continuing to research and troubleshoot where I can - or perhaps one could call it trial and error!)




 

 




406 posts

Ultimate Geek


  #1552526 14-May-2016 09:12
Send private message

I'm fairly sure I've confirmed the issue is power supply related - its run off USB power all night and had no control panel resets/beeps - at least not I've seen or heard!

 

So the likely solution now is to use an ESP module only (currently using a NodeMCU dev kit with ESP 12E module as pictured above) - as the ESP module alone should only require 3.3V to run so I'll throw in a voltage regulator to match.  

 

TBA!...

 

 





 

 




406 posts

Ultimate Geek


  #1559358 25-May-2016 13:22
Send private message

I have this working pretty mint now.  Bugs in code ironed out.  Running this on an ESP8266-01 (3.3V) now and its been running pretty solid for 3 days without failure (a couple of Wifi dropouts)  I've added the following since last time:

 

1. HRV temperatures sent to MQTT broker in 0.5 of a degree

 

2. Temperatures only sent to MQTT if changed since last time

 

3. HRV temperatures added to database in OpenHAB for historical graphing of roof and house temperatures (see image below)

 

4. Fan speed and Control Panel temperatures sent to MQTT / OpenHAB also (see image below)

 

 

 

Link to latest code here: HRV-ESP8266.INO

 

 

 

Top of code outlines what you need.  And of course no post is complete without pictures...

 

 

 

Breadboard layout... (check voltage regulator datasheet for recommended cap sizes for whatever you use)

 

 

 

 

Running on breadboard...

 

 

 

 

View of HRV data on iPhone...

 

 

 

 

Example of graph if clicking on 'Roof' from iPhone...

 





 

 


1724 posts

Uber Geek

Subscriber

  #1559377 25-May-2016 13:52
Send private message

Nice work Chimera - looking good!


253 posts

Ultimate Geek


  #1559400 25-May-2016 15:07
Send private message

Thanks Chimera for the great write-up, good timing I picked up a ESP8266 on Monday ;)




406 posts

Ultimate Geek


  #1559461 25-May-2016 16:44
Send private message

Blanch:

 

Thanks Chimera for the great write-up, good timing I picked up a ESP8266 on Monday ;)

 

 

Sweet as.

 

Note: I've just added a diode to the mix (I used a Schottky 1N5817) and updated the breadboard image above. Without the diode, the HRV control panel beeps/resets as soon as you plug in the ESP (but continues to run fine with the diode there) If the Wifi drops out, the code tries to reconnect for up to 30 seconds and if it fails, it reboots the ESP. The rebooting may potentially cause the HRV control panel to beep/reset itself - the diode should alleviate this.  Also, the reset button on the breadboard is optional, I figured if I solder to PCB I'll drill a small hole in the HRV control panel to let me manually reset the ESP in times of need (TBA!)

 

If you do try it please report back on your findings, especially if you use an ESP that's newer than the 01 version.  I am fairly confident it will work with any ESP version that draws 3.3V (you may just need to change the first GPIO pin number for hrvSerial definition, the TX is irrelevant/unused)  The ESP 12E as I eluded too on prior posts caused me issues - that may have just been "early days code / lack of testing" - but at least with 3.3V ESP its lower draw than the 12E version.

 

I'm going to leave the breadboard setup as is for another couple days now, if its all good I'll solder to PCB and chuck it in the wall.

 

I'd suggest if you do the same, just double check and make sure the flush box that the HRV control panel mounts too isn't the metal type may interfere with the Wifi.

 

The next revision I'll be using something like this: https://tzapu.com/esp8266-wifi-connection-manager-library-arduino-ide/ so you can connect wirelessly to the ESP itself, open a web browser and point too it, then in the web page enter your AP SSID, password and MQTT broker IP address and have it write to EEPROM, then reboot itself set it to STA mode and continue as is (saves having to alter the code and flash update)  

 

Cheers

 

 





 

 




406 posts

Ultimate Geek


  #1559487 25-May-2016 17:21
Send private message

Also, OpenHAB changes as follows (assumes you have OpenHAB configured and also running RRD4J for graphing (google it if you need to install, pretty easy)

 

items file:

 

/* HRV */
Number houseTemp "House [%.1f C]" <temperature> (All) { mqtt="<[mqttbroker:openhab/hrv/housetemp:state:default]" }
Number houseTemp_Chart_Period "Chart Period"
Number roofTemp "Roof [%.1f C]" <temperature> (All) { mqtt="<[mqttbroker:openhab/hrv/rooftemp:state:default]" }
Number roofTemp_Chart_Period "Chart Period"
Number controlTemp "Control [%.1f C]" <hrvcontrol> (All) { mqtt="<[mqttbroker:openhab/hrv/controltemp:state:default]" }
String fanSpeed "Fan Speed [%s]" <hrvfan> (All) { mqtt="<[mqttbroker:openhab/hrv/fanspeed:state:default]" }

 

 

 

sitemap file:

 

Frame label="HRV Temperature" {
  Text item=roofTemp {
    Frame {
      Switch item=roofTemp_Chart_Period label="Period" mappings=[0="Hour", 1="Day", 2="Week"]
        Image url="http://localhost:8080/rrdchart.png?items=roofTemp&period=h" refresh=6000 visibility=[roofTemp_Chart_Period==0, roofTemp_Chart_Period=="Uninitialized"]
        Image url="http://localhost:8080/rrdchart.png?items=roofTemp&period=D" refresh=30000 visibility=[roofTemp_Chart_Period==1]
        Image url="http://localhost:8080/rrdchart.png?items=roofTemp&period=W" refresh=30000 visibility=[roofTemp_Chart_Period==2]
    }
  }
  Text item=houseTemp {
    Frame {
      Switch item=houseTemp_Chart_Period label="Period" mappings=[0="Hour", 1="Day", 2="Week"]
        Image url="http://localhost:8080/rrdchart.png?items=houseTemp&period=h" refresh=6000 visibility=[houseTemp_Chart_Period==0, houseTemp_Chart_Period=="Uninitialized"]
        Image url="http://localhost:8080/rrdchart.png?items=houseTemp&period=D" refresh=30000 visibility=[houseTemp_Chart_Period==1]
        Image url="http://localhost:8080/rrdchart.png?items=houseTemp&period=W" refresh=30000 visibility=[houseTemp_Chart_Period==2]
    }
  }
  Text item=controlTemp
  Text item=fanSpeed
}

 

 

 

Forgot to add, links to the icons if you need them cool   Save to ..\OpenHAB Home\webapps\images folder

 

 

 

hrvfan.png

 

hrvcontrol.png 

 

 





 

 




406 posts

Ultimate Geek


  #1561962 30-May-2016 01:15
Send private message

The almost finished product - although will also be altering the cable from the HRV to the ESP to something better and as soon as my 3D printer turns up, I'll print a case for it.  The 4 right most plugs are soldered up for connecting the FTDI cable, I just need to add one more cable from GPIO0 plus a switch to pull the pin to ground incase I need to re-flash it.

 

 

 





 

 


 1 | 2
View this topic in a long page with up to 500 replies per page Create new topic




News »

Freeview On Demand app launches on Sony Android TVs
Posted 6-Aug-2020 13:35


UFB hits more than one million connections
Posted 6-Aug-2020 09:42


D-Link A/NZ extends COVR Wi-Fi EasyMesh System series with new three-pack
Posted 4-Aug-2020 15:01


New Zealand software Rfider tracks coffee from Colombia all the way to New Zealand businesses
Posted 3-Aug-2020 10:35


Logitech G launches Pro X Wireless gaming headset
Posted 3-Aug-2020 10:21


Sony Alpha 7S III provides supreme imaging performance
Posted 3-Aug-2020 10:11


Sony introduces first CFexpress Type A memory card
Posted 3-Aug-2020 10:05


Marsello acquires Goody consolidating online and in-store marketing position
Posted 30-Jul-2020 16:26


Fonterra first major customer for Microsoft's New Zealand datacentre
Posted 30-Jul-2020 08:07


Everything we learnt at the IBM Cloud Forum 2020
Posted 29-Jul-2020 14:45


Dropbox launches native HelloSign workflow and data residency in Australia
Posted 29-Jul-2020 12:48


Spark launches 5G in Palmerston North
Posted 29-Jul-2020 09:50


Lenovo brings speed and smarter features to new 5G mobile gaming phone
Posted 28-Jul-2020 22:00


Withings raises $60 million to enable bridge between patients and healthcare
Posted 28-Jul-2020 21:51


QNAP integrates Catalyst Cloud Object Storage into Hybrid Backup solution
Posted 28-Jul-2020 21:40



Geekzone Live »

Try automatic live updates from Geekzone directly in your browser, without refreshing the page, with Geekzone Live now.


Support Geekzone »

Our community of supporters help make Geekzone possible. Click the button below to join them.

Support Geezone on PressPatron



Are you subscribed to our RSS feed? You can download the latest headlines and summaries from our stories directly to your computer or smartphone by using a feed reader.

Alternatively, you can receive a daily email with Geekzone updates.