RCS RS485 thermostat
-
So I have been working on my RS485 gateway/bridge for my RCS thermostat. I have the code set up no so that commands sent from the thermostat will update Domoticz, but I ran into a snag that I cannot figure out. Here is the code I have so far. Still a bit rough.
/* RCS Thermostat for MySensors Arduino RCS RS485 thermostat control July 7,2016 This is a gateway bridge to allow an RCS serial thermostat to be accessible to a MySensors gateway. The thermostat being used to test this is an RCS TR40 RS485 thermostat. The published protocol for RCS thermostats can be found at the following address; http://www.rcstechnology.com/oldsite/docs/thermostats/serial/SERIAL%20PROTOCOL%20REV%204.3%20%20150-00225-43.pdf This sketch features the following: Add features here */ // Import needed libraries #include <MySensor.h> #include <SPI.h> #include <SoftwareSerial.h> #define SKETCH_NAME "RCS Thermostat" #define SKETCH_VERSION "1.0" #define CHILD_ID_TEMP 0 // V_TEMP #define CHILD_ID_STATUS 1 // V_STATUS #define CHILD_ID_SETPOINT_COOL 2 // V_HVAC_SETPOINT_COOL #define CHILD_ID_SETPOINT_HEAT 3 // V_HVAC_SETPOINT_HEAT #define CHILD_ID_FLOW_STATE 4 // V_HVAC_FLOW_STATE #define CHILD_ID_FLOW_MODE 5 // V_HVAC_FLOW_MODE #define CHILD_ID_HVAC_SPEED 6 // V_HVAC_SPEED // Declare Constants and Pin Numbers #define SSerialRX 5 //Serial Receive pin 8 #define SSerialTX 3 //Serial Transmit pin 7 #define SSerialTxControl 4 //RS485 Direction control #define RS485Transmit HIGH #define RS485Receive LOW #define Pin12LED 12 #define Pin13LED 13 // Declare objects SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX MySensor gw; // Sensor values // V_TEMP, V_STATUS, V_HVAC_FLOW_STATE, V_HVAC_SPEED // V_HVAC_SETPOINT_COOL, V_HVAC_SETPOINT_HEAT, V_HVAC_FLOW_MODE MyMessage msgTemp( CHILD_ID_TEMP, V_TEMP ); MyMessage msgStatus( CHILD_ID_STATUS, V_STATUS ); MyMessage msgSetCool( CHILD_ID_SETPOINT_COOL, V_HVAC_SETPOINT_COOL ); MyMessage msgSetHeat( CHILD_ID_SETPOINT_HEAT, V_HVAC_SETPOINT_HEAT ); MyMessage msgFlowState( CHILD_ID_FLOW_STATE, V_HVAC_FLOW_STATE ); MyMessage msgFlowMode( CHILD_ID_FLOW_MODE, V_HVAC_FLOW_MODE ); MyMessage msgHvacSpeed( CHILD_ID_HVAC_SPEED, V_HVAC_SPEED ); // Sensor sub-type // S_HVAC // Declare Variables int byteReceived; int byteSend; String rcvString; String sndString; //This is for storing the last command that was sent String lastSent; //the last sent set point String setPoint; String mode; //This is the RS485 address of this node that gets sent to the thermostat String serialAddr = "1"; //Placeholder for the last command sent String LastSent = ""; void setup() { Serial.begin(9600); gw.begin( incomingMessage, AUTO, true ); gw.sendSketchInfo( SKETCH_NAME, SKETCH_VERSION ); // Register the thermostat with the gateway gw.present( CHILD_ID_TEMP, S_HVAC ); gw.present( CHILD_ID_STATUS, S_HVAC ); gw.present( CHILD_ID_SETPOINT_COOL, S_HVAC ); gw.present( CHILD_ID_SETPOINT_HEAT, S_HVAC ); gw.present( CHILD_ID_FLOW_STATE, S_HVAC ); gw.present( CHILD_ID_FLOW_MODE, S_HVAC ); // put your setup code here, to run once: pinMode(SSerialTxControl, OUTPUT); digitalWrite(SSerialTxControl, RS485Receive); // Init Transceiver // Start the software serial port, to another device RS485Serial.begin(9600); // set the data rate } //End setup void loop() { String dataIn; if (RS485Serial.available()) { dataIn = RS485Serial.readStringUntil('\n'); ParseReceived(dataIn); } } //End loop void ParseReceived(String Message) { String StatusData; //int Count; String StatusString; String Status; String Type; String Value; int Index; int Start; int End; int StatIndex; Index = Message.indexOf(' '); Start = 0; Serial.println("Message: " + Message); if (Message.startsWith("A=")) { do { End =(Index == -1) ? Message.length() : Index; //Get the status string to process StatusString = Message.substring(Start, End); //Change our start position to 1 over the last space found Start = Index + 1; //Find the end of the next status string Index = Message.indexOf(' ', Start); //Now we need to process the status string into it's Type and Value StatIndex = StatusString.indexOf('='); Type = StatusString.substring(0, StatIndex); Value = StatusString.substring(StatIndex + 1); ParseStatus(Type, Value); } while (Index != -1); } else { SendCmd(LastSent); } } //End ParseReceived void ParseStatus(String Type, String Value) { //int stg1; //int stg2; //Serial.write("Type = " + Type + " : Value = " + Value + "\r\n"); //Process each kind of status type if (Type == "OA") { //Outside Air not used } else if (Type == "Z") { //Zone not used } else if (Type == "T") { //logging.AddToLog("Temperature reading: " & Value, True) gw.send(msgTemp.set(Value.toInt())); } else if (Type == "SP") { //logging.AddToLog("Set point: " & Value, True) Serial.println("Set point: " + Value); gw.send(msgSetCool.set(Value.toInt())); } else if (Type == "SPH") { //logging.AddToLog("Heat set point: " & Value, True) Serial.println("Heat set point: " + Value); gw.send(msgSetHeat.set(Value.toInt))); } else if (Type == "SPC") { //logging.AddToLog("Cold set point: " & Value, True) Serial.println("Cold set point: " + Value); gw.send(msgSetCool.set(Value.toInt())); } else if (Type == "M") { //logging.AddToLog("Mode: " & Value, True) Serial.println("Mode: " + Value); gw.send(msgFlowMode.set(Value.c_str())); } else if (Type == "FM") { //logging.AddToLog("Fan mode: " & Value, True) Serial.println("Fan mode: " + Value); gw.send(msgFlowMode.set(Value.c_str())); //Type 2 status message types } else if (Type == "H1A") { //logging.AddToLog("Heat stage 1: " & Value, True) Serial.println("Heat stage 1: " + Value); gw.send(msgHvacSpeed.set("Min")); } else if (Type == "H2A") { //logging.AddToLog("Heat stage 2: " & Value, True) Serial.println("Heat stage 2: " + Value); gw.send(msgHvacSpeed.set("Normal")); } else if (Type == "H3A") { //logging.AddToLog("Heat stage 3: " & Value, True) Serial.println("Heat stage 3: " + Value); gw.send(msgHvacSpeed.set("Max")); } else if (Type == "C1A") { //logging.AddToLog("Cool stage 1: " & Value, True) Serial.println("Cool stage 1: " + Value); gw.send(msgHvacSpeed.set("Min")); } else if (Type == "C2A") { //logging.AddToLog("Cool stage 2: " & Value, True) Serial.println("Cool stage 2: " + Value); gw.send(msgHvacSpeed.set("Normal")); } else if (Type == "FA") { //logging.AddToLog("Fan status: " & Value, True) Serial.println("Mode: " + Value); gw.send(msgFlowMode.set("Normal")); } else if (Type == "VA") { //logging.AddToLog("Vent damper: " & Value, True) //Vent damper not used } else if (Type == "D1") { //logging.AddToLog("Zone damper: " & Value, True) //Damper #1 not used } else if (Type == "SCP") { //stg1 = Value.substring(0, 1) //stg2 = Value.substring(0, -1) //logging.AddToLog("MOT/MRT stage 1: " & stg1, True) //Deal with minimum off time and minimum run times //for stage 1 //logging.AddToLog("MOT/MRT stage 2: " & stg2, True) //Deal with minimum off time and minimum run times //for stage 2 } else if (Type == "SM") { //logging.AddToLog("System mode: " & Value, True) String FlowState; if (Value == "O") { FlowState = "Off"; } else if (Value == "H") { FlowState = "HeatOn"; } else if (Value == "C") { FlowState = "CoolOn"; } else { FlowState = "AutoChangeOver"; } Serial.println("Flow state: " + FlowState); gw.send(msgFlowState.set(FlowState.c_str())); } else if (Type == "SF") { //logging.AddToLog("System fan: " & Value, True) Serial.println("System fan : " + Value); gw.send(msgStatus.set(Value.toInt())); } } //End ParseStatus void SendCmd(String cmd) { String commandStr; commandStr = "A=" + serialAddr + " O=00 " + cmd; //DEBUG_PRINTLN("Writing to serial port: " + Command); // Enable RS485 Transmit only for the duration of the send digitalWrite(SSerialTxControl, RS485Transmit); RS485Serial.print(commandStr + "\r"); LastSent = cmd; //Return to RS485 receive mode digitalWrite(SSerialTxControl, RS485Receive); } //End SendCmd void SetProperty(String PropertyName, String Data) { // PropertyName = ""; Data = ""; } //End SendCmd void incomingMessage(const MyMessage &message) { Serial.println(message.type); // We only expect one type of message from controller. But we better check anyway. if (message.isAck()) { Serial.println("This is an ack from gateway"); } if (message.type == V_HVAC_SETPOINT_COOL) { Serial.println("Message received"); setPoint = String(message.data).toInt(); Serial.println("New Set Temp is : " + String(setPoint)); SendCmd("SPC=" + setPoint + " R=1"); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.data); } if (message.type == V_HVAC_SETPOINT_HEAT) { Serial.println("Message received"); setPoint = String(message.data).toInt(); Serial.println("New Set Temp is : " + String(setPoint)); SendCmd("SPH=" + setPoint + " R=1"); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.data); } } //End incomingMessageThe problem I have is that I am trying to send a decimal or float number for my temp value and I cannot figure out how. In the code, there is the ParseStatus function which takes a Type and Value as it's arguments. For types like "SP" , "SPH", "SPC", etc... I have it converting the value to an integer ( Value.toInt() ) which works. But if I try to convert it to a floating point decimal ( Value.toFloat() ), I get an error:
C:\Users\dbemowsk\Documents\Arduino\RCS_RS485_Thermostat\RCS_RS485_Thermostat.ino: In function 'void ParseStatus(String, String)': RCS_RS485_Thermostat:176: error: call of overloaded 'set(float)' is ambiguous gw.send(msgSetHeat.set(Value.toFloat())); ^ C:\Users\dbemowsk\Documents\Arduino\RCS_RS485_Thermostat\RCS_RS485_Thermostat.ino:176:45: note: candidates are: In file included from C:\Program Files (x86)\Arduino\libraries\MySensors/MyParser.h:23:0, from C:\Program Files (x86)\Arduino\libraries\MySensors/MySensor.h:29, from C:\Users\dbemowsk\Documents\Arduino\RCS_RS485_Thermostat\RCS_RS485_Thermostat.ino:19: C:\Program Files (x86)\Arduino\libraries\MySensors/MyMessage.h:262:13: note: MyMessage& MyMessage::set(uint8_t) MyMessage& set(uint8_t value); ^ C:\Program Files (x86)\Arduino\libraries\MySensors/MyMessage.h:264:13: note: MyMessage& MyMessage::set(long unsigned int) MyMessage& set(unsigned long value); ^ C:\Program Files (x86)\Arduino\libraries\MySensors/MyMessage.h:265:13: note: MyMessage& MyMessage::set(long int) MyMessage& set(long value); ^ C:\Program Files (x86)\Arduino\libraries\MySensors/MyMessage.h:266:13: note: MyMessage& MyMessage::set(unsigned int) MyMessage& set(unsigned int value); ^ C:\Program Files (x86)\Arduino\libraries\MySensors/MyMessage.h:267:13: note: MyMessage& MyMessage::set(int) MyMessage& set(int value); ^ exit status 1 call of overloaded 'set(float)' is ambiguousIs it possible to send decimal numbers?
The next issue is that when I send values for the heat or cool set points, I have to send them as metric Celsius values. When I send them in Farenheit the number shown in Dompticz is WAY too high. That I am sure is a setting somewhere in Domoticz, but I haven't found it yet.
The last thing is that when I send an "SPC" or Set Point Cool value, Domoticz shows a value of 190.2 and it doesn't change if I send another value. I looked over the code and I am not seeing anything that looks to be wrong (other than the floating point number issue).
-
@dbemowsk try
gw.send(msgSetHeat.set(Value.toFloat(),1));I think that will do the conversion with 1 decimal.
As for the fareheit setting, it is at Settings->Meters/counters

@mfalkvidd said:
As for the fareheit setting, it is at Settings->Meters/counters
I have the temperature setting to display Fahrenheit, but when I send a value in Fahrenheit from the MySensors bridge, it displays a lot higher value. If I send the value in Celsius, it displays the correct Fahrenheit value. So the setting under Meters/Counters seems to ONLY tell the system to convert the stored value from Celsius to Fahrenheit prior to display. I will just add a function to do the conversion in my thermostat bridge sketch prior to sending it to the gateway.
The other problem as I mentioned is that Domoticz is not seeing the incoming V_HVAC_SETPOINT_COOL. I send different values and it displays 190.4 every time (I said 190.2 last time, but it's 190.4). Is there something that I am doing wrong, or is this a limitation in Domoticz?
-
@mfalkvidd said:
As for the fareheit setting, it is at Settings->Meters/counters
I have the temperature setting to display Fahrenheit, but when I send a value in Fahrenheit from the MySensors bridge, it displays a lot higher value. If I send the value in Celsius, it displays the correct Fahrenheit value. So the setting under Meters/Counters seems to ONLY tell the system to convert the stored value from Celsius to Fahrenheit prior to display. I will just add a function to do the conversion in my thermostat bridge sketch prior to sending it to the gateway.
The other problem as I mentioned is that Domoticz is not seeing the incoming V_HVAC_SETPOINT_COOL. I send different values and it displays 190.4 every time (I said 190.2 last time, but it's 190.4). Is there something that I am doing wrong, or is this a limitation in Domoticz?
@dbemowsk said:
The other problem as I mentioned is that Domoticz is not seeing the incoming V_HVAC_SETPOINT_COOL. I send different values and it displays 190.4 every time (I said 190.2 last time, but it's 190.4). Is there something that I am doing wrong, or is this a limitation in Domoticz?
Works for me Although I'm using celsius scale in my setup.. One direfference we have. I have only one S_HVAC child defined and in my setup it sends ON/OFF state, V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COOL and V_TEMP -messges. Domoticz registers these separate node-child-sub-devices when it gots first messages from them. But I think this shouldnt be an issue..
-
@dbemowsk said:
The other problem as I mentioned is that Domoticz is not seeing the incoming V_HVAC_SETPOINT_COOL. I send different values and it displays 190.4 every time (I said 190.2 last time, but it's 190.4). Is there something that I am doing wrong, or is this a limitation in Domoticz?
Works for me Although I'm using celsius scale in my setup.. One direfference we have. I have only one S_HVAC child defined and in my setup it sends ON/OFF state, V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COOL and V_TEMP -messges. Domoticz registers these separate node-child-sub-devices when it gots first messages from them. But I think this shouldnt be an issue..
@pjr said:
I have only one S_HVAC child defined and in my setup it sends ON/OFF state, V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COOL and V_TEMP -messges.
I have a few questions regarding your setup.
- First, what type of thermostat do you run?
- How are you MySensorizing your thermostat?
- Does your thermostat have a single set point, or does it have separate heating and cooling set points?
- When you set your temp at the thermostat itself, be it the heating or cooling set point, does it report that back to your gateway/Domoticz. If so, How do you have your code set to report that back?
Could I possibly see how you have your code set up to compare what I have? I am thinking that it is something in the way that I am reporting back to the gateway. My MySensors bridge that I am building just translates what my thermostat sends for data on the RS485 network and converts that to the MySensors standard that should work with Domoticz. I just can't seem to figure out what I am doing wrong with the cooling set point. Sending the temp and the heating set point values works perfect, just not the cooling set point.
-
@dbemowsk try
gw.send(msgSetHeat.set(Value.toFloat(),1));I think that will do the conversion with 1 decimal.
As for the fareheit setting, it is at Settings->Meters/counters

@mfalkvidd said:
try
gw.send(msgSetHeat.set(Value.toFloat(),1));
@mfalkvidd Forgot to say thanks for that tip. That worked.
-
@pjr said:
I have only one S_HVAC child defined and in my setup it sends ON/OFF state, V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COOL and V_TEMP -messges.
I have a few questions regarding your setup.
- First, what type of thermostat do you run?
- How are you MySensorizing your thermostat?
- Does your thermostat have a single set point, or does it have separate heating and cooling set points?
- When you set your temp at the thermostat itself, be it the heating or cooling set point, does it report that back to your gateway/Domoticz. If so, How do you have your code set to report that back?
Could I possibly see how you have your code set up to compare what I have? I am thinking that it is something in the way that I am reporting back to the gateway. My MySensors bridge that I am building just translates what my thermostat sends for data on the RS485 network and converts that to the MySensors standard that should work with Domoticz. I just can't seem to figure out what I am doing wrong with the cooling set point. Sending the temp and the heating set point values works perfect, just not the cooling set point.
@dbemowsk said:
@pjr said:
I have only one S_HVAC child defined and in my setup it sends ON/OFF state, V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COOL and V_TEMP -messges.
I have a few questions regarding your setup.
- First, what type of thermostat do you run?
So the node integrates my Amitime air source heat pump to domoticz.
gw.present(2, S_HVAC);- How are you MySensorizing your thermostat?
Its not actually thermostat. Its heat pump. Same way as thermostat is has set point heat, cool and current temp readings.
- Does your thermostat have a single set point, or does it have separate heating and cooling set points?
It has both
- When you set your temp at the thermostat itself, be it the heating or cooling set point, does it report that back to your gateway/Domoticz. If so, How do you have your code set to report that back?
Yes it report back.
Could I possibly see how you have your code set up to compare what I have? I am thinking that it is something in the way that I am reporting back to the gateway. My MySensors bridge that I am building just translates what my thermostat sends for data on the RS485 network and converts that to the MySensors standard that should work with Domoticz. I just can't seem to figure out what I am doing wrong with the cooling set point. Sending the temp and the heating set point values works perfect, just not the cooling set point.
Its very similar setup. Instead of raw rs485 I'm using modbus with my heat pump. I'll send you a PM about the sketch.
-
@dbemowsk said:
@pjr said:
I have only one S_HVAC child defined and in my setup it sends ON/OFF state, V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COOL and V_TEMP -messges.
I have a few questions regarding your setup.
- First, what type of thermostat do you run?
So the node integrates my Amitime air source heat pump to domoticz.
gw.present(2, S_HVAC);- How are you MySensorizing your thermostat?
Its not actually thermostat. Its heat pump. Same way as thermostat is has set point heat, cool and current temp readings.
- Does your thermostat have a single set point, or does it have separate heating and cooling set points?
It has both
- When you set your temp at the thermostat itself, be it the heating or cooling set point, does it report that back to your gateway/Domoticz. If so, How do you have your code set to report that back?
Yes it report back.
Could I possibly see how you have your code set up to compare what I have? I am thinking that it is something in the way that I am reporting back to the gateway. My MySensors bridge that I am building just translates what my thermostat sends for data on the RS485 network and converts that to the MySensors standard that should work with Domoticz. I just can't seem to figure out what I am doing wrong with the cooling set point. Sending the temp and the heating set point values works perfect, just not the cooling set point.
Its very similar setup. Instead of raw rs485 I'm using modbus with my heat pump. I'll send you a PM about the sketch.
-
@dbemowsk said:
The other problem as I mentioned is that Domoticz is not seeing the incoming V_HVAC_SETPOINT_COOL. I send different values and it displays 190.4 every time (I said 190.2 last time, but it's 190.4). Is there something that I am doing wrong, or is this a limitation in Domoticz?
Works for me Although I'm using celsius scale in my setup.. One direfference we have. I have only one S_HVAC child defined and in my setup it sends ON/OFF state, V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COOL and V_TEMP -messges. Domoticz registers these separate node-child-sub-devices when it gots first messages from them. But I think this shouldnt be an issue..
@pjr said:
I have only one S_HVAC child defined and in my setup it sends ON/OFF state, V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COOL and V_TEMP -messges.
OK, so I have a question on this. You say you have it sending ON/OFF, V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COOL and V_TEMP. For ON/OFF, do you mean the V_HVAC_FLOW_STATE which is "Off", "HeatOn", "CoolOn", or "AutoChangeOver"? Can I send all of the following V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COLD, V_HVAC_FLOW_STATE, V_HVAC_FLOW_MODE, V_HVAC_SPEED through the one child ID as defined in the v 1.5.x serial API docs. That may be my problem as in my code I was trying to send each through it's own child ID. Also, when you define your S_HVAC as the single child, how does Domoticz see that? The way I have mine set up, each one is seen as a separate device.
Thanks for letting me check out your code.
-
@pjr said:
I have only one S_HVAC child defined and in my setup it sends ON/OFF state, V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COOL and V_TEMP -messges.
OK, so I have a question on this. You say you have it sending ON/OFF, V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COOL and V_TEMP. For ON/OFF, do you mean the V_HVAC_FLOW_STATE which is "Off", "HeatOn", "CoolOn", or "AutoChangeOver"? Can I send all of the following V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COLD, V_HVAC_FLOW_STATE, V_HVAC_FLOW_MODE, V_HVAC_SPEED through the one child ID as defined in the v 1.5.x serial API docs. That may be my problem as in my code I was trying to send each through it's own child ID. Also, when you define your S_HVAC as the single child, how does Domoticz see that? The way I have mine set up, each one is seen as a separate device.
Thanks for letting me check out your code.
@dbemowsk
These are not supported yet by domoticz:- V_HVAC_FLOW_STATE
- V_HVAC_FLOW_MODE
- V_HVAC_SPEED
Thats why I'm using V_LIGHT (ON/OFF) currently at the code.
You can check it from here: https://github.com/domoticz/domoticz/blob/master/hardware/MySensorsBase.cpp#L70
Those are not mentioned anywhere but the one list. -
@dbemowsk
These are not supported yet by domoticz:- V_HVAC_FLOW_STATE
- V_HVAC_FLOW_MODE
- V_HVAC_SPEED
Thats why I'm using V_LIGHT (ON/OFF) currently at the code.
You can check it from here: https://github.com/domoticz/domoticz/blob/master/hardware/MySensorsBase.cpp#L70
Those are not mentioned anywhere but the one list.@pjr OK, that helps me understand your code better. I am assuming that the "onModbusProcessed" method is to process incoming messages sent by the modbus network and sending them to Domoticz, correct? Processing incoming messages from the RS485 network is where some of my problems are in my setup. I will try tonight to make some code changes to see if I can get it working. My main problem was my cooling set point was not updating in Domoticz correctly. The Heat set point and temp seemed to work. I'll post my findings.
-
@dbemowsk said:
@pjr OK, that helps me understand your code better. I am assuming that the "onModbusProcessed" method is to process incoming messages sent by the modbus network and sending them to Domoticz, correct?
Thats correct. There I handle the result of a modbus query.
I'm not handling decimals since the heat pump controller supports only full numbers.. -
So last night I figured out my issue with why my code was not updating the set point cool value. Turns out it was the way I was parsing the string passed from the RS485 side to it's key/value pairs. The string that it was working on was this:
A=0 O=01 T=73.4 SPH=72.1 SPC=70.0\rThe code I had was only taking the key/value pairs up to the last one because I had it keying off of the space character. Since there was no trailing space in the string, the last pair got skipped which was the cooling set point.
I will post some updated code once I get a little more done.
-
OK, so I had this project on hold for a while and am getting back to it. My issue now is that for some reason I am not receiving messages from Domoticz for this node. If I send a temp set point or status from the RS485 side, it updates in Domoticz, but if I try to change a set point or status in Domoticz, the MySensors node doesn't receive it. The code is a bit messy right now, but it should work with what I have. If someone could look it over and advise, that would be a big help. The sketch is a MySensors 1.5.4 sketch.
/* RCS Thermostat for MySensors Arduino RCS RS485 thermostat control July 7,2016 This is a gateway bridge to allow an RCS serial thermostat to be accessible to a MySensors gateway. The thermostat being used to test this is an RCS TR40 RS485 thermostat. The published protocol for RCS thermostats can be found at the following address; http://www.rcstechnology.com/oldsite/docs/thermostats/serial/SERIAL%20PROTOCOL%20REV%204.3%20%20150-00225-43.pdf This sketch features the following: Add features here */ // Import needed libraries #include <SPI.h> #include <MySensor.h> #include <SoftwareSerial.h> #define SKETCH_NAME "RCS TR40 Thermostat" #define SKETCH_VERSION "1.1" #define CHILD_ID_HVAC 0 // S_HVAC #define CHILD_ID_STATE 1 // S_LIGHT // Declare Constants and Pin Numbers #define SSerialRX 5 //Serial Receive pin 8 #define SSerialTX 3 //Serial Transmit pin 7 #define SSerialTxControl 4 //RS485 Direction control #define RS485Transmit HIGH #define RS485Receive LOW // Declare objects SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX MySensor gw; // Sensor values MyMessage msgStatus ( CHILD_ID_STATE, V_LIGHT ); MyMessage msgTemp ( CHILD_ID_HVAC, V_TEMP ); MyMessage msgSetCool( CHILD_ID_HVAC, V_HVAC_SETPOINT_COOL ); MyMessage msgSetHeat( CHILD_ID_HVAC, V_HVAC_SETPOINT_HEAT ); // Declare Variables int byteReceived; int byteSend; String rcvString; String sndString; //This is for storing the last command that was sent String lastSent; //the last sent set point String setPoint; String mode; //This is the RS485 address of this node that gets sent to the thermostat String serialAddr = "1"; //Placeholder for the last command sent String LastSent = ""; void setup() { Serial.begin(9600); gw.begin( incomingMessage, AUTO, false ); gw.sendSketchInfo( SKETCH_NAME, SKETCH_VERSION ); // Register the thermostat with the gateway gw.present( CHILD_ID_HVAC, S_HVAC ); gw.present( CHILD_ID_STATE, S_LIGHT ); // put your setup code here, to run once: pinMode( SSerialTxControl, OUTPUT ); digitalWrite( SSerialTxControl, RS485Receive ); // Init Transceiver // Start the software serial port, to another device RS485Serial.begin(9600); // set the data rate } //End setup void loop() { String dataIn; if (RS485Serial.available()) { dataIn = RS485Serial.readStringUntil('\n'); ParseReceived(dataIn); } } //End loop void ParseReceived(String Message) { String StatusData; //int Count; String StatusString; String Status; String Type; String Value; int Index; int Start; int End; int StatIndex; Index = Message.indexOf(' '); Start = 0; Serial.println("Message: " + Message); if (Message.startsWith("A=")) { while (End != Message.length()) { End = (Index == -1) ? Message.length() : Index; //Get the status string to process StatusString = Message.substring(Start, End); //Change our start position to 1 over the last space found Start = Index + 1; //Find the end of the next status string Index = Message.indexOf(' ', Start); //Now we need to process the status string into it's Type and Value StatIndex = StatusString.indexOf('='); Type = StatusString.substring(0, StatIndex); Value = StatusString.substring(StatIndex + 1); ParseStatus(Type, Value); } } else { SendCmd(LastSent); } } //End ParseReceived void ParseStatus(String Type, String Value) { // if (Type == "OA") { //Outside Air not used } else if (Type == "Z") { //Zone not used } else if (Type == "T") { Serial.println("T: " + Value); gw.send(msgTemp.set( F2C( Value.toFloat() ), 2 )); } else if (Type == "SP") { Serial.println("SP: " + Value); gw.send(msgSetCool.set( F2C( Value.toFloat() ), 2 )); } else if (Type == "SPH") { Serial.println("SPH: " + Value); gw.send(msgSetHeat.set( F2C( Value.toFloat() ), 2 )); } else if (Type == "SPC") { Serial.println("SPC: " + Value); gw.send(msgSetCool.set( F2C( Value.toFloat() ), 2 )); } else if (Type == "M") { //Serial.println("M: " + Value); //gw.send(msgFlowMode.set(Value.c_str())); } else if (Type == "FM") { //Serial.println("FM: " + Value); //gw.send(msgFlowMode.set(Value.c_str())); //Type 2 status message types } else if (Type == "H1A") { Serial.println("H1A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Min")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "H2A") { Serial.println("H2A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Normal")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "H3A") { Serial.println("H3A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Max")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "C1A") { Serial.println("C1A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Min")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "C2A") { Serial.println("C2A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Normal")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "FA") { Serial.println("FA: " + Value); if (Value == "1") { //gw.send(msgFlowMode.set("ContinuousOn")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "VA") { //Vent damper not used } else if (Type == "D1") { //Damper #1 not used } else if (Type == "SCP") { String stg1 = Value.substring(0, 1); String stg2 = Value.substring(0, Value.length() - 1); //logging.AddToLog("MOT/MRT stage 1: " & stg1, True) //Deal with minimum off time and minimum run times //for stage 1 //logging.AddToLog("MOT/MRT stage 2: " & stg2, True) //Deal with minimum off time and minimum run times //for stage 2 } else if (Type == "SM") { //logging.AddToLog("System mode: " & Value, True) String FlowState; if (Value == "O") { FlowState = "Off"; } else if (Value == "H") { FlowState = "HeatOn"; } else if (Value == "C") { FlowState = "CoolOn"; } else { FlowState = "AutoChangeOver"; } //Serial.println("SM: " + FlowState); //gw.send(msgFlowState.set(FlowState.c_str())); } else if (Type == "SF") { //logging.AddToLog("System fan: " & Value, True) Serial.println("SF: " + Value); gw.send(msgStatus.set(Value.toInt())); } } //End ParseStatus float F2C(float Fahrenheit) { return (5.0f/9.0f) * (Fahrenheit-32); } //End F2C float C2F(float Celsius) { return (Celsius * 9.0f) / 5.0f + 32.0f; } //End C2F void SendCmd(String cmd) { String commandStr; commandStr = "A=" + serialAddr + " O=00 " + cmd; Serial.println("Writing to serial port: " + commandStr); // Enable RS485 Transmit only for the duration of the send digitalWrite(SSerialTxControl, RS485Transmit); RS485Serial.print(commandStr + "\r"); LastSent = cmd; //Return to RS485 receive mode digitalWrite(SSerialTxControl, RS485Receive); } //End SendCmd /** * incomingMessage - Process the incoming messages. */ void incomingMessage(const MyMessage &message) { Serial.println("message received");//String(message.type)); //Serial.println(message.data); // We only expect one type of message from controller. But we better check anyway. if (message.isAck()) { Serial.println("This is an ack from gateway"); } Serial.println("Temp: " + String(message.data) + " -- " + message.type); if ( message.type == V_TEMP ) { // Serial.println("Temp: " + String(message.data)); } //End V_TEMP if ( message.type == V_STATUS ) { // Serial.println("Status: " + String(message.data)); } //End V_STATUS if ( message.type == V_HVAC_FLOW_STATE ) { // Serial.println("Flow State: " + String(message.data)); } //End V_HVAC_FLOW_STATE if ( message.type == V_HVAC_SPEED ) { // Serial.println("Speed: " + String(message.data)); } //End V_HVAC_SPEED if (message.type == V_HVAC_SETPOINT_COOL) { Serial.println("Message received"); String setPoint = String(C2F(atoi(message.data))); Serial.println("New Set Temp is : " + String(setPoint)); SendCmd("SPC=" + setPoint + " R=1"); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.data); } //End V_HVAC_SETPOINT_COOL if (message.type == V_HVAC_SETPOINT_HEAT) { Serial.println("Message received"); String setPoint = String(C2F(atoi(message.data))); //.toInt(); Serial.println("New Set Temp is : " + String(setPoint)); SendCmd("SPH=" + setPoint + " R=1"); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.data); } //End V_HVAC_SETPOINT_HEAT if ( (message.type == V_HVAC_FLOW_MODE) ) { // Serial.println("Flow Mode: " + String(message.data)); } //End V_HVAC_FLOW_MODE } //End incomingMessageThanks
-
OK, so I had this project on hold for a while and am getting back to it. My issue now is that for some reason I am not receiving messages from Domoticz for this node. If I send a temp set point or status from the RS485 side, it updates in Domoticz, but if I try to change a set point or status in Domoticz, the MySensors node doesn't receive it. The code is a bit messy right now, but it should work with what I have. If someone could look it over and advise, that would be a big help. The sketch is a MySensors 1.5.4 sketch.
/* RCS Thermostat for MySensors Arduino RCS RS485 thermostat control July 7,2016 This is a gateway bridge to allow an RCS serial thermostat to be accessible to a MySensors gateway. The thermostat being used to test this is an RCS TR40 RS485 thermostat. The published protocol for RCS thermostats can be found at the following address; http://www.rcstechnology.com/oldsite/docs/thermostats/serial/SERIAL%20PROTOCOL%20REV%204.3%20%20150-00225-43.pdf This sketch features the following: Add features here */ // Import needed libraries #include <SPI.h> #include <MySensor.h> #include <SoftwareSerial.h> #define SKETCH_NAME "RCS TR40 Thermostat" #define SKETCH_VERSION "1.1" #define CHILD_ID_HVAC 0 // S_HVAC #define CHILD_ID_STATE 1 // S_LIGHT // Declare Constants and Pin Numbers #define SSerialRX 5 //Serial Receive pin 8 #define SSerialTX 3 //Serial Transmit pin 7 #define SSerialTxControl 4 //RS485 Direction control #define RS485Transmit HIGH #define RS485Receive LOW // Declare objects SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX MySensor gw; // Sensor values MyMessage msgStatus ( CHILD_ID_STATE, V_LIGHT ); MyMessage msgTemp ( CHILD_ID_HVAC, V_TEMP ); MyMessage msgSetCool( CHILD_ID_HVAC, V_HVAC_SETPOINT_COOL ); MyMessage msgSetHeat( CHILD_ID_HVAC, V_HVAC_SETPOINT_HEAT ); // Declare Variables int byteReceived; int byteSend; String rcvString; String sndString; //This is for storing the last command that was sent String lastSent; //the last sent set point String setPoint; String mode; //This is the RS485 address of this node that gets sent to the thermostat String serialAddr = "1"; //Placeholder for the last command sent String LastSent = ""; void setup() { Serial.begin(9600); gw.begin( incomingMessage, AUTO, false ); gw.sendSketchInfo( SKETCH_NAME, SKETCH_VERSION ); // Register the thermostat with the gateway gw.present( CHILD_ID_HVAC, S_HVAC ); gw.present( CHILD_ID_STATE, S_LIGHT ); // put your setup code here, to run once: pinMode( SSerialTxControl, OUTPUT ); digitalWrite( SSerialTxControl, RS485Receive ); // Init Transceiver // Start the software serial port, to another device RS485Serial.begin(9600); // set the data rate } //End setup void loop() { String dataIn; if (RS485Serial.available()) { dataIn = RS485Serial.readStringUntil('\n'); ParseReceived(dataIn); } } //End loop void ParseReceived(String Message) { String StatusData; //int Count; String StatusString; String Status; String Type; String Value; int Index; int Start; int End; int StatIndex; Index = Message.indexOf(' '); Start = 0; Serial.println("Message: " + Message); if (Message.startsWith("A=")) { while (End != Message.length()) { End = (Index == -1) ? Message.length() : Index; //Get the status string to process StatusString = Message.substring(Start, End); //Change our start position to 1 over the last space found Start = Index + 1; //Find the end of the next status string Index = Message.indexOf(' ', Start); //Now we need to process the status string into it's Type and Value StatIndex = StatusString.indexOf('='); Type = StatusString.substring(0, StatIndex); Value = StatusString.substring(StatIndex + 1); ParseStatus(Type, Value); } } else { SendCmd(LastSent); } } //End ParseReceived void ParseStatus(String Type, String Value) { // if (Type == "OA") { //Outside Air not used } else if (Type == "Z") { //Zone not used } else if (Type == "T") { Serial.println("T: " + Value); gw.send(msgTemp.set( F2C( Value.toFloat() ), 2 )); } else if (Type == "SP") { Serial.println("SP: " + Value); gw.send(msgSetCool.set( F2C( Value.toFloat() ), 2 )); } else if (Type == "SPH") { Serial.println("SPH: " + Value); gw.send(msgSetHeat.set( F2C( Value.toFloat() ), 2 )); } else if (Type == "SPC") { Serial.println("SPC: " + Value); gw.send(msgSetCool.set( F2C( Value.toFloat() ), 2 )); } else if (Type == "M") { //Serial.println("M: " + Value); //gw.send(msgFlowMode.set(Value.c_str())); } else if (Type == "FM") { //Serial.println("FM: " + Value); //gw.send(msgFlowMode.set(Value.c_str())); //Type 2 status message types } else if (Type == "H1A") { Serial.println("H1A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Min")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "H2A") { Serial.println("H2A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Normal")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "H3A") { Serial.println("H3A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Max")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "C1A") { Serial.println("C1A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Min")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "C2A") { Serial.println("C2A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Normal")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "FA") { Serial.println("FA: " + Value); if (Value == "1") { //gw.send(msgFlowMode.set("ContinuousOn")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "VA") { //Vent damper not used } else if (Type == "D1") { //Damper #1 not used } else if (Type == "SCP") { String stg1 = Value.substring(0, 1); String stg2 = Value.substring(0, Value.length() - 1); //logging.AddToLog("MOT/MRT stage 1: " & stg1, True) //Deal with minimum off time and minimum run times //for stage 1 //logging.AddToLog("MOT/MRT stage 2: " & stg2, True) //Deal with minimum off time and minimum run times //for stage 2 } else if (Type == "SM") { //logging.AddToLog("System mode: " & Value, True) String FlowState; if (Value == "O") { FlowState = "Off"; } else if (Value == "H") { FlowState = "HeatOn"; } else if (Value == "C") { FlowState = "CoolOn"; } else { FlowState = "AutoChangeOver"; } //Serial.println("SM: " + FlowState); //gw.send(msgFlowState.set(FlowState.c_str())); } else if (Type == "SF") { //logging.AddToLog("System fan: " & Value, True) Serial.println("SF: " + Value); gw.send(msgStatus.set(Value.toInt())); } } //End ParseStatus float F2C(float Fahrenheit) { return (5.0f/9.0f) * (Fahrenheit-32); } //End F2C float C2F(float Celsius) { return (Celsius * 9.0f) / 5.0f + 32.0f; } //End C2F void SendCmd(String cmd) { String commandStr; commandStr = "A=" + serialAddr + " O=00 " + cmd; Serial.println("Writing to serial port: " + commandStr); // Enable RS485 Transmit only for the duration of the send digitalWrite(SSerialTxControl, RS485Transmit); RS485Serial.print(commandStr + "\r"); LastSent = cmd; //Return to RS485 receive mode digitalWrite(SSerialTxControl, RS485Receive); } //End SendCmd /** * incomingMessage - Process the incoming messages. */ void incomingMessage(const MyMessage &message) { Serial.println("message received");//String(message.type)); //Serial.println(message.data); // We only expect one type of message from controller. But we better check anyway. if (message.isAck()) { Serial.println("This is an ack from gateway"); } Serial.println("Temp: " + String(message.data) + " -- " + message.type); if ( message.type == V_TEMP ) { // Serial.println("Temp: " + String(message.data)); } //End V_TEMP if ( message.type == V_STATUS ) { // Serial.println("Status: " + String(message.data)); } //End V_STATUS if ( message.type == V_HVAC_FLOW_STATE ) { // Serial.println("Flow State: " + String(message.data)); } //End V_HVAC_FLOW_STATE if ( message.type == V_HVAC_SPEED ) { // Serial.println("Speed: " + String(message.data)); } //End V_HVAC_SPEED if (message.type == V_HVAC_SETPOINT_COOL) { Serial.println("Message received"); String setPoint = String(C2F(atoi(message.data))); Serial.println("New Set Temp is : " + String(setPoint)); SendCmd("SPC=" + setPoint + " R=1"); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.data); } //End V_HVAC_SETPOINT_COOL if (message.type == V_HVAC_SETPOINT_HEAT) { Serial.println("Message received"); String setPoint = String(C2F(atoi(message.data))); //.toInt(); Serial.println("New Set Temp is : " + String(setPoint)); SendCmd("SPH=" + setPoint + " R=1"); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.data); } //End V_HVAC_SETPOINT_HEAT if ( (message.type == V_HVAC_FLOW_MODE) ) { // Serial.println("Flow Mode: " + String(message.data)); } //End V_HVAC_FLOW_MODE } //End incomingMessageThanks
-
OK, so I had this project on hold for a while and am getting back to it. My issue now is that for some reason I am not receiving messages from Domoticz for this node. If I send a temp set point or status from the RS485 side, it updates in Domoticz, but if I try to change a set point or status in Domoticz, the MySensors node doesn't receive it. The code is a bit messy right now, but it should work with what I have. If someone could look it over and advise, that would be a big help. The sketch is a MySensors 1.5.4 sketch.
/* RCS Thermostat for MySensors Arduino RCS RS485 thermostat control July 7,2016 This is a gateway bridge to allow an RCS serial thermostat to be accessible to a MySensors gateway. The thermostat being used to test this is an RCS TR40 RS485 thermostat. The published protocol for RCS thermostats can be found at the following address; http://www.rcstechnology.com/oldsite/docs/thermostats/serial/SERIAL%20PROTOCOL%20REV%204.3%20%20150-00225-43.pdf This sketch features the following: Add features here */ // Import needed libraries #include <SPI.h> #include <MySensor.h> #include <SoftwareSerial.h> #define SKETCH_NAME "RCS TR40 Thermostat" #define SKETCH_VERSION "1.1" #define CHILD_ID_HVAC 0 // S_HVAC #define CHILD_ID_STATE 1 // S_LIGHT // Declare Constants and Pin Numbers #define SSerialRX 5 //Serial Receive pin 8 #define SSerialTX 3 //Serial Transmit pin 7 #define SSerialTxControl 4 //RS485 Direction control #define RS485Transmit HIGH #define RS485Receive LOW // Declare objects SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX MySensor gw; // Sensor values MyMessage msgStatus ( CHILD_ID_STATE, V_LIGHT ); MyMessage msgTemp ( CHILD_ID_HVAC, V_TEMP ); MyMessage msgSetCool( CHILD_ID_HVAC, V_HVAC_SETPOINT_COOL ); MyMessage msgSetHeat( CHILD_ID_HVAC, V_HVAC_SETPOINT_HEAT ); // Declare Variables int byteReceived; int byteSend; String rcvString; String sndString; //This is for storing the last command that was sent String lastSent; //the last sent set point String setPoint; String mode; //This is the RS485 address of this node that gets sent to the thermostat String serialAddr = "1"; //Placeholder for the last command sent String LastSent = ""; void setup() { Serial.begin(9600); gw.begin( incomingMessage, AUTO, false ); gw.sendSketchInfo( SKETCH_NAME, SKETCH_VERSION ); // Register the thermostat with the gateway gw.present( CHILD_ID_HVAC, S_HVAC ); gw.present( CHILD_ID_STATE, S_LIGHT ); // put your setup code here, to run once: pinMode( SSerialTxControl, OUTPUT ); digitalWrite( SSerialTxControl, RS485Receive ); // Init Transceiver // Start the software serial port, to another device RS485Serial.begin(9600); // set the data rate } //End setup void loop() { String dataIn; if (RS485Serial.available()) { dataIn = RS485Serial.readStringUntil('\n'); ParseReceived(dataIn); } } //End loop void ParseReceived(String Message) { String StatusData; //int Count; String StatusString; String Status; String Type; String Value; int Index; int Start; int End; int StatIndex; Index = Message.indexOf(' '); Start = 0; Serial.println("Message: " + Message); if (Message.startsWith("A=")) { while (End != Message.length()) { End = (Index == -1) ? Message.length() : Index; //Get the status string to process StatusString = Message.substring(Start, End); //Change our start position to 1 over the last space found Start = Index + 1; //Find the end of the next status string Index = Message.indexOf(' ', Start); //Now we need to process the status string into it's Type and Value StatIndex = StatusString.indexOf('='); Type = StatusString.substring(0, StatIndex); Value = StatusString.substring(StatIndex + 1); ParseStatus(Type, Value); } } else { SendCmd(LastSent); } } //End ParseReceived void ParseStatus(String Type, String Value) { // if (Type == "OA") { //Outside Air not used } else if (Type == "Z") { //Zone not used } else if (Type == "T") { Serial.println("T: " + Value); gw.send(msgTemp.set( F2C( Value.toFloat() ), 2 )); } else if (Type == "SP") { Serial.println("SP: " + Value); gw.send(msgSetCool.set( F2C( Value.toFloat() ), 2 )); } else if (Type == "SPH") { Serial.println("SPH: " + Value); gw.send(msgSetHeat.set( F2C( Value.toFloat() ), 2 )); } else if (Type == "SPC") { Serial.println("SPC: " + Value); gw.send(msgSetCool.set( F2C( Value.toFloat() ), 2 )); } else if (Type == "M") { //Serial.println("M: " + Value); //gw.send(msgFlowMode.set(Value.c_str())); } else if (Type == "FM") { //Serial.println("FM: " + Value); //gw.send(msgFlowMode.set(Value.c_str())); //Type 2 status message types } else if (Type == "H1A") { Serial.println("H1A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Min")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "H2A") { Serial.println("H2A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Normal")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "H3A") { Serial.println("H3A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Max")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "C1A") { Serial.println("C1A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Min")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "C2A") { Serial.println("C2A: " + Value); if (Value == "1") { //gw.send(msgHvacSpeed.set("Normal")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "FA") { Serial.println("FA: " + Value); if (Value == "1") { //gw.send(msgFlowMode.set("ContinuousOn")); } else { //gw.send(msgHvacSpeed.set("Auto")); } } else if (Type == "VA") { //Vent damper not used } else if (Type == "D1") { //Damper #1 not used } else if (Type == "SCP") { String stg1 = Value.substring(0, 1); String stg2 = Value.substring(0, Value.length() - 1); //logging.AddToLog("MOT/MRT stage 1: " & stg1, True) //Deal with minimum off time and minimum run times //for stage 1 //logging.AddToLog("MOT/MRT stage 2: " & stg2, True) //Deal with minimum off time and minimum run times //for stage 2 } else if (Type == "SM") { //logging.AddToLog("System mode: " & Value, True) String FlowState; if (Value == "O") { FlowState = "Off"; } else if (Value == "H") { FlowState = "HeatOn"; } else if (Value == "C") { FlowState = "CoolOn"; } else { FlowState = "AutoChangeOver"; } //Serial.println("SM: " + FlowState); //gw.send(msgFlowState.set(FlowState.c_str())); } else if (Type == "SF") { //logging.AddToLog("System fan: " & Value, True) Serial.println("SF: " + Value); gw.send(msgStatus.set(Value.toInt())); } } //End ParseStatus float F2C(float Fahrenheit) { return (5.0f/9.0f) * (Fahrenheit-32); } //End F2C float C2F(float Celsius) { return (Celsius * 9.0f) / 5.0f + 32.0f; } //End C2F void SendCmd(String cmd) { String commandStr; commandStr = "A=" + serialAddr + " O=00 " + cmd; Serial.println("Writing to serial port: " + commandStr); // Enable RS485 Transmit only for the duration of the send digitalWrite(SSerialTxControl, RS485Transmit); RS485Serial.print(commandStr + "\r"); LastSent = cmd; //Return to RS485 receive mode digitalWrite(SSerialTxControl, RS485Receive); } //End SendCmd /** * incomingMessage - Process the incoming messages. */ void incomingMessage(const MyMessage &message) { Serial.println("message received");//String(message.type)); //Serial.println(message.data); // We only expect one type of message from controller. But we better check anyway. if (message.isAck()) { Serial.println("This is an ack from gateway"); } Serial.println("Temp: " + String(message.data) + " -- " + message.type); if ( message.type == V_TEMP ) { // Serial.println("Temp: " + String(message.data)); } //End V_TEMP if ( message.type == V_STATUS ) { // Serial.println("Status: " + String(message.data)); } //End V_STATUS if ( message.type == V_HVAC_FLOW_STATE ) { // Serial.println("Flow State: " + String(message.data)); } //End V_HVAC_FLOW_STATE if ( message.type == V_HVAC_SPEED ) { // Serial.println("Speed: " + String(message.data)); } //End V_HVAC_SPEED if (message.type == V_HVAC_SETPOINT_COOL) { Serial.println("Message received"); String setPoint = String(C2F(atoi(message.data))); Serial.println("New Set Temp is : " + String(setPoint)); SendCmd("SPC=" + setPoint + " R=1"); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.data); } //End V_HVAC_SETPOINT_COOL if (message.type == V_HVAC_SETPOINT_HEAT) { Serial.println("Message received"); String setPoint = String(C2F(atoi(message.data))); //.toInt(); Serial.println("New Set Temp is : " + String(setPoint)); SendCmd("SPH=" + setPoint + " R=1"); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); Serial.print(", New status: "); Serial.println(message.data); } //End V_HVAC_SETPOINT_HEAT if ( (message.type == V_HVAC_FLOW_MODE) ) { // Serial.println("Flow Mode: " + String(message.data)); } //End V_HVAC_FLOW_MODE } //End incomingMessageThanks
@dbemowsk And... (sorry to bother you with things you didn't ask for) Your sketch is loaded with String object definitions and therefore open fora lot of problems. String looks like an easy solution but not really suited for real time (MySensors) purposes.
An interesting article/ opinion background on the subject...My advice: Forget about String and get back to comprehensible char arrays. (unless somebody can convince me otherwise) .
-
@AWI said:
@dbemowsk What does the serial log of the node tell you? Does it show messages coming in?
I put the first Serial.println in the incomingMessage function to test and see if it was even hitting that function. I am not even seeing that in the serial monitor. That was the thing that prompted me to post this.
The set-up I have for testing right now is I have my node connected to the FTDI usb cable on one end (COM5). On the RS485 end (COM10) I have it looped back to my laptop through a USB to RS485 adapter. I then use a serial terminal program to transmit and receive strings similar to what would come from my thermostat. As I mentioned in my post, if I send a command on the RS485 side as if my thermostat controller sent it, it goes through ParseReceived and ParseStatus normally and the gw.send commands push it to Domoticz just fine.
I just can't think of any reason why the incoming messages from Domoticz are not being seen by the node. One thing I did find strange was that in order to see the Serial.println messages in the arduino serial monitor, I have it set to a baud of 115200 bps. The thing that confused me was that I have the first line in set-up as :
Serial.begin(9600);I did this because that is the baud rate that my thermostat communicates at on the RS485 side of things. I realize that this is for the RS232 serial side on the arduino which is why I was confused.
-
@dbemowsk And... (sorry to bother you with things you didn't ask for) Your sketch is loaded with String object definitions and therefore open fora lot of problems. String looks like an easy solution but not really suited for real time (MySensors) purposes.
An interesting article/ opinion background on the subject...My advice: Forget about String and get back to comprehensible char arrays. (unless somebody can convince me otherwise) .
@AWI said:
@dbemowsk And... (sorry to bother you with things you didn't ask for) Your sketch is loaded with String object definitions and therefore open fora lot of problems. String looks like an easy solution but not really suited for real time (MySensors) purposes.
An interesting article/ opinion background on the subject...My advice: Forget about String and get back to comprehensible char arrays. (unless somebody can convince me otherwise) .
No need to appologize. C and C++ are languages that I have not done much programming in. Well, a very limited amount of C++ and I have never used C (until getting into arduino which seems to be more C based). As I have been working in my arduuino stuff I have been seeing more people using char and char* definitions. That and converting to these using c_str(). As mentioned, I am new to these languages, so if you know of any good tutorials on how to use these versus String, I am open to suggestions. I have not yet looked at the link you posted, but will shortly. If this is the more proper way to do things in arduino, I would like to shift my thinking in that direction.