Guten Tag alle zusammen,
ich versuche mich gerade an einer Verbindung zwischen einem Arduino Nano und einem Raspberry Pi über Modbus. Die Verbindung wird über ein normales USB Kabel hergestellt, der USB MINI Stecker steckt also am Arduino (Slave), der normale am Raspberry Pi (Master). Auf diesem läuft Codesys, welches per Modbus bestimmte Werte aus dem Arduino ausliest.
Ich nutze die Modbusino.h Bibliothek für die Modbus Kommunikation, als auch die wire.h Bibliothek für das Auslesen der Sensoren (in diesem Fall sind es 4 kapazitive Sensoren, die die Erdfeuchte von Zimmer- oder Balkonpflanzen inkl. Temperatur messen). Es werden daher insgesamt 10 (Integer) Werte übertragen: Register 0-7 sind die Erdfeuchten und Temperaturen, Register 8 hat immer den Testwert "999" und Register 9 kann den Wert 0 oder 100 annehmen (eine Art Watchdog Signal für den Modbus Master).
Soweit funktioniert mein Arduino Programm eigentlich: Wenn ich den Arduino per USB an den PC anschließe und den Serial Monitor betrachte, erhalte ich genau die Sensor Werte, die ich erwarte (ausgegeben werden immer nur die Mittelwerte, sowohl beim SerialMonitor, also auch über Modbus).
Wenn ich den Arduino allerdings an den Raspberry Pi anschließe (Modbusverbindung über USB Kabel), bekomme ich nur die beiden letzten Werte richtig angezeigt (die "999", die nur zu Testzwecken übertragen wird und den xWatchdog).
Die 8 Sensorwerte sind immer nur "0" (Die Werte werden alle 6 Sekunden ausgelesen und mit je 10 Einzelwerten dann gemittelt - daher stehen die ersten Sensor Mittelwerte auch erst nach einer Minute bereit).
Es scheint so, als würden die onewire Sensoren im Arduino nicht ausgelesen, sobald der Raspberry per Modbus auf den Arduino zugreift.
Kann das sein? Und kann man das beheben bzw. optimieren?
Ich habe beim Modbus Master mit verschiedenen Abfrageintervallen herum probiert, zwischen 200ms und 75 Sekunden. Alle paar Sekunden bekommt der Master auch einen Timeout Fehler oder unbekannten Fehler. Die Abfrage funktioniert also auch nicht immer zuverlässig.
Könnt Ihr mir hier bitte helfen, ich finde ansonsten auch keine ähnlichen Probleme mit der Suchfunktion.
Vielen Dank im Voraus und eine schöne Woche!
Speedriff
#include <Wire.h> // für Tindie Erdfeuchte Sensoren
#include <Modbusino.h> // Modbus Bib
// Funktion zum Beschreiben bestimmter Sensor Register (aus Beispiel Sketch)
void writeI2CRegister8bit(int addr, int value) {
Wire.beginTransmission(addr);
Wire.write(value);
Wire.endTransmission();
}
// Funktion um Sensoren auszulesen (aus Beispiel Sketch)
unsigned int readI2CRegister16bit(int addr, int reg) {
Wire.beginTransmission(addr);
Wire.write(reg);
Wire.endTransmission();
delay(20);
Wire.requestFrom(addr, 2);
unsigned int t = Wire.read() << 8;
t = t | Wire.read();
return t;
}
// Arrays für die Sensorwerte, die später gemittelt werden (interessant nur [1..10])
int T_Sensor_gelb[11];
int T_Sensor_rot[11];
int T_Sensor_blau[11];
int T_Sensor_gruen[11];
int Erde_Sensor_gelb[11];
int Erde_Sensor_rot[11];
int Erde_Sensor_blau[11];
int Erde_Sensor_gruen[11];
// Berechnete Mittelwerte aus 10 Einzelwerten
int T_Sensor_gelb_mittel;
int T_Sensor_rot_mittel;
int T_Sensor_blau_mittel;
int T_Sensor_gruen_mittel;
int Erde_Sensor_gelb_mittel;
int Erde_Sensor_rot_mittel;
int Erde_Sensor_blau_mittel;
int Erde_Sensor_gruen_mittel;
// Temporäre Variablen, die die Summen der 10 Einzelwerte enthalten
int T_Sensor_gelb_mittel_temp;
int T_Sensor_rot_mittel_temp;
int T_Sensor_blau_mittel_temp;
int T_Sensor_gruen_mittel_temp;
int Erde_Sensor_gelb_mittel_temp;
int Erde_Sensor_rot_mittel_temp;
int Erde_Sensor_blau_mittel_temp;
int Erde_Sensor_gruen_mittel_temp;
// Timer Variablen: Alle 6000ms (6s) finden die Sensorabfragen statt. Nach 10 Abfragen werden die Mittelwerte gebildet und über SerialPrint ausgegeben
unsigned long previousMillis = 0;
const long interval_readingSensors = 6000;
int icounter = 1;
bool xAusgabe; // Wenn true, dann Ausgabe über SerialPrint
////////////////////// MODBUS /////////////////////////
/* Initialize the slave with the ID 1 */
ModbusinoSlave modbusino_slave(1);
/* Allocate a mapping of 10 values */
uint16_t tab_reg[10];
uint16_t xWatchdog;
uint16_t counter;
////////////////////// VOID SETUP /////////////////////////
void setup() {
Wire.begin();
Serial.begin(9600);
writeI2CRegister8bit(0x21, 6); //reset Sensor
delay(1000);
writeI2CRegister8bit(0x22, 6); //reset Sensor
delay(1000);
writeI2CRegister8bit(0x23, 6); //reset Sensor
delay(1000);
writeI2CRegister8bit(0x24, 6); //reset Sensor
delay(1000);
// Modbus slave configuration parameters
modbusino_slave.setup(9600);
}
////////////////////// VOID LOOP /////////////////////////
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval_readingSensors) { // Abfrage aller Sensoren alle 6 Sekunden
previousMillis = currentMillis;
T_Sensor_gelb[icounter] = readI2CRegister16bit(0x21, 5);
T_Sensor_rot[icounter] = readI2CRegister16bit(0x22, 5);
T_Sensor_blau[icounter] = readI2CRegister16bit(0x23, 5);
T_Sensor_gruen[icounter] = readI2CRegister16bit(0x24, 5);
Erde_Sensor_gelb[icounter] = readI2CRegister16bit(0x21, 0);
Erde_Sensor_rot[icounter] = readI2CRegister16bit(0x22, 0);
Erde_Sensor_blau[icounter] = readI2CRegister16bit(0x23, 0);
Erde_Sensor_gruen[icounter] = readI2CRegister16bit(0x24, 0);
icounter = icounter + 1; // Counter beginnt bei 1 und zählt nacht jedem Auslesevorgang um 1 hoch
if (icounter == 11) { // Wenn 10 Abfragen abgearbeitet
T_Sensor_gelb_mittel_temp = 0; // Init der Summenvariablen
T_Sensor_rot_mittel_temp = 0;
T_Sensor_blau_mittel_temp = 0;
T_Sensor_gruen_mittel_temp = 0;
Erde_Sensor_gelb_mittel_temp = 0;
Erde_Sensor_rot_mittel_temp = 0;
Erde_Sensor_blau_mittel_temp = 0;
Erde_Sensor_gruen_mittel_temp = 0;
// Bildung der Mittelwerte aus je 10 Einzelwerten
for (int i = 1; i < 11; i++) {
T_Sensor_gelb_mittel_temp = T_Sensor_gelb_mittel_temp + T_Sensor_gelb[i];
T_Sensor_rot_mittel_temp = T_Sensor_rot_mittel_temp + T_Sensor_rot[i];
T_Sensor_blau_mittel_temp = T_Sensor_blau_mittel_temp + T_Sensor_blau[i];
T_Sensor_gruen_mittel_temp = T_Sensor_gruen_mittel_temp + T_Sensor_gruen[i];
Erde_Sensor_gelb_mittel_temp = Erde_Sensor_gelb_mittel_temp + Erde_Sensor_gelb[i];
Erde_Sensor_rot_mittel_temp = Erde_Sensor_rot_mittel_temp + Erde_Sensor_rot[i];
Erde_Sensor_blau_mittel_temp = Erde_Sensor_blau_mittel_temp + Erde_Sensor_blau[i];
Erde_Sensor_gruen_mittel_temp = Erde_Sensor_gruen_mittel_temp + Erde_Sensor_gruen[i];
}
T_Sensor_gelb_mittel = T_Sensor_gelb_mittel_temp / 10;
T_Sensor_rot_mittel = T_Sensor_rot_mittel_temp / 10;
T_Sensor_blau_mittel = T_Sensor_blau_mittel_temp / 10;
T_Sensor_gruen_mittel = T_Sensor_gruen_mittel_temp / 10;
Erde_Sensor_gelb_mittel = Erde_Sensor_gelb_mittel_temp / 10;
Erde_Sensor_rot_mittel = Erde_Sensor_rot_mittel_temp / 10;
Erde_Sensor_blau_mittel = Erde_Sensor_blau_mittel_temp / 10;
Erde_Sensor_gruen_mittel = Erde_Sensor_gruen_mittel_temp / 10;
icounter = 1; // Zurücksetzen des Counters
xAusgabe = HIGH; // Auslöser für die Ausgabe der Sensorwerte über SerialPrint
}
}
if (xAusgabe == HIGH) {
Serial.print("Feuchtigkeit Erde gelb: ");
Serial.print(Erde_Sensor_gelb_mittel); //read capacitance register
Serial.print(", Feuchtigkeit Erde rot: ");
Serial.print(Erde_Sensor_rot_mittel); //read capacitance register
Serial.print(", Feuchtigkeit Erde blau: ");
Serial.print(Erde_Sensor_blau_mittel); //read capacitance register
Serial.print(", Feuchtigkeit Erde grün: ");
Serial.print(Erde_Sensor_gruen_mittel); //read capacitance register
Serial.print(" || T gelb: ");
Serial.print(T_Sensor_gelb_mittel / float(10)); //temperature register
Serial.print(", T rot: ");
Serial.print(T_Sensor_rot_mittel / (float)10); //temperature register
Serial.print(", T blau: ");
Serial.print(T_Sensor_blau_mittel / float(10)); //temperature register
Serial.print(", T gruen: ");
Serial.print(T_Sensor_gruen_mittel / (float)10); //temperature register
Serial.println();
xAusgabe = LOW; // Auslöser zurücksetzen
}
counter = counter + 1; // Counter zählt jeden Programmdurchlauf
// Bedingung für den Watchdog (der ist nur für den ModBus Master interessant)
if (counter <= 32000)
{
xWatchdog = 0;
}
else
{
xWatchdog = 100;
}
if (counter > 64000)
{
counter = 0;
}
// Array befüllen, welches über Modbus bereitgestellt wird
/* Initialize the first register to have a value to read */
tab_reg[0] = Erde_Sensor_gelb_mittel; // #0 Sensor gelb Erdfeuchtigkeit
tab_reg[1] = Erde_Sensor_rot_mittel; // #1 Sensor rot Erdfeuchtigkeit
tab_reg[2] = Erde_Sensor_blau_mittel; // #2 Sensor blau Erdfeuchtigkeit
tab_reg[3] = Erde_Sensor_gruen_mittel; // #3 Sensor weiss Erdfeuchtigkeit
tab_reg[4] = T_Sensor_gelb_mittel; // #4 Sensor gelb Temperatur
tab_reg[5] = T_Sensor_rot_mittel; // #5 Sensor rot Temperatur
tab_reg[6] = T_Sensor_blau_mittel; // #6 Sensor blau Temperatur
tab_reg[7] = T_Sensor_gruen_mittel; // #7 Sensor weiss Temperatur
tab_reg[8] = 999; // #8 999 - Testwert
tab_reg[9] = xWatchdog; // #9 Watchdog Blinker
/* Launch Modbus slave loop with:
- pointer to the mapping
- max values of mapping */
modbusino_slave.loop(tab_reg, 10); // Modbus Slave jeden Programm Durchgang aufrufen
}