In my project, I am using Modbus ASCII protocol with an arduino uno, MAX485, with 7 data bits and even parity. There are few options for this type, so I simply want to hard-code reading a register.
The server id is 75
The function code is 0x04 (input register)
The register # is 30001 (datasheet)
Here is my code. Note that I am using PuTTY to see the data being sent/response as the serial monitor cannot handle SERIAL_7E1.
'''
// Calculate LRC (Longitudinal Redundancy Check)
byte calculateLRC(String data) {
byte sum = 0;
for (int i = 0; i < data.length(); i++) {
sum += data[i]; // Add the ASCII values of each character
}
// Return the LRC (two's complement of the sum)
byte lrc = (~sum + 1) & 0xFF;
return lrc;
}
void setup() {
// Initialize RE/DE pin (pin 2) to control RS-485 transmission/reception
pinMode(2, OUTPUT); // Set pin 2 as OUTPUT for controlling RE/DE
Serial.begin(19200); // Set baud rate to 19200
Serial.begin(19200, SERIAL_7E1); // 7 data bits, Even Parity, 1 stop bit
String slaveID = "4B";
String functionCode = "04";
String startRegister = "9C40"; // Address of the Input Register (30001 -> 9C40
String quantity = "0001"; // 1 register
String message = ":" + slaveID + functionCode + startRegister + quantity;
byte lrc = calculateLRC(message);
char lrcHex[3];
sprintf(lrcHex, "%02X", lrc);
// Append the LRC to the message
message += lrcHex;
// Append carriage return and line feed
message += "\r\n";
// Enable Transmission by setting RE/DE HIGH
digitalWrite(2, HIGH);
Serial.print(message); // Send message
delay(2000);
digitalWrite(2, LOW); // Disable the transmitter (DE), enable receiver (RE)
}
void loop() {
if (Serial.available()) {
String response = "";
// Read response
while (Serial.available()) {
response += (char)Serial.read();
}
// Display response
Serial.print("Response: ");
Serial.println(response);
// : [Slave ID] [Function Code] [Data] [LRC] <CR><LF>
// Extract data (after function code) and print the register value
if (response.length() > 5) {
String data = response.substring(4, 8); // Extract the data bytes
unsigned int registerValue = strtol(data.c_str(), NULL, 16); // Convert from hex to integer
Serial.print("Register Value: ");
Serial.println(registerValue);
} else {
Serial.println("Error: Invalid response");
}
}
}
'''
The problem is that I'm not getting anything on the serial monitor -- it seems to be stuck in the loop. Is there an easily spotted problem in the code? Or, is there a library anyone is aware of that works with arduino uno AND modbus ascii?