Hallo Freunde,
und zwar habe ich eine Frage zur Modbus Kommunikation. Ich habe einen Sensor ( OLS20-BB1118142 | Lokalisierungs- und Positionierlösungen | SICK ), welcher Modbus fähig ist und einen Controllino ( CONTROLLINO MAXI – CONTROLLINO ). Ich habe vor dem Controllino als Master zu nutzen und habe daher schon folgenden Code drauf geladen:
#include <Controllino.h> /* Usage of CONTROLLINO library allows you to use CONTROLLINO_xx aliases in your sketch. */
#include "ModbusRtu.h" /* Usage of ModBusRtu library allows you to implement the Modbus RTU protocol in your sketch. */
// This MACRO defines Modbus master address.
// For any Modbus slave devices are reserved addresses in the range from 1 to 247.
// Important note only address 0 is reserved for a Modbus master device!
#define MasterModbusAdd 0
#define SlaveModbusAdd 10
// This MACRO defines number of the comport that is used for RS 485 interface.
// For MAXI and MEGA RS485 is reserved UART Serial3.
#define RS485Serial 3
// The object ControllinoModbuSlave of the class Modbus is initialized with three parameters.
// The first parametr specifies the address of the Modbus slave device.
// The second parameter specifies type of the interface used for communication between devices - in this sketch - RS485.
// The third parameter can be any number. During the initialization of the object this parameter has no effect.
Modbus ControllinoModbusMaster(MasterModbusAdd, RS485Serial, 0);
// This uint16 array specified internal registers in the Modbus slave device.
// Each Modbus device has particular internal registers that are available for the Modbus master.
// In this example sketch internal registers are defined as follows:
// (ModbusSlaveRegisters 0 - 3 read only and ModbusSlaveRegisters 4 - 7 write only from the Master perspective):
// ModbusSlaveRegisters[0] - Read an analog value from the CONTROLLINO_A0 - returns value in the range from 0 to 1023.
// ModbusSlaveRegisters[1] - Read an digital value from the CONTROLLINO_D0 - returns only the value 0 or 1.
// ModbusSlaveRegisters[2] - Read the number of incoming messages - Communication diagnostic.
// ModbusSlaveRegisters[3] - Read the number of number of outcoming messages - Communication diagnostic.
// ModbusSlaveRegisters[4] - Sets the Relay output CONTROLLINO_R0 - only the value 0 or 1 is accepted.
// ModbusSlaveRegisters[5] - Sets the Relay output CONTROLLINO_R1 - only the value 0 or 1 is accepted.
// ModbusSlaveRegisters[6] - Sets the Relay output CONTROLLINO_R2 - only the value 0 or 1 is accepted.
// ModbusSlaveRegisters[7] - Sets the Relay output CONTROLLINO_R3 - only the value 0 or 1 is accepted.
uint16_t ModbusSlaveRegisters[8];
// This is an structe which contains a query to an slave device
modbus_t ModbusQuery[2];
uint8_t myState; // machine state
uint8_t currentQuery; // pointer to message query
unsigned long WaitingTime;
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
Serial.println("-----------------------------------------");
Serial.println("CONTROLLINO Modbus RTU Master Test Sketch");
Serial.println("-----------------------------------------");
Serial.println("");
// ModbusQuery 0: read registers
ModbusQuery[0].u8id = SlaveModbusAdd; // slave address
ModbusQuery[0].u8fct = 3; // function code (this one is registers read)
ModbusQuery[0].u16RegAdd = 0; // start address in slave
ModbusQuery[0].u16CoilsNo = 4; // number of elements (coils or registers) to read
ModbusQuery[0].au16reg = ModbusSlaveRegisters; // pointer to a memory array in the CONTROLLINO
// ModbusQuery 1: write a single register
ModbusQuery[1].u8id = SlaveModbusAdd; // slave address
ModbusQuery[1].u8fct = 6; // function code (this one is write a single register)
ModbusQuery[1].u16RegAdd = 4; // start address in slave
ModbusQuery[1].u16CoilsNo = 1; // number of elements (coils or registers) to write
ModbusQuery[1].au16reg = ModbusSlaveRegisters+4; // pointer to a memory array in the CONTROLLINO
ModbusSlaveRegisters[4] = 1; // initial value for the relays
ControllinoModbusMaster.begin( 9600 ); // baud-rate at 19200; jetzt 9600
ControllinoModbusMaster.setTimeOut( 5000 ); // if there is no answer in 5000 ms, roll over
WaitingTime = millis() + 1000;
myState = 0;
currentQuery = 0;
}
void loop() {
switch( myState ) {
case 0:
if (millis() > WaitingTime) myState++; // wait state
break;
case 1:
Serial.print("---- Sending query ");
Serial.print(currentQuery);
Serial.println(" -------------");
ControllinoModbusMaster.query( ModbusQuery[currentQuery] ); // send query (only once)
myState++;
currentQuery++;
if (currentQuery == 2)
{
currentQuery = 0;
}
break;
case 2:
ControllinoModbusMaster.poll(); // check incoming messages
if (ControllinoModbusMaster.getState() == COM_IDLE)
{
// response from the slave was received
myState = 0;
WaitingTime = millis() + 1000;
// debug printout
if (currentQuery == 0)
{
// registers write was proceed
Serial.println("---------- WRITE RESPONSE RECEIVED ----");
Serial.println("");
}
if (currentQuery == 1)
{
// registers read was proceed
Serial.println("---------- READ RESPONSE RECEIVED ----");
Serial.print("Slave ");
Serial.print(SlaveModbusAdd, DEC);
Serial.print(" ADC0: 0x");
Serial.print(ModbusSlaveRegisters[0], HEX);
Serial.print(" , Digital0: ");
Serial.print(ModbusSlaveRegisters[1], BIN);
Serial.print(" , ModbusCounterIn: ");
Serial.print(ModbusSlaveRegisters[2], DEC);
Serial.print(" , ModbusCounterOut: ");
Serial.println(ModbusSlaveRegisters[3], DEC);
Serial.println("-------------------------------------");
Serial.println("");
// toggle with the relays
ModbusQuery[1].u16RegAdd++;
if (ModbusQuery[1].u16RegAdd == 8)
{
ModbusQuery[1].u16RegAdd = 4;
if (ModbusSlaveRegisters[4])
{
ModbusSlaveRegisters[4] = 0;
}
else
{
ModbusSlaveRegisters[4] = 1;
}
}
}
}
break;
}
}
Jetzt würde ich gerne fragen, ob sich jemand mit dem Thema etwas besser auskennt als ich, da ich leider noch recht neu in diesem Thema bin.
Das was ich bisher weiss ist, dass mein Sensor die Baudrate 9600 und die Slaveadresse 10 besitzt ( Im Code, so weit ich weiss, angepasst)
Weiterhin weiss ich, dass der Master ein Request schicken muss, damit der Slave darauf antworten kann.
Die Statusabfrage in HEX, ob der Sensor etwas erkennt order nicht, wäre in dem Fall:
0A 04 00 C0 00 01 30 8D
dabei steht 0A für die Slave adresse, 04 ist mein Function Code, 00C0 ist meine Startadresse, 0001 meine Registeranzahl und die 308D ist dabei meine Checksumme.
Wenn der sensor was erkennt ( OK ), gibt der die Anwort: 0A 04 02 00 02 9D 30 und bei NOK wäre es 0A 04 02 00 00 10 F1.
weiss einer vieleicht wie ich den oberen Code verändern muss um eine Kommunikation herzustellen?
ich habe auch versucht hier alles einzutragen aber es ändert sich leider nichts.
// ModbusQuery 0: read registers
ModbusQuery[0].u8id = SlaveModbusAdd; // slave address
ModbusQuery[0].u8fct = 3; // function code (this one is registers read)
ModbusQuery[0].u16RegAdd = 0; // start address in slave
ModbusQuery[0].u16CoilsNo = 4; // number of elements (coils or registers) to read
ModbusQuery[0].au16reg = ModbusSlaveRegisters; // pointer to a memory array in the CONTROLLINO
ordr brauche ich einen einfachen if - else Befehl? Ich wäre sehr dankbar, wenn mir einer dabei helfen könnte
Vielen Dank schonmal und Gruß
Aram