Hi All,
I've been searching for a solution to this problem on the net and this forum, but can't find anything about what I'm experiencing.
I'm using a Mega2560 and SN75176 (RS485) chip to talk to a digital AC meter, as shown below:
Everything works fine if I connect the D/R lines (Sn75176) to TX0/RX0 (Mega), respectively, and run the following code:
int RS485EnablePin = 3; //1 to send, 0 to receive
byte DigMeterAddr = 0x01; //RS485 address of the digital AC meter (used to measure V,I,P, etc. of the variac secondary)
byte Modbus_GetVIDataCmd_Meter[] = {DigMeterAddr, 0x04, 0x00, 0x00, 0x00, 0x03, 0xb0, 0x0b}; //Command to be sent to the AC digital meter in order to get just the V,I electrical data returned
byte ReturnedModbusDat_Meter[25]; //Setup a byte array to receive the Modbus data from digital AC meter
String ReturnedModbusDat_Str = ""; //Setup a String to convert the ReturnedModbusDat into a String
unsigned long StartTime;
void setup() {
Serial.begin(9600);
pinMode(RS485EnablePin, OUTPUT);
}
void loop() {
digitalWrite(RS485EnablePin, HIGH); //Enable high, RS485 shield waiting to transmit data*/
Serial.write(Modbus_GetVIDataCmd_Meter, 8); //Send the modbus command to receive data to AC meter
Serial.flush(); //Ensure serial buffer has been sent before putting RS485 shield into receive mode (otherwise sending data is truncated & terminated and the full message is not received by the listening device)
digitalWrite(RS485EnablePin, LOW); //Enable low, RS485 shield waiting to receive data
StartTime = millis(); //Set the start time before waiting on a Serial.available response from the RS485 devices
while ((Serial.available() == 0) && (millis() - StartTime < 50)) {}
if (Serial.available() == 0) {
Serial.println("Meter unavailable");
}
else {
Serial.readBytes(ReturnedModbusDat_Meter, 11);
ReturnedModbusDat_Str=ByteArr2ASCIIHexString(ReturnedModbusDat_Meter,11);
Serial.println("ReturnedModbusDat_Str= "+ReturnedModbusDat_Str);
}
delay(1000);
}
//Function ByteArr2ASCIIHexString to convert a byte array to an ASCII Hex string (for printing)
String ByteArr2ASCIIHexString(byte dat[], int lngth) {
String HexString = "";
for (int i = 0; i < lngth; i++) {
if (dat[i] < 0x10) {
HexString += '0';
}
HexString += String(dat[i], HEX);
}
return HexString;
}
The output on the Serial Monitor shows the correct response coming back from the AC Meter every time (except for the 5 characters of garbage preceding each data line - not sure why this appears):
The hex strings are the correct format and contain the correct data (I've checked by converting the register bytes to their corresponding float values, and they are showing the right values as read by the AC meter).
However, instead of using RX0/TX0, I want to use one of the hardware serial ports on the Mega, say, RX1/TX1.
So, I rewire the circuit as follows (change RX0/TX0 to RX1/TX1):
and run the following code:
int RS485EnablePin = 3; //1 to send, 0 to receive
byte DigMeterAddr = 0x01; //RS485 address of the digital AC meter (used to measure V,I,P, etc. of the variac secondary)
byte Modbus_GetVIDataCmd_Meter[] = {DigMeterAddr, 0x04, 0x00, 0x00, 0x00, 0x03, 0xb0, 0x0b}; //Command to be sent to the AC digital meter in order to get V,I electrical data returned
byte ReturnedModbusDat_Meter[25]; //Setup a byte array to receive the Modbus data from digital AC meter
String ReturnedModbusDat_Str = ""; //Setup a String to convert the ReturnedModbusDat into a String
unsigned long StartTime;
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
pinMode(RS485EnablePin, OUTPUT);
}
void loop() {
digitalWrite(RS485EnablePin, HIGH); //Enable high, SN75176 waiting to transmit data*/
Serial1.write(Modbus_GetVIDataCmd_Meter, 8); //Send the modbus command to receive data to AC meter
Serial1.flush(); //Ensure serial buffer has been sent before putting RS485 shield into receive mode (otherwise sending data is truncated & terminated and the full message is not received by the listening device)
digitalWrite(RS485EnablePin, LOW); //Enable low, SN75176 waiting to receive data
StartTime = millis(); //Set the start time before waiting on a Serial.available response from the RS485 devices
while ((Serial1.available() == 0) && (millis() - StartTime < 50)) {}
if (Serial1.available() == 0) {
Serial.println("Meter unavailable");
}
else {
Serial1.readBytes(ReturnedModbusDat_Meter, 11);
ReturnedModbusDat_Str=ByteArr2ASCIIHexString(ReturnedModbusDat_Meter,11);
Serial.println("ReturnedModbusDat_Str= "+ReturnedModbusDat_Str);
}
delay(1000);
}
//Function ByteArr2ASCIIHexString to convert a byte array to an ASCII Hex string (for printing)
String ByteArr2ASCIIHexString(byte dat[], int lngth) {
String HexString = "";
for (int i = 0; i < lngth; i++) {
if (dat[i] < 0x10) {
HexString += '0';
}
HexString += String(dat[i], HEX);
}
return HexString;
}
But now, the Serial Monitor reports the following:
The returned Modbus data shows that the stream appears to be 'walking' off by sometimes, 0, 1 or 2 bytes each time the data is read.
At least the garbage preceding the printed line is gone, but I can't figure out what is causing the hex stream to walk about the way it is.
Any thoughts/suggestions would be much appreciated.
Many thanks...