smarmengol / Modbus-Master-Slave-for-Arduino

Modbus Master-Slave library for Arduino
GNU Lesser General Public License v2.1
473 stars 328 forks source link

Sending data through MODBUS master #58

Open vishalbhat88 opened 3 years ago

vishalbhat88 commented 3 years ago

Hey, I am trying to send int type data through MODBUS with arduino uno acting as the master and a slave MODBUS simulator on my PC. Communication is working but the data i am sending is not right. Any suggestions or advice would be really helpful Below is the code

#include <ModbusRtu.h>
//#include <SimpleModbusMaster.h>
//#include <ModbusRTUMaster.h>
//#include<RS485.h>

#include <Timer.h>
#include <Event.h>

#include<ezButton.h>

//Pin definitions
#define PowerOnOffButtonPin 3
#define StatusLED1 4
#define StatusLED2 5
#define StatusLED3 6
#define StatusLED4 7
#define StatusLED5 8

#define T1 A0
#define T2 A1
#define T3 A2
#define T4 A3
#define T5 A4
#define T6 A5
#define T7 A6
#define T8 A7

// Definitions for temperature
#define T_REF 25.0
#define DEG_K 273.16
#define THERM_BETA 3435.0
#define c1 1.009249522e-03 
#define c2 2.378405444e-04 
#define c3 2.019202697e-07
#define SERIES_RESISTOR 21020

//different MODBUS libraries to use
#define MODBUS_1 1    // include ModbusRtu.h
#define MODBUS_2 0    // include SimpleModbusMaster.h
#define MODBUS_3 0    // include ModbusRTUMaster.h and RS485.h

#if MODBUS_1 || MODBUS_2 || MODBUS_3
#define AUX_ADDRESS 0
#define BMS_ADDRESS 0x31

#define AUX_STATE_VARIABLES_REGISTER 0x01
#define AUX_SYSTEM_STATUS_REGISTER 0x02
#define AUX_DISCHARGE_ONOFF_REGISTER 0x03
#define AUX_TEMP_1_REGISTER 0x04
#define AUX_TEMP_2_REGISTER 0x05
#define AUX_TEMP_3_REGISTER 0x06
#define AUX_TEMP_4_REGISTER 0x07
#define AUX_TEMP_5_REGISTER 0x08
#define AUX_TEMP_6_REGISTER 0x09
#define AUX_TEMP_7_REGISTER 0x0A
#define AUX_TEMP_8_REGISTER 0x0B

#define TOTAL_NO_OF_REGISTERS 11

#define RS485_TX_EN_PIN 2
#define baud 19200
#endif

#if MODBUS_2
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 10

enum
{
  PACKET1,
  PACKET2,
  TOTAL_NO_OF_PACKETS
};

Packet packets[TOTAL_NO_OF_PACKETS];
//Master register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];
#endif

#if MODBUS_3
ModbusRTUMaster master(RS485);
#endif

const int shortPressTime = 800;                //max time considered for a short press
const int longPressTime = 3000;                //min time considered for a long press 

int buttonLastState = LOW;
int buttonCurrentState;

unsigned long pressedTime = 0;
unsigned long releasedTime = 0;

float soc;
float temp1,temp2,temp3,temp4,temp5,temp6,temp7,temp8;
float V1,V2,V3,V4,V5,V6,V7,V8;
int R1,R2,R3,R4,R5,R6,R7,R8;
int tempSensorValue1,tempSensorValue2,tempSensorValue3,tempSensorValue4,tempSensorValue5,tempSensorValue6,tempSensorValue7,tempSensorValue8;

//float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;

bool isCharging = false;                 // is true if pack is charging(Ich > 0 )
bool dischargeMosfetStatus = false;      // is true if discharge MOSFET is ON

ezButton powerOnOffSwitch(PowerOnOffButtonPin);
Timer secondsTimer;

#if MODBUS_1
Modbus master(AUX_ADDRESS, Serial, RS485_TX_EN_PIN);
//uint16_t modbusData[16];
uint16_t state[TOTAL_NO_OF_REGISTERS] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B};
uint8_t u8state;
uint8_t u8query;
modbus_t telegram[TOTAL_NO_OF_REGISTERS];
unsigned long u32wait;
#endif

/****************************** Function Declarations    ***********************/
void interruptRoutine();
void showSoC();
void showChargingStatus();
void calculateTemperatures();
void serialFlush();
void modbus_setup();
void modbusLoop();

/****************************** Main Function Definitions    ***********************/
void setup() {
  Serial.begin(baud);

  pinMode(StatusLED1,OUTPUT);
  pinMode(StatusLED2,OUTPUT);
  pinMode(StatusLED3,OUTPUT);
  pinMode(StatusLED4,OUTPUT);
  pinMode(StatusLED5,OUTPUT);

  pinMode(PowerOnOffButtonPin, INPUT_PULLUP);
  powerOnOffSwitch.setDebounceTime(50);

  //attachInterrupt(digitalPinToInterrupt(PowerOnOffButtonPin),interruptRoutine,FALLING);
  modbus_setup();
}

void loop() {
  //modbusLoop();
  //modbus_update();
  powerOnOffSwitch.loop();
  secondsTimer.update();
  //buttonCurrentState = digitalRead(PowerOnOffButtonPin);

  if(!isCharging)
  {
    if(powerOnOffSwitch.isPressed())        // button is pressed
      {
        pressedTime = millis();
      }
    else if(powerOnOffSwitch.isReleased()) // button is released
      { 
        releasedTime = millis();
        long pressDuration = releasedTime - pressedTime;

        if( pressDuration < shortPressTime )
        {
          soc = 88.43;
          showSoC();
          delay(100);
          Serial.println("A short press is detected");
        }

        if( pressDuration > longPressTime )
        {
          Serial.println("A long press is detected");
          state[AUX_DISCHARGE_ONOFF_REGISTER] = true;
          if(dischargeMosfetStatus)
          {
            //Serial.println("A long press is detected");
            secondsTimer.oscillate(StatusLED5,1000, LOW, 3);
            secondsTimer.oscillate(StatusLED1,1000, LOW, 3);
            delay(100);
          }
        }
      }
  }

  modbusLoop();

  //analog read for thermistor temperature readings
  tempSensorValue1 = analogRead(T1);
  tempSensorValue2 = analogRead(T2);
  tempSensorValue3 = analogRead(T3);
  tempSensorValue4 = analogRead(T4);
  tempSensorValue5 = analogRead(T5);
  tempSensorValue6 = analogRead(T6);
  tempSensorValue7 = analogRead(T7);
  tempSensorValue8 = analogRead(T8);

  calculateTemperatures();
  //Serial.print("Temp4 :");
  //Serial.println(temp4);

  delay(150);

  //modbusData[4] = (int)temp4;
  #if MODBUS_1
  state[AUX_TEMP_1_REGISTER] = (int)temp1;
  state[AUX_TEMP_2_REGISTER] = (int)temp2;
  state[AUX_TEMP_3_REGISTER] = (int)temp3;
  state[AUX_TEMP_4_REGISTER] = (int)temp4;
  state[AUX_TEMP_5_REGISTER] = (int)temp5;
  state[AUX_TEMP_6_REGISTER] = (int)temp6;
  state[AUX_TEMP_7_REGISTER] = (int)temp7;
  state[AUX_TEMP_8_REGISTER] = (int)temp8;
  #endif
  //Serial.println(state[AUX_TEMP_4_REGISTER]);
  delay(50);

  //Serial.println(state[AUX_TEMP_3TO4_REGISTER]);
  if(isCharging)
  {
    soc = 72;
    showChargingStatus();
  }

  //buttonLastState = buttonCurrentState;
  serialFlush();
}

void interruptRoutine()
{

}

void showSoC()
{
  if(soc >= 90.0)
  {
    digitalWrite(StatusLED5,HIGH);
    digitalWrite(StatusLED4,HIGH);
    digitalWrite(StatusLED3,HIGH);
    digitalWrite(StatusLED2,HIGH);
    digitalWrite(StatusLED1,HIGH);
  }
  else if(soc < 90.0 && soc >= 70.0)
  {
    digitalWrite(StatusLED5,LOW);
    digitalWrite(StatusLED4,HIGH);
    digitalWrite(StatusLED3,HIGH);
    digitalWrite(StatusLED2,HIGH);
    digitalWrite(StatusLED1,HIGH);    
  }
  else if(soc< 70.0 && soc >= 50.0)
  {
    digitalWrite(StatusLED5,LOW);
    digitalWrite(StatusLED4,LOW);
    digitalWrite(StatusLED3,HIGH);
    digitalWrite(StatusLED2,HIGH);
    digitalWrite(StatusLED1,HIGH);    
  }
  else if(soc< 50.0 && soc >= 30.0)
  {
    digitalWrite(StatusLED5,LOW);
    digitalWrite(StatusLED4,LOW);
    digitalWrite(StatusLED3,LOW);
    digitalWrite(StatusLED2,HIGH);
    digitalWrite(StatusLED1,HIGH);     
  }
  else if(soc < 30.0 && soc >= 10.0)
  {
    digitalWrite(StatusLED5,LOW);
    digitalWrite(StatusLED4,LOW);
    digitalWrite(StatusLED3,LOW);
    digitalWrite(StatusLED2,LOW);
    digitalWrite(StatusLED1,HIGH);     
  }
  else if(soc < 10.0)
  {
    digitalWrite(StatusLED5,LOW);
    digitalWrite(StatusLED4,LOW);
    digitalWrite(StatusLED3,LOW);
    digitalWrite(StatusLED2,LOW);
    digitalWrite(StatusLED1,LOW);
  }

  delay(1000);

  digitalWrite(StatusLED5,LOW);
  digitalWrite(StatusLED4,LOW);
  digitalWrite(StatusLED3,LOW);
  digitalWrite(StatusLED2,LOW);
  digitalWrite(StatusLED1,LOW);  
}

void showChargingStatus()
{
  if(isCharging)
  {
    if(soc>0.0 && soc <= 30.0)
    {
      digitalWrite(StatusLED1,HIGH);
      delay(250);
      digitalWrite(StatusLED1,LOW);
      digitalWrite(StatusLED2,LOW);
      digitalWrite(StatusLED3,LOW);
      digitalWrite(StatusLED4,LOW);
      digitalWrite(StatusLED5,LOW);    
    }
    else if (soc > 30.0 && soc <= 50.0)
    {
      digitalWrite(StatusLED1,HIGH);
      digitalWrite(StatusLED2,HIGH);
      delay(250);
      digitalWrite(StatusLED2,LOW);
      digitalWrite(StatusLED3,LOW);
      digitalWrite(StatusLED4,LOW);
      digitalWrite(StatusLED5,LOW); 
    }
    else if (soc > 50.0 && soc <= 70)
    {
      digitalWrite(StatusLED1,HIGH);
      digitalWrite(StatusLED2,HIGH);
      digitalWrite(StatusLED3,HIGH);
      delay(250);
      digitalWrite(StatusLED3,LOW);
      digitalWrite(StatusLED4,LOW);
      digitalWrite(StatusLED5,LOW);    
    }
    else if(soc > 70.0 && soc <= 90.0)
    {
      digitalWrite(StatusLED1,HIGH);
      digitalWrite(StatusLED2,HIGH);
      digitalWrite(StatusLED3,HIGH);
      digitalWrite(StatusLED4,HIGH);
      delay(250);
      digitalWrite(StatusLED4,LOW);
      digitalWrite(StatusLED5,LOW);     
    }
    else if( soc > 90.0 && soc < 100.0)
    {
      digitalWrite(StatusLED1,HIGH);
      digitalWrite(StatusLED2,HIGH);
      digitalWrite(StatusLED3,HIGH);
      digitalWrite(StatusLED4,HIGH);
      digitalWrite(StatusLED5,HIGH);
      delay(250);
      digitalWrite(StatusLED5,LOW);     
    }
    else if (soc == 100.0)
    {
      digitalWrite(StatusLED1,HIGH);
      digitalWrite(StatusLED2,HIGH);
      digitalWrite(StatusLED3,HIGH);
      digitalWrite(StatusLED4,HIGH);
      digitalWrite(StatusLED5,HIGH);     
    }
  }
}

void calculateTemperatures()
{
  R1 = SERIES_RESISTOR *(1024.0 / float(tempSensorValue1) - 1.0);
  R2 = SERIES_RESISTOR *(1024.0 / float(tempSensorValue2) - 1.0);
  R3 = SERIES_RESISTOR *(1024.0 / float(tempSensorValue3) - 1.0);
  R4 = SERIES_RESISTOR *(1024.0 / float(tempSensorValue4) - 1.0);
  R5 = SERIES_RESISTOR *(1024.0 / float(tempSensorValue5) - 1.0);
  R6 = SERIES_RESISTOR *(1024.0 / float(tempSensorValue6) - 1.0);
  R7 = SERIES_RESISTOR *(1024.0 / float(tempSensorValue7) - 1.0);
  R8 = SERIES_RESISTOR *(1024.0 / float(tempSensorValue8) - 1.0);

  temp1 = (1.0 / (c1 + c2*log(R1) + c3*log(R1)*log(R1)*log(R1))) - DEG_K;
  temp2 = (1.0 / (c1 + c2*log(R2) + c3*log(R2)*log(R2)*log(R2))) - DEG_K;
  temp3 = (1.0 / (c1 + c2*log(R3) + c3*log(R3)*log(R3)*log(R3))) - DEG_K;
  temp4 = (1.0 / (c1 + c2*log(R4) + c3*log(R4)*log(R4)*log(R4))) - DEG_K;
  temp5 = (1.0 / (c1 + c2*log(R5) + c3*log(R5)*log(R5)*log(R5))) - DEG_K;
  temp6 = (1.0 / (c1 + c2*log(R6) + c3*log(R6)*log(R6)*log(R6))) - DEG_K;  
  temp7 = (1.0 / (c1 + c2*log(R7) + c3*log(R7)*log(R7)*log(R7))) - DEG_K;
  temp8 = (1.0 / (c1 + c2*log(R8) + c3*log(R8)*log(R8)*log(R8))) - DEG_K;

}

void serialFlush()
{
  while(Serial.available()>0)
    char t = Serial.read();
}

void modbus_setup()
{
  #if MODBUS_1 
//  state[AUX_STATE_VARIABLES_REGISTER] = 0;
//  state[AUX_SYSTEM_STATUS_REGISTER] = 0;
//  state[AUX_DISCHARGE_ONOFF_REGISTER] = 0;
//  state[AUX_TEMP_1TO2_REGISTER] = 0;
//  state[AUX_TEMP_3TO4_REGISTER] = 0;
//  state[AUX_TEMP_5TO6_REGISTER] = 0;
//  state[AUX_TEMP_7TO8_REGISTER] = 0;

  telegram[0].u8id = BMS_ADDRESS; // slave address
  telegram[0].u8fct = 4; // function code (this one is registers read)
  telegram[0].u16RegAdd = 0; // start address in slave
  telegram[0].u16CoilsNo = 4; // number of elements (coils or registers) to read
  telegram[0].au16reg = state[AUX_STATE_VARIABLES_REGISTER]; // pointer to a memory array in the Arduino

  telegram[1].u8id = BMS_ADDRESS; // slave address
  telegram[1].u8fct = 4; // function code (this one is registers read)
  telegram[1].u16RegAdd = 0; // start address in slave
  telegram[1].u16CoilsNo = 4; // number of elements (coils or registers) to read
  telegram[1].au16reg = state[AUX_SYSTEM_STATUS_REGISTER]; // pointer to a memory array in the Arduino

  telegram[2].u8id = BMS_ADDRESS; // slave address
  telegram[2].u8fct = 6; // function code (this one is registers read)
  telegram[2].u16RegAdd = 0; // start address in slave
  telegram[2].u16CoilsNo = 1; // number of elements (coils or registers) to read
  telegram[2].au16reg = state[AUX_DISCHARGE_ONOFF_REGISTER]; // pointer to a memory array in the Arduino

  telegram[3].u8id = BMS_ADDRESS; // slave address
  telegram[3].u8fct = 6; // function code (this one is single coil write)
  telegram[3].u16RegAdd = 1; // start address in slave
  telegram[3].u16CoilsNo = 1; // number of elements (coils or registers) to write
  telegram[3].au16reg = state[AUX_TEMP_1_REGISTER]; // pointer to a memory array in the Arduino

  telegram[4].u8id = BMS_ADDRESS; // slave address
  telegram[4].u8fct = 6; // function code (this one is single coil write)
  telegram[4].u16RegAdd = 2; // start address in slave
  telegram[4].u16CoilsNo = 1; // number of elements (coils or registers) to write
  telegram[4].au16reg = state[AUX_TEMP_2_REGISTER]; // pointer to a memory array in the Arduino  

  telegram[5].u8id = BMS_ADDRESS; // slave address
  telegram[5].u8fct = 6; // function code (this one is single coil write)
  telegram[5].u16RegAdd = 3; // start address in slave
  telegram[5].u16CoilsNo = 1; // number of elements (coils or registers) to write
  telegram[5].au16reg = state[AUX_TEMP_3_REGISTER]; // pointer to a memory array in the Arduino

  telegram[6].u8id = BMS_ADDRESS; // slave address
  telegram[6].u8fct = 6; // function code (this one is single coil write)
  telegram[6].u16RegAdd = 4; // start address in slave
  telegram[6].u16CoilsNo = 1; // number of elements (coils or registers) to write
  telegram[6].au16reg = state[AUX_TEMP_4_REGISTER]; // pointer to a memory array in the Arduino

  telegram[7].u8id = BMS_ADDRESS; // slave address
  telegram[7].u8fct = 6; // function code (this one is single coil write)
  telegram[7].u16RegAdd = 5; // start address in slave
  telegram[7].u16CoilsNo = 1; // number of elements (coils or registers) to write
  telegram[7].au16reg = state[AUX_TEMP_5_REGISTER]; // pointer to a memory array in the Arduino

  telegram[8].u8id = BMS_ADDRESS; // slave address
  telegram[8].u8fct = 6; // function code (this one is single coil write)
  telegram[8].u16RegAdd = 6; // start address in slave
  telegram[8].u16CoilsNo = 1; // number of elements (coils or registers) to write
  telegram[8].au16reg = state[AUX_TEMP_6_REGISTER]; // pointer to a memory array in the Arduino    

  telegram[9].u8id = BMS_ADDRESS; // slave address
  telegram[9].u8fct = 6; // function code (this one is registers read)
  telegram[9].u16RegAdd = 7; // start address in slave
  telegram[9].u16CoilsNo = 1; // number of elements (coils or registers) to write
  telegram[9].au16reg = state[AUX_TEMP_7_REGISTER]; // pointer to a memory array in the Arduino

  // telegram 10: write a single coil
  telegram[10].u8id = BMS_ADDRESS; // slave address
  telegram[10].u8fct = 6; // function code (this one is write a single register)
  telegram[10].u16RegAdd = 8; // start address in slave
  telegram[10].u16CoilsNo = 1; // number of elements (coils or registers) to write
  telegram[10].au16reg =  state[AUX_TEMP_8_REGISTER]; // pointer to a memory array in the Arduino

  master.start();
  master.setTimeOut( 5000 ); // if there is no answer in 5000 ms, roll over
  u32wait = millis() + 1000;
  u8state = u8query = 0; 
  #endif

  #if MODBUS_2
// Initialize each packet: packet, slave-id, function, start of slave index, number of regs, start of master index

  modbus_construct(&packets[PACKET1], BMS_ADDRESS, READ_HOLDING_REGISTERS, 0,TOTAL_NO_OF_REGISTERS, 0);
  modbus_construct(&packets[PACKET2], BMS_ADDRESS, PRESET_MULTIPLE_REGISTERS, 1, TOTAL_NO_OF_REGISTERS, 0);
  modbus_configure(&Serial, baud, SERIAL_8N1, timeout, polling, retry_count,RS485_TX_EN_PIN, packets, TOTAL_NO_OF_PACKETS, regs);

  #endif
}

void modbusLoop()
{
  #if MODBUS_2
  modbus_update();
  #endif

  #if MODBUS_1
  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1: 
    master.query( telegram[u8query] ); // send query (only once)
    u8state++;
    u8query++;
    if (u8query > TOTAL_NO_OF_REGISTERS) u8query = 0;
      break;
  case 2:
    //Serial.println(state[AUX_TEMP_4_REGISTER]);    
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 1000; 
    }
    break;
  }
  #endif
}