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?
Arduino steuern per AutoIt-GUI
-
- [ offen ]
-
Scritch -
19. Oktober 2014 um 13:18 -
Erledigt
-
-
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.
-
Ü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]
[/autoit] [autoit][/autoit] [autoit]
;Schnietzel
#include <FileConstants.au3>$MsComm = ObjCreate("MSCOMMLib.MsComm.1")
[/autoit] [autoit][/autoit] [autoit]$MsComm.CommPort = 1
[/autoit] [autoit][/autoit] [autoit]
$MsComm.Settings = "9600,N,8,1"
$MsComm.Handshaking = 0
$MsComm.InBufferSize = 1024
$MsComm.InputLen = 1$MsComm.PortOpen = 1
[/autoit] [autoit][/autoit] [autoit]$TempFile = FileOpen("Temp.txt",2)
[/autoit] [autoit][/autoit] [autoit]While 1
[/autoit]
FileWrite($TempFile, $MsComm.Input)
WEnd
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
C
Alles anzeigen//rgb_led // NeoPixel Ring simple sketch (c) 2013 Shae Erisson // released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library #include <Adafruit_NeoPixel.h> // Which pin on the Arduino is connected to the NeoPixels? #define PIN_vorne 9 // How many NeoPixels are attached to the Arduino? #define NUMPIXELS 6 // When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals. // Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest // example for more information on possible values. Adafruit_NeoPixel pixels_vorne = Adafruit_NeoPixel(NUMPIXELS, PIN_vorne, NEO_GRB + NEO_KHZ800); int incomingByte = 0; // for incoming serial data //------------------------------------------------------------------------------------------------ void setup() { //Beginn des Setups pixels_vorne.begin(); // This initializes the NeoPixel library. //pinMode(rx_signal_pin_throttle, INPUT); Serial.begin(9600); // initalisierung der seriellen Schnittstelle } //------------------------------------------------------------------------------------------------ void loop() { //hauptschleife if (Serial.available() > 0) { // read the incoming byte: incomingByte = Serial.read(); } pixels_vorne.setPixelColor(1, pixels_vorne.Color(0, incomingByte, 0)); // Hier müsste die Farbe gesetzt werden, die per Serial.read() (dem gesendeten String) gesendet wird. pixels_vorne.show(); // This sends the updated pixel color to the hardware. }
Ich habe die Zeile mal entsprechend kommentiert in der die Farbe der RGB-LED gesetzt wird.
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: 0Wenn 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#FeaturesDamit 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. -
@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>
[/autoit] [autoit][/autoit] [autoit]
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <StaticConstants.au3>
#include <CommMG.au3>
_Connect()#region ### START Koda GUI section ### Form=
[/autoit] [autoit][/autoit] [autoit]
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 ###While 1
[/autoit] [autoit][/autoit] [autoit]
$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)$list = ""
[/autoit]
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 ;==>_resetBild:
[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.
-
Danke für eure ganzen Lösungsansätze. In abgewandelter Form funktioniert die Vorlage von Kilroy schon sehr gut.
-
@Kilroy: Ich habe dir bereits eine private Nachricht geschrieben, weil ich noch Fragen zu deinem Arduino-Sketch habe. Ich bräuchte da bitte eine kurze Erläuterung zu
-
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.
-
Okay. Ich dachte halt da es auch Arduinotechnischer Natur ist klären wir das lieber privat.
Also, das hier ist dein Code:
Spoiler anzeigen
Code
Alles anzeigenconst int rot = 6; // analog Pin 6 const int gruen = 5; // analog Pin 5 const int blau = 3; // analog Pin 3 void setup() { pinMode(rot, OUTPUT); // OUTPUT pinMode(gruen, OUTPUT); // OUTPUT pinMode(blau, OUTPUT); // OUTPUT Serial.begin(9600); // Serial.begin } /* Was passiert: AutoIT Schickt erst den Buchstaben dann den Wert. Ablauf ----> - AutoIT schickt Wert -> Daten empfangen Serial also größer 0 - wenn gelesener Byte = R -> case 'R' - keine Datenempfangen Serial kleiner 1 - while -> warte da keine Empfangen werden ist kleiner 1 - AutoIt schickt Wert -> 0-255 - Daten werden Empfangen also größer 1 -> While weiter - analogWrite Wert - break -> raus aus dem case */ void loop() { if (Serial.available() > 0) { // werden Daten empfangen? switch(Serial.read()) { // Serial auslesen + Switch case 'R': // wenn R dann while (Serial.available() < 1) ; analogWrite(rot, Serial.read()); // analogWrite Serial. break; case 'G': // wenn R dann while (Serial.available() < 1) ; analogWrite(gruen, Serial.read()); break; case 'B': // wenn R dann while (Serial.available() < 1) ; analogWrite(blau, Serial.read()); break; } } }
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. -
Alles klar, danke dir. Das hilft mir weiter