thoms Posted April 5, 2014 Posted April 5, 2014 Hi TheReal, You made a great job with the little indication I gave. Nice! Everything seems to work, but : - you changed, I mean removed, the _CommAPI_ReceiveLine() and _CommAPI_ReceiveData(). Some people using these functions should have a surprise when compiling older scripts with new UDF. At least, you should keep the older ones calling the new ones. - in the same renamed function _CommAPI_ReceiveLine(), you changed the order of parameters and added one (however optional) : _CommAPI_ReceiveLine(Const $hFile, Const $sSeparator = @CRLF, Const $iTimeout = 1, Const $iMaxLen = 0) _CommAPI_ReceiveString(Const $hFile, Const $iTimeout = 1, Const $iMaxLength = 0, Const $sSeparator = "", Const $iFlag = 1) - in both functions ReceiveLine and ReceiveString, you are returning the separator, which is not specially desired. ie for an empty line (0x0D0A), I've to use StringStripCR if I don't want a StringLen of 2 instead of 0, which it is indeed. See http://msdn.microsoft.com/en-us/library/h7se9d4f%28v=vs.84%29.aspx : Reads an entire line (up to, but not including, the newline character) Really sorry to bother you with these little details, but it's a way to keep the confidence in your GREAT UDF. Untill i've to use other functions... Thx, Thoms
adom Posted April 7, 2014 Posted April 7, 2014 (edited) Hello thoms, it seems you are havy on wire with this project. Can you help me with my 2 questions? Subject: _CommAPI_ReceiveString($hFile, 5000) while counterpart still sending after RX received $vSeparator Important Question. Let's say: If $bSeparator = BinaryMid($vResult, 1 + $iResLength - $iSepLength) Then Return $vResult --> True and Func Returns 1. What happen, if the the counterpart just send a new telegram just in the time of reading Buffer and returning? Could it happen that the 2. telegram blows in nirvana? 2. Generall asked: what happens with the buffer after has been readed and func returns? Will buffer erased or ha to be separately purged by script? THX for answering me. Edited April 8, 2014 by adom Thanks! :bye: Greetings Andrew
therealhanuta Posted April 7, 2014 Author Posted April 7, 2014 (edited) - you changed, I mean removed, the _CommAPI_ReceiveLine() and _CommAPI_ReceiveData(). Some people using these functions should have a surprise when compiling older scripts with new UDF. At least, you should keep the older ones calling the new ones. - in the same renamed function _CommAPI_ReceiveLine(), you changed the order of parameters and added one (however optional) : _CommAPI_ReceiveLine(Const $hFile, Const $sSeparator = @CRLF, Const $iTimeout = 1, Const $iMaxLen = 0) _CommAPI_ReceiveString(Const $hFile, Const $iTimeout = 1, Const $iMaxLength = 0, Const $sSeparator = "", Const $iFlag = 1) - in both functions ReceiveLine and ReceiveString, you are returning the separator, which is not specially desired. ie for an empty line (0x0D0A), I've to use StringStripCR if I don't want a StringLen of 2 instead of 0, which it is indeed. See http://msdn.microsoft.com/en-us/library/h7se9d4f%28v=vs.84%29.aspx : Reads an entire line (up to, but not including, the newline character) Hi thoms, you are right. separator is no longer returned CommObsolete.au3 is created for backward compatibility Edited April 7, 2014 by therealhanuta
thoms Posted April 7, 2014 Posted April 7, 2014 (edited) Hi TheReal, Thanks for your modifications. I'm going further now. In the Func _CommAPI_OpenPort, you're refering to the http://msdn.microsoft.com/en-us/library/aa365430(v=vs.85).aspx which is about OpenFile, that says "Note This function has limited capabilities and is not recommended. For new application development, use the CreateFile function." Actually, you're using CreateFile, which is referenced here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx The later one says in "Communications Resources": The CreateFile function can create a handle to a communications resource, such as the serial port COM1. For communications resources, the dwCreationDisposition parameter must be OPEN_EXISTING, the dwShareMode parameter must be zero (exclusive access), and the hTemplateFile parameter must be NULL. Read, write, or read/write access can be specified, and the handle can be opened for overlapped I/O. In your Func _CommAPI_OpenPort, you fix this $iCreation to 3 that is OPEN_ALWAYS (a file), when it should be 2 : OPEN_EXISTING(a file or device). I made that modification _CommAPI_OpenPort_WinAPI_CreateFile($sFileName, 2, 6), and it seems to be working well for physical COM19 and USB COM20 ports, above COM9! Right now, I couldn't get virtual ports. I've to check further. BTW, "COM1:" and "COM1", with/wo colon doesn't make any difference. It seem's that Kernel is dealing with that by itself. Hope this helps you further. I like when reading somewhere else: "But who needs serial port today?" . I think that some people (like M$) are very far away from industrial environment, where tough communication links are needed. Thx, Thom's Edited April 8, 2014 by thoms
thoms Posted April 8, 2014 Posted April 8, 2014 @adom Your questions are to be reviewed given the updated UDF from TheReal. It seems that separator doesn't have to be checked or removed anymore. Anyway, if your asking for a string of xx Chars, you'll receive it in the $var that was waiting for it as soon as MaxLengh was received, or nothing or few chars in $var if nothing or few received at the end of timeout: $var = _CommAPI_ReceiveString(Const $hFile[, $iTimeout = 1[, $iMaxLength = 0[, $sSeparator = ""]]]) Then, it depends on what you intend to do with $var. But the receiving buffer will be emptied from the amount you were wating for, or the few chars that were received at timeout. The discarded receveided chars from counterpart depend on the size of the COM buffer and how fast you can manage the received $var before asking again a $var = _CommAPI_ReceiveString(...). Especially if you don't manage the flow control (XON/XOFF, DSR, others) TheReal, pls, am I right ? Thoms DevMode 1
adom Posted April 8, 2014 Posted April 8, 2014 @adom Your questions are to be reviewed given the updated UDF from TheReal. It seems that separator doesn't have to be checked or removed anymore. Anyway, if your asking for a string of xx Chars, you'll receive it in the $var that was waiting for it as soon as MaxLengh was received, or nothing or few chars in $var if nothing or few received at the end of timeout: $var = _CommAPI_ReceiveString(Const $hFile[, $iTimeout = 1[, $iMaxLength = 0[, $sSeparator = ""]]]) Then, it depends on what you intend to do with $var. But the receiving buffer will be emptied from the amount you were wating for, or the few chars that were received at timeout. The discarded receveided chars from counterpart depend on the size of the COM buffer and how fast you can manage the received $var before asking again a $var = _CommAPI_ReceiveString(...). Especially if you don't manage the flow control (XON/XOFF, DSR, others) TheReal, pls, am I right ? Thoms THX Thoms. Have to workout your infos. Just to be shure: is XON a software flow control? Because often Devices in my case of AV-Systems have no HW-Flow-control. Thanks! :bye: Greetings Andrew
thoms Posted April 8, 2014 Posted April 8, 2014 THX Thoms. Have to workout your infos. Just to be shure: is XON a software flow control? Because often Devices in my case of AV-Systems have no HW-Flow-control. Hi adom, Your right, it's a SW control that can't be used for binary transfer as it uses ASCII control chars ^Q-Chr(17) for Xon and ^S-Chr(19) for Xoff. Thoms
thoms Posted April 9, 2014 Posted April 9, 2014 (edited) Hi TheReal, Actually, I've any kind of COM port opening : physical, virtual/USB and virtual/Com0com from COM1 to COM21. I didn't try above. Yes, COM99 works, COM126 doesn't. I think I'll be able to do something with 99 COM ports And that only by changing the CreateFile in _CommAPI_OpenPort to "_WinAPI_CreateFile($sFileName, 2, 6). Other thing: I noticed an ambiguity when creating the ModeString: concerning the StopBits, depending on the type of var your passing, ie "1" or 1, you have 1.5 or 1 stopbit. It's only an ambiguity that doesn't disturb me. Thoms Edit: maybe above COM99, I've to change my StringRegExp in GetPorts. No time now. Edited April 9, 2014 by thoms
thoms Posted April 16, 2014 Posted April 16, 2014 Oops! I don't know if I was dreaming or under influence, but anyway, the colon doesn't work. Now, depending on what computer I'm working with, sometimes I can get COM ports above COM9, sometimes nope. I have 2 other computers to check: XP SP3 in VM, W7/32, and then I'll try to see what's wrong and where. Anyway, my app was working well and I could finish that one, but only on COM1 and USB/COM2 on that XP SP3. I have other app's to do with COM ports, specially one that will surely need the WaitCommEvent. I should be able to give an example then. Read you later, Thoms
nend Posted September 13, 2014 Posted September 13, 2014 (edited) Hello, I've got a problem with the commapi to a Arduino. This program give's every 3 seconds a pulse to my arduino and the arduino knows that the pc is alive. This program works fine but a lot of time when the pc has gone into standby and back he won't reconise the com port anymore. I've I look into a terminal programm it said the "com already is in use" even if this program is shutdown. It looks like it loose the handle to _CommAPI_OpenCOMPort I've tryd to close the port and opened it before sending the pulse but the same thing keeps happening. Strange thing about it that it not happend every time, 90% goes well. I think it goes wrong when he tryd to send the pulse and the pc goes into standby exactly the same moment. If he won't react anymore the only thing I can do is restart the pc. Does someone know the solution to this. Windows 7 Autoit V3.3.8.1 expandcollapse popup#include <include\CommInterface.au3> #include <include\Services.au3> Global $sServiceName = "Pc Tools (Nend Software)"; Service name Global $hFile If @Compiled = 1 Then If _Service_QueryType($sServiceName) = 0 Then InstallService() Exit EndIf Else _code() EndIf If $cmdline[0] > 0 Then Switch $cmdline[1] Case "-i" InstallService() Case "-u" RemoveService() Case "-r" _Service_Stop($sServiceName) Sleep(2000) _Service_Stop($sServiceName) Sleep(2000) _Service_Start($sServiceName) Case Else Exit EndSwitch Else _Service_init($sServiceName) Exit EndIf Func _main($iArg, $sArgs) If Not _Service_ReportStatus($SERVICE_RUNNING, $NO_ERROR, 0) Then _Service_ReportStatus($SERVICE_STOPPED, _WinAPI_GetLastError(), 0) Exit EndIf _code() _Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, 1000) DllCallbackFree($tServiceMain) DllCallbackFree($tServiceCtrl) _Service_ReportStatus($SERVICE_STOPPED, $NO_ERROR, 0) DllClose($hAdvapi32_DLL) DllClose($hKernel32_DLL) EndFunc ;==>main Func _code() local $timer, $timerdif $bServiceRunning = True ; REQUIRED OnAutoItExitRegister("_ExitPC") $port = _comm_start_port() $hFile = _CommAPI_OpenCOMPort($port, 9600, 0, 8, 0) _comm_arduino("Ÿ"); 159 send pulse $timer = TimerInit() While $bServiceRunning #region --> insert your running code here $timerdif = TimerDiff($timer) If $timerdif > 3000 Then ; 3 second $timer = TimerInit() _comm_arduino("Ÿ"); 159 send pulse EndIf _Sleep(20) #endregion --> insert your running code here WEnd EndFunc Func _comm_arduino($sendstring) _CommAPI_TransmitData($hFile, $sendstring) EndFunc Func _ExitPC() _comm_arduino("ž"); 158 _CommAPI_ClosePort($hFile) Exit EndFunc Func _comm_start_port() Local $oWMIService, $oItems, $port $oWMIService = ObjGet("winmgmts:\\localhost\root\CIMV2"); auto serial port select $oItems = $oWMIService.ExecQuery("SELECT * FROM Win32_PnPEntity WHERE Name LIKE 'USB Serial Port%'", "WQL", 48) For $oItem In $oItems $commsplit = StringSplit($oItem.Name, "(COM", 1) $port = StringReplace($commsplit[2], ")", "") Next ConsoleWrite($port & @CRLF) If $port = "" Then _ExitPC() EndIf Return $port EndFunc Func _Sleep($delay) Local $result = DllCall($hKernel32_DLL, "none", "Sleep", "dword", $delay) EndFunc ;==>_Sleep Func InstallService() #RequireAdmin _Service_Create($sServiceName, $sServiceName, $SERVICE_WIN32_OWN_PROCESS, $SERVICE_AUTO_START, $SERVICE_ERROR_SEVERE, '"' & @ScriptFullPath & '"') If @error Then ConsoleWrite("InstallService(): Problem installing service, Error number is " & @error & @CRLF & " message : " & _WinAPI_GetLastErrorMessage() & @CRLF) Else ConsoleWrite("InstallService(" & $sServiceName & "): Installation of service successful" & @CRLF) EndIf EndFunc ;==>InstallService Func RemoveService() _Service_Stop($sServiceName) _Service_Delete($sServiceName) EndFunc ;==>RemoveService Func logprint($text, $nolog = 0); log print for services ConsoleWrite($text & @CRLF) EndFunc Edited September 13, 2014 by nend
Gianni Posted November 2, 2014 Posted November 2, 2014 According to what I read in the "Features" session, this UDF is capable of LPT ports management. "Possibility of parallel communication (parallel port, LPT port)" Unfortunately I haven't found nor examples, nor mentions about this functionality within udf. could someone please post a simple example on how to put a byte on an LPT port? Thanks a lot Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....
ckovoor Posted January 17, 2015 Posted January 17, 2015 (edited) I have been using this UDF to communicate with my Arduino Mega and it has been entirely successful. I was not so successful with the other options offered, so THANK YOU!!!!! (Using Win 7 x64 Home Premium) Edited January 17, 2015 by ckovoor
Terribletrux Posted March 6, 2015 Posted March 6, 2015 Hello, I'm trying to communicate with a Agilent E3649A DC Power Supply. I have written some code using the CommAPI and so far I am only able to send commands, I cannot receive anything. When I use the application that comes with the power supply everything is working as it should so that rules out the cable. Can someone look over my test code? I may have missed something... #include <CommInterface.au3> #include <MsgBoxConstants.au3> Local Const $iPort = 1 Local Const $iBaud = 9600 Local Const $iParity = 0 Local Const $iByteSize = 8 Local Const $iStopBits = 2 Local $hFile =_CommAPI_OpenCOMPort($iPort, $iBaud, $iParity, $iByteSize, $iStopBits) _CommAPI_ClearCommError($hFile) _CommAPI_PurgeComm($hFile) _CommAPI_TransmitString($hFile, "OUTP ON"&@LF) ;Turn output on Sleep (1000) _CommAPI_TransmitString($hFile, "VOLT 7.0"&@LF) ;Adjust voltage to 7 volts Sleep (1000) _CommAPI_TransmitString($hFile, "VOLT 0.0"&@LF) ;Adjust voltage to 0 volts Sleep (1000) _CommAPI_TransmitString($hFile, "OUTP OFF"&@LF) ;Turn output off Sleep (1000) _CommAPI_TransmitString($hFile, "*IDN?") ;Identify your-self Local $sResult =_CommAPI_ReceiveString($hFile, 1, 0);Recieve string _CommAPI_ClosePort($hFile) MsgBox($MB_SYSTEMMODAL, "Title", $sResult, 5) I know that the commands are being sent properly because I can see the output status change on the display of the power supply and my connected LED lights up and then goes out. Also here is a link to the user manual http://cp.literature.agilent.com/litweb/pdf/E3646-90001.pdf Thank you in advance!
Terribletrux Posted March 16, 2015 Posted March 16, 2015 (edited) I was able to figure this out, please go >here for more information. Edited March 16, 2015 by Terribletrux
Allow2010 Posted April 15, 2015 Posted April 15, 2015 Hello, thanks for this UDF, i really like it! But i have a small problem: When i try to receive strings, some characters are not read right. For example german "umlauts" like öäü are received as " I think this may have to do with codepage? Any ideas how i can fix it? Thanks in advance...
Allow2010 Posted April 15, 2015 Posted April 15, 2015 ok, i figured it out, i need to convert the chars with chrw() and i also needed to chage some settings in the sending software side
mnbcv Posted May 16, 2015 Posted May 16, 2015 (edited) Hello,Thank you for this great UDF. Edited May 18, 2015 by mnbcv
rainer560 Posted August 28, 2015 Posted August 28, 2015 Problem with Windows 10:The scripts do not work with Windows 10 - _CommAPI_OpenCOMPort fails.I found however that a Sleep(100) after _CommAPI_BuildCommDCB in the function _CommAPI_OpenPort in script CommInterface.au3 fixes the problem! RainerFunc _CommAPI_OpenPort(Const $sMode) Local $sFileName = "\\.\" & StringLeft($sMode, StringInStr($sMode, ":") - 1) ; Local $sFileName = ".\" & StringLeft($sMode, StringInStr($sMode, ":") - 1) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $sFileName = ' & $sFileName & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console Local $hFile = _WinAPI_CreateFile($sFileName, 3, 6) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hFile = ' & $hFile & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console If @error Then Return SetError(@error, @ScriptLineNumber, 0) If $hFile <= 0 Then Return SetError(-1, @ScriptLineNumber, 0) Local $tDCB = DllStructCreate($tagDCB) Local $tCommTimeouts = DllStructCreate($tagCOMMTIMEOUTS) _CommAPI_BuildCommDCB($sMode, $tDCB) Sleep(100); If @error Then Return SetError(@error, @extended, 0) _CommAPI_SetCommTimeoutsElement($tCommTimeouts, "ReadTotalTimeoutMultiplier", 1) If @error Then Return SetError(@error, @extended, 0) _CommAPI_SetCommTimeoutsElement($tCommTimeouts, "WriteTotalTimeoutMultiplier", 1) If @error Then Return SetError(@error, @extended, 0) If Not _CommAPI_SetCommState($hFile, $tDCB) Then Return SetError(@error, @extended, 0) If Not _CommAPI_SetCommTimeouts($hFile, $tCommTimeouts) Then Return SetError(@error, @extended, 0) Return $hFile EndFunc ;==>_CommAPI_OpenPort
M2C Posted September 11, 2015 Posted September 11, 2015 Hi,This UDF have a BIG MISTAKE and doesn't work fine on Windows 10 with some hardware &There is problem with COM10 (uper to COM9) After several test i have found the mistake :For function "_CommAPI_BuildCommDCB" parameter- $sMode = "COM14: BAUD=9600 PARITY=N DATA=8 STOP=1" - This is WRONG !!!- $sMode = "BAUD=9600 PARITY=N DATA=8 STOP=1" - This is GOOOD !!! So this, how i have modified the function "_CommAPI_OpenPort(Const $sMode)" in file "CommInterface.au3" Func _CommAPI_OpenPort(Const $sMode) ;// split the $sMode string in 2 parts ($aMode[1] = "COMx" & $aMode[2] = "BAUD=xxxx PARITY=x DATA=x STOP=x") Local $aMode = StringSplit($sMode, ": ",1) If @error Then Return SetError(-1, @ScriptLineNumber, 0) Local $sFileName = "\\.\" & $aMode[1] Local $hFile = _WinAPI_CreateFile($sFileName, 3, 6) If @error Then Return SetError(@error, @ScriptLineNumber, 0) If $hFile <= 0 Then Return SetError(-1, @ScriptLineNumber, 0) Local $tDCB = DllStructCreate($tagDCB) Local $tCommTimeouts = DllStructCreate($tagCOMMTIMEOUTS) _CommAPI_BuildCommDCB($aMode[2], $tDCB) If @error Then Return SetError(@error, @extended, 0) _CommAPI_SetCommTimeoutsElement($tCommTimeouts, "ReadTotalTimeoutMultiplier", 1) If @error Then Return SetError(@error, @extended, 0) _CommAPI_SetCommTimeoutsElement($tCommTimeouts, "WriteTotalTimeoutMultiplier", 1) If @error Then Return SetError(@error, @extended, 0) If Not _CommAPI_SetCommState($hFile, $tDCB) Then Return SetError(@error, @extended, 0) If Not _CommAPI_SetCommTimeouts($hFile, $tCommTimeouts) Then Return SetError(@error, @extended, 0) Return $hFileEndFunc ;==>_CommAPI_OpenPort Enjoy ;-)PS: sorry for my bad english, i am french
M2C Posted September 11, 2015 Posted September 11, 2015 Hi,This UDF have a BIG MISTAKE and doesn't work fine on Windows 10 with some hardware &There is problem with COM10 (uper to COM9) After several test i have found the mistake :For function "_CommAPI_BuildCommDCB" parameter- $sMode = "COM14: BAUD=9600 PARITY=N DATA=8 STOP=1" - This is WRONG !!!- $sMode = "BAUD=9600 PARITY=N DATA=8 STOP=1" - This is GOOOD !!! So this, how i have modified the function "_CommAPI_OpenPort(Const $sMode)" in file "CommInterface.au3"Func _CommAPI_OpenPort(Const $sMode) ;// split the $sMode string in 2 parts ($aMode[1] = "COMx" & $aMode[2] = "BAUD=xxxx PARITY=x DATA=x STOP=x") Local $aMode = StringSplit($sMode, ": ",1) If @error Then Return SetError(-1, @ScriptLineNumber, 0) Local $sFileName = "\\.\" & $aMode[1] Local $hFile = _WinAPI_CreateFile($sFileName, 3, 6) If @error Then Return SetError(@error, @ScriptLineNumber, 0) If $hFile <= 0 Then Return SetError(-1, @ScriptLineNumber, 0) Local $tDCB = DllStructCreate($tagDCB) Local $tCommTimeouts = DllStructCreate($tagCOMMTIMEOUTS) _CommAPI_BuildCommDCB($aMode[2], $tDCB) If @error Then Return SetError(@error, @extended, 0) _CommAPI_SetCommTimeoutsElement($tCommTimeouts, "ReadTotalTimeoutMultiplier", 1) If @error Then Return SetError(@error, @extended, 0) _CommAPI_SetCommTimeoutsElement($tCommTimeouts, "WriteTotalTimeoutMultiplier", 1) If @error Then Return SetError(@error, @extended, 0) If Not _CommAPI_SetCommState($hFile, $tDCB) Then Return SetError(@error, @extended, 0) If Not _CommAPI_SetCommTimeouts($hFile, $tCommTimeouts) Then Return SetError(@error, @extended, 0) Return $hFile EndFunc ;==>_CommAPI_OpenPortEnjoy ;-)PS: sorry for my bad english, i am french
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now