Hilfe - Arduino will Modbus Temperatursensor nicht auslesen (RS485 Linksprite)

Hi agmue,

vielen Dank fuer deine Antwort.

Habe alle drei Vorschläge ausprobiert, aber es gab keine Ausgabe auf dem Monitor. Dann habe ich versucht mithilfe des Monitors zu debuggen. Dazu an fünf verschiedenen Stellen des Codes jeweils die Zahlen 1 bis 5 ausgegeben:

#include <ModbusRtu.h>
#include <SoftwareSerial.h>

// data array for modbus network sharing
uint16_t au16data[16];
uint8_t u8state;

/**se
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  u8serno : serial port (use 0 for Serial)
 *  u8txenpin : 0 for RS-232 and USB-FTDI 
 *               or any pin number > 1 for RS-485
 */
Modbus master(0, 4, 3); // this is master and RS-232 or USB-FTDI via software serial

/**
 * This is an structe which contains a query to an slave device
 */
modbus_t telegram;

unsigned long u32wait;

SoftwareSerial mySerial(2, 3);//Create a SoftwareSerial object so that we can use software serial. Search "software serial" on Arduino.cc to find out more details.

void setup() {
  Serial.begin(9600);//use the hardware serial if you want to connect to your computer via usb cable, etc.
  master.begin( &mySerial, 9600 ); // begin the ModBus object. The first parameter is the address of your SoftwareSerial address. Do not forget the "&". 9600 means baud-rate at 9600
  
  master.setTimeOut( 2000 ); // if there is no answer in 2000 ms, roll over
  u32wait = millis() + 1000;
  u8state = 0; 
  Serial.println("1");
  delay(2000);
}

void loop() {
  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++; // wait state
    Serial.println("2");
    delay(2000);
    break;
  case 1: 
    
    telegram.u8id = 1; // slave address
    telegram.u8fct = 4; // function code (this one is registers read)
    telegram.u16RegAdd = 1; // start address in slave
    telegram.u16CoilsNo = 1; // number of elements (coils or registers) to read
    telegram.au16reg = au16data; // pointer to a memory array in the Arduino
    Serial.println("3");
    
    master.query( telegram ); // send query (only once)
    Serial.println("4");
    u8state++;
    break;
  case 2:
    master.poll(); // check incoming messages
      Serial.println("5");
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 2000; 
      for(int i = 0 ; i < 10 ; i++ )
        Serial.print(au16data[i]);//Or do something else!
    }
    break;
  }
}

Bild 1 im Anhang zeigt was auf dem Monitor zu sehen ist.

Bei master.query resettet er einfach das gesamte Programm? Wie kann das sein, dass er nach 3 einfach wieder 1 ausgibt, dazu muss er ja wieder ins Setup. Verstehst du das?

edit: Ich habe mal den von dir verlinkten Header ModbusRTU.h in Notepad++ geöffnet, um zu schauen wo der Fehler sein könnte und habe dazu die selbe Methode wie oben angewendet. Bei Modbus::query nach und nach die LED D2 von meinem Shield getoggled und einen kleinen delay dahinter, damit ich sehe wenn es passiert. Header eingebunden und Modbus::query durchläuft er zunächst tadellos. Am Ende von dieser Funktion springt er jedoch in sendTxBuffer(). Da habe ich die Fehlersuche fortgeführt und die Problemstelle entdeckt, an dem das Programm wieder auf Null zurückspringt:

if(u8serno<4)
        port->write( au8Buffer, u8BufferSize );

Wohlgemerkt bei u8serno<4, nicht bei dem darauf folgenden:

else
        softPort->write( au8Buffer, u8BufferSize );

Habe also mal überprüft und obwohl ich bei Modbus master(0, 4, 3) eine 4 für u8serno übergebe, ist bereits gleich danach bei Modbus::begin() wieder u8serno == 0... Und dann versucht er dieses au8Buffer welcher das CRC enthält auf den Port "port" zu schreiben, statt auf softPort, welcher ja &mySerial enthält.

edit2: u8serno im Header manuell zu 4 zu setzen, macht zwar, dass es zu softPort->write( au8Buffer, u8BufferSize ); kommt, aber da resettet das Programm ebenfalls...

Das ist mein derzeitiger Stand... Sorry für die ausschweifenden Antworten. :sweat_smile:

Viele Gruesse
Winterwurst

Bild 1.PNG