Arduino Visual Basic mehrere Werte auswerten Seriell

  • VB.NET

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von Thunderbolt.

    Arduino Visual Basic mehrere Werte auswerten Seriell

    Hallo an alle VB Freunde,

    ich bin neu in diesem Forum und beschäftige mich aktuell mit dem Thema Sensorwerte mit einem Arduino UNO zu erfassen
    und an VB zu senden.

    Hab mich lange mit der Kommunikation auseinander gesetzt und bekomme es hin Daten von Arduino zu VB zu senden und umgekehrt.
    Nun ist es so das ich mehrere Sensoren (Temperatursensoren) auswerten und an VB senden möchte.
    Mit einem Sensorwert ist das ganze absolut problem los.
    Doch wie sieht es mit zwei, drei oder vier Werte aus?

    Folgendes habe ich schon realisiert. Grundsätzlich funktioniert es. Aber es
    gibt einige Probleme. Doch zunächst mal etwas code:

    VB-Code:

    Vorab bitte die Chart1. erstmal ignorieren. Dazu komme ich später noch.

    Hier
    mache folgendes. In einem switch Case frage ich im case0 ab ob die
    Checkbox1 angeklickt ist. Wenn ja sendet VB auf den Seriellen Port das
    Zeichen "A".
    Der Arduino empfängt das Zeichen (Ascii 65) und sendet dann den aktuellen Analogwert von A0 zurück.
    Dieser Wert z.B. 316 wird in receivedData gespeichert und an die TextBox1.Text gegeben.

    Die Case Variable (iState) wird auf 10 gesetzt.

    In Case10 wird statt "A" ein "B" (Ascii 66) gesendet. Worauf der Arduino dann den aktuellen Wert von A1 zurück sendet.
    In VB wird dann dieser wert in TextBox2.Text ausgegeben.

    Die Case Variable (iState) wird auf 0 gesetzt.

    Das ganze passiert in einem Timer1 alle 500ms.

    VB.NET-Quellcode

    1. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    2. Select Case iState
    3. Case "0"
    4. If CheckBox1.Checked = True Then
    5. SerialPort1.Write("A")
    6. receivedData = ReceiveSerialData()
    7. TextBox1.Text = receivedData & " °C"
    8. Chart1.Series(0).Points.AddY(Val(receivedData))
    9. iState = 10
    10. Else
    11. TextBox1.Text = ""
    12. receivedData = ""
    13. iState = 10
    14. End If
    15. Case "10"
    16. If CheckBox2.Checked = True Then
    17. SerialPort1.Write("B")
    18. receivedData = ReceiveSerialData()
    19. TextBox2.Text = receivedData & " °C"
    20. Chart1.Series(1).Points.AddY(Val(receivedData))
    21. iState = 0
    22. Else
    23. TextBox2.Text = ""
    24. receivedData = ""
    25. iState = 0
    26. End If
    27. End Select
    28. End Sub


    Arduino-Code:
    Wie oben beschrieben!!!

    C-Quellcode

    1. void loop()
    2. {
    3. if (Serial.available() > 0)
    4. {
    5. Einles = Serial.read();
    6. if (Einles == 65)
    7. {
    8. Wert1 = analogRead(A0);
    9. Serial.println(Wert1);
    10. }
    11. else if (Einles == 66)
    12. {
    13. Wert2 = analogRead(A1);
    14. Serial.println(Wert2);
    15. }
    16. }


    Jetzt mein Problem:
    TextBox1 und Checkbox1 sind für den Wert von A0.
    TextBox2 und Checkbox2 für den Wert von A1.
    .
    .
    .

    Wähle ich nur Checkbox1 wird der Wert A0 in TextBox1 korrekt dargestellt. Siehe Bild "VB2"

    Wähle ich nur Checkbox2 wird der Wert A1 in TextBox2 korrekt dargestellt. Siehe Bild "VB3"

    Wähle ich aber beide Checkboxen wird der Wert A0 nicht in TextBox1 sondern TextBox2 dargestellt.
    Und der Wert A1 nicht in TextBox2 sondern ind TextBox1 dargestellt. Siehe Bild "VB1"

    Mit sicherheit hängt es mit der Methode zusammen wie ich versuche die
    richtigen Werte vom Arduino in die richtigen TextBoxen zu bekommen.

    Ich würde mich sehr freuen wenn mir da jemand weiterhelfen könnte.
    Bin natürlich für eine elegantere Methode absolut offen.

    Vielen Dank im Voraus.

    LG
    Temp-22
    Bilder
    • VB1.JPG

      16,67 kB, 462×132, 225 mal angesehen
    • VB2.JPG

      16,01 kB, 445×100, 208 mal angesehen
    • VB3.JPG

      16,29 kB, 431×118, 202 mal angesehen
    @Temp-22 Deinem Quellcode entnehme ich, dass, wenn Du eine Pizza bwestellst, Du alle 3 Minuten zur Tür rennst um nachzusehen, ob der Pizza-Bote da ist.
    Warum wartest Du nicht, bis er klingelt :?:
    Das SerialPort hat ein DataReceived-Event, nutze es, um Daten abzuholen, wenn sie da sind.
    Beachte dabei, dass das SerialPort nicht im GUI-Thread läuft, Du musst also die Daten in den GUI-Thread invoken.
    Einzelheiten dazu findest Du bei der Forensuche: SerialPort Invoke.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ist zwar keine direkte Antwort auf Deine Frage, aber evtl. eine Alternative.

    Wenn es Dich interessiert, dann wirf mal einen Blick auf diesen Controller:

    amazon.de/gp/aw/d/B06Y1ZPNMS/r…rds=nodemcu+esp8266&psc=1

    Ist durch WLAN wesentlich flexibler als ein nackter Arduino. Programmieren kannst Du ihn jedoch fast genauso (ArduinoIDE, C++). Jedenfalls entfällt dann das Gefrickel mit der seriellen Kommunikation.

    Wie gesagt, soll nicht als Antwort auf Deine Frage sein, sondern eine Alternative.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Hallo,

    vielen Dank für die Antworten.
    @ RodFromGermany
    ich habe über den DataReceived-Event einiges gelesen und auch dieverse beispiele gesehen.
    Leider habe ich das ganze nicht wirklich verstanden. Alle meine Versuche sind schiefgegangen...
    Vor allem kapiere ich nicht wie ich zwichen den sensorwerten unterscheiden kann.
    Kennst du eventuel ein Example woran ich mich orientieren kann?

    @SpaceyX
    Ja diesen Controller habe ich schon öffters gesehen.
    Jedoch für mein aktuelles Projekt keine Option.

    Denn noch vielen Dank.


    LG

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Temp-22“ ()

    Temp-22 schrieb:

    Alle meine Versuche sind schiefgegangen...
    Offensichtlich hast Du zwei drei Probleme:
    1. Wie empfange ich Daten über das SerialPort?
    2. Wie werte ich meine Daten aus?
      und
    3. Wie beschaffe ich mir Informationen:

    RodFromGermany schrieb:

    Forensuche: SerialPort Invoke

    => erweiterte Suche => =>
    Das sind jetzt Deine Hausaufgaben. ;)
    Übrigens ist auch die MSDN Dein Froind: msdn.microsoft.com/de-de/libra…tareceived(v=vs.110).aspx
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RodFromGermany“ ()

    Vielen Dank für den deutlichen Tipp ;) .
    Ich werde mich mal damit auseinander setzten.

    Dennoch hätte ich hier mal unabhängig davon einen weiteren Ansatz und hätte da eine Frage dazu.


    Visual Basic:
    Hier sendet der Arduino z.B. für A0 erst das Zeichen "A" dann den A0 Wert.
    Anschließend wird für den Wert A1 das Zeichen "B" und dann der Wert von A1 gesendet.
    .
    .
    .

    Die Auswertung funktioniert auch. D.h. Ich kann auch mehrere Werte auswerten und darstellen.
    Das Problem ist nun, wenn ich das ganze länger laufen lasse, wird die aktualisierung immer lansamer.
    Z.B. wenn ich den Wert für A0 verändere (Poti) dann dauert es etwa 5 bis 6 Sekunden bis der Wert aktualisiert wird.
    Wie länger das ganze läuft desto langsamer wird es.

    Gibt es da irgendwie einen Puffer oder so den ich zwichendurch mal leeren müsste?


    VB.NET-Quellcode

    1. Werte = SerialPort1.ReadLine()
    2. If Werte <> "" Then
    3. If Mid(Werte, 1, 1) = "A" And CheckBox1.Checked = True Then
    4. TextBox1.Text = FormatNumber(CDbl(Mid(Werte, 2, (Len(Werte) - 1))), 2)
    5. Chart1.Series(0).Points.AddY(Val(TextBox1.Text))
    6. ElseIf Mid(Werte, 1, 1) = "B" And CheckBox2.Checked = True Then
    7. TextBox2.Text = FormatNumber(CDbl(Mid(Werte, 2, (Len(Werte) - 1))), 2)
    8. Chart1.Series(1).Points.AddY(Val(TextBox2.Text))
    9. .
    10. .
    11. .



    Arduino:

    C-Quellcode

    1. switch (PortNum)
    2. {
    3. case 0:
    4. Serial.print("A");
    5. Serial.println(analogRead(A0));
    6. break;
    7. case 1:
    8. Serial.print("B");
    9. Serial.println(analogRead(A1));
    10. break;
    11. .
    12. .
    13. .



    LG
    Temp-22

    Temp-22 schrieb:

    Hier sendet der Arduino z.B. für A0 erst das Zeichen "A" dann den A0 Wert.
    Poste exakt den String, den der Arduino sendet, besser sind mehrere Beispiele.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo hier ist der gesamte Arduino Code für meine Tests.
    Also ich lege keine Variable des typs Sting an sondern sende die Zeichen direkt mit Serial.print("A").

    C-Quellcode

    1. int PortNum = 0;
    2. void setup() {
    3. // put your setup code here, to run once:
    4. Serial.begin(9600);
    5. }
    6. void loop() {
    7. switch (PortNum)
    8. {
    9. case 0:
    10. Serial.print("A");
    11. Serial.println(analogRead(A0));
    12. break;
    13. case 1:
    14. Serial.print("B");
    15. Serial.println(analogRead(A1));
    16. break;
    17. case 2:
    18. Serial.print("C");
    19. Serial.println(analogRead(A2));
    20. break;
    21. case 3:
    22. Serial.print("D");
    23. Serial.println(analogRead(A3));
    24. break;
    25. case 4:
    26. Serial.print("E");
    27. Serial.println(analogRead(A4));
    28. break;
    29. case 5:
    30. Serial.print("F");
    31. Serial.println(analogRead(A5));
    32. break;
    33. case 6:
    34. Serial.print("G");
    35. Serial.println(analogRead(A6));
    36. break;
    37. case 7:
    38. Serial.print("H");
    39. Serial.println(analogRead(A7));
    40. break;
    41. }
    42. PortNum = PortNum + 1;
    43. if(PortNum >= 8)
    44. {
    45. PortNum = 0;
    46. }
    47. delay(200);
    48. }


    Oder meinst du etwas anderes?


    LG

    RodFromGermany schrieb:

    den String, den der Arduino sendet
    Du postetest die Prozedur, die an den Arduino sendet.
    Ich beziehe mich auf Dein ursprüngliches Problem: Extrahieren von Messwerten aus einem String, den Dir der Arduino gesendet hat.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Bitte weiter oben lesen.
    Da steht was mein aktuelles Problem ist.


    Die Auswertung funktioniert auch. D.h. Ich kann auch mehrere Werte auswerten und darstellen.
    Das Problem ist nun, wenn ich das ganze länger laufen lasse, wird die aktualisierung immer lansamer.
    Z.B. wenn ich den Wert für A0 verändere (Poti) dann dauert es etwa 5 bis 6 Sekunden bis der Wert aktualisiert wird.
    Wie länger das ganze läuft desto langsamer wird es.

    Gibt es da irgendwie einen Puffer oder so den ich zwichendurch mal leeren müsste?
    ...



    LG
    @Temp-22 Sorry, hab ich überlesen.
    Der Rechner in sich hat da keine Verzögerung, vom Arduino glaub ich das auch nicht.
    Kommt der Analogwert unmittelbar an (Spannungsmesser)?
    Wenn Du das Programm neu startest unbd dann nach einer Änderung unmittelbar einen Wert ausliest - was passiert da?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Kein Problem kann passieren.

    Also die Analogwerte werden vom Arduino direkt rausgeschickt.
    Bis auf die 200ms pause gibt es keine Verzögerung. Das kann man sehr schön im Serial Monitor beobachten.
    Wenn ich mein VB programm starte, werden wie oben beschrieben die Werte eingelesen und in Textboxen ausgegeben.
    Wie länger das Programm läuft, desto langsamer wird die reaktion auf veränderungen. Starte ich das VB Programm neu,
    ist erst alles gut. Wie länger das Programm dann läuft, desto langsamer wird es.


    LG

    Temp-22 schrieb:

    Wie länger das Programm dann läuft
    Was macht denn Dein Programm sonst noch so?
    Vielleicht machst Du mal eine kleine Test-GUI, die nix anderes tut als Werte einlesen und anzeigen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo, An sich hat das Programm nix anderes zutun. Hab jetzt mal nur 8 Textboxen angelegt und die Werte ausgeben lassen.
    Das Problem besteht nach wie vor. Hier der VB Code.

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim Werte As String
    3. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    4. Werte = SerialPort1.ReadLine()
    5. If Werte <> "" Then
    6. If Mid(Werte, 1, 1) = "A" Then
    7. TextBox1.Text = FormatNumber(CDbl(Mid(Werte, 2, (Len(Werte) - 1))), 0)
    8. ' Chart1.Series(0).Points.AddY(Val(TextBox1.Text))
    9. ElseIf Mid(Werte, 1, 1) = "B" Then
    10. TextBox2.Text = FormatNumber(CDbl(Mid(Werte, 2, (Len(Werte) - 1))), 0)
    11. 'Chart1.Series(1).Points.AddY(Val(TextBox2.Text))
    12. ElseIf Mid(Werte, 1, 1) = "C" Then
    13. TextBox3.Text = FormatNumber(CDbl(Mid(Werte, 2, (Len(Werte) - 1))), 0)
    14. 'Chart1.Series(2).Points.AddY(Val(TextBox3.Text))
    15. ElseIf Mid(Werte, 1, 1) = "D" Then
    16. TextBox4.Text = FormatNumber(CDbl(Mid(Werte, 2, (Len(Werte) - 1))), 0)
    17. 'Chart1.Series(3).Points.AddY(Val(TextBox4.Text))
    18. ElseIf Mid(Werte, 1, 1) = "E" Then
    19. TextBox5.Text = FormatNumber(CDbl(Mid(Werte, 2, (Len(Werte) - 1))), 0)
    20. 'Chart1.Series(4).Points.AddY(Val(TextBox5.Text))
    21. ElseIf Mid(Werte, 1, 1) = "F" Then
    22. TextBox6.Text = FormatNumber(CDbl(Mid(Werte, 2, (Len(Werte) - 1))), 0)
    23. 'Chart1.Series(5).Points.AddY(Val(TextBox6.Text))
    24. ElseIf Mid(Werte, 1, 1) = "G" Then
    25. TextBox7.Text = FormatNumber(CDbl(Mid(Werte, 2, (Len(Werte) - 1))), 0)
    26. 'Chart1.Series(6).Points.AddY(Val(TextBox7.Text))
    27. ElseIf Mid(Werte, 1, 1) = "H" Then
    28. TextBox8.Text = FormatNumber(CDbl(Mid(Werte, 2, (Len(Werte) - 1))), 0)
    29. 'Chart1.Series(7).Points.AddY(Val(TextBox8.Text))
    30. End If
    31. End If
    32. End Sub
    33. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    34. SerialPort1.Open()
    35. Timer1.Enabled = True
    36. End Sub
    37. End Class


    LG
    @Temp-22 Wie schnell tickt denn der Timer?
    Warum nimmst Du nicht das .DataReceived-Event des SerialPorts?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Temp-22 schrieb:

    VB.NET-Quellcode

    1. FormatNumber(CDbl(Mid(Werte, 2, (Len(Werte) - 1))), 0)


    An dieser Stelle könnte man auch Böses aus VB6/VB2003 - und die richtigen VB.NET-Alternativen einstreuen. Zur Sicherheit auch: Visual Studio - Empfohlene Einstellungen
    Mit freundlichen Grüßen,
    Thunderbolt