Rotary Encoder per Arduino und SerialCom auslesen // Wie werde ich das Bouncing los?

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von wolfi_bayern.

    Rotary Encoder per Arduino und SerialCom auslesen // Wie werde ich das Bouncing los?

    Moin Leute,

    ich dache ach, dass wird nicht so schwer sein einfach mal einen Drehknopf (Rotary Encoder) per Arduino und VB.net über Serial Com auslesen. Leider wurde ich mal wieder eines besseren belehrt.
    Im Prinzip funktioniert alles. Leider springt das ausgelesene Ergebnis zu häufig hin und her.



    Wenn ich den Drehknopf (Encoder) in eine Richtung drehe soll der Wert immer um +1 steigen und wenn ich dann in die andere Richtung drehe soll er immer um -1 fallen. Die Summe lass ich mir zu Debbug-Zwecken einmal in einer RichTextBox und einmal im Graph anzeigen.
    Da wo im Screenshot der rote Kasten ist sollte eigentlich "normal" weiter hochgezählt werden.
    Meine Recherche im Internet führte mich zum "Debouncing from Rotary Encoder" leider haben alle Maßnahmen bei mir noch keinen wirkliche gutes Ergebnis erzeugt.

    Ich möchte das bei drehen in eine Richtung nicht auf einmal "falsche" Sprünge erzeugt werden.

    Das Bauteil habe ich wir im Datenblatt des Herstellers empfohlen angeschlossen:

    Arduino Code habe ich mehrere ausprobiert // der einfachste ->
    Spoiler anzeigen

    Quellcode

    1. ​int messungPin1 = LOW;
    2. int messungPin1Alt = LOW;
    3. int encoderWert = 0;
    4. void setup() {
    5. pinMode(3, INPUT);
    6. pinMode(4, INPUT);
    7. Serial.begin(9600);
    8. }
    9. void loop() {
    10. messungPin1 = digitalRead(3);
    11. if ((messungPin1 == HIGH) && (messungPin1Alt == LOW)) {
    12. if (digitalRead(4) == HIGH) {
    13. encoderWert++;
    14. } else {
    15. encoderWert--;
    16. }
    17. Serial.print (encoderWert);
    18. }
    19. messungPin1Alt = messungPin1;
    20. }


    Vb.Net Code um dann alles am PC anzuzeigen :

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    2. Try
    3. Dim i As Single = SerialPort1.ReadExisting
    4. LblPotentiometer.Text = "Encoder-Wert : " & i.ToString
    5. RichTextBox1.Text &= i.ToString & vbNewLine 'Richtext Feld
    6. Encoder.Series("Encoder").Points.AddY(i.ToString)
    7. If Encoder.Series(0).Points.Count = 20 Then
    8. Encoder.Series(0).Points.RemoveAt(0)
    9. End If
    10. Encoder.ChartAreas(0).AxisY.Maximum = 300
    11. Catch ex As Exception
    12. End Try
    13. End Sub



    Wo soll ich ansetzen? Danke für Vorschläge
    Bilder
    • EncoderBounce.jpg

      60,31 kB, 838×705, 105 mal angesehen
    • Schaltplan.jpg

      16,13 kB, 419×354, 102 mal angesehen
    codewars.com Rank: 4 kyu
    Danke euch beiden für die Links und Infos!!

    @wolfi_bayern : Das mit dem Event vom Data received hatte ich auch mal wir folgt probiert

    VB.NET-Quellcode

    1. Private Sub SerialPort1_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    2. Try
    3. Dim i As Single = SerialPort1.ReadExisting
    4. LblPotentiometer.Text = "Encoder-Wert : " & i.ToString
    5. RichTextBox1.Text &= i.ToString & vbNewLine
    6. Catch ex As Exception
    7. End Try
    8. End Sub


    So wird aber nichts an Daten angezeigt! Weißt Du wie man in diesem Event an die Daten am Serial Port rankommt. Das Event wird ausgelöst, dass habe ich mit einer MessageBox.show getestet, aber ich weiß nicht wie ich dann die Daten lesen kann oder wo die hin sind.
    codewars.com Rank: 4 kyu

    nogood schrieb:

    VB.NET-Quellcode

    1. Dim i As Single = SerialPort1.ReadExisting
    Fang an mit Option Strict On.
    Visual Studio - Empfohlene Einstellungen
    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!
    Ich habe Option Strict On "An" unter Extras->Optionen->VB-Standart ! Es ist bei jedem Projekt auto an gestellt und ich habe es nicht manuell auf off gestellt.

    Ich hab schon gesehen das SerialPort1.ReadExisting eigentlich einen String zurück geben soll laut Msdoc

    VB.NET-Quellcode

    1. ​Public Function ReadExisting () As String
    .
    So hat es jedoch bei mir nicht funktioniert und mit Single ging es dann plötzlich. Warum wie so bin ich leider überfragt.

    Der Kompiler meckert nicht daher dache ich alles i.O.
    codewars.com Rank: 4 kyu
    @wolfi_bayern Ich denke ich lese einen String aus (Integerzahlen und Leerzeichen oder Nothing)! Fälschlicherweise lese ich das in eine Single ein und Caste dann nach String. Was RodfromGermany bemängelte.

    Nach etwas längerem hin und her. Meine Gedanken :

    Arduino Code hab ich "verbessert" es erfolgt jetzt noch eine Abfrage ob der neue Wert größer als alterWert+1 ist wenn ja dann nimm alten Wert (da es sich um einen "FehlerWert" handeln muss).

    Spoiler anzeigen

    Quellcode

    1. if (encoderWert > alterEncoderWert+1) {encoderWert= alterEncoderWert;}else {encoderWert++;}} else {if (encoderWert < alterEncoderWert-1) {encoderWert= alterEncoderWert;}else {encoderWert--;}



    Zum VB.Net Strict On Problem: ich hab es vorher nicht ernst genommen oder verdrängt, der Kompilierer gibt keinen Fehler, aber zu Laufzeit zeigt Visual Studio einen Fehler an:

    Ausnahme ausgelöst: "System.InvalidCastException" in Microsoft.VisualBasic.dll


    Der Fehler kommt nicht wenn ich
    Dim i As String = SerialPort1.ReadExisting
    benutze.
    ----------------------

    Unter der IDE des Arduinos sehen die Werte mit dem verbesserten Code auch schon ganz gut aus (3 Bouncer pro 400 Werte).





    Unter VB "zittern" die Werte noch arg hin und her.



    Zwei Probleme geh ich jetzt an

    1. Ich versuche
    Dim i As String = SerialPort1.ReadExisting
    (um den Cast Fehler zu vermeiden). Problem hier ist ich muss das String noch so editieren dass nur Zahlwerte angezeigt werden und nicht die ganzen Nothings oder Leerzeichen.

    2. Es mit -- SerialDataReceivedEvent -- hinbekommen die Werte anzuzeigen. Dann dürfte ich ja keine Werte mehr verpassen?!

    Falls das nix bringt weiß ich nicht weiter

    Falls jemand ne Ahnung hat, warum es so einen großen Unterschied zwischen dem SerialMonitor-Ergebnis unter Arduino IDE (erste Bild) und dem was ich unter VB auslese gibt (zweite Bild) wäre ne Antwort toll. Danke fürs Interesse
    Bilder
    • DebounceEncoder.jpg

      82,14 kB, 1.035×958, 95 mal angesehen
    • debounceVB.jpg

      89,5 kB, 827×695, 84 mal angesehen
    codewars.com Rank: 4 kyu

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „nogood“ ()

    nogood schrieb:

    Little Endian Format
    ist was für Unicode-Text, nichts jedoch für Bytes, die Zahlen repräsentieren.
    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!
    @Eierlein Da für Nicht-Texte Big-Endian-Format nicht definiert ist, ist die Angabe LittleEndian obsolete.
    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!
    Wieso nicht definiert? Es gibt genügend Architekturen die BigEndian für alles > 1 Byte verwenden(auch float). Manche Mikrocontroller und PLCs z.B.. Ist das der Fall muss man halt die Bytes tauschen.

    Guck dir mal die BitConverter Klasse inner ReferenceSource an. Da ist Byte Swapping theoretisch auch vorgesehen.
    Bin über folgenden Code gestolpert, der SerialCom mit Delegaten und Invoce ausliest ich versteh den Code nicht wirklich, aber er verbessert das Auslesen wesentlich (Perfekt ist es aber auch nicht. Es werden immer noch aber seltener falsche Werte ausgelesen).
    Falls jemand Langeweile hat und die paar Code Zeilen mal für einen Anfänger kommentieren möchte ....

    VB.NET-Quellcode

    1. Delegate Sub SetTextCallback(ByVal txt As String)...
    2. Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    3. ReceivedText(SerialPort1.ReadExisting())
    4. End Sub
    5. Private Sub ReceivedText(ByVal txt As String)
    6. If Me.rtbReceived.InvokeRequired Then
    7. Dim x As New SetTextCallback(AddressOf ReceivedText)
    8. Me.Invoke(x, New Object() {(txt)})
    9. Else
    10. Me.rtbReceived.Text &= txt
    11. End If
    12. txtTransmit.Text = txt 'Val(text)
    13. End Sub


    Am meisten "verwirrt" mich:

    VB.NET-Quellcode

    1. ​Dim x As New SetTextCallback(AddressOf ReceivedText)
    2. Me.Invoke(x, New Object() {(txt)})
    codewars.com Rank: 4 kyu

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

    Gonger96 schrieb:

    Da ist Byte Swapping theoretisch auch vorgesehen
    Das zeigt die Weisheit von Bills Männern. ;)
    Ich hab schon mit ner Menge Hardwaren zu tun gehabt, mir ist noch keine BigEndian-solche untergekommen. :/
    Da müsste ja die (Arithmetik-)Prozessor-Architektur für 16-Bit- oder Float/Double-Einheiten anders herum sein, sonst müssten die bei jedem Zugriff die Bytes rumdrehen.
    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!