Hallo,
ich benötige einen Tip oder ähnliches.
Ziel:
Der Uno R3 soll mittels RS485 die Daten eines Kostal Smart Meters auslesen.
Hardware:
- Arduino Uno R3
- JZK TTL auf RS485 Modul (Amazon)
- Kostal Smart Energy Meter (Als slave)
Ich habe zusätzlich einen USB zu RS458 und die SimpleModbus Software.
Wenn ich den Uno (Master) mit dem PC (Slave) verbinde kann ich die
Daten normal abfragen.
Das gleiche mit dem PC (Master) und dem Smart Meter (Slave).
Nur wenn ich den Uno (Master) mit dem Meter (Slave) verbinde ..
passiert nichts.
Ich habe parallel den USB angeschlossen und sehe wie der Uno sendet. Er
bekommt aber keine Antwort.
(In dem Bild sind noch weitere Bauteile für späteres. Habe später alles entfernt.)
#include <SoftwareSerial.h>
// Create a SoftwareSerial object to communicate with the MAX485 module
SoftwareSerial mySerial(11, 10); // RX, TX
// Define Modbus parameters
const byte slaveAddress = 0x01; // Address of the Modbus slave device
const byte functionCode = 0x03; // Function code to read holding registers
const byte startAddressHigh = 0x00; // High byte of the starting address
const byte startAddressLow = 0x28; //2A; // Low byte of the starting address
const byte registerCountHigh = 0x00; // High byte of the number of registers to read
const byte registerCountLow = 0x01; // Low byte of the number of registers to read
uint32_t data;
void setup() {
// Initialize serial communication for debugging
Serial.begin(9600);
// Initialize SoftwareSerial for Modbus communication
mySerial.begin(9600);
// Allow some time for initialization
delay(1000);
}
void loop() { Serial.println("- - - - - Start - - - - - ");
// Create a request frame for Modbus communication
byte requestFrame[8];
constructModbusRequest(requestFrame, slaveAddress, functionCode, startAddressHigh, startAddressLow, registerCountHigh, registerCountLow);
// Send the Modbus request frame
sendModbusRequest(requestFrame, 8);
// Read and process the Modbus response frame
if (mySerial.available()) {
// Create a buffer to store the response frame
byte responseFrame[9];
// Read the response frame from the slave device
readModbusResponse(responseFrame, 9);
// Process the response frame to extract data
processModbusResponse(responseFrame);
} /*else { just for testing
// Print an error message if no response is received
Serial.println("No response from slave.");
}*/
Serial.print("Daten - ");
Serial.println(data);
Serial.println(data, HEX);
// Wait for 2 seconds before the next request
delay(10000);
}
// Function to construct a Modbus request frame
void constructModbusRequest(byte *frame, byte address, byte function, byte startHigh, byte startLow, byte countHigh, byte countLow) {
frame[0] = address; // Address of the slave device
frame[1] = function; // Function code
frame[2] = startHigh; // High byte of the starting address
frame[3] = startLow; // Low byte of the starting address
frame[4] = countHigh; // High byte of the number of registers to read
frame[5] = countLow; // Low byte of the number of registers to read
// Calculate and append the CRC to the request frame
uint16_t crc = calculateCRC(frame, 6);
frame[6] = crc & 0xFF; // CRC low byte
frame[7] = (crc >> 8) & 0xFF; // CRC high byte
}
// Function to send a Modbus request frame
void sendModbusRequest(byte *frame, byte length) {
for (byte i = 0; i < length; i++) {
mySerial.write(frame[i]); // Send each byte of the frame
}
}
// Function to read a Modbus response frame
void readModbusResponse(byte *frame, byte length) {
for (byte i = 0; i < length; i++) {
if (mySerial.available()) {
frame[i] = mySerial.read(); // Read each byte of the frame
Serial.println(frame[i]);
}
}
}
// Function to process the Modbus response frame and extract data
void processModbusResponse(byte *frame) {
uint32_t data1 = (frame[3] << 8) | frame[4]; //Translate the int16 to int32. Otherwise it deletes the bits (when shifting with ">> 24")
uint16_t data2 = (frame[5] << 8) | frame[6];
data = (data1 << 16) | data2; //int32
//Serial.print("Daten - ");
//Serial.println(data);
//Serial.println(data, HEX);
}
// Function to calculate the CRC of a Modbus frame
uint16_t calculateCRC(byte *frame, byte length) {
uint16_t crc = 0xFFFF; // Initialize CRC to 0xFFFF
for (byte i = 0; i < length; i++) {
crc ^= frame[i]; // XOR the frame byte with the CRC
for (byte j = 0; j < 8; j++) {
if (crc & 0x0001) { // Check if the LSB of the CRC is 1
crc >>= 1; // Right shift the CRC
crc ^= 0xA001; // XOR the CRC with the polynomial 0xA001
} else {
crc >>= 1; // Right shift the CRC
}
}
}
return crc; // Return the calculated CRC
}




