我的愿望是通过USB端口( COM3-9600,N,8,1 )与 Arduino Uno 通信。 我打算在运行 Windows 10 的计算机上使用Autohotkey管理信息。
该测试仅用于读取Arduino的信息。但是后来我也希望能够从PC向Arduino Uno发送信息。
Arduino Uno附带了一张额外的卡(Funduino JoyStick Shield V1.A)-仅用于测试。
这是我在Arduino上使用的程序。
// Armuino --- Funduino Joystick Shield ---
// Playlist: https://www.youtube.com/playlist?list=PLRFnGJH1nJiKIpz_ZyaU-uAZOkMH8GAcw
//
// Part 1. Introduction - Basic Functions: https://www.youtube.com/watch?v=lZPZuBCFMH4
// Arduino digital pins associated with buttons
const byte PIN_BUTTON_A = 2;
const byte PIN_BUTTON_B = 3;
const byte PIN_BUTTON_C = 4;
const byte PIN_BUTTON_D = 5;
const byte PIN_BUTTON_E = 6;
const byte PIN_BUTTON_F = 7;
// Arduino analog pins associated with joystick
const byte PIN_ANALOG_X = 0;
const byte PIN_ANALOG_Y = 1;
void setup() {
Serial.begin(9600);
pinMode(PIN_BUTTON_B, INPUT);
digitalWrite(PIN_BUTTON_B, HIGH);
pinMode(PIN_BUTTON_E, INPUT);
digitalWrite(PIN_BUTTON_E, HIGH);
pinMode(PIN_BUTTON_C, INPUT);
digitalWrite(PIN_BUTTON_C, HIGH);
pinMode(PIN_BUTTON_D, INPUT);
digitalWrite(PIN_BUTTON_D, HIGH);
pinMode(PIN_BUTTON_A, INPUT);
digitalWrite(PIN_BUTTON_A, HIGH);
}
void loop() {
Serial.print("Buttons A:");
Serial.print(digitalRead(PIN_BUTTON_A));
Serial.print(" ");
Serial.print("B:");
Serial.print(digitalRead(PIN_BUTTON_B));
Serial.print(" ");
Serial.print("C:");
Serial.print(digitalRead(PIN_BUTTON_C));
Serial.print(" ");
Serial.print("D:");
Serial.print(digitalRead(PIN_BUTTON_D));
Serial.print(" ");
Serial.print("E:");
Serial.print(digitalRead(PIN_BUTTON_E));
Serial.print(" ");
Serial.print("F:");
Serial.print(digitalRead(PIN_BUTTON_F));
Serial.print(" -- ");
Serial.print("Position X:");
Serial.print(analogRead(PIN_ANALOG_X));
Serial.print(" ");
Serial.print("Y:");
Serial.print(analogRead(PIN_ANALOG_Y));
Serial.print(" ");
Serial.println();
delay(1000);
}
当我在PC上运行Arduino串行编辑器时,此程序似乎可以运行。 值在屏幕上逐行显示,例如..
**00:58:44.434 -> Buttons A:1 B:1 C:1 D:1 E:1 F:1 -- Position X:334 Y:321**
(I can't see any wrong values in the Serial Editor. - maybe in higher speed)
但是,如果我尝试使用Autohotkey“执行相同操作”,有时字符可能会丢失。
喜欢这个。:
But:322
Buttons A:1 B:1 C:1 D:1 E:1 F:1 -- Position X:334 Y:322
334 Y:322
Buttons A:1 B:1 C:1 D:1 E:1 F:1 -- Position X:334 Y:322
我不知道与USB的通信在Windows 10中应该是什么样子。 (我认为它与Windows XP不同) 我已经研究过此解决方案。:Arduino + AutoHotKey > Serial Connection -不确定我找到了正确的Arduino.ahk -可能需要Windows XP? -它对我不起作用!
此技巧更好(但较旧)。: Arduino.ahk beta .01
大多数测试都基于此链接,我创建了以下AHK程序。:
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#Singleinstance force
COM = 3
Num_Bytes = 500
Mode =
; Initialize COM-port
COM_Port = COM%COM%
COM_Baud = 9600
COM_Parity = N
COM_Data = 8
COM_Stop = 1
COM_DTR = Off
FilNamn := A_ScriptDir "/Test.txt"
IfExist %FilNamn%
FileDelete %FilNamn%
COM_Settings = %COM_Port%:baud=%COM_Baud% parity=%COM_Parity% data=%COM_Data% stop=%COM_Stop% dtr=%COM_DTR%
COM_FileHandle := Serial_Initialize(COM_Settings)
Loop 100
{ ; ReadResult := Serial_Read(COM_FileHandle, Num_Bytes, Mode)
ReadResult := Serial_Read_Raw(COM_FileHandle, Num_Bytes, Mode)
asciiString := Hex2ASCII(ReadResult)
sleep 20
FileAppend %asciiString%, %FilNamn%, UTF-8
; SplashTextOn 800, 100, Arduino Read, %asciiString%
; Sleep 1000
; MsgBox ,, Rad %A_LineNumber% -> %A_ScriptName%, % COM_Settings "`n`n" ReadResult "`n`n- " StrLen(ReadResult) "`n`n- " Bytes_Received "`n`n- " asciiString, 1
}
Serial_Close(COM_FileHandle)
; MsgBox ,, Rad %A_LineNumber% -> %A_ScriptName%, % COM_Settings "`n`n" ReadResult "`n`n- " StrLen(ReadResult) "`n`n- " Bytes_Received
; asciiString := Hex2ASCII(ReadResult)
; MsgBox ,, Rad %A_LineNumber% -> %A_ScriptName%, % ReadResult "`n`n"asciiString
MsgBox ,, Rad %A_LineNumber% -> %A_ScriptName%, Klart!
ExitApp
ESC::
SplashTextOff
Serial_Close(COM_FileHandle)
MsgBox ,,, Programmet avslutas!, 1
ExitApp
Return
Hex2ASCII(fHexString)
{ Loop Parse, fHexString
NewHexString .= A_LoopField (Mod(A_Index,2) ? "" : ",")
Loop Parse, NewHexString, `,
ConvString .= Chr("0x" A_LoopField)
Return ConvString
} ;http://www.autohotkey.com/forum/post-211769.html#211769
;########################################################################
;###### Initialize COM Subroutine #######################################
;########################################################################
Serial_Initialize(SERIAL_Settings){
;Global SERIAL_FileHandle ;uncomment this if there is a problem
;###### Build COM DCB ######
;Creates the structure that contains the COM Port number, baud rate,...
VarSetCapacity(DCB, 28)
BCD_Result := DllCall("BuildCommDCB"
,"str" , SERIAL_Settings ;lpDef
,"UInt", &DCB) ;lpDCB
If (BCD_Result <> 1){
error := DllCall("GetLastError")
MsgBox, There is a problem with Serial Port communication. `nFailed Dll BuildCommDCB, BCD_Result=%BCD_Result% `nLasterror=%error%`nThe Script Will Now Exit.
ExitApp
}
;###### Extract/Format the COM Port Number ######
StringSplit, SERIAL_Port_Temp, SERIAL_Settings, `:
SERIAL_Port_Temp1_Len := StrLen(SERIAL_Port_Temp1) ;For COM Ports > 9 \\.\ needs to prepended to the COM Port name.
If (SERIAL_Port_Temp1_Len > 4) ;So the valid names are
SERIAL_Port = \\.\%SERIAL_Port_Temp1% ; ... COM8 COM9 \\.\COM10 \\.\COM11 \\.\COM12 and so on...
Else ;
SERIAL_Port = %SERIAL_Port_Temp1%
;MsgBox, SERIAL_Port=%SERIAL_Port%
;###### Create COM File ######
;Creates the COM Port File Handle
;StringLeft, SERIAL_Port, SERIAL_Settings, 4 ; 7/23/08 This line is replaced by the "Extract/Format the COM Port Number" section above.
SERIAL_FileHandle := DllCall("CreateFile"
,"Str" , SERIAL_Port ;File Name
,"UInt", 0xC0000000 ;Desired Access
,"UInt", 3 ;Safe Mode
,"UInt", 0 ;Security Attributes
,"UInt", 3 ;Creation Disposition
,"UInt", 0 ;Flags And Attributes
,"UInt", 0 ;Template File
,"Cdecl Int")
If (SERIAL_FileHandle < 1){
error := DllCall("GetLastError")
MsgBox, There is a problem with Serial Port communication. `nFailed Dll CreateFile, SERIAL_FileHandle=%SERIAL_FileHandle% `nLasterror=%error%`nThe Script Will Now Exit.
ExitApp
}
;###### Set COM State ######
;Sets the COM Port number, baud rate,...
SCS_Result := DllCall("SetCommState"
,"UInt", SERIAL_FileHandle ;File Handle
,"UInt", &DCB) ;Pointer to DCB structure
If (SCS_Result <> 1){
error := DllCall("GetLastError")
MsgBox, There is a problem with Serial Port communication. `nFailed Dll SetCommState, SCS_Result=%SCS_Result% `nLasterror=%error%`nThe Script Will Now Exit.
Serial_Close(SERIAL_FileHandle)
ExitApp
}
;###### Create the SetCommTimeouts Structure ######
ReadIntervalTimeout = 0xffffffff
ReadTotalTimeoutMultiplier = 0x00000000
ReadTotalTimeoutConstant = 0x00000000
WriteTotalTimeoutMultiplier= 0x00000000
WriteTotalTimeoutConstant = 0x00000000
VarSetCapacity(Data, 20, 0) ; 5 * sizeof(DWORD)
NumPut(ReadIntervalTimeout, Data, 0, "UInt")
NumPut(ReadTotalTimeoutMultiplier, Data, 4, "UInt")
NumPut(ReadTotalTimeoutConstant, Data, 8, "UInt")
NumPut(WriteTotalTimeoutMultiplier, Data, 12, "UInt")
NumPut(WriteTotalTimeoutConstant, Data, 16, "UInt")
;###### Set the COM Timeouts ######
SCT_result := DllCall("SetCommTimeouts"
,"UInt", SERIAL_FileHandle ;File Handle
,"UInt", &Data) ;Pointer to the data structure
If (SCT_result <> 1){
error := DllCall("GetLastError")
MsgBox, There is a problem with Serial Port communication. `nFailed Dll SetCommState, SCT_result=%SCT_result% `nLasterror=%error%`nThe Script Will Now Exit.
Serial_Close(SERIAL_FileHandle)
ExitApp
}
Return SERIAL_FileHandle
}
;########################################################################
;###### Close COM Subroutine ############################################
;########################################################################
Serial_Close(SERIAL_FileHandle){
;###### Close the COM File ######
CH_result := DllCall("CloseHandle", "UInt", SERIAL_FileHandle)
If (CH_result <> 1)
MsgBox, Failed Dll CloseHandle CH_result=%CH_result%
Return
}
;########################################################################
;###### Write to COM Subroutines ########################################
;########################################################################
Serial_Write(SERIAL_FileHandle, Message){
;Global SERIAL_FileHandle
OldIntegerFormat := A_FormatInteger
SetFormat, Integer, DEC
;Parse the Message. Byte0 is the number of bytes in the array.
StringSplit, Byte, Message, `,
Data_Length := Byte0
;msgbox, Data_Length=%Data_Length% b1=%Byte1% b2=%Byte2% b3=%Byte3% b4=%Byte4%
;Set the Data buffer size, prefill with 0xFF.
VarSetCapacity(Data, Byte0, 0xFF)
;Write the Message into the Data buffer
i=1
Loop %Byte0% {
NumPut(Byte%i%, Data, (i-1) , "UChar")
;msgbox, %i%
i++
}
;msgbox, Data string=%Data%
;###### Write the data to the COM Port ######
WF_Result := DllCall("WriteFile"
,"UInt" , SERIAL_FileHandle ;File Handle
,"UInt" , &Data ;Pointer to string to send
,"UInt" , Data_Length ;Data Length
,"UInt*", Bytes_Sent ;Returns pointer to num bytes sent
,"Int" , "NULL")
If (WF_Result <> 1 or Bytes_Sent <> Data_Length)
MsgBox, Failed Dll WriteFile to COM Port, result=%WF_Result% `nData Length=%Data_Length% `nBytes_Sent=%Bytes_Sent%
SetFormat, Integer, %OldIntegerFormat%
Return Bytes_Sent
}
;########################################################################
;###### Read from COM Subroutines #######################################
;########################################################################
;########################################################################
;###### Read from COM Subroutines #######################################
;########################################################################
Serial_Read(COM_FileHandle, Num_Bytes, mode = "",byref Bytes_Received = "")
{
;Global COM_FileHandle
;Global COM_Port
;Global Bytes_Received
SetFormat, Integer, HEX
;Set the Data buffer size, prefill with 0x55 = ASCII character "U"
;VarSetCapacity won't assign anything less than 3 bytes. Meaning: If you
; tell it you want 1 or 2 byte size variable it will give you 3.
Data_Length := VarSetCapacity(Data, Num_Bytes, 0x55)
;msgbox, Data_Length=%Data_Length%
;###### Read the data from the COM Port ######
;msgbox, COM_FileHandle=%COM_FileHandle% `nNum_Bytes=%Num_Bytes%
Read_Result := DllCall("ReadFile"
,"UInt" , COM_FileHandle ; hFile
,"Str" , Data ; lpBuffer
,"Int" , Num_Bytes ; nNumberOfBytesToRead
,"UInt*", Bytes_Received ; lpNumberOfBytesReceived
,"Int" , 0) ; lpOverlapped
;MsgBox, Read_Result=%Read_Result% `nBR=%Bytes_Received% ,`nData=%Data%
If (Read_Result <> 1)
{
MsgBox, There is a problem with Serial Port communication. `nFailed Dll ReadFile on COM Port, result=%Read_Result% - The Script Will Now Exit.
Serial_Close(COM_FileHandle)
Exit
}
;if you know the data coming back will not contain any binary zeros (0x00), you can request the 'raw' response
If (mode = "raw")
Return Data
;###### Format the received data ######
;This loop is necessary because AHK doesn't handle NULL (0x00) characters very nicely.
;Quote from AHK documentation under DllCall:
; "Any binary zero stored in a variable by a function will hide all data to the right
; of the zero; that is, such data cannot be accessed or changed by most commands and
; functions. However, such data can be manipulated by the address and dereference operators
; (& and *), as well as DllCall itself."
i = 0
Data_HEX =
Loop %Bytes_Received%
{
;First byte into the Rx FIFO ends up at position 0
Data_HEX_Temp := NumGet(Data, i, "UChar") ;Convert to HEX byte-by-byte
StringTrimLeft, Data_HEX_Temp, Data_HEX_Temp, 2 ;Remove the 0x (added by the above line) from the front
;If there is only 1 character then add the leading "0'
Length := StrLen(Data_HEX_Temp)
If (Length =1)
Data_HEX_Temp = 0%Data_HEX_Temp%
i++
;Put it all together
Data_HEX .= Data_HEX_Temp
}
;MsgBox, Read_Result=%Read_Result% `nBR=%Bytes_Received% ,`nData_HEX=%Data_HEX%
SetFormat, Integer, DEC
Data := Data_HEX
Return Data
}
;########################################################################
;###### Read from COM Subroutines #######################################
;########################################################################
Serial_Read_Raw(SERIAL_FileHandle, Num_Bytes, mode = "",byref Bytes_Received = ""){
;Global SERIAL_FileHandle
;Global SERIAL_Port
;Global Bytes_Received
OldIntegerFormat := A_FormatInteger
SetFormat, Integer, HEX
;Set the Data buffer size, prefill with 0x55 = ASCII character "U"
;VarSetCapacity won't assign anything less than 3 bytes. Meaning: If you
; tell it you want 1 or 2 byte size variable it will give you 3.
Data_Length := VarSetCapacity(Data, Num_Bytes, 0)
;msgbox, Data_Length=%Data_Length%
;###### Read the data from the COM Port ######
;msgbox, SERIAL_FileHandle=%SERIAL_FileHandle% `nNum_Bytes=%Num_Bytes%
Read_Result := DllCall("ReadFile"
,"UInt" , SERIAL_FileHandle ; hFile
,"Str" , Data ; lpBuffer
,"Int" , Num_Bytes ; nNumberOfBytesToRead
,"UInt*", Bytes_Received ; lpNumberOfBytesReceived
,"Int" , 0) ; lpOverlapped
;MsgBox, Read_Result=%Read_Result% `nBR=%Bytes_Received% ,`nData=%Data%
If (Read_Result <> 1){
MsgBox, There is a problem with Serial Port communication. `nFailed Dll ReadFile on COM Port, result=%Read_Result% - The Script Will Now Exit.
Serial_Close(SERIAL_FileHandle)
Exit
}
;if you know the data coming back will not contain any binary zeros (0x00), you can request the 'raw' response
If (mode = "raw")
Return Data
;###### Format the received data ######
;This loop is necessary because AHK doesn't handle NULL (0x00) characters very nicely.
;Quote from AHK documentation under DllCall:
; "Any binary zero stored in a variable by a function will hide all data to the right
; of the zero; that is, such data cannot be accessed or changed by most commands and
; functions. However, such data can be manipulated by the address and dereference operators
; (& and *), as well as DllCall itself."
i = 0
Data_HEX =
Loop %Bytes_Received%
{
;First byte into the Rx FIFO ends up at position 0
Data_HEX_Temp := NumGet(Data, i, "UChar") ;Convert to HEX byte-by-byte
StringTrimLeft, Data_HEX_Temp, Data_HEX_Temp, 2 ;Remove the 0x (added by the above line) from the front
;If there is only 1 character then add the leading "0'
Length := StrLen(Data_HEX_Temp)
If (Length =1)
Data_HEX_Temp = 0%Data_HEX_Temp%
i++
;Put it all together
Data_HEX .= Data_HEX_Temp
}
;MsgBox, Read_Result=%Read_Result% `nBR=%Bytes_Received% ,`nData_HEX=%Data_HEX%
SetFormat, Integer, DEC
Data := Data_HEX
SetFormat, Integer, %OldIntegerFormat%
Return Data
}
答案 0 :(得分:1)
感谢您的时间!
设法在Windows和Arduino之间获得更好的通信。 (具有不同的配置)。在GUI中创建了两个窗口
它可以工作(9600bps),但是首先我发送一个标题,如果波特率增加,“奇怪”字符总是出现在测试开始。
不知道在以清晰模式开始读取字符之前是否需要清除Arduino / PC中的串行缓冲区? (怎么做?) 在Arduino SerialMonitor中,我没有从其他测试程序获得波特率更高的可读信息
我在Arduino中的ECHO程序
int incomingByte;
void setup() {
Serial.begin(9600);
}
void loop(){
if (Serial.available() > 0) {
incomingByte = Serial.read();
//Serial.print(incomingByte);
Serial.write(incomingByte);
}
}