Hallo Community,
ich habe ein Problem mit meinem Code und komme nicht dahinter wie ich es lösen kann.
Folgender Aufbau:
Messwerte eines Linearschiebers (Schnittstelle RS-422) wird über einen RS422 to TLL Konverter im Arduino mittels Software.Serial eingelesen. Das Messergebnis wird dann für verschiedene Dinge genutzt. Die Werte kommen solange richtig an, bis ich:
- In der Loop-Funktion das Display update
- Ich einen Button gedrückt halte
Wenn ich z.B. das Display-update einbinde, kommen die nächsten 10 Werte falsch an (z.B. Prüfsumme falsch, oder STX nicht erkannt,...)
Scheinbar verliert die serielle Schnittstelle dann vorübergehend die Synchronisation?
Hier die Info über das Datenprotokoll des Linearschiebers:
02h STX
xxh ABS-Daten
xxh ABS-Daten
xxh ABS-Daten
xxh ABS-Daten
xxh ABS-Daten
xxh ABS-Daten
03h ETX
xxh BCC
1 Start Bit
8 Daten Bits
1 Stopp Bit
keine Parität
Die Blockprüfsumme ist ein "Exklusiv-Oder" aller Daten inklusive STX und ETX. Sämtliche Werte werden im ASCII-Format übertragen.
Vielleicht könnt ihr mir ja helfen.
Hier der Code:
#include <Adafruit_GFX.h> // Adafruit Grafikbibliothek
#include <Adafruit_ST7735.h> // Adafruit ST7735-Bibliothek
#include <Arduino.h>
#include <OneButton.h>
#include <SoftwareSerial.h>
#include <SPI.h>
// Definieren der SoftwareSerial-Pins
const int rxPin = 3; // RX Pin
const int txPin = 2; // TX Pin
// Initialisieren der SoftwareSerial-Instanz
SoftwareSerial rs422(rxPin, txPin);
// TFT-Display-Pins
#define TFT_CS 10
#define TFT_RST 8
#define TFT_DC 9
#define REDLEDPin 5
#define GREENLEDPin 6
// Initialisieren des TFT-Displays
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
// Knopf- und Relais-Pins
const int buttonPin1 = A0;
const int relayPin1 = 4;
const int buttonPin2 = A1;
const int relayPin2 = 7;
int AbsLength = 0;
OneButton button1(buttonPin1);
OneButton button2(buttonPin2);
// Variable zum Speichern der Linearschieberposition
int PosLEND = -200;
int sliderPosition = 0;
int PosL2ori = -150;
int PosL2 = PosL2ori;
int PosL1 = -75;
int Pos0 = 0;
int PosR1 = 75;
int PosR2 = 150;
int PosR2ori = 150;
int PosREND = 200;
int sliderPositionCm = 0;
int toubleclick_tedection = 0;
void setup() {
// Beginnen der Kommunikation mit dem Messgerät
Serial.begin(9600);
rs422.begin(9600); // Initialize software
// Initialisieren des TFT-Displays
tft.initR(INITR_BLACKTAB); // Initialisierung für 1.44" und 1.8" TFT mit schwarzem Tab
tft.fillScreen(ST7735_BLACK); // Hintergrundfarbe
// Initialisieren der Knopf- und Relais-Pins
pinMode(buttonPin1, INPUT);
pinMode(relayPin1, OUTPUT);
pinMode(buttonPin2, INPUT);
pinMode(relayPin2, OUTPUT);
// Initialisieren der LED Pins
pinMode(REDLEDPin, OUTPUT);
pinMode(GREENLEDPin, OUTPUT);
// Relais initial ausschalten
digitalWrite(relayPin1, LOW);
digitalWrite(relayPin2, LOW);
// LED initial ausschalten
digitalWrite(REDLEDPin, HIGH);
digitalWrite(GREENLEDPin, LOW);
button1.attachClick(click1);
button1.attachDoubleClick(doubleclick1);
button1.attachLongPressStart(longPressStart1);
button1.attachLongPressStop(longPressStop1);
button1.attachDuringLongPress(longPress1);
// link the button 2 functions.
button2.attachClick(click2);
button2.attachDoubleClick(doubleclick2);
button2.attachLongPressStart(longPressStart2);
button2.attachLongPressStop(longPressStop2);
button2.attachDuringLongPress(longPress2);
toubleclick_tedection = 0;
}
void loop() {
// Serial.print("Ready");
// Linearschieberposition lesen, wenn Daten verfügbar sind
button1.tick();
button2.tick();
if (rs422.available()) {
digitalWrite(REDLEDPin, LOW);
digitalWrite(GREENLEDPin, HIGH);
sliderPosition = readLinearPosition();
sliderPositionCm = sliderPosition/100;
if (sliderPositionCm >= PosREND) {
digitalWrite(relayPin1, LOW);
}
if (sliderPositionCm <= PosLEND) {
digitalWrite(relayPin2, LOW);
}
Serial.print(sliderPositionCm);
Serial.print('\n');
Serial.println(toubleclick_tedection);
Serial.print('\n');
if (toubleclick_tedection == 0){
if(sliderPositionCm == PosL2 || sliderPositionCm == PosL1 || sliderPositionCm == Pos0 || sliderPositionCm == PosR1 || sliderPositionCm == PosR2) {
digitalWrite(relayPin1, LOW);
digitalWrite(relayPin2, LOW);
if (sliderPositionCm == Pos0) {
PosL2 = -150;
PosL1 = -75;
Pos0 = 10000000;
PosR1 = 75;
PosR2 = 150;
}
if (sliderPositionCm == PosL2) {
PosL2 = 1000000;
PosL1 = -75;
Pos0 = 0;
PosR1 = 75;
PosR2 = 150;
}
if (sliderPositionCm == PosL1) {
PosL2 = -150;
PosL1 = 10000000;
Pos0 = 0;
PosR1 = 75;
PosR2 = 150;
}
if (sliderPositionCm == PosR1) {
PosL2 = -150;
PosL1 = -75;
Pos0 = 0;
PosR1 = 10000000;
PosR2 = 150;
}
if (sliderPositionCm == PosR2) {
PosL2 = -150;
PosL1 = -75;
Pos0 = 0;
PosR1 = 75;
PosR2 = 10000000;
}
}
}
if (toubleclick_tedection == 1 && sliderPositionCm == 0) {
digitalWrite(relayPin1, LOW);
digitalWrite(relayPin2, LOW);
toubleclick_tedection = 0;
}
}
// updateDisplay(sliderPositionCm);
}
void updateDisplay(int position) {
// Berechnung der Balkenlänge basierend auf der Position des Linearschiebers
int barLength = map(position, 0, 100, 0, tft.width()); // Angenommen, die maximale Position ist 100
tft.fillRect(0, tft.height() / 2 - 10, barLength, 20, ST7735_GREEN); // Zeichnen des Balkens
tft.fillRect(barLength, tft.height() / 2 - 10, tft.width() - barLength, 20, ST7735_BLACK); // Rest des Balkens löschen
// Anzeigen des aktuellen Messwerts
tft.setCursor(0, 0); // Setzt den Cursor in die obere linke Ecke
tft.setTextColor(ST7735_WHITE); // Setzt die Textfarbe
tft.setTextSize(1); // Setzt die Textgröße
tft.print("Position: ");
tft.println(position); // Zeigt den aktuellen Messwert an
}
float readLinearPosition() {
if (rs422.available()) {
if (rs422.read() == 0x02) { // Beginn bei STX
char data[6];
char bcc = 0x02;
for (int i = 0; i < 6; i++) {
while (!rs422.available());
data[i] = rs422.read();
bcc ^= data[i];
}
while (!rs422.available());
char etx = rs422.read();
bcc ^= etx;
while (!rs422.available());
char receivedBcc = rs422.read();
if (receivedBcc == bcc) {
return parsePosition(data);
} else {
Serial.println("Fehler in der Blockprüfsumme!");
digitalWrite(REDLEDPin, HIGH);
digitalWrite(GREENLEDPin, LOW);
rs422.end();
delay(1000);
rs422.begin(9600);
return -1.0;
}
}
}
return -1.0;
}
float parsePosition(char* data) {
int multiplier = 1;
float position = 0;
for (int i = 5; i >= 0; i--) { // Umkehrung der Schleife für die korrekte Berechnung
if (data[i] >= '0' && data[i] <= '9') {
position += (data[i] - '0') * multiplier;
multiplier *= 10;
} else {
Serial.print("Ungültiges Zeichen in den Daten: ");
Serial.println(data[i]);
return -1.0;
}
}
return (position+32765-9125);
}
void click1() {
Serial.println("Button 1 click.");
int TurnOffFunction = 0;
if (digitalRead(relayPin2) == LOW && digitalRead(relayPin1) == HIGH && sliderPositionCm <= PosR2) {
digitalWrite(relayPin1, LOW); // Relais ausschalten
TurnOffFunction = 1;
}
if (digitalRead(relayPin2) == LOW && TurnOffFunction == 0 && sliderPositionCm <= PosR2) {
digitalWrite(relayPin1, HIGH); // Relais einschalten
}
} // click1
void click2() {
Serial.println("Button 2 click.");
int TurnOffFunction = 0;
if (digitalRead(relayPin1) == LOW && digitalRead(relayPin2) == HIGH && sliderPositionCm >= PosL2ori) {
digitalWrite(relayPin2, LOW); // Relais einschalten
TurnOffFunction = 1;
}
if (digitalRead(relayPin1) == LOW && TurnOffFunction == 0 && sliderPositionCm >= PosL2ori) {
digitalWrite(relayPin2, HIGH); // Relais einschalten
}
} // click2
// This function will be called when the button1 was pressed 2 times in a short timeframe.
void doubleclick1() {
Serial.println("Button 1 doubleclick.");
toubleclick_tedection = 1;
if (digitalRead(relayPin2) == LOW && sliderPositionCm > 0) {
digitalWrite(relayPin1, HIGH); // Relais einschalten
}
if (digitalRead(relayPin1) == LOW && sliderPositionCm < 0) {
digitalWrite(relayPin2, HIGH); // Relais einschalten
}
} // doubleclick1
void doubleclick2() {
Serial.println("Button 2 doubleclick.");
toubleclick_tedection = 1;
if (digitalRead(relayPin2) == LOW && sliderPositionCm > 0) {
digitalWrite(relayPin1, HIGH); // Relais einschalten
}
if (digitalRead(relayPin1) == LOW && sliderPositionCm < 0) {
digitalWrite(relayPin2, HIGH); // Relais einschalten
}
} // doubleclick2
// This function will be called once, when the button1 is pressed for a long time.
void longPressStart1() {
Serial.println("Button 1 longPress start");
if (digitalRead(relayPin2) == LOW && sliderPositionCm <= PosR2) {
digitalWrite(relayPin1, HIGH); // Relais einschalten
}
} // longPressStart1
// This function will be called once, when the button1 is released after beeing pressed for a long time.
void longPressStop1() {
Serial.println("Button 1 longPress stop");
digitalWrite(relayPin1, LOW); // Relais ausschalten
}
void longPressStart2() {
Serial.println("Button 2 longPress start");
if (digitalRead(relayPin1) == LOW && sliderPositionCm >= PosL2) {
digitalWrite(relayPin2, HIGH); // Relais einschalten
}
} // longPressStart1
// This function will be called once, when the button1 is released after beeing pressed for a long time.
void longPressStop2() {
Serial.println("Button 1 longPress stop");
digitalWrite(relayPin2, LOW); // Relais ausschalten
}
// This function will be called often, while the button1 is pressed for a long time.
void longPress1() {
Serial.println("Button 1 longPress...");
} // longPress1
// ... and the same for button 2:
void longPress2() {
Serial.println("Button 2 longPress...");
} // longPress2
Hier die Ausgabe vom Serial Monitor wenn ich in der Loop die Funktion Displayupdate hinzufüge:
-47
-47
-47
-47
-47
0
0
0
0
0
0
0
Fehler in der Blockprüfsumme!
0
0
0
-47
-47
usw.
Wenn ich das Displayupdate in der Loop-Funktion nicht einbinde (und auch einen der Taster nicht gedrückt halte - aslo so wie im eingefügten Code) kommt das richtige Ergebnis. Auch click oder dopelklick haben keinen negativen Einfluss:
-47
-47
-47
-47
-47
-47
usw.
Mir kommt es so vor, als würde der Buffer überlaufen, will euch aber auch nicht auf die falsche Fährte locken. Jedenfalls hoffe ich ihr könnt mir helfen. Bin mit meinem Latein am Ende.
LG
Chris