therealhanuta Posted October 24, 2013 Posted October 24, 2013 In the moment there are two UDF's for serial communication: >Serial Port / COM Port UDF (needs comMG.dll) >Serial Communication using kernel32.dll The first UDF is very popular, but it has the disadvantage, that an unknown DLL needs to be used. The second UDF use the Windows API, but it has much less features. So, I decided to create an another UDF for my requirements. You can find the result here: http://www.autoitscript.com/wiki/CommAPI It is a further development of the second UDF and has (almost) all functions of the first UDF. Feel free to fix any existing bugs and to extend it with additional functions. stormbreaker, Moriba, funkey and 1 other 3 1
joseLB Posted October 25, 2013 Posted October 25, 2013 Hi therealhanuta Could you supply a simple example on how to use your routines, I mean, to open a serial port, set baudrate, read, write and close? I´m asking that as most of the time these are the really needed functions. The good point is to not use any dll.... Thanks Jose antonioj84 1
joseLB Posted October 30, 2013 Posted October 30, 2013 (edited) Hi therealhanuta FOr many and many years I have being using ObjCreate ("NETCommOCX.NETComm") -> It has the basic functions and all my programs work with those functions without problems, besides to xoff when receive 0X00 byte and the dll to install that is a nightmare in some places. While I had evaluated martin´s Udf, they are really great, but would be very complex to update in my programs, and maybe has so many options. And also,still has a dll to make things complex to install. So, my question/suggestion ( I believe ist´s a subset of your udfs): It´s possible to you to create a separate and simple UDF with just the basic functions (without dll, of course), as the above link , where the functions really needed are as follows(I represented them with that dll interface): ==> one to declare / activate serial port. $comRS232 = ObjCreate("NETCommOCX.NETComm") ==> one to set parameters: (it also must be able to be called later to change parameters, like baud rate) With $comRS232 .CommPort = $serialPort .PortOpen = True .Settings = "600,N,8,1" ==> manipulation routines $comRS232.InBufferCount = 0 and $numChars= $comRS232.InBufferCount $buffer= $comRS232.InputData $comRS232.Output = $msg $comRS232.PortOpen=false or true -> one routine to list (in an array, for example) the avaiable serial ports (new function) ==> desired extra functions/issues (they must be optional): - have a way to declare an event when something arrives in buffer (best if just when "n" bytes arrives, but one event for each open port) - have a way to declare event when transmition finishes - be able to receive/treat x00 byte normally as any other character (without create a xoff) Thanks Jose Edited October 30, 2013 by joseLB
therealhanuta Posted October 30, 2013 Author Posted October 30, 2013 (edited) Hi joseLB, here is an example, which do not ignore 0x00: expandcollapse popup#include "CommInterface.au3" Global Const $iPort = 3 Global Const $iBaud = 9600 Global Const $iParity = 0 Global Const $iByteSize = 8 Global Const $iStopBits = 0 Global Const $sCommand = "Command" & @CRLF Main() Func Main() Local $iErrorLine = COMHandling() If @extended Then MsgBox(32, "Error", _WinAPI_GetLastErrorMessage()) ElseIf @error Then MsgBox(32, "Error", "Error in line " & $iErrorLine) EndIf EndFunc Func COMHandling() Local $hFile = 0 Local $sResult = "" ToolTip(_CommAPI_GetCOMPorts(), Default, Default, "COM Ports", 1) $hFile = _CommAPI_OpenCOMPort($iPort, $iBaud, $iParity, $iByteSize, $iStopBits) If @error Then Return SetError(@error, @extended, @ScriptLineNumber) _CommAPI_ClearCommError($hFile) If @error Then Return SetError(@error, @extended, @ScriptLineNumber) For $i = 1 To 10 _CommAPI_TransmitData($hFile, $sCommand) If @error Then Return SetError(@error, @extended, @ScriptLineNumber) Sleep(5000) $sResult = _CommAPI_ReceiveData($hFile) If @error Then Return SetError(@error, @extended, @ScriptLineNumber) If $sResult Then ToolTip($sResult, Default, Default, "Received data", 1) Else ToolTip("Loop " & $i, Default, Default, "No received data", 3) EndIf Next _CommAPI_CLosePort($hFile) If @error Then Return SetError(@error, @extended, @ScriptLineNumber) Sleep(5000) EndFunc BufferCount is not implemented in the moment. Maybe I can add this next week. Edited November 4, 2013 by therealhanuta
joseLB Posted October 30, 2013 Posted October 30, 2013 (edited) Hi joseLB,...... BufferCount is not implemented in the moment. Maybe I can add this next week. THANKS A LOT for sharing and for all your support !!!!! I will try them and report results here!!!!! Sorry, but 2 more questions: 1- Can I use many times $hFile = _CommAPI_OpenCOMPort($iPort, $iBaud, $iParity, $iByteSize, $iStopBits) on the same serial port, for example, to change baud, or you recomend close and open it again? 2- Can I declare $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc"), so if an error like "port does not exists", or whatever other error could be traped, like at this exampe: Func MyErrFunc($oError) ..... $msgError = "error at module "& $oError.source &@cr & " - description: " & StringStripWS($oMyError.description, 3) &@cr _ & " - error: " & Hex($oMyError.number, 8) &" : "& $oError.retcode &@cr _ & " - script line: " & $oMyError.scriptline &@cr _ & " - descr.Windows: " & $oError.windescription .... msgBox (4096, "error detected during execution", $msgError) Jose Edited October 30, 2013 by joseLB
joseLB Posted October 31, 2013 Posted October 31, 2013 (edited) Hi therealhanuta Up to now the routines are working great! Not all tests yet... I will post here some tips in receiving binary data thru a serial port. I hope it can help someone.. First, what is a binary stream? As an example, a microcontroler (PIC) getting data thru ADC and sending the 2 adquired bytes straight thru serial, without any treatment. Now supose your message has: 1 letter(A-Z) + 4 ADC values + 3 counters of anything (each one byte). Your message will arrive with 1 + 4 x 2 + 3 = 12 bytes (or as AU3 sees it, string with 12 "chars"). $sResult = _CommAPI_ReceiveData($hFile) will have at $sResult a "string" with 12 "chars". besides the first one, each of these chars are byte values. On them can exist binary value 0. So, it´s vital that 0 be not interpreted as XOFF by receiver (PC) now let´s separate the 1 + 4 + 3 = 8 fields field1= StringMid($sResult,1,1) ;this is just a characterbetwen A-Z field2= ASC(StringMid($sResult,2,1)) ;LSB of the ADC value. First byte = LSBb, 2nd. byte = MSB field2= field2 + ASC(StringMid($sResult,3,1))*256 ;MSB of the ADC value - now field2 is a number, betwen 0-65535 ;field3..5 are similar to field 2, just increase by one the start position in stringMid field6= ASC(StringMid($sResult,10,1)) ;now field6 a "number" betwen 0-255 ;filed7-8 are similar to field 6, just increase by one the start position in stringMid Edited October 31, 2013 by joseLB
joseLB Posted October 31, 2013 Posted October 31, 2013 Hi therealhanuta Using an usb-to-serial converter (prolific), if, after a sucessful open and loop reading data ok, if I remove the usb converter, no error is reported (@error and @extended = 0). That´s the intended behavior? Jose
joseLB Posted November 1, 2013 Posted November 1, 2013 (edited) This very very simple and TESTED example to show basic usage of CommAPI or to test your serial connection (CommAPI works like a charm) It needs a terminal emulator, like putty, on your pc (with a loopback cable= pins 2<->3) or a emulator in another PC with cross cable ( pins 2 <->3 and 3<->2) It asks at terminal emulator to type something and shows what was typed 3 seconds later. Typing ... (3 dots) terminate the program. Tested with a USB - serial converter (prolific) at 9600 cross cabled to another PC with putty terminal emulator Jose #include "CommInterface.au3" Global Const $iPort = 6 ;============== > CHANGE HERE TO THE PORT YOU ARE USING ================== Global Const $iBaud = 9600 Global Const $iParity = 0 Global Const $iByteSize = 8 Global Const $iStopBits = 0 $x=_CommAPI_GetCOMPorts() ;get a string with all your serial ports separated with @CRLF MsgBox(4096,"list of Com Ports",$x) ;show avaiable ports $loop=1 $hFile = _CommAPI_OpenCOMPort($iPort, $iBaud, $iParity, $iByteSize, $iStopBits) $x= _CommAPI_ClearCommError($hFile) Do _CommAPI_TransmitData($hFile, @crlf&"type anything (... = end):") ;send prompt sleep (3000) ;user have up to 3 seconds to type something $digitado= _CommAPI_ReceiveData($hFile) ;get typed string _CommAPI_TransmitData($hFile, @crlf&"-->" & $digitado) ;echoes to serial what was typed above ToolTip($loop & $digitado) ;shows in tooltip typed chars, preceded by number of iterations $loop=$loop+1 Until $digitado= "..." ;if user types ... (3 dots) program finishes _CommAPI_CLosePort($hFile) Exit Edited November 1, 2013 by joseLB
therealhanuta Posted November 4, 2013 Author Posted November 4, 2013 1- Can I use many times $hFile = _CommAPI_OpenCOMPort($iPort, $iBaud, $iParity, $iByteSize, $iStopBits) on the same serial port, for example, to change baud, or you recomend close and open it again? No, you have to close port before you can use _CommAPI_OpenCOMPort again. Instead of this you can use function _CommAPI_ChangeCommStateElement. Or you can use _CommAPI_BuildCommDCB in combination with _CommAPI_SetCommState. 2- Can I declare $oMyError = ObjEvent("AutoIt.Error", "MyErrFunc"), so if an error like "port does not exists", or whatever other error could be traped, like at this exampe: No, because I use only DLL calls and no COM object. You habe to check @error after every function. Using an usb-to-serial converter (prolific), if, after a sucessful open and loop reading data ok, if I remove the usb converter, no error is reported (@error and @extended = 0). That´s the intended behavior? I would expect, that @error is set when you try to transmit or receive data. Unfortunately I habe no USB-to-serial converter to test this.
joseLB Posted November 5, 2013 Posted November 5, 2013 Hi therenauta Thanks for your answers I hope i´m wrong, but here follows one more observation / question. Seems to me that only when you have an active _CommAPI_ReceiveData command, PC is able to receive data thru serial, discarding all messages that arrive during the period you do not have an active _CommAPI_ReceiveData command. In other words: you give an _CommAPI_ReceiveData. I suppose that it "waits" for a message to arrive during "timeout"(default=100ms). After that program continues it´s execution doing other stuff. If new messages arrives before another _CommAPI_ReceiveData all that data is ignored? My suspection is due to one part of program where: - give _CommAPI_TransmitData to send a command to an external device - this message can take up to 10 seconds to be executed, and nothing else will be done by the device - so, during this time PC is doing other stuff (or in sleep) - after > 10 secs, PC issues _CommAPI_ReceiveData - but nothing comes, and I know that the message arrived. Thanks Jose
saget Posted December 9, 2013 Posted December 9, 2013 wow, thanks for sharing, i have been using COMMGvv2 [by Martin Gibson] for years. And, the only bug for COMMMGvv2 is it seems not handling error package very well. i will try urs in my appliaction!~
nend Posted December 31, 2013 Posted December 31, 2013 Thanks for this UDF. I used it now for a while and it works great.
CountyIT Posted January 2, 2014 Posted January 2, 2014 There was a third UDF using kernel32 I downloaded maybe a year and a half ago. I saw it two days ago but can't find it again. It was 90% complete and one of the last threads was to the effect would anyone have an interest in developing it further. Anyway.... it was very, very similar to this one therealhanuta but yours seems a whole lot more complete and polished. The problem, as mentioned above, is that there aren't any examples. Just the basics would be a huge help. Open, send, receive and close would be a huge, huge help. Any chance of getting some examples?
therealhanuta Posted February 3, 2014 Author Posted February 3, 2014 Anyway.... it was very, very similar to this one therealhanuta but yours seems a whole lot more complete and polished. The problem, as mentioned above, is that there aren't any examples. Just the basics would be a huge help. Open, send, receive and close would be a huge, huge help. Any chance of getting some examples? Here you can find some examples, now.
sulfurious Posted February 20, 2014 Posted February 20, 2014 I've got a question if someone might be able to help. I've built a small app to read an MSR for a cash register. It works with track2 of a gift card and the end result is to read the number, query a website and get a balance. Anyway, the MSR is an idtech idmb-3321 rs232 reader. It comes with a utility to modify settings within the MSR. The issue is that if I start the utility and connect to the MSR, my code gathers the output of a card swipe without issue. Depending on the settings of the MSR that might include STX/ETX or not, or whatever I want to format it as pre/post fix or terminations, etc. It works fine though, as long as I parse the text to my likings. However, if I don't start the config util, my app does not work. It is also interesting in that if I start hyperterminal, read the swipe, then shut hyperterminal down, my app will read it just fine. Its like there is a driver needed or a service, but I did not think rs232 needed a driver. This is on win7 ult x32, and the hyperterminal is missing from win7, so I used hyperterm .exe and .dll from winxp. I've looked at the idtech website, and they say there is no driver for rs232. Of course for usb2rs232 there are. I get no errors in the code. The handle is good. As a matter of fact, what is returned is DC3 (BE. After running hyperterm or the config utiity, it works perfectly. I tried raw mode in the MSR, but there is some decoding there that I don't understand, although the output is readable without running hyperterm or the config utility. The settings are: port 1 baud 9600 parity 0 stop bits 1 byte size 8 handshake XonXoff Any ideas?
sulfurious Posted February 20, 2014 Posted February 20, 2014 I tried it on a couple xpsp3 machines, it does the exact same thing. Run HT once, and it is fine. Otherwise, it does not get the data sent. Interestingly here is a post that describes what is happening, with a reply that just figures lol http://answers.microsoft.com/en-us/windows/forum/windows_7-hardware/initialize-serial-port/a9fa325b-fafc-44b1-b7c1-9501c1dca09b I've searched init/initializing com/serial ports, but found nothing. I have no idea what the issue might be really. Anyone?
therealhanuta Posted February 20, 2014 Author Posted February 20, 2014 Hi sulfurious, there are 3 useful tools.that I use: command MODE in command line (it shows you the current settings of COM ports) HTerm as a better HyperTerminal (German developer site, but English GUI) Null-modem emulator com0com (virtual serial port driver for test purposes) First, try following steps: run MODE run HyperTerminal run MODE again compare both results if there is a different, this is the solution If there is no different, try application HTerm. Play with options "CTS Flow control", DTR and RTS.
adom Posted March 7, 2014 Posted March 7, 2014 (edited) Hello, I am just working on understanding of CommAPI. Can anybody explain to me which meaning has the parameter 15: _CommAPI_PurgeComm($hFile, 15) And What is the meaning of "5000" ? Local $sResult = _CommAPI_ReceiveData($hFile, IniRead($sFileINI, "Timeout", "IDSR", 5000)) I found this in commInterface.au3. In my view Timeout and Buffer is mismatched. ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CommAPI_ReceiveData ; Description ...: Receives data (RxD/RX/RD) to a specified communications device. ; Syntax ........: _CommAPI_ReceiveData(Const $hFile[, $iMinBufferSize = 1[, $iMaxWaitTime = 100]]) Thanks and greetings Andrew Edited March 7, 2014 by adom Thanks! :bye: Greetings Andrew
adom Posted March 7, 2014 Posted March 7, 2014 Hello, I suppose I have found some not-logical in sample code: Call string: Local $sResult = _CommAPI_ReceiveData($hFile, 500) error: _CommAPI_ReceiveData() called with wrong number of args. ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CommAPI_ReceiveData ; Description ...: Receives data (RxD/RX/RD) to a specified communications device. ; Syntax ........: _CommAPI_ReceiveData(Const $hFile[, $iMinBufferSize = 1[, $iMaxWaitTime = 100]]) ; Parameters ....: $hFile - [in] A handle to the communications device. ; Return values .: Success - Received string ; Failure - Empty string ; Author ........: ; Modified ......: ; Remarks .......: If the result contains Chr(0), you should convert the result with function Binary(). ; Related .......: _CommAPI_TransmitData ; Link ..........: ; Example .......: No ; ===============================================================================================================================Func _CommAPI_ReceiveData(Const $hFile) ; only one Parameter!!!!!!!!!!!!! Local $tBuffer = DllStructCreate("char") Local $iWritten = 0 Local $sResult = "" Do _WinAPI_ReadFile($hFile, DllStructGetPtr($tBuffer), 1, $iWritten) If @error Then Return SetError(@error, 0, $sResult) If $iWritten Then $sResult &= DllStructGetData($tBuffer, 1) Until Not $iWritten Return $sResult EndFunc ;==>_CommAPI_ReceiveData Has anybody knowledge to clarify this? THX Greetings Andrew Thanks! :bye: Greetings Andrew
adom Posted March 7, 2014 Posted March 7, 2014 Hello, I have a work to do with Serial communication: If the receiver wants to send to my PC more than one telegram lets say 10 telegrams with each a <CR> at the end of telegram. The <CR> should tell me that after it a new telegram starts. Now the problem: How can I recognize these <CR> with Local $sResult = _CommAPI_ReceiveData($hFile) ? Any idea is welcome. Greetings Andrew Thanks! :bye: Greetings Andrew
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