Forum: Mikrocontroller und Digitale Elektronik VB.net Serial Port: Arduino Uno -> Okay ABER Arduino Micro -> Fehler


von Jens (Gast)


Lesenswert?

Moin Nerds,

Sachen gibts ... Ich dachte ich hätte alles für mein Projekt erledigt. 
Ich lese einen Rotary Encoder der an einen Arduino Uno angeschlossen ist 
über Serial Port in Vb.net aus. Alles schick.

Für die endgültige Lösung wollte ich nun einen Arduino Micro aus 
Platzgründen benutzen.

Das überraschende Problem ist nun, dass es mit dem Micro nicht klappt.
Ich kann in der Arduino IDE am Serial Monitor sehen das alles 
funktioniert. Also Hardware, Kompilierer ist alles okay, aber das 
Auslesen unter VB.net, das mit dem Uno eben noch geklappt hat geht mir 
dem Micro nicht.

Ich steh auf dem Schlauch, wo könnte ich ansetzen?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Anderer COM-Port?

von Jens (Gast)


Lesenswert?

Unter VB.net lasse ich nach Com Ports scannen und verbinde dann mit dem 
entsprechendem Port.

Der Port wechselt wenn ich den USB Stecker in eine andere Buchse stecke 
oder wenn ich den Arduino (Micro - UNO) wechsele.

Meintest Du das?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Jens schrieb:
> Meintest Du das?

Ja. Was heißt denn "klappt nicht"? Kann der Port nicht geöffnet werden? 
Setzt du von VB.net aus die Baudrate richtig?

Jens schrieb:
> Sachen gibts ...

Auf den beiden Arduinos sind wahrscheinlich andere USB-UART-Konverter 
drauf. Daher ist es nicht sehr verwunderlich, dass die sich anders 
verhalten.

von Einer K. (Gast)


Lesenswert?

Niklas G. schrieb:
> Auf den beiden Arduinos sind wahrscheinlich andere USB-UART-Konverter
> drauf.

Beim originalen UNO machts ein Coprozessor, ein ATMega16U2
Beim Micro machts der Hauptprozessor, ein ATMega32U4

Niklas G. schrieb:
> Setzt du von VB.net aus die Baudrate richtig?
Beim Micro ist die Baudrate recht egal. Ist voll virtuell.
Einzig die 1200 Baud macht sich eine Arduino Extrawurst.

von Jens (Gast)


Lesenswert?

Niklas G. schrieb:
> Ja. Was heißt denn "klappt nicht"? Kann der Port nicht geöffnet werden?
> Setzt du von VB.net aus die Baudrate richtig?

Ich sehe unter der IDE des Arduinos am Serial Monitor oder am Serial 
Plotter was am Serial ausgegeben wird. Das ist alles i.O. auch beim 
Micro.

Unter VB.net kommt kein Fehler wenn ich den SerialPort Arduino-PC 
verbinde. Es werden jedoch keine Daten empfangen. Bautrate hab ich auf 
9600 in VB.net und im Arduino festgelegt.

Wie gesagt unter dem UNO gehts mit dem Mico gehts nicht mehr.

Arduino Fanboy D. schrieb:
> Niklas G. schrieb:
>> Auf den beiden Arduinos sind wahrscheinlich andere USB-UART-Konverter
>> drauf.
>
> Beim originalen UNO machts ein Coprozessor, ein ATMega16U2
> Beim Micro machts der Hauptprozessor, ein ATMega32U4

Könnte das das Problem erklären? Wo Wie soll ich ansetzen?

von Thomas W. (diddl)


Lesenswert?

Jens schrieb:
> Könnte das das Problem erklären? Wo Wie soll ich ansetzen?

Ja das erklärt das Problem.

Bei einem UNO oder einem NANO sind die RX0/TX0 an dem USB Chip 
angeschlossen.

Bei dem Atmega32U4 gibt BEIDES: USB und RX/TX

========

Wenn du nun Daten über RX/TX ausgibst, dann enden die wahrscheinlich an 
einem pin deines Arduino und nicht am virtuellen COM deines PC ...

Beitrag #5962114 wurde von einem Moderator gelöscht.
von Jens (Gast)


Lesenswert?

Thomas W. schrieb:
> Bei dem Atmega32U4 gibt BEIDES: USB und RX/TX
>
> ========
>
> Wenn du nun Daten über RX/TX ausgibst, dann enden die wahrscheinlich an
> einem pin deines Arduino und nicht am virtuellen COM deines PC ...

Also sollte ich mir einen Nano kaufen?

Oder wie kann ich das noch mit dem Arduino Micro realisieren?

von Einer K. (Gast)


Lesenswert?

Jens schrieb:
> Oder wie kann ich das noch mit dem Arduino Micro realisieren?

Der Micro/Leonardo/Beetle funktioniert bei mir mit allen Programmen, 
welche über die Serielle quasseln.
Leider ist da kein VB Programm bei (glaube ich)

Ich vermute daher eher, dass da mit VB irgendwas falsch läuft.

Thomas W. schrieb:
> Wenn du nun Daten über RX/TX ausgibst, dann enden die wahrscheinlich an
> einem pin deines Arduino und nicht am virtuellen COM deines PC ...

TX/RX ist Serial1
Der virtuelle ist Serial

Da läuft nichts schief, oder ist mit Wahrscheinlichkeiten behaftet.
No.

von Jens (Gast)


Lesenswert?

Falls es hilft hier mal der VB.net Code -- Serial Monitor.

So wird der Arduino dann auch im "echten" Programm abgerufen. Hier als 
Beispiel nur das nötigste.

Ist hier was falsch (wie gesagt mit dem UNO ging alles ohne Probleme)?

2 Buttens 2 Comboxen 1 RichTextbox
--------------------------------------------------


Imports System
Imports System.ComponentModel
Imports System.Threading
Imports System.IO.Ports

Public Class Form1
    Dim myPort As String()
    Delegate Sub SetTextCallback(ByVal txt As String)

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles 
MyBase.Load
        myPort = IO.Ports.SerialPort.GetPortNames()
        CbxBaud.Items.Add(9600)
        CbxBaud.Items.Add(19200)
        CbxBaud.Items.Add(38400)
        CbxBaud.Items.Add(57600)
        CbxBaud.Items.Add(115200)
        For i = 0 To UBound(myPort)
            CbxPort.Items.Add(myPort(i))
        Next
        CbxPort.Text = CType(CbxPort.Items.Item(0), String)
        CbxBaud.Text = CType(CbxBaud.Items.Item(0), String)
        BtnDisconnect.Enabled = False
    End Sub

    Private Sub BtnConnect_Click(sender As Object, e As EventArgs) 
Handles BtnConnect.Click
        SerialPort1.PortName = CbxPort.Text
        SerialPort1.BaudRate = CInt(CbxBaud.Text)
        SerialPort1.Parity = IO.Ports.Parity.None
        SerialPort1.StopBits = IO.Ports.StopBits.One
        SerialPort1.DataBits = 8
        SerialPort1.Encoding = System.Text.Encoding.Default
        SerialPort1.Open()
        SerialPort1.DiscardOutBuffer()
        BtnConnect.Enabled = False
        BtnDisconnect.Enabled = True
    End Sub

    Private Sub BtnDisconnect_Click(sender As Object, e As EventArgs) 
Handles BtnDisconnect.Click
        SerialPort1.Close()
        BtnConnect.Enabled = True
        BtnDisconnect.Enabled = False
    End Sub

    Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e 
As System.IO.Ports.SerialDataReceivedEventArgs) Handles 
SerialPort1.DataReceived
        ReceivedText(SerialPort1.ReadExisting())
    End Sub

    Private Sub ReceivedText(ByVal txt As String)
        If Me.RtxAusgabe.InvokeRequired Then
            Dim x As New SetTextCallback(AddressOf ReceivedText)
            Me.Invoke(x, New Object() {(txt)})
        ElseIf txt IsNot Nothing Then
            txt = txt.Trim
            Me.RtxAusgabe.Text &= txt & vbNewLine  'original line
        End If
    End Sub
End Class

von c-hater (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:

> Ich vermute daher eher, dass da mit VB irgendwas falsch läuft.

Das kannste knicken. Ich habe mit VB.net schon derart viele Daten über 
ale möglichen COM-Ports bewegt: das funktioniert schon. Wenn man's 
richtig macht, natürlich.

Übrigens: es ist unter VB.net natürlich derselbe SerialPort wie unter C# 
und er ist auch genauso zu benutzen...

von Jens (Gast)


Lesenswert?

Gelöst

laut:

Amazingly in the meantime (5mins) Smiley I have stumbled upon the cause 
of the problem.

For Leonardo when opening the COMport you have to set both DtrEnable and 
RtsEnable properties true.

Unlike the Uno or Mega2560. The default is that they are false, and many 
code examples out there set them false explicitly.

Hope this saves someone else some headbanging.

RogerCO

https://www.visualmicro.com/forums/YaBB.pl?num=1431524832
Post Nr. 14

Das noch in den VB.net Code implementiert plus auf dem Arduino noch
  while (!Serial) {
  ; //diese Zeile ist für den Mirco Arduino nötig da der Port etwas zeit 
braucht zu öffnen
  }

von Einer K. (Gast)


Lesenswert?

c-hater schrieb:
> Das kannste knicken. Ich habe mit VB.net schon derart viele Daten über
> ale möglichen COM-Ports bewegt: das funktioniert schon. Wenn man's
> richtig macht, natürlich.
Du siehst....

@ Jens (Gast)
Danke für die Rückmeldung!

von c-hater (Gast)


Lesenswert?

Jens schrieb:

> Ist hier was falsch

Definitiv. Das ist Bullshit:

>     Private Sub ReceivedText(ByVal txt As String)
>         If Me.RtxAusgabe.InvokeRequired Then
>             Dim x As New SetTextCallback(AddressOf ReceivedText)
>             Me.Invoke(x, New Object() {(txt)})
>         ElseIf txt IsNot Nothing Then
>             txt = txt.Trim
>             Me.RtxAusgabe.Text &= txt & vbNewLine  'original line
>         End If
>     End Sub

Du verstehst nicht, was InvokeRequired tatsächlich tut.

Etwas vereinfachend kann man das etwa so aufbereiten: Wenn 
AnyControl.InvokeRequired in irgendeinem Eventhandler des Serialport 
false liefert, dann darfst du AnyControl dort in keinster Weise 
anfassen. D.h.: entferne den ElseIf-Zweig. Der hat das Potential, böse 
Schäden zu verursachen.

Allerdings: Auch wenn das definitiv falsch ist, ob es nun für dein 
konkretes Problem verantwortlich ist, kann man nicht sicher sagen. Du 
selber kannst das aber: indem du einfach mal einen Breakpoint auf den 
Start der Routine setzt. Wird der überhaupt jemals erreicht? Und wenn 
ja: Wie oft...

Ich vermute: Exakt einmal. Und genau dann geht's in den ElseIf-Zweig...

von c-hater (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:

> Du siehst....

Wie ich sagte: Wenn man's richtig macht...

Wenn der Peer irgendeinen Handshake erwartet, dann muss man ihn 
natürlich ermöglichen oder ersatzweise wenigstens ein Dauer-ACK 
implementieren...

von Jens (Gast)


Lesenswert?

c-hater schrieb:
> Du verstehst nicht, was InvokeRequired tatsächlich tut.

Da hast du recht, ich versteh es wirklich nicht genau.
ABER der elseif Zeig wird "ständig" ausgeführt er ist es ja, der den 
Output des SerialPorts in VB anzeigt. Der Zweig füllt die Textbox mit 
den Werten.

Der Invoke Kram war nötig wegen Threadproblemen (genauer kann ich da 
nicht wiedergeben; leider fehlt mir da das Wissen; Multithread etc).

Bist Du sicher, dass es so wirklich nicht okay ist? Könntest Du es noch 
besser erklären.

-----
ganz davon ab mit den Änderungen s.o. läuft ja jetzt alles tiptop

von c-hater (Gast)


Lesenswert?

Jens schrieb:

> Der Invoke Kram war nötig wegen Threadproblemen

Ganz genau dafür ist er da. Man muss ihn allerdings auch korrekt 
benutzen, sonst löst er das Problem nicht wirklich.

> Bist Du sicher, dass es so wirklich nicht okay ist?

Jepp. Da stecken sogar zwei satte Fehler drin. Der erste, der mir sofort 
aufgefallen ist, ist die schiere Existenz des ElseIf-Zweiges. Es gibt 
aber noch einen zweiten: Du benutzt Me.RtxAusgabe.InvokeRequired zur 
Entscheidungsfindung, ob Invoke erforderlich ist, aber dann Me.Invoke, 
um die Synchronisation sicher zu stellen. Das ist in etwa so, als wenn 
du fragst "Brennt's in Australien?" und dann die heimische Feuerwehr 
alarmierst...

Der grundlegende Konstruktionsfehler ist, den synchronen Teil und den 
asynchronen Teil in einem Callback abwickeln zu wollen.

> ganz davon ab mit den Änderungen s.o. läuft ja jetzt alles tiptop

Das kann sich mit kleinsten Änderung am Code oder beim Timing schnell 
ändern. Entsprechende Probleme machen sich typisch gehäuft beim Start 
oder beim Beenden der Anwendung bemerkbar.

von Jens (Gast)


Lesenswert?

Danke das Du darauf nochmal eingegangen bist könntest Du eventuell ein 
Code Schnipsel Posten wie man das mit Invoke richtig macht.  Da Beispiel 
von mir ist mein erster Code mit delegaten und callback. Danke von einem 
Anfänger...

von Jens (Gast)


Lesenswert?

@ c-hater

Wäre es so okay????


    Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e 
As System.IO.Ports.SerialDataReceivedEventArgs) Handles 
SerialPort1.DataReceived
        Me.Invoke(Sub() ReceivedText(SerialPort1.ReadExisting()))
    End Sub

    Private Sub ReceivedText(ByVal txt As String)
        Me.RtxAusgabe.Text &= txt
    End Sub

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.