Serielle Schnittstelle soll nur nach Zustandsänderung senden, oder Empfangen

Hallo!

Da ich mich erst seit ein paar Tagen mit dem Arduino und der Programmierung beschäftige, und mit meinem aktuellen Versuch nicht weiterkommen, wollte ich mal hier um Rat fragen...

Folgendes soll gemacht werden:

  • die Pins allen alle 10 ms abgefragt werden, und der Zustand dann auf die Serielle Schnittstelle geschickt werden
  • genauso soll die Serielle Schnittstelle abgefragt werden, und dann entsprechend die Pins schalten
  • die Daten sollen aber nur gesendet oder empfangen werden, wenn sich was geändert hat (aktuell läuft das durch, was bei der aktuelle Anzahl der Pins noch nicht schlimm ist, aber es werden mehr werden)
  • die Daten sollen dann von einem VB Programm oder ggf. einer DLL gelesen und an ein anderen Programm weitergeleitet werde.

Anbei mal der Code als Beispiel, welchen ich zum testen und experimentieren gebastelt habe.

const int HS = 2;
const int STROM = 7;
const int LED1 = 8;
const int LED2 = 4;

int buttonState = 0;
int incomingByte = 0;

void setup() {
  Serial.begin(9600);
  pinMode(HS, INPUT);
  pinMode(STROM, INPUT);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
}

// Abfrage von Pins oder Schalter.
void loop() {
  buttonState = digitalRead(HS);
  if (buttonState == HIGH) {
    Serial.println("HS_ein");
  } else {
    Serial.println("HS_aus");
  }
  
  buttonState = digitalRead(STROM);
  if (buttonState == HIGH) {
    Serial.println("STROM_ein");
    digitalWrite(LED1, HIGH);
  } else {
    Serial.println("STROM_aus");
    digitalWrite(LED1, LOW);
  }

// Ein- und Ausschalten einer Led, oder eines Leuchtmelders.
  if (Serial.available() > 0)
  {
    incomingByte = Serial.read();
    if (incomingByte == '6')  digitalWrite(LED2, HIGH);
    else if (incomingByte == '7') digitalWrite(LED2, LOW);
  }
// Zeitverzögerung, damit der nicht non Stop sendet - soll eigentlich nur nach Zustandsänderung sein.  
  delay(1000);
}

Hat vielleicht jemand eine Idee, wie dies richtig klappen könnte? Habe schon bei google geschaut, aber da blicke ich dann absolut nicht mehr durch.

Danke schonmal.

Gruß

Ben

Bitte setze Deinen Sketch in Codetags (oben links </> im Foreneditor oder [code] davor und [/code] dahinter - ohne die *).
Das kannst Du auch noch nachträglich durch Editieren tun. Bitte mach das, der Sketch ist besser zu lesen, besonders auf mobilen Geräten.
Um eine Änderung zu erkennen, mußt Du Dir den alten Status merken und nur wenn der neue Status anders ist, senden.
Also etwa so (ohne Entprellen des Schalters):

byte status = 0, statusAlt = 0;

...

// Hier muss noch entprellt werden
status = analogRead(STROM);
if (status != statusAlt) {
  statusAlt = status;
  Serial.println(status);
}

// Seriell einlesen
const byte IN_LEN = 20; // Puffergroesse Eingabe
char inStr[IN_LEN];  // Lesepuffer

// true = fertig (LF oder zu lang), false = noch nicht fertig
boolean einlesen() {
static byte i = 0; // Positionsindex in inStr
static boolean fertig = false;
char inputChar;

  if (!Serial.available() > 0) return false;
  // wenn es schon eine vollstaendige Eingabe gab -> zuruecksetzen
  if (fertig) {
    fertig = false;  // neuer Anfang
    inStr[0] = '\0'; // Puffer initialisieren
    i = 0; // Positionsindex auf Anfang
  }
  inputChar = Serial.read();
  // Wenn nicht Zeilenende und nicht Puffer voll
  if (inputChar != '\n' && i < IN_LEN -1) {
    // Zeichen in inStr schreiben
    inStr[i] = inputChar;
    inStr[++i] = '\0'; // Abschluss dahinter schreiben, um evtl. Debugausgaben richtig anzuzeigen
    return false;
  }  
  fertig = true;
  // leere Zeilen ausblenden
  if (i > 0) return true;
  return false;
}

Delay ist ganz schlecht, wenn Du von seriell lesen willst. Dort würde ich Dir empfehlen die Zeile vom PC mit NL (Newline) abzuschließen und dann die Zeile mithilfe von strtok zu zerlegen. Grundlagen dazu findest Du hier.

Gruß Tommy

Gruß Tommy

Delay ist ganz schlecht, wenn Du von seriell lesen willst.

Delay ist nicht ganz schlecht, wenn man es sparsam verwendet und nicht Massen an Seriellen Daten schnell übertragen muss.

delay(5); // Entprellen bei Änderung eines Taster-Zustands

ist in der Regel ganz ok...

Seriell selbst ist relativ langsam (z.B. 1 ms / Zeichen bei 9600 Baud). Mit dem Standard-Eingangspuffer von 64 Zeichen würdest du selbst bei unendlich großen empfangenen Texten mit einem gelegentlichen  delay(50) zurechtkommen können.

michael_x:
Delay ist nicht ganz schlecht, wenn man es sparsam verwendet und nicht Massen an Seriellen Daten schnell übertragen muss.

delay(5); // Entprellen bei Änderung eines Taster-Zustands

ist in der Regel ganz ok...

Seriell selbst ist relativ langsam (z.B. 1 ms / Zeichen bei 9600 Baud). Mit dem Standard-Eingangspuffer von 64 Zeichen würdest du selbst bei unendlich großen empfangenen Texten mit einem gelegentlichen  delay(50) zurechtkommen können.

Aber mit Sicherheit nicht mit dem delay(1000), das da drin war. Beim delay(5) fürs Entprellen gebe ich Dir Recht, wobei ich die Variante mit RC-Glied vorziehe.
Deshalb hatte ich auch geschrieben, dass das Entprellen noch rein muss.

Gruß Tommy

Um Änderungen festzustellen brauchst Du einen Speicher für jeden Eingang, am einfachsten ein Array. Dann vergleichst Du jeden neu eingelesenen Wert mit dem alten, und schickst ihn bei einer Änderung entweder gleich ab, oder setzst ein Flag daß alles abgeschickt werden soll.