//---------------------device address 0x04-----------------------
#define DE_RE_PIN 25      // DE and RE pins linked to GPIO 4
#define rx2_pin 16        // rx2 pin link to pin RI rs 485
#define tx2_pin 17        // tx2_pin link to pin DI rs 485 
#define MODE_SEND HIGH   // HIGH for transmitting
#define MODE_RECV LOW    // LOW for receiving
#define led 2
uint16_t crcx;
byte crc_bytehigh;
byte crc_bytelow;
byte ByteArray[40];int ByteData[40];

//all relay on send :FF 0F 00 00 00 08 01 FF
//all relay off:FF 0F 00 00 00 08 01 00 


uint8_t all_relay_on[]={0x0f,0x0f,0x00,0x00,0x00,0x08,0x01,0xff};
uint8_t all_relay_off[]={0x0f,0x0f,0x00,0x00,0x00,0x08,0x01,0x00};


uint16_t calculateModbusCRC(const uint8_t* datax, int len) {
  uint16_t crc = 0xFFFF; // Initial value

  for (int i = 0; i < len; i++) {
    crc ^= datax[i]; // XOR with current byte
    for (int j = 0; j < 8; j++) {
      if (crc & 0x0001) {
        crc = (crc >> 1) ^ 0xA001; // Right shift and XOR with polynomial
      } else {
        crc = crc >> 1; // Right shift
      }
    }
  }
  return crc;
}

void write_coil( uint8_t *buff,uint8_t l) {
  // Calculate the CRC value.
  uint16_t crcx = calculateModbusCRC(buff, l); 
  
  //  Separate the Low and High bytes 
  uint8_t crc_bytelow = crcx & 0xFF;        // บิตล่าง (8 บิตท้าย)
  uint8_t crc_bytehigh = (crcx >> 8) & 0xFF; // บิตบน (8 บิตแรก)
  
  // Display the results on the Serial Monitor for verification.
  Serial.print("CRC Byte Low : 0x"); Serial.println(crc_bytelow, HEX);
  Serial.print("CRC Byte High: 0x"); Serial.println(crc_bytehigh, HEX);

  
  digitalWrite(DE_RE_PIN, MODE_SEND); // Enable transmission
  Serial2.write(buff, l);   // Send the command via Serial2
  Serial2.write(crc_bytelow);  Serial2.write(crc_bytehigh);// Send the crc byte high and crc byte low
  Serial2.flush();                     // Wait for send to complete
  digitalWrite(DE_RE_PIN, MODE_RECV);  // Enable reception

  int a = 0;

  while(Serial2.available()){
    ByteArray[a] = Serial2.read();
    a++;
  }
  //  respond  packet 
  int b = 0;
  String Register;
  Serial.println("Receiving Data...");
  for(b=0;b<a;b++){
    Serial.print("[");
    Serial.print(b);
    Serial.print("]");
    Serial.print("=");

    Register = String(ByteArray[b],HEX);
    Serial.print(Register);
    Serial.print(" ");
  }

  Serial.println();


}
void setup() {
  pinMode(DE_RE_PIN, OUTPUT); pinMode(led, OUTPUT);
  digitalWrite(DE_RE_PIN, MODE_RECV); // Start in receive mode
  Serial.begin(115200);               // Serial monitor output
  Serial2.begin(9600, SERIAL_8N1, rx2_pin, tx2_pin); // Initialize Serial2 with standard Modbus settings
  Serial2.setTimeout(200);            // Set a timeout for response

}
void loop() {
    digitalWrite(led, 1); 
    write_coil(all_relay_on,sizeof(all_relay_on));
    delay(1000);digitalWrite(led, 0); 
    write_coil(all_relay_off,sizeof(all_relay_off));
    delay(1000);

}
