Arduino steuern per AutoIt-GUI

  • Hallo. Ich möchte gerne einen Arduino µController per AutoIt GUI steuern. Am Beispiel gezeigt:
    Ich habe RGB-LED-Stripes zu Hause. Diese kann man per Steuerung mit einem µController in verschiedenen Farben zum Leuchten bringen. Damit man sie in einer bestimmten Farbe leuchten lässt kann man sie mit RGB-Farben "füttern". Sprich sende ich 255, 255, 255 so leuchtet sie weiß. Diese Farbe möchte ich jetzt z. B. mit drei Schiebereglern in der GUI von AutoIt verändern können. Ich muss ja nun irgendwie ein Kommando über die serielle Schnittstelle versenden können - wie bewerkstellige ich dies?

  • Unter Windows nennt man so eine Schnittstelle bekanntlich COM-Interface, da hätte eine Google-Suche nach "COM UDF AutoIt" sicher nicht geschadet. ^^

    Ich habe für Arduino-Projekte bisher immer diese UDF aus dem EN-Forum genommen, ich habe jetzt neulich aber auch einen deutlich einfacheren Ansatz über ein COM-Objekt gesehen. Genau genommen ist es ein COM-COM-Objekt, fällt mir gerade auf. :D

  • Über die Seite bin ich bei meiner Suche auch gestolpert. Ich hatte eigentlich gehofft dass igendwo mal etwas anhand von Beispielen gezeigt wird. War bisher aber nicht so. Ich habe mir die UDF mal heruntergeladen und schaue da gleich mal rein. Kannst du mir ggf. schonmal vorab irgendwelchen hilfreichen Tipps auf den Weg geben?

  • Guck mal an's Ende von dem Post im EN-Forum. Da ist ein (zugegeben ein wenig versteckter) Anhang mit einem Beispiel. Ansonsten kann ich auch gleich mal mein COM-Werk raussuchen.

    Das hier ist das Beispiel mit dem COM-COM-Objekt:

    Spoiler anzeigen
    [autoit]


    ;Schnietzel
    #include <FileConstants.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $MsComm = ObjCreate("MSCOMMLib.MsComm.1")

    [/autoit] [autoit][/autoit] [autoit]

    $MsComm.CommPort = 1
    $MsComm.Settings = "9600,N,8,1"
    $MsComm.Handshaking = 0
    $MsComm.InBufferSize = 1024
    $MsComm.InputLen = 1

    [/autoit] [autoit][/autoit] [autoit]

    $MsComm.PortOpen = 1

    [/autoit] [autoit][/autoit] [autoit]

    $TempFile = FileOpen("Temp.txt",2)

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    FileWrite($TempFile, $MsComm.Input)
    WEnd

    [/autoit]


    Ist allerdings ungetestet.

  • So! Es funktioniert, aber nicht so wie es soll. Ich habe es gerade mal mit dem Example probiert aus dem Forum. Wenn ich nun einen String Sende über das Example per

    [autoit]

    _CommSendstring

    [/autoit]


    und diesen String am µController empfange, dann setzt der Controller etwas um, aber nicht das, was gesendet wurde. Mein Arduino-Code sieht folgendermaßen aus:

    Spoiler anzeigen

    Ich habe die Zeile mal entsprechend kommentiert in der die Farbe der RGB-LED gesetzt wird.

    Code
    pixels_vorne.setPixelColor(1, pixels_vorne.Color(0, incomingByte, 0));


    Setzt die Farbe der LED. Wichtig ist (0, incomingByte, 0), das setzt die Farbe.
    Anteile Rot: 0
    Anteile grün: Wird aus dem serial.read() gelesen
    Anteile blau: 0

    Wenn ich nun also über den Example-Sketch 255 sende, sollte die grüne LED mit voller Leuchtkraft leuchten. Sie glimmt aber nur etwas. Per serial.read() wird also irgendwas empfangen, aber nicht die 255 die ich gesendet habe. Wieso nicht?

  • Ah... Ich erinnere mich an gewisse Schwierigkeiten im Zusammenhang mit der CommMG-UDF.
    Selbst bei richtigen Parametern wurde immer nur das erste Byte richtig übertragen, der Rest der Daten war immer irgendein Kauderwelsch. Die Verbindungsdaten haben natürlich übereingestimmt mit denen aus dem Arduino-Monitor, bei dem die Verbindung funktioniert hat... Für mich hat das keine Rolle gespielt, weil mein entwickeltes Protokoll nur aus den Zahlen von 0 bis 7 bestanden hat, daher habe ich das einfach so belassen. Ich meine aber, dass der COM-COM-Objekt-Ansatz da weiterhelfen könnte, da das ein Problem von CommMG zu sein scheint. Daher habe ich diesen Snippet auch; als Alternative zu CommMG.

  • Okay, gut zu wissen. Allerdings wäre es dann nett von dir, wenn du zu deinem Ansatz nochmal etwas sagen könntest. Dein Beispiel verstehe ich nicht. Wie kann ich darüber z. B. den String "255" senden sodass er von serial.read() auch als "255" gelesen wird?

  • Hallo Scritch,
    ich kann dir "CommAPI" empfehlen -> https://www.autoitscript.com/wiki/CommAPI#Features

    Damit kannst du die COM-Schnittstelle ohne externe DLL etc. ansprechen. Hier (https://www.autoitscript.com/wiki/CommAPI_Examples)
    findest du auch einige Beispiele um ein eigenes Skript zu schreiben.
    Allerdings hatte ich damit ein kleines Problem, was ich hier (Problem mit CommAPI (Version: 2014-04-08) - RS232 | RS485) gelöst habe.

    Hoffe ich konnte dir weiter helfen?!

    Gruß
    Homer J. S.

    ...wenn die Donuts auch nur halb so gut schmecken wie sie aussehen, dann sehen sie doppelt so gut aus wie sie schmecken...

  • @Scritch,
    natürlich wird ein String gesendet, wenn du aber "255" sendest, sind das 3 Bytes mit den Werten asc("2")=50 asc("5")=53 und asc("5")=53
    Daher glimmt deine LED nur!
    Sende einfach mal chr(255) an den Arduino!

  • Ich hab vor geraumer Zeit dasselbe gemacht.
    Verwendet habe ich die CommMG.au3
    AutoIt Code:

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <EditConstants.au3>
    #include <StaticConstants.au3>
    #include <CommMG.au3>
    _Connect()

    [/autoit] [autoit][/autoit] [autoit]

    #region ### START Koda GUI section ### Form=
    GUICreate("Arduino & AutoIT", 270, 167, -1, -1) ; GUI
    GUICtrlCreateLabel("Rot", 8, 12, 21, 12) ; Label
    GUICtrlCreateLabel("Grün", 8, 62, 27, 12) ; Label
    GUICtrlCreateLabel("Blau", 8, 112, 25, 17) ; Label
    $InRed = GUICtrlCreateLabel("0", 35, 12, 40, 12) ; Label
    $InGreen = GUICtrlCreateLabel("0", 35, 62, 40, 12) ; Label
    $InBlue = GUICtrlCreateLabel("0", 35, 112, 40, 12) ; Label
    $slRed = GUICtrlCreateSlider(8, 32, 250, 20) ; Slider
    GUICtrlSetLimit(-1, 255, 0)
    GUICtrlSetBkColor(-1, 0xFF0000)
    $slGreen = GUICtrlCreateSlider(8, 82, 250, 20); Slider
    GUICtrlSetLimit(-1, 255, 0)
    GUICtrlSetBkColor(-1, 0x00FF00)
    $slBlue = GUICtrlCreateSlider(8, 132, 250, 20); Slider
    GUICtrlSetLimit(-1, 255, 0)
    GUICtrlSetBkColor(-1, 0x0000FF)
    GUISetState(@SW_SHOW) ; GUI SHOW
    #endregion ### END Koda GUI section ###

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    _reset()
    Exit
    EndSwitch
    InRedChange()
    InGreenChange()
    InBlueChange()
    WEnd
    Func InRedChange()
    $tmp2 = GUICtrlRead($InRed)
    If GUICtrlRead($slRed) <> ($tmp2) Then
    GUICtrlSetData($InRed, GUICtrlRead($slRed))
    _CommSendByte(Asc("R"))
    _CommSendByte(GUICtrlRead($slRed))
    EndIf
    EndFunc ;==>InRedChange
    Func InGreenChange()
    $tmp1 = GUICtrlRead($InGreen)
    If GUICtrlRead($slGreen) <> ($tmp1) Then
    GUICtrlSetData($InGreen, GUICtrlRead($slGreen))
    _CommSendByte(Asc("G"))
    _CommSendByte(GUICtrlRead($slGreen))
    EndIf
    EndFunc ;==>InGreenChange
    Func InBlueChange()
    $tmp = GUICtrlRead($InBlue)
    If GUICtrlRead($slBlue) <> ($tmp) Then
    GUICtrlSetData($InBlue, GUICtrlRead($slBlue))
    _CommSendByte(Asc("B"))
    _CommSendByte(GUICtrlRead($slBlue))
    EndIf
    EndFunc ;==>InBlueChange
    Func _Connect()
    _CommSetDllPath("C:\Program Files (x86)\AutoIt3\Include\commg.dll")
    $ports = _CommListPorts(0)

    [/autoit] [autoit][/autoit] [autoit]

    $list = ""
    For $x = 1 To UBound($ports) - 1
    $list &= $ports[$x] & @CRLF
    Next
    $input = InputBox("Port wählen", "Verfügbare Ports:" & @CRLF & $list)
    If $input == "" Then
    Exit
    EndIf
    Local $Error
    _CommSetPort($input, $Error, 9600, 8, "none", 2, 1)
    If @error Then
    MsgBox(0, "", "Keine Verbindung zu Port " & $input & " möglich.")
    Exit
    EndIf
    EndFunc ;==>_Connect
    Func _reset()
    _CommSendByte(Asc("R"))
    _CommSendByte(0)
    _CommSendByte(Asc("G"))
    _CommSendByte(0)
    _CommSendByte(Asc("B"))
    _CommSendByte(0)
    EndFunc ;==>_reset

    [/autoit]

    Bild:
    [Blockierte Grafik: http://i.epvpimg.com/BuANd.png]

    Alles weitere wie Arduino-Sketch und das AutoIt-Script als .au3 sowie ein Fritzingaufbauplan ist im Anhang zu finden.

    AutoIt.de :love:

    2 Mal editiert, zuletzt von Kilroy (28. Oktober 2014 um 20:29)

  • Ich habe keine private Nachricht erhalten? Wenn du Fragen hast, stelle sie doch in diesem Thema, es gibt vielleicht noch andere Menschen die genau die selben Fragen hätten.

    AutoIt.de :love:

  • Okay. Ich dachte halt da es auch Arduinotechnischer Natur ist klären wir das lieber privat.

    Also, das hier ist dein Code:

    Spoiler anzeigen


    Per Autoit schickst du ja erst den Buchstaben für die Farbe, und dann den Wert hinterher. Solange du den Schieber für eine Farbe betätigt wird, wird quasi immer abwechselnd z. B. "R" "125" "R" "125" "R" "125" gesendet. Im Arduinocode fragst du diesen Strom nun ab, soweit klar. Mit deinem switch(Serial.read()) { fragst du ja quasi den seriellen Strom ab. Was genau wird denn hier abgefragt, immer das erste Byte welches gerade gesendet wurde, also quasi erst das Kürzel für Farbe? Und sofern gerade "G" gesendet wurde, greift die entsprechende Case-Anweisung. Dort machst du dann das nächste Serial.Read: analogWrite(rot, Serial.read());
    Liest das dann das nächste Byte im Datenstrom? Also das Byte, welches den Wert "125" enthält? Oder ist es Zufall welches Byte gelesen wird? Oder anders gefragt: Wenn ich alle Bytes eines seriellen Datenstroms auslesen möchte, muss ich dann für jedes Byte ein separates serial.read(); machen?

  • Wie in dem Sketch schon erklärt, sendet AutoIt nur bei verschieben des Reglers z.B "R" "125" (es wird geprüft ob der Wert des Reglers ungleich dem Label ist). Alles was du an den Arduino Port sendest wird erstmal gelagert (serial receive buffer). Geprüft ob etwas vorhanden ist wird durch serial.available(). Mit serial.read() wird das aktuellste Byte gelesen. Da der Arduino durch den ersten Wert "R" schon im Case ist wird das nächste aktuelle Byte also "125" welches ja sofort danach kommt gelesen.

    So verstehe ich das, also so ist es für mich logisch und nachvollziehbar.

    Nachtrag:
    Das ganze geht so auch mit dem Seriellen Monitor. Sendest du dem Arduino dadurch z.B. R dann wird er in den Case R gehen und solange warten bis etwas gesendet wird. Sendest du also 5min später erst die 125, wird er im Case R in der while weiter gehen und die 125 verwerten.

    AutoIt.de :love:

    Einmal editiert, zuletzt von Kilroy (30. Oktober 2014 um 18:54)