Arduino Projekt Sensoreinheit über ttl- Modul anschließen

Hallo zusammen, ich versuche, Messdaten von einer Sensoreinheit (Jumo BlackLine + Jumo CR ST10) mit meinem Arduino auszulesen. Leider bekomme ich nur fehlerhafte Werte wie 0,00, ovf oder den Fehlercode 224/ 226. Ich vermute, dass der Arduino zwar Daten sendet, aber keine empfängt, da nur die TX-LED am Arduino leuchtet, nicht jedoch die RX-LED. Ich habe auch einen Logic Analyzer verwendet, aber konnte bisher keine Lösung finden.

Anbei findet ihr meinen Code, die Ausgabe des Logic Analyzers und den Schaltplan meiner Verdrahtung.

#include <ModbusMaster.h>

const int DE_RE = 2; // Pin für DE/RE auf dem RS-485 Modul

ModbusMaster node; // ModbusMaster Objekt erstellen

void preTransmission() {
  digitalWrite(DE_RE, HIGH); // Umschalten auf Senden

}

void postTransmission() {
  delay(10); // Verzögerung, um sicherzustellen, dass die Übertragung abgeschlossen ist
  digitalWrite(DE_RE, LOW);  // Umschalten auf Empfangen

}

void setup() {
  // Pin für DE/RE setzen
  pinMode(DE_RE, OUTPUT);

  // Serielle Schnittstelle 1 (RX1/TX1) für die Modbus-Kommunikation initialisieren
  Serial1.begin(9600, SERIAL_8N2);

  // Modbus-Instanz konfigurieren; Sensoradresse 42 (Modbus-ID des Sensors)
  node.begin(42, Serial1); // Serial1 für Modbus verwenden

  // Callbacks für die Steuerung von DE/RE vor und nach der Übertragung setzen
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);

  // Standard-Serial für Debugging initialisieren
  Serial.begin(9600); 
  Serial.println("Sensorabfrage gestartet...");
}

void loop() {
  uint8_t result;
  uint16_t highRegister, lowRegister;
  uint32_t sensorValue;
  float sensorFloatValue; // Variable für den Float-Wert

  // Modbus-Anfrage: Ein bestimmtes Register vom Sensor lesen
  result = node.readHoldingRegisters(9728, 2);

  // Überprüfe, ob die Abfrage erfolgreich war
  if (result == node.ku8MBSuccess) {
    highRegister = node.getResponseBuffer(0); // Register 1 (high bytes)
    lowRegister = node.getResponseBuffer(1); // Register 2 (low bytes)

    // Bytes in der richtigen Reihenfolge kombinieren
    sensorValue = (static_cast<uint32_t>(highRegister) << 16) | lowRegister;

    // Gelesene Daten als float interpretieren
    sensorFloatValue = *reinterpret_cast<float*>(&sensorValue);

    // Sensorwert ausgeben
    Serial.print("Aktueller Sensorwert: ");
    Serial.println(sensorFloatValue); // Wert ausgeben
  } else {
    // Fehler ausgeben, wenn die Kommunikation fehlschlägt
    Serial.print("Fehlercode: ");
    Serial.println(result);
  }

  // 5 Sekunden warten, bevor der nächste Messwert abgefragt wird 
  delay(5000);
}

Bin für jede Hilfe dankbar :slight_smile:

Die erste Verbesserungsmaßnahme ist die zeitliche Auflösung des Logic-Analysers auf einen höheren Wert einzustellen und / oder mal auf der Zeitachse heineinzoomen.

Dieser graue Block
image
setzt sich garantiert aus mindestens 20 Pegelwechseln zusammen.
Und wenn es 200 sind würde es mich auch nicht wundern.

Wenn du jetzt weitere Hilfe haben willst, dann solltest du möglichst viel Arebit von den Schultern deiner potentiellen Helfer herunter nehmen.
damit ist gemeint:

Rx/Tx: wer empfängt/sendet da? Arduino oder Sensor?
Was ist OE/RE für eine Signalleitung?

  • Schaltplan

  • Datenblätter von den Sensoren als Download-Link posten

Genauen Github-Link angeben welche Modbus-Library du da verwendest.

8N2 zwei Stopbits ist relativ ungewöhnlich. Üblicher ist 8N1
Aber auch das steht im Datenlatt.
Falls nicht, dann hilft der Logic-Analyser weiter aber nur dann wenn man die einzelnen Flankenwechsel auch wirklich erkennen kann.

Wie viel Strom zieht der Sensor?
Auch ein Arduino Mega kann nur sehr begrenzt Strom liefern aus dem 5V-Pin

Da hilft nur Stück für Stück analysieren was kommen da für Daten rein.

Hier ist dein Demo-Code mit Serial debug-macros und serialdebug-output

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *

unsigned long MyTestTimer = 0;                   // Timer-variables MUST be of type unsigned long
const byte    OnBoard_LED = 2;     // onboard-LEDESP32 / ESP8266
//const byte    OnBoard_LED = 25;  // onboard-LED Raspberry Pi pico
//const byte    OnBoard_LED = 13;   // onboard-LED uno, mega

/*
  Serial.begin(115200);
  Serial.println("Setup-Start");
  PrintFileNameDateTime();

  BlinkHeartBeatLED(OnBoard_LED,250);

  if ( TimePeriodIsOver(MyTestTimer,1000) ) {

  }  

*/

#include <ModbusMaster.h>

const int DE_RE = 2; // Pin für DE/RE auf dem RS-485 Modul

ModbusMaster node; // ModbusMaster Objekt erstellen

void preTransmission() {
  digitalWrite(DE_RE, HIGH); // Umschalten auf Senden

}

void postTransmission() {
  delay(10); // Verzögerung, um sicherzustellen, dass die Übertragung abgeschlossen ist
  digitalWrite(DE_RE, LOW);  // Umschalten auf Empfangen

}

void setup() {
  // Standard-Serial für Debugging initialisieren
  Serial.begin(9600); 
  Serial.println("Sensorabfrage gestartet...");

  // Pin für DE/RE setzen
  pinMode(DE_RE, OUTPUT);

  // Serielle Schnittstelle 1 (RX1/TX1) für die Modbus-Kommunikation initialisieren
  Serial1.begin(9600, SERIAL_8N2);

  // Modbus-Instanz konfigurieren; Sensoradresse 42 (Modbus-ID des Sensors)
  node.begin(42, Serial1); // Serial1 für Modbus verwenden

  // Callbacks für die Steuerung von DE/RE vor und nach der Übertragung setzen
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);

}

void loop() {
  uint8_t result;
  uint16_t highRegister, lowRegister;
  uint32_t sensorValue;
  float sensorFloatValue; // Variable für den Float-Wert

  // Modbus-Anfrage: Ein bestimmtes Register vom Sensor lesen
  result = node.readHoldingRegisters(9728, 2);
  dbg("01",result);

  // Überprüfe, ob die Abfrage erfolgreich war
  if (result == node.ku8MBSuccess) {
    highRegister = node.getResponseBuffer(0); // Register 1 (high bytes)
    dbg("02",highRegister);
    
    lowRegister = node.getResponseBuffer(1); // Register 2 (low bytes)
    dbg("03",lowRegister);

    // Bytes in der richtigen Reihenfolge kombinieren
    sensorValue = (static_cast<uint32_t > (highRegister) << 16) | lowRegister;
    dbg("04",sensorValue);
    
    // Gelesene Daten als float interpretieren
    sensorFloatValue = *reinterpret_cast<float*>(&sensorValue);
    dbg("05",sensorFloatValue)

    // Sensorwert ausgeben
    Serial.print("Aktueller Sensorwert: ");
    Serial.println(sensorFloatValue); // Wert ausgeben
  } 
  else {
    // Fehler ausgeben, wenn die Kommunikation fehlschlägt
    Serial.print("Fehlercode: ");
    Serial.println(result);
  }

  // 5 Sekunden warten, bevor der nächste Messwert abgefragt wird 
  delay(5000);
}

Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden.
Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.

mfg ein Moderator.

das sind zwei verschiedene Fehlercodes - nur wann genau kommt welcher?
Gib sie dir in HEX aus und schau in der modbusmaster.h nach was E0 und E2 genau bedeuten.

E0 wäre nicht mehr so schlecht, ...
E2 ist ein Timeout

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.