Ok, verstanden. Damit kann ich jetzt erstmal weiterarbeiten! Klasse von dir!
Allerdings bin ich jetzt noch auf ein "neues" Problem gestoßen.
Zum Testen habe ich mal Werte von VB an den Arduino übertragen um die generelle Zusammenarbeit zu testen. Bisher habe ich das immer so in der Art gemacht:
If SerialPort1.IsOpen = True Then
SerialPort1.Write("500|1000|33|44|555|66|77|88|0|1" & vbCrLf) 'hier mal "hardgecoded"
SerialPort1.DiscardInBuffer() ' Zum löschen des Eingangspuffers
SerialPort1.DiscardOutBuffer() ' Zum löschen des Ausgangspuffers
End If
Ich hoffe, ich krieg keins auf den "Deckel", wenn ich hier VB poste, aber vielleicht liegt es an einer Besonderheit deines Codes, dass das nicht funktioniert. An RX sehe ich aber, dass was ankommt.
Und bisher hat das auch funktioniert. (Habe ja bisher ein Ventil mit delay() so gesteuert.)
Mein Fehler: hatte die Übertragunsrate nicht angepasst! Es geht. Yippi! 
Ich könnte verzweifeln: bevor ich mich an die Routine für Ventil 1 mache, wollte ich sehen, ob VB überhaupt längere Werte senden bzw. Arduino empfangen kann.
Ich habe mal die Feldanzahl auf 30 gesetzt und sende auch 30 Werte, Arduino empfängt zwar was, startet aber die Routine nicht?!
aus VB ...
SerialPort1.Write("5000|1000|3003|44|555|66|77|88|0|1|5000|1000|3003|44|555|66|77|88|0|1|5000|1000|3003|44|555|66|77|88|0|1" & vbNewLine)
EDIT
Wenn ich in der seriellen Monitor zu lange Ausdrücke, z. B. 30 Felder eingebe, dann macht Arduino übrigens auch nichts. Gibt es da eine "Begrenzung"?
Also wenn ich in den Code aus #37 (mit angepasster Variable feldAnzahl=30) diese lange Zeile mit dem seriellen Monitor abschicke, kommt die auch an und es funktioniert.
Start
LED_timestore gesetzt auf: 18669
5000 1000 3003 44 555 66 77 88 0 1 5000 1000 3003 44 555 66 77 88 0 1 5000 1000 3003 44 555 66 77 88 0 1
Millis: 23669 LED_timestore: 18669
Abschnitt HIGH0
LED_timestore gesetzt auf: 23670
Millis: 24670 LED_timestore: 23670
Abschnitt LOW 0
Es funktioniert auch mit 120 problemlos.
Gruß Tommy
Du hast Recht. So gehts. Vermutlich lag es daran, dass ich vom Arduino etwas sende, damit ich unter VB erkenne, ob ich verbunden bin. Das habe ich raus. Jetzt klappt es.
Leider nicht über VB
SerialPort1.Write("500|1000|3003|44|555|66|77|88|0|1|5000|1000|3003|44|555|66|77|88|0|1|5000|1000|3003|44|555|66|77|88|0|1" & vbNewLine)
Deinen Code habe ich nur um eine Zeile erweitert
...
boolean einlesen() {
char c;
if (Serial.available()) {
Serial.println("verbunden"); //*** ERWEITERUNG
if (gelesen) loeschen();
c = Serial.read();..
In VB frage ich den Inhalt ab. Wenn der gesendete Text = verbunden ist, dann bekomme ich eine "Meldung".
Das Senden klappt dann leider nicht mehr wie soll.
Mach dir keine Mühe, ich lasse das Serial.println("verbunden"); einfach weg, dann gehts ja. Aber dass es daran lag/liegt, ist ja verrückt. Ich habe heute Nachmittag wieder ewig probiert. 
Das hat an der Stelle auch nichts verloren Du willst es ja nicht laufend senden.
Schreibe die Zeile doch erst mal ins Setup.
Serial.println("verbunden"); //*** ERWEITERUNG
Gruß Tommy
Ok, aber im steup ist es doch auch wohl zu früh, oder?
Es soll doch erst gesendet werden, wenn ich über den COM-Port verbunden bin. Klar, und dann nur einmal.
Nur noch mal zum Verstädnis:
Ich habe Serial.println("verbunden"); nun in setup()
- Ich starte den Arduino.
- via VB verbinde ich mich mit dem Arduino
- "verbunden" ist noch nicht angekommen
- ich sende Daten -> jetzt kommt "verbunden" an?
Wenn ich dann VB wieder trenne, neu verbinde und Daten sende, dann kommt wieder "verbunden" an.
Ganz verstehe ich das nicht. Ich dachte, alles in setup() wird nur EINMAL beim Anlauf des Arduino ausgeführt?!
Danke für deine Geduld!
Dann hat der Arduino gebootet. Schau mal, ob Dein VB-Programm DTR setzt.
Das macht der serielle Monitor auch, wenn er geöffnet wird und resetet damit den Arduino.
Eigentlich müßtest Du erst Dein VB starten und dann den Arduino. Probier das mal aus.
Wenn das dann immer noch kommt (und Du es nicht nochmal wo anders hast), dannsetzt Dein Programm DTR bei Verbindungsaufnahme. Dann musst Du Dich durch die VB-Dokus wühlen.
Gruß Tommy
Perfekt! Du bist großartig!
Ich habe in VB das ergänzt.
.DtrEnable = True
.RtsEnable = True
Jetzt wird der Arduino beim Verbinden neu gestartet! Ich bin begeistert!
Prima, dass es funktioniert. Nimm aber für die Arduino-Entwicklung lieber den seriellen Monitor, da siehst Du die Abläufe besser.
Gruß Tommy
Dürfte ich nochmal ein kleine Frage stellen?
Also, ich habe meinen Code erweitert. Das erste Ventil öffnet nun dreimal.
ABER: Egal welchen Wert der erste Wert in der Eingabe hat, die Ausgabe liefert immer 1?!
500|1000|330|44|555|66|77|88|0|1
Das verstehe ich nicht? Ich sehe auch keinen "Unterschied" zwischen meinem Skript und deinem aus Post #37, zumindest keinen offensichtlich relevanten.
Anmerkung
Die Zeile mit if (werte[0] = !0)
habe ich übrigens verwendet, weil ich zum "Spülen" alle Werte auf Null setze, außer werte[9]. Da blieb ich dann hängen und habe am Serial Monitor eben die Sache mit dem ersten Wert (werte[0] = 1) entdeckt.
// intRead
// Beispieleingabe 10 Werte (mit NL abschließen) 5000|1000|33|44|555|66|77|88|0|1
const uint8_t feldAnzahl = 60;
int werte[feldAnzahl];
uint8_t feldIdx, pufferIdx;
char puffer[60];
boolean gelesen = false;
boolean abgearbeitet = false;
boolean runde1 = true;
boolean runde2 = true;
boolean runde3 = true;
//
int ventil_1 = 2;
unsigned long LED_timestore;
int LedStatus = LOW;
int LedStatus_float1 = LOW;
void setup() {
Serial.begin(115200);
Serial.println("Start");
Serial.println("verbunden");
pinMode (2, OUTPUT);
}
void loeschen() {
for (uint8_t i = 0; i < feldAnzahl; i++) {
werte[i] = 0;
}
feldIdx = 0;
gelesen = false;
}
// return true, wenn ganze Zeile eingelesen, sonst false
boolean einlesen() {
char c;
if (Serial.available()) {
//
if (gelesen) loeschen();
c = Serial.read();
if (c == '|' || c == '\n') {
puffer[pufferIdx] = '\0'; // Abschließen der Zeichenkette
if (feldIdx < feldAnzahl) {
werte[feldIdx++] = atoi(puffer);
pufferIdx = 0;
if (c == '\n') {
gelesen = true;
abgearbeitet = false;
runde1 = false;
runde2 = false;
runde3 = false;
LED_timestore = millis(); // jetzt erst geht die Zeit los
Serial.println("******"); Serial.println(runde1); Serial.println("*** START ***"); Serial.print(" LED_timestore gesetzt auf: "); Serial.println(LED_timestore);
return true; // Zeile fertig
}
}
}
else if (c >= '0' && c <= '9') puffer[pufferIdx++] = c; // Nur Ziffern
}
return false;
}
void anzeigen() {
for (uint8_t i = 0; i < feldAnzahl; i++) {
Serial.print(werte[i]); Serial.print(" ");
}
Serial.println("-------------------");
}
void loop() {
if (einlesen()) anzeigen();
if (werte[0] = !0) {
if (runde1 != true ) {
if (LedStatus == LOW && millis() - LED_timestore >= werte[1] ) { // zeit für aus
Serial.print("Millis: "); Serial.print(millis()); Serial.print(" LED_timestore: "); Serial.println(LED_timestore); Serial.print("Abschnitt 1 HIGH ");
digitalWrite(ventil_1, HIGH);
LED_timestore = millis();
Serial.print(" LED_timestore gesetzt auf: "); Serial.println(LED_timestore);
LedStatus = HIGH;
}
if (LedStatus == HIGH && millis() - LED_timestore >= werte[2]) { //zeit für an
Serial.print("Millis: "); Serial.print(millis()); Serial.print(" LED_timestore: "); Serial.println(LED_timestore); Serial.print("Abschnitt 1 LOW ");
digitalWrite(ventil_1, LOW);
LED_timestore = millis();
LedStatus = LOW;
runde1 = true;
}
}
if (runde2 != true && runde1 == true && werte[3] == 1) {
if (LedStatus == LOW && millis() - LED_timestore >= werte[4] ) { // zeit für aus
Serial.print("Millis: "); Serial.print(millis()); Serial.print(" LED_timestore: "); Serial.println(LED_timestore); Serial.print("Abschnitt 2 HIGH ");
digitalWrite(ventil_1, HIGH);
LED_timestore = millis();
Serial.print(" LED_timestore gesetzt auf: "); Serial.println(LED_timestore);
LedStatus = HIGH;
}
if (LedStatus == HIGH && millis() - LED_timestore >= werte[5]) { //zeit für an
Serial.print("Millis: "); Serial.print(millis()); Serial.print(" LED_timestore: "); Serial.println(LED_timestore); Serial.print("Abschnitt 2 LOW ");
digitalWrite(ventil_1, LOW);
LED_timestore = millis();
LedStatus = LOW;
runde2 = true;
}
}
if (runde3 != true && runde1 == true && runde2 == true && werte[6] == 1) {
if (LedStatus == LOW && millis() - LED_timestore >= werte[7] ) { // zeit für aus
Serial.print("Millis: "); Serial.print(millis()); Serial.print(" LED_timestore: "); Serial.println(LED_timestore); Serial.print("Abschnitt 3 HIGH ");
digitalWrite(ventil_1, HIGH);
LED_timestore = millis();
Serial.print(" LED_timestore gesetzt auf: "); Serial.println(LED_timestore);
LedStatus = HIGH;
}
if (LedStatus == HIGH && millis() - LED_timestore >= werte[8]) { //zeit für an
Serial.print("Millis: "); Serial.print(millis()); Serial.print(" LED_timestore: "); Serial.println(LED_timestore); Serial.print("Abschnitt 3 LOW ");
digitalWrite(ventil_1, LOW);
LedStatus = LOW;
runde3 = true;
abgearbeitet = true;
//LED_timestore = millis();
}
}
}
//LED=Ventil ein/ausschalten ENDE
}
Wenn Du den Code umbaust, dann passe bitte auch die Aufrufzeile oben mit an. Ich habe es jetzt mal so geändert, wie ich es mir vorstelle.
Denk daran, Du hast einen kleinen Arduino und keinen großen PC 
Dass läßt sich einfacher und kürzer schreiben.
// intRead2
// Beispieleingabe 10 Werte (mit NL abschließen) 1|5000|1000|1|3000|1000|1|2000|1000|0
const uint8_t feldAnzahl = 10;
int werte[feldAnzahl];
uint8_t feldIdx, pufferIdx;
char puffer[60];
boolean gelesen = false;
uint8_t runde = 99;
//
int ventil_1 = 2;
unsigned long LED_timestore;
int LedStatus = LOW;
int LedStatus_float1 = LOW;
void setup() {
Serial.begin(115200);
Serial.println("Start");
Serial.println("verbunden");
pinMode (2, OUTPUT);
}
void loeschen() {
for (uint8_t i = 0; i < feldAnzahl; i++) {
werte[i] = 0;
}
feldIdx = 0;
gelesen = false;
}
// return true, wenn ganze Zeile eingelesen, sonst false
boolean einlesen() {
char c;
if (Serial.available()) {
//
if (gelesen) loeschen();
c = Serial.read();
if (c == '|' || c == '\n') {
puffer[pufferIdx] = '\0'; // Abschließen der Zeichenkette
if (feldIdx < feldAnzahl) {
werte[feldIdx++] = atoi(puffer);
pufferIdx = 0;
if (c == '\n') {
gelesen = true;
runde = 0;
LED_timestore = millis(); // jetzt erst geht die Zeit los
Serial.println("******"); Serial.println(runde); Serial.println("*** START ***"); Serial.print(" LED_timestore gesetzt auf: "); Serial.println(LED_timestore);
return true; // Zeile fertig
}
}
}
else if (c >= '0' && c <= '9') puffer[pufferIdx++] = c; // Nur Ziffern
}
return false;
}
void anzeigen() {
for (uint8_t i = 0; i < feldAnzahl; i++) {
Serial.print(werte[i]); Serial.print(" ");
}
Serial.println("-------------------");
}
void loop() {
if (einlesen()) anzeigen();
if (werte[9] == 0) {
if (runde < 3 && werte[runde*3] != 0) {
if (LedStatus == LOW && millis() - LED_timestore >= werte[runde*3+1] ) { // zeit für aus
Serial.print("Millis: "); Serial.print(millis()); Serial.print(" LED_timestore: "); Serial.println(LED_timestore);
digitalWrite(ventil_1, HIGH);
LED_timestore = millis();
Serial.print(" HIGH "); Serial.print("Runde: "); Serial.print(runde); Serial.print(" LED_timestore gesetzt auf: "); Serial.println(LED_timestore);
LedStatus = HIGH;
}
if (LedStatus == HIGH && millis() - LED_timestore >= werte[runde*3+2]) { //zeit für an
Serial.print("Millis: "); Serial.print(millis()); Serial.print(" LED_timestore: "); Serial.println(LED_timestore);
digitalWrite(ventil_1, LOW);
LED_timestore = millis();
LedStatus = LOW;
Serial.print(" LOW "); Serial.print("Runde: "); Serial.println(runde);
runde++;
}
}
}
else {
//Spuelen
Serial.println("Spuelen");
}
//LED=Ventil ein/ausschalten ENDE
}
Und wenn Du Dich evtl. doch noch für Strukturen erwärmen kannst, wird das nicht mehr viel komplexer. Ich vermute ja mal, die beiden anderen Ventile sollen unabhängig ihre eigenen Zeiten benutzen.
Gruß Tommy
Danke, klappt! Das mit den Strukturen mache ich, sicher, versprochen.
Aber im Moment muss ich mich aber echt noch mit den Grundlagen beschäftigen. Immer wenn ich deinen Code teste, bin ich sehr zuversichtlich. Aber nach kurzer Zeit komme ich schon wieder an meine Grenzen. Die LED werte[9]=1 anzuschalten bis werte[9]=0 bereitet mir dann doch wieder mehr Probleme als ich vermutet habe.
Ich bin einfach zu doof. 
Ist das in deinem Code Absicht oder ein Versehen?
const uint8_t feldAnzahl = 10; <------------------
int werte[feldAnzahl];
uint8_t feldIdx, pufferIdx;
char puffer[60]; <------------------ ABER
boolean gelesen = false;
uint8_t runde = 99;
Hier mal eine klitzkleine Erweiterung von mir, die mich einfach verzweifeln lässt. Das ist doch in meinen Augen absolut schlüssig.
werte[9] == 1 -> schalte ein
werte[9] == 0 und auch werte[0]==0 -> schalte aus
<SNIP>
void loop() {
if (einlesen()) anzeigen();
if (werte[9] == 0 && werte[0] != 0) {
if (runde < 3 && werte[runde * 3] != 0) {
if (LedStatus == LOW && millis() - LED_timestore >= werte[runde * 3 + 1] ) { // zeit für aus
Serial.print("Millis: "); Serial.print(millis()); Serial.print(" LED_timestore: "); Serial.println(LED_timestore);
digitalWrite(ventil_1, HIGH);
LED_timestore = millis();
Serial.print(" HIGH "); Serial.print("Runde: "); Serial.print(runde); Serial.print(" LED_timestore gesetzt auf: "); Serial.println(LED_timestore);
LedStatus = HIGH;
}
if (LedStatus == HIGH && millis() - LED_timestore >= werte[runde * 3 + 2]) { //zeit für an
Serial.print("Millis: "); Serial.print(millis()); Serial.print(" LED_timestore: "); Serial.println(LED_timestore);
digitalWrite(ventil_1, LOW);
LED_timestore = millis();
LedStatus = LOW;
Serial.print(" LOW "); Serial.print("Runde: ");
} Serial.println(runde);
runde++;
}
}
else {
//Spuelen
Serial.println("Spuelen");
if (werte[9] == 1 && werte[0] == 0)
{
digitalWrite(ventil_1, HIGH);
Serial.println("Spuelen ein");
}
else if (werte[9] == 0 && werte[0] == 0)
{
digitalWrite(ventil_1, LOW);
Serial.println("Spuelen aus");
}
}
<SNIP>
photojo:
Ist das in deinem Code Absicht oder ein Versehen?
const uint8_t feldAnzahl = 10; <------------------
int werte[feldAnzahl];
uint8_t feldIdx, pufferIdx;
char puffer[60]; <------------------ ABER
boolean gelesen = false;
uint8_t runde = 99;
Die beiden haben nichts miteinander zu tun aber puffer ist zu groß, da reichen 10 Zeichen. Das ist nur für die Zahlen.
photojo:
Hier mal eine klitzkleine Erweiterung von mir, die mich einfach verzweifeln lässt. Das ist doch in meinen Augen absolut schlüssig.
werte[9] == 1 -> schalte ein
werte[9] == 0 und auch werte[0]==0 -> schalte aus
Nicht ganz: werte[9] == 1 ist Spülen, dann sollte man die Werte 0,3,6 nicht berücksichtigen. Das sollte eine eigene Routine werden. werte[9] == 0 könnte das Spülen ausschalten, dann entscheidet werte[0] über den Zyklus;
werte[0] != 0 oder == 1 sagt aus, dass der Zyklus laufen soll in Runde 1
Ich würde das lieber getrennt halten, das ist übersichtlicher.
Deine else machen nicht immer das, was Du Dir vorstellst. Deshalb nicht zu viel zusammenfassen.
Das mit dem Spülen könnte man so machen:
// intRead2
// Beispieleingabe 10 Werte (mit NL abschließen) 1|5000|1000|1|3000|1000|1|2000|1000|0
const uint8_t feldAnzahl = 11;
int werte[feldAnzahl];
uint8_t feldIdx, pufferIdx;
char puffer[10];
boolean gelesen = false;
boolean inSpuelen = false;
uint8_t runde = 99;
//
int ventil_1 = 2;
unsigned long LED_timestore;
int LedStatus = LOW;
int LedStatus_float1 = LOW;
void setup() {
Serial.begin(115200);
Serial.println("Start");
Serial.println("verbunden");
pinMode (2, OUTPUT);
}
void loeschen() {
for (uint8_t i = 0; i < feldAnzahl; i++) {
werte[i] = 0;
}
feldIdx = 0;
gelesen = false;
}
// return true, wenn ganze Zeile eingelesen, sonst false
boolean einlesen() {
char c;
if (Serial.available()) {
//
if (gelesen) loeschen();
c = Serial.read();
if (c == '|' || c == '\n') {
puffer[pufferIdx] = '\0'; // Abschließen der Zeichenkette
if (feldIdx < feldAnzahl) {
werte[feldIdx++] = atoi(puffer);
pufferIdx = 0;
if (c == '\n') {
gelesen = true;
runde = 0;
LED_timestore = millis(); // jetzt erst geht die Zeit los
Serial.println("******"); Serial.println(runde); Serial.println("*** START ***"); Serial.print(" LED_timestore gesetzt auf: "); Serial.println(LED_timestore);
return true; // Zeile fertig
}
}
}
else if (c >= '0' && c <= '9') puffer[pufferIdx++] = c; // Nur Ziffern
}
return false;
}
void anzeigen() {
for (uint8_t i = 0; i < feldAnzahl; i++) {
Serial.print(werte[i]); Serial.print(" ");
}
Serial.println("-------------------");
}
void loop() {
if (einlesen()) anzeigen();
if (werte[9] == 0) {
if (inSpuelen) {
digitalWrite(ventil_1, HIGH);
inSpuelen = false;
Serial.println("Spuelen aus");
}
if (runde < 3 && werte[runde*3] != 0) {
if (LedStatus == LOW && millis() - LED_timestore >= werte[runde*3+1] ) { // zeit für aus
Serial.print("Millis: "); Serial.print(millis()); Serial.print(" LED_timestore: "); Serial.println(LED_timestore);
digitalWrite(ventil_1, HIGH);
LED_timestore = millis();
Serial.print(" HIGH "); Serial.print("Runde: "); Serial.print(runde); Serial.print(" LED_timestore gesetzt auf: "); Serial.println(LED_timestore);
LedStatus = HIGH;
}
if (LedStatus == HIGH && millis() - LED_timestore >= werte[runde*3+2]) { //zeit für an
Serial.print("Millis: "); Serial.print(millis()); Serial.print(" LED_timestore: "); Serial.println(LED_timestore);
digitalWrite(ventil_1, LOW);
LED_timestore = millis();
LedStatus = LOW;
Serial.print(" LOW "); Serial.print("Runde: "); Serial.println(runde);
runde++;
}
}
}
else {
//Spülen
inSpuelen = true;
digitalWrite(ventil_1, LOW);
Serial.println("Spuelen an");
}
//LED=Ventil ein/ausschalten ENDE
}