Smart Home Automation Forum
Tuya adapter V2 arduino source code - RS485 relay controller KC868-H32BS - Printable Version

+- Smart Home Automation Forum (https://www.kincony.com/forum)
+-- Forum: Technical Support (https://www.kincony.com/forum/forumdisplay.php?fid=20)
+--- Forum: KC868-ATC / Tuya adapter V2 (https://www.kincony.com/forum/forumdisplay.php?fid=32)
+--- Thread: Tuya adapter V2 arduino source code - RS485 relay controller KC868-H32BS (/showthread.php?tid=5732)



Tuya adapter V2 arduino source code - RS485 relay controller KC868-H32BS - admin - 05-14-2024

This is sample demo let RS485 digital output device (KinCony KC868-H32BS controller) can work with Tuya app by internet.  you can let your own RS485 relay board add to Tuya app.
added Tuya adapter v2, relay board will support alexa or Google home speaker for voice control directly.
   
   
   
arduino source code download: 
.zip   Tuya_AdapterV2_RS485_Relay.zip (Size: 2.63 KB / Downloads: 65)
Code:
#include <ModbusMaster.h>
#include <Arduino.h>
#include <TuyaWifi.h>
#include "HardwareSerial.h"
//---------RS485 setting
#define DEBUG   1

#define SERIAL_BAUD   9600
#define RX_PIN    32
#define TX_PIN    33
#define ADAPT485_NUM  2
#define SLAVE_ADDR  1
#define READ_ADDR  0
#define READ_NUM   32 

/* Current device DP values */
bool rt_coils_status[32] = {0};

HardwareSerial My485Serial(ADAPT485_NUM);
ModbusMaster node;
uint16_t rcv_buf[READ_NUM>>4] = {0};
  
static void ReadEmeterRegs(void)
{
  uint32_t read_tmp = 0;
  
  uint8_t result = node.readCoils(READ_ADDR, READ_NUM);
  if (result == node.ku8MBSuccess) {//if communicate successful then
       
    for (uint8_t i = 0; i < 2; i++)
    {
      rcv_buf[i] = node.getResponseBuffer(i);
      for(uint8_t j = 0; j < 16; j++)
      {
        if(j<8) rt_coils_status[i*16 + j+8] = (rcv_buf[1-i]&(1<<j))?true:false;
        else rt_coils_status[i*16 + j - 8] = (rcv_buf[1-i]&(1<<j))?true:false;
      }
    }
   
    #if DEBUG
    Serial1.print("Get switch[0..31] value is");
    Serial1.print(":<0x");
    Serial1.print(rcv_buf[0],HEX);
    Serial1.print(rcv_buf[1],HEX);
    Serial1.println("> ");
    #endif
    
  }
  else
  {
    node.clearResponseBuffer();
  }

  delay(100);
}

//---RS485 setting end----

TuyaWifi my_device;



/* Current LED status */
unsigned char led_state = 0;
/* Connect network button pin */
int key_pin = 25;


/* Data point define */
typedef enum
{
  DPID_SWITCH01 = 1,
  DPID_SWITCH02,DPID_SWITCH03,
  DPID_SWITCH04,DPID_SWITCH05,DPID_SWITCH06,
  DPID_SWITCH07 = 113,
  DPID_SWITCH08,DPID_SWITCH09,DPID_SWITCH10,
  DPID_SWITCH11,DPID_SWITCH12,DPID_SWITCH13,
  DPID_SWITCH14,DPID_SWITCH15,DPID_SWITCH16,
  DPID_SWITCH17,DPID_SWITCH18,DPID_SWITCH19,
  DPID_SWITCH20,DPID_SWITCH21,DPID_SWITCH22,
  DPID_SWITCH23,DPID_SWITCH24,DPID_SWITCH25,
  DPID_SWITCH26,DPID_SWITCH27,DPID_SWITCH28,
  DPID_SWITCH29,DPID_SWITCH30,DPID_SWITCH31,
  DPID_SWITCH32,
}H32BS_DPID_DEF;

/*const unsigned char dpid_arr[32] = {
  1,2,3,4,5,6,
  113,114,115,116,117,118,119,120,
  121,122,123,124,125,126,127,128,
  129,130,131,132,133,134,135,136,
  137,138,
};*/

#define LED_WiFi  26
//#define LED_User  33



/* Stores all DPs and their types. PS: array[][0]:dpid, array[][1]:dp type.
*                                     dp type(TuyaDefs.h) : DP_TYPE_RAW, DP_TYPE_BOOL, DP_TYPE_VALUE, DP_TYPE_STRING, DP_TYPE_ENUM, DP_TYPE_BITMAP
*/
unsigned char dp_array[][2] =
{
  {DPID_SWITCH01, DP_TYPE_BOOL},{DPID_SWITCH02, DP_TYPE_BOOL},
  {DPID_SWITCH03, DP_TYPE_BOOL},{DPID_SWITCH04, DP_TYPE_BOOL},
  {DPID_SWITCH05, DP_TYPE_BOOL},{DPID_SWITCH06, DP_TYPE_BOOL},
  {DPID_SWITCH07, DP_TYPE_BOOL},{DPID_SWITCH08, DP_TYPE_BOOL},

  {DPID_SWITCH09, DP_TYPE_BOOL},{DPID_SWITCH10, DP_TYPE_BOOL},
  {DPID_SWITCH11, DP_TYPE_BOOL},{DPID_SWITCH12, DP_TYPE_BOOL},
  {DPID_SWITCH13, DP_TYPE_BOOL},{DPID_SWITCH14, DP_TYPE_BOOL},
  {DPID_SWITCH15, DP_TYPE_BOOL},{DPID_SWITCH16, DP_TYPE_BOOL},

  {DPID_SWITCH17, DP_TYPE_BOOL},{DPID_SWITCH18, DP_TYPE_BOOL},
  {DPID_SWITCH19, DP_TYPE_BOOL},{DPID_SWITCH20, DP_TYPE_BOOL},
  {DPID_SWITCH21, DP_TYPE_BOOL},{DPID_SWITCH22, DP_TYPE_BOOL},
  {DPID_SWITCH23, DP_TYPE_BOOL},{DPID_SWITCH24, DP_TYPE_BOOL},

  {DPID_SWITCH25, DP_TYPE_BOOL},{DPID_SWITCH26, DP_TYPE_BOOL},
  {DPID_SWITCH27, DP_TYPE_BOOL},{DPID_SWITCH28, DP_TYPE_BOOL},
  {DPID_SWITCH29, DP_TYPE_BOOL},{DPID_SWITCH30, DP_TYPE_BOOL},
  {DPID_SWITCH31, DP_TYPE_BOOL},{DPID_SWITCH32, DP_TYPE_BOOL},
};

unsigned char pid[] = {"3ocztklfu3q32jab"}; ////change pid here....
unsigned char mcu_ver[] = {"1.0.0"};

/* last time */
unsigned long last_time = 0;

/**
* @description: DP download callback function.
* @param {unsigned char} dpid
* @param {const unsigned char} value
* @param {unsigned short} length
* @return {unsigned char}
*/
unsigned char dp_process(unsigned char dpid,const unsigned char value[], unsigned short length)
{
  int16_t index_out_coil = -1;
  unsigned char get_down_cmd = false;
 
  for(int16_t i=0;i<32;i++)
  {
    if(dpid == dp_array[i][0])
    {
      index_out_coil = i;
      break;
    }
  }
  if(index_out_coil < 0) return TY_ERROR;

  get_down_cmd = my_device.mcu_get_dp_download_data(dpid,value,length);

  Serial1.print("Rcv Command:<dpid,");
  Serial1.print(dpid,DEC);
  Serial1.print(" value,");
  Serial1.print(value[0],HEX);
  Serial1.print(" len,");
  Serial1.println(length,HEX);
  Serial1.println("> ");
   
 

  #if DEBUG
    Serial1.print("get_down_cmd value is:<");
    Serial1.print(get_down_cmd,DEC); 
    Serial1.println("> ");
    Serial1.print("Node WriteCoilAddr<");
    Serial1.print(index_out_coil,DEC);
    Serial1.print("> ");
  #endif

  delay(100);
  uint8_t result = node.writeSingleCoil(index_out_coil, value[0]);
  #if DEBUG
    Serial1.print(" result:<");
    Serial1.print(result,DEC); 
    Serial1.println("> ");
  #endif

  delay(100);
  my_device.mcu_dp_update(dpid, value, length);
  return TY_SUCCESS;
}

void setup()
{

  My485Serial.begin(SERIAL_BAUD, SERIAL_8N1, RX_PIN, TX_PIN); //RS485 serial port
  node.begin(SLAVE_ADDR,My485Serial);
  Serial.begin(9600,SERIAL_8N1,22,19);  //Tuya module serial port
  Serial1.begin(115200,SERIAL_8N1,3,1);   //USB serial port

 
  // Serial with tuyawifi
 
 

  //Initialize led port, turn off led.
  pinMode(LED_WiFi, OUTPUT);
  digitalWrite(LED_WiFi, LOW);

/*  pinMode(LED_User, OUTPUT);
  digitalWrite(LED_User, LOW);*/

  //Initialize networking keys.
  pinMode(key_pin, INPUT_PULLUP);

  //Enter the PID and MCU software version
  my_device.init(pid, mcu_ver);
  //incoming all DPs and their types array, DP numbers
  my_device.set_dp_cmd_total(dp_array, 2);
  //register DP download processing callback function
  my_device.dp_process_func_register(dp_process);
  //register upload all DP callback function
  my_device.dp_update_all_func_register(dp_update_all);
 
  //delay(300);
  last_time = millis();
}

void loop()
{
  ReadEmeterRegs();  // read RS485 sensor
  my_device.uart_service();

  //Enter the connection network mode when Pin7 is pressed.
  if (digitalRead(key_pin) == LOW) {
    delay(80);
    if (digitalRead(key_pin) == LOW) {
      my_device.mcu_set_wifi_mode(SMART_CONFIG);
    }
  }
  /* LED blinks when network is being connected */
  if ((my_device.mcu_get_wifi_work_state() != WIFI_LOW_POWER) && (my_device.mcu_get_wifi_work_state() != WIFI_CONN_CLOUD) && (my_device.mcu_get_wifi_work_state() != WIFI_SATE_UNKNOW)) {
    if (millis()- last_time >= 500) {
      last_time = millis();

      if (led_state == LOW) {
        led_state = HIGH;
      } else {
        led_state = LOW;
      }
      digitalWrite(LED_WiFi, led_state);
    }
  }

  /* report the temperature and humidity */
  if ((my_device.mcu_get_wifi_work_state() == WIFI_CONNECTED) ||
      (my_device.mcu_get_wifi_work_state() == WIFI_CONN_CLOUD)) {
    dp_update_all();
  }

  delay(500);
}

static bool coils_old_status[32] = {false};

unsigned char tmp_cmd = 0;
static void CompareAndReport(void)
{
  for(int16_t i=0;i<32;i++)
  {
    if(coils_old_status[i] != rt_coils_status[i])
    {
      coils_old_status[i] = rt_coils_status[i];
      tmp_cmd = rt_coils_status[i]?1:0;
      #if 0
      Serial1.print("Changed happed:<dpid,");
      Serial1.print(dp_array[i][0],DEC);
      Serial1.println("> ");
      #endif
      my_device.mcu_dp_update(dp_array[i][0],tmp_cmd, 1);
      delay(10);
      //break;
    }
  }
}
/**
* @description: Upload all DP status of the current device.
* @param {*}
* @return {*}
*/
void dp_update_all(void)
{
  CompareAndReport();
 
}



RE: Tuya adapter V2 arduino source code - RS485 relay controller KC868-H32BS - admin - 09-02-2024

which relay controller you are using? how you set RS485 for relay controller. take a photo of setting.


RE: Tuya adapter V2 arduino source code - RS485 relay controller KC868-H32BS - Bart - 09-03-2024

There is another question, if we would be suceeded to force the adapter to work as a slave, would it be pousible to add number of coils to 64 (in tuya device) or (even 256 max possible on Modbus), could be added the indicators for inputs to control the status of PLC, and maybe to modify the Tuya app (device) to add some meters in app (for voltage, amperage, temperatures, humidity etc.), it is possible to send some registers to the Adapter. Is it worth to consider as there is not such device on the market, and as far as I know there is a lot of homes working on PLC as main controlers, and in Europe the most of industrial buildings has bulding automation on PLC controlers as well known reliable long-time solution. Each PLC has standarized communication wher modbus RTU is the most popular.  

This is the potential that could be a game changer, requires of development of the software side only as hardware is ready?


RE: Tuya adapter V2 arduino source code - RS485 relay controller KC868-H32BS - admin - 09-03-2024

1. now the Arduino code only work for KinCony's relay board. if you want connect with your own hardware, you need modify Arduino code, don't use chatGPT, suggest you find a software engineer to do that.

2. if you want create your own hardware connection, you need write the software for ESP32 , also you need to create Tuya device in your own Tuya iot platform, they need modify all.


RE: Tuya adapter V2 arduino source code - RS485 relay controller KC868-H32BS - Bart - 09-04-2024

(09-03-2024, 11:53 PM)admin Wrote: 1. now the Arduino code only work for KinCony's relay board. if you want connect with your own hardware, you need modify Arduino code, don't use chatGPT, suggest you find a software engineer to do that.

2. if you want create your own hardware connection, you need write the software for ESP32 , also you need to create Tuya device in your own Tuya iot platform, they need modify all.

I have removed the file and post, to not provoke other users to download, as this version do not compile in Arduino, when I started to analize deeply it seems that it is written without the correct analisys of libary ModbuRTUslave

What is the corect board to chose in Arduino IDE to upload the code for Tuya Adapter, I'm not able to corectly debug the oryginal code. 

Are You able to suggest the contact of software engineer that could do the job right?


RE: Tuya adapter V2 arduino source code - RS485 relay controller KC868-H32BS - admin - 09-04-2024

chose "NodeMcu-32S" in arduino IDE.


RE: Tuya adapter V2 arduino source code - RS485 relay controller KC868-H32BS - Bart - 09-05-2024

Hi, I have read the ModbusRTUslave libary manual, and I have modify existing code, with my basic knowledge - 
Adapter is working as a MODBUS RTU Slave with such parameters 
addresss - 2
baund 9600

None



It is working correctly with PLC as Master with coil READ, Adapter is working as Slave


I will attache the file for other users 

I have also made an WRITE option for coils, but that need to be tested - it is usefull if the state of coil change in the PLC then the change is visible on the adapter app (for example You swith on the light and the status in Tuya app will be changed) , as the coil status is overwritten in the adapter in the loop - that cause some issues with stable switching on or off - as there are some transmision going so you could switch on and the incoming transmision will switch off - so if enybody has an idea how to solve it that will be nice