Erweitertes Arduino Tutorial

    • VB.NET

    Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von faxe1008.

      Erweitertes Arduino Tutorial

      Hallo

      Das ist mein erstes Tutorial, also Verbesserungen und Kritik sind sehr erwünscht.
      In diesem Tutorial geht es um die Kommunikation mit VB und dem Arduino über die Serielle Schnittstelle.
      Folgende Punkte werde ich behandeln:
      - Simple Kommunikation (Nur einzelene Chars)
      - Erweiterte Kommunikation (Ganze Strings übergeben)
      - Automatische Erkennung des Arduino

      Simple Kommunikation:

      Das wurde hier schon einmal leicht angesprochen doch ich werde es trozdem einbauen so als kleiner start.
      Hier geht es darum einzelne Chars vom PC aus an den Arduino zu senden und diese auszuwerten. Dies wird mittels eines SerialPorts gemacht.
      Erstellen eines SerialPorts:
      Entweder wählt man ihn als SerialPort in der Toolbox aus oder man erstellt ihn über Code:

      VB.NET-Quellcode

      1. Dim SerialPort1 As New SerialPort


      Nun muss unserem Serialport einen Namen zugewiesen werden, welcher mit dem Port des Arduinos übereinstimmt. Welcher das ist, ist überall anderst, darum wird später noch die Automatische Erkennung erklärt.
      In diesem Beispiel sagen wir einfach ist es „COM5“.

      VB.NET-Quellcode

      1. SerialPort1.PortName = "COM5"


      Nachdem dies geschehen ist kann der Port geöffnet werden. Achtung ein Port kann immer nur von einem Programm gleichzeitig verwendet werden.

      VB.NET-Quellcode

      1. SerialPort1.Open()


      Jetzt ist er bereit um die Chars an den Arduino zu senden. Wir senden hier jetzt einfach eine 0 an den Arduino, was dieser nacher damit anfängt kommt später.

      VB.NET-Quellcode

      1. SerialPort1.Write(„0“)


      Gut und nun zum Arduino:
      Als allererstes muss beim Arduino auch den SerialPort aktiviert werden. Dies geschiet im setup loop:


      Quellcode

      1. Int inByte;
      2. void setup() {
      3. Serial.begin(9600);
      4. }

      Die 9600 gibt die Baud-Rate an, die ist Standard immer 9600 darum auch hier. Der Integer „inByte“ wird dazu verwendet den einkommenden Char zu speichern.
      Und nun zum Empfangen des Signals:

      Quellcode

      1. void loop() {
      2. if (Serial.available() > 0) {
      3. inByte = Serial.read();
      4. if (inByte == 48) {
      5. // zu wünschende Aktion z.B. LED einschalten
      6. }
      7. }
      8. }


      So, der ganze code der in void loop drin steht wird immer wiederholt. Über Seriel.available() wird überprüft ob etwas gesendet wurde und fals ja wird es mit Serial.read() ausgelesen und in inByte gespeichert.
      In unserem Fall die „0“, jetzt wie komme ich auf 48? Gesendet wurde ein Char, doch der Arduino nimmt diesen als Byte auf. Welcher Char welches Byte ist kann man in einer Ascii-Tabelle nachschauen.

      Erweiterte Kommunikation:

      Hier geht es darum einen ganzen String zu versenden und der Arduino zeigt den dann vielleicht auf einem kleinen Display an.
      Das senden geht genau wie oben nur das man statt „0“ auch „Hallo Test Test“ versenden kann.
      Doch wie weiss der Arduino jetzt wann der ganze String gesendet wurde? Ganz einfach, nach jedem Senden eines Strings wird noch ein „Enter“ gesendet:

      VB.NET-Quellcode

      1. SerialPort1.Write(vbCr)


      So nun zum Arduino:

      Quellcode

      1. int inByte;
      2. char inText[300];
      3. int index;
      4. void setup() {
      5. Serial.begin(9600);
      6. }
      7. if (Serial.available() > 0) {
      8. inByte = Serial.read();
      9. if (inByte == 13) // Wenn das Enter ankommt
      10. {
      11. // Hier kann alles Mögliche stehen, der vor dem Enter gesendete Text steht im inText Array
      12. // Nach der Verarbeitung des Textes muss der Index auf 0 gesetzt werden und das Array gelöscht
      13. index = 0;
      14. memset(&inText[0], 0, sizeof(inText));
      15. }
      16. else // Falls kein Enter kommt muss der Text gespeichert werden in dem inText Array
      17. {
      18. if (index < 300) { // Diese Überprüfung ist nötig, damit das Array nicht überfüllt wird sonst werden andere Variablen überschrieben.
      19. inText[index] = inByte;
      20. index += 1;
      21. }
      22. }


      Automatische Erkennung des Arduinos:

      Die Idee ist sehr simpel. Man programmiert den Arduino so das wenn man z.B. „$“ sendet das er statt es in das inText Array schreibt, einen String zurücksendet der z.B. der Name des Gerätes ist.

      Quellcode

      1. if (Serial.available() > 0) {
      2. inByte = Serial.read();
      3. if (inByte == 36) { // 36 ist das Dollar-Zeichen „$“
      4. Serial.Write(„test_geraet“)
      5. }
      6. }


      So und nun muss man in VB noch alle Ports auflisten und jedem ein „$“ senden, und bei dem wo die Antwort „test_geraet“ zurückkommt, den kann man als Arduino Port nehmen.
      Ein Beispiel wie das zu lösen ist:

      VB.NET-Quellcode

      1. Dim SP_Empfangen As String
      2. Private _Encoding As System.Text.Encoding
      3. Public Sub New()
      4. InitializeComponent()
      5. _Encoding = System.Text.Encoding.Default
      6. End Sub
      7. Private Sub SP_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SP.DataReceived
      8. Dim ToRead As Integer = SP.BytesToRead
      9. If ToRead > 0 Then
      10. Dim Buffer(ToRead - 1) As Byte
      11. SP.Read(Buffer, 0, ToRead)
      12. SP_Empfangen &= _Encoding.GetString(Buffer)
      13. End If
      14. End Sub
      15. Private Sub check_port()
      16. For Each Port As String In ComboBox1.Items
      17. If SP.IsOpen = True Then
      18. SP.Close()
      19. End If
      20. SP.PortName = Port
      21. SP.Open()
      22. SP_Empfangen = Nothing
      23. SP.Write("1")
      24. sleep(100)
      25. If Not SP_Empfangen = Nothing Then
      26. If SP_Empfangen.Contains("test_geraet") Then
      27. ComboBox1.SelectedItem = Port
      28. Exit Sub
      29. End If
      30. End If
      31. Next
      32. MessageBox.Show("Gerät wurde nicht gefunden!", "Fehler!", MessageBoxButtons.OK, MessageBoxIcon.Error)
      33. End Sub


      Nun kann das check_port Event aufgerufen werden und es wird jeder Port abgescannt ob der Arduino angeschlossen ist.

      So das wars mit meinem Tutorial, ich hoffe es hat euch gefallen und ihr habt dabei was gelernt.
      Bei Fragen und Kritik nicht zögern, beides ist sehr erwünscht.

      Mfg Ebrithil

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ebrithil“ ()

      Zweiter Teil

      Hallo

      Mir ist noch eine sehr nützliche Funktion eingefallen, die vielleicht einigen von euch weiterhelfen kann.
      Und zwar das speichern von Werten auf dem Arduino obwohl er nicht mit Strom versorgt ist, bzw Resetet wird.

      Dazu wird Gebrauch vom EPROM gemacht. Das EEPROM ist ein kleiner interner Speicher von Arduino in welchen bis zu ( beim Arduino UNO ) 1kB Daten speichern kann.

      Das ganze funktioniert so:

      Schreiben:

      Quellcode

      1. EEPROM.write(address, value)


      value:

      ist der Wert ( 1 Byte ) der gespeichert wird.

      adress:

      Ist die Adresse wo der Wert abgelegt wird. Die Adresse ist eine Zahl vom 0 - 1023

      Wichtige Information:

      Bei grösseren Datenmengen sollte ein SD-Karten Shield verwendet werden bei welchem man eine SD-Karte an den Arduino hängen kann, denn das EEPROM lässt sich laut der Arduino Seite nur ca. 100'000 beschreiben. Also bei grossen Datenmenge und häufiges beschreiben bitte eine SD-Karte verwenden.

      Lesen:

      Quellcode

      1. EEPROM.read(address)


      Gibt das Byte zurück welches an der angegeben Adresse gespeichert wurde.

      Info: eine noch nie beschriebene Adresse hat den Wert: 255

      Im Gegensatz zum Schreiben, kann das lesen so gesehen unendlich viel mal benutzt werden ohne das EEPROM zu zerstören.

      Allgemein:

      Um diese Befehle erst nutzen zu können, muss ganz am Anfang des Programms immer:

      Quellcode

      1. #include <EEPROM.h>


      stehen, damit man das EEPROM benutzen kann.

      ---------------------------------------------------------------------------------------------------------------------------------------------------------

      Ich hoffe ich konnte euch helfen, und das es informativ war. Wie immer Kritik und Fragen sind erwünscht.

      Weitere Teile werden vielleicht folgen.


      MFG Ebrithil
      Dritter Teil

      Senden von Strings vom Arduino an VB


      Das Prinzip bleibt das gleiche wie beim umgekehrten Vorgang. Also zuerst wie bei der Automatischen Erkennung den Teil hinzufügen, das VB die Schnittstelle ausliest.

      VB.NET-Quellcode

      1. Dim SP_Empfangen As String
      2. Dim inByte As String
      3. Private _Encoding As System.Text.Encoding
      4. Public Sub New()
      5. InitializeComponent()
      6. _Encoding = System.Text.Encoding.Default
      7. End Sub
      8. Private Sub SP_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SP.DataReceived
      9. Dim ToRead As Integer = SP.BytesToRead
      10. If ToRead > 0 Then
      11. Dim Buffer(ToRead - 1) As Byte
      12. SP.Read(Buffer, 0, ToRead)
      13. SP_Empfangen &= _Encoding.GetString(Buffer)
      14. End If
      15. End Sub


      Gut jetzt aber weiss VB noch nicht wann der String zu Ende ist. Also das geht folgendermassen:

      Der obere Teil wird ein bisschen abgeändert und zwar brauchen wir wie beim Arduino die inByte Variable. Und ein Neuer Sub, welche ausgelöst wird wenn ein neuer String gesendet wurde, so kan man diesen dann ganz gemütlich auswerten.

      VB.NET-Quellcode

      1. Dim SP_Empfangen As String
      2. Private _Encoding As System.Text.Encoding
      3. Public Sub New()
      4. InitializeComponent()
      5. _Encoding = System.Text.Encoding.Default
      6. End Sub
      7. Private Sub SP_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SP.DataReceived
      8. Dim ToRead As Integer = SP.BytesToRead
      9. If ToRead > 0 Then
      10. Dim Buffer(ToRead - 1) As Byte
      11. SP.Read(Buffer, 0, ToRead)
      12. inByte = _Encoding.GetString(Buffer)
      13. If inByte = vbCr Then
      14. Me.Invoke(Sub() New_Message(SP_Empfangen))
      15. SP_Empfangen = Nothing
      16. Else
      17. SP_Empfangen &= inByte
      18. End If
      19. End If
      20. End Sub
      21. Private Sub New_Message(ByVal m As String)
      22. End Sub


      So nun wird jedes einkommende eichen überprüft ob es ein Enter (vbCr) ist. Falls nicht, wird es der Variable SP_Empfangen zugewiesen, falls es ein Enter ist, wird die Variable SP_Empfangen an den Sub New_Message weitergegeben und anschliessend geleert, damit der Nächste String empfangen werden kann.

      So und wie sende ich jetzt mit dem Arduino einen String an VB sodass dieser erkannt wird? Ganz einfanch zuerst wird wie bei der Erkennung der String versendet, doch danach muss noch das Enter kommen um zu sagen das der String fertig ist.

      Quellcode

      1. Serial.write("Dies ist ein Test");
      2. Serial.write(13);


      So, das 13 ist wieder die ASCCI Nummer von Enter, und nun wird in VB das Event New_Message gefeuert wenn das ENter angekommen ist un die Variabel SP_Empfangen ist dann mit "Dies ist ein Test" gefüllt.

      mfg Ebrithil

      Edit:

      Danke an Manawyrm für den Tip mit dem Me.Invoke. Habs mal hinzugefügt.
      Mein Erstes Tutorial: Erweitertes Arduino Tutorial

      Simpler D&D FTP Uploader: Edge-Load

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

      @ebrithil:

      Habe vor einen Monitor für den Arduino zu bauen allerdings scheitert es bis Weilen an dem Empfangen der Werte:
      Spoiler anzeigen

      VB.NET-Quellcode

      1. Imports System.IO.Ports
      2. Public Class Form1
      3. Public WithEvents SerialPort1 As New SerialPort
      4. Dim SP_Empfangen As String
      5. Dim inByte As String
      6. Private Sub SP_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
      7. Dim ToRead As Integer = SerialPort1.BytesToRead
      8. If ToRead > 0 Then
      9. Dim Buffer(ToRead - 1) As Byte
      10. SerialPort1.Read(Buffer, 0, ToRead)
      11. inByte = System.Text.Encoding.Default.GetString(Buffer)
      12. If inByte = vbCr Then
      13. Me.Invoke(Sub() New_Message(SP_Empfangen))
      14. SP_Empfangen = Nothing
      15. Else
      16. SP_Empfangen &= inByte
      17. End If
      18. End If
      19. End Sub
      20. Private Path As New MetroSuite.MetroTrackerPath
      21. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      22. Path.Name = "Arduino Übermittlung"
      23. Path.IsFilled = True
      24. Path.Maximum = 10
      25. Path.Style = MetroSuite.Design.TrackerStyle.CPU
      26. SerialPort1.PortName = "COM9"
      27. SerialPort1.BaudRate = 9600
      28. SerialPort1.Open()
      29. MetroTracker1.Paths.Add(Path)
      30. End Sub
      31. Private Sub New_Message(ByVal m As String)
      32. Path.Add(Integer.Parse(SP_Empfangen))
      33. End Sub
      34. End Class


      Ich bekomme trotzdem keinen Wert zurück?

      8-) faxe1008 8-)

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