Jump to content

Serial Port /COM Port UDF


martin
 Share

Recommended Posts

Mark,

The dll will set any baud rate less than 2000000 (2MBaud). Most devices won't operate anything like fast. The hardware in the sender and the receiver will determine the maximum speed you can use. It looks like I should have set <= 2000000 but I find it hard to believe a serial port will work reliably at that speed if at all and I very much doubt a PC can deal with it.

You can easily add other baud rates to the sample script by adding them in the GuiCtrlSetDat line after $CmboBaud = GuiCtrCreateCombo.

Apart from restricting the baud rates in my sample app, if you tell me what other annoyances there are I will think about whether to change the example; it has never had much attention from me.

I had no problem making the changes, I just didn't know if there were any limits in the DLL for maxbaud. I have tested the dll to 1M. I have a USB/serial uart that can talk to a micro at up to 2mbs. The project uses non-standard baud rates with a common divisor. I will test @ 2M later in the project (I really don't need but 1M for the current project I am working on) (Monitoring a HS-CAN network in a car)

Here is the changelog and I have attached the modified version of the sample app. The example/sample was a great starting point! I do need to look at the strip lf checkbox, from a quick scan I think the UI is there, but the code is commented out. (I moved on)

;Version 2.1 21th June 2011

;changes-

;Added $progname variable and utilized in all titles.

;bugfix - version of dll shown as unknown until port setting menu closed.

;changed output window to courier font. Monospaced fonts easier to read if data is lined up in terminal output.

;changed - removed sorting of baud rate in drop down window. Sorting was from left character, not from numeric value.

;changed/added additional "standard baud rates": 300, 230400, 460800, 921600 as well as 1000000 and 2000000 (Tested to 921600)

;bugfix - only display error message box if error exists.

;bugfix - fixed spelling of "quit" from "quite"

Thank you again for your work and attention!

Mark Cheavens

CommgExampleA.au3

Link to comment
Share on other sites

It looks like I should have set <= 2000000 but I find it hard to believe a serial port will work reliably at that speed if at all and I very much doubt a PC can deal with it.

FTDI makes USB to UART devices that can do UART at up to 12Mbaud.

http://www.ftdichip.com/Products/ICs/FT232H.htm

(But then again, you could always use their D2XX drivers if you're using that part.)

However, I agree that you probably want to implement HDLC on top of UART if you're using it that fast.

Edited by dpryan
Link to comment
Share on other sites

  • 4 weeks later...

Hi,

I use the commg to communicate with a device, but when I want to use the timeout functionality, it crash when the timeout come.

The windows (Windows XP pro SP3) report crash is:

AppName: autoit3.exe

AppVer: 3.3.7.14

ModName: kernel32.dll

MpdVer: 5.1.2600.5781

Offset: 00012afb

And the crash is in function _CommReadByte inside the call of the DLL.

A simple program to test:

#include <CommMG.au3>

const $iTimeOut = 10000
Local $sportSetError = ""
local $char

local $log = FileOpen("Log.txt", 1)

FileWrite($log, "App Start" & @CRLF)
_CommSetPort(1, $sportSetError, 9600, 8, 0, 1, 2)
if $sportSetError = "" then
    FileWrite($log, "COM1 open" & @CRLF)
    _CommSetTimeouts($iTimeOut, $iTimeOut, 0, $iTimeOut, 0)
else
    FileWrite($log, "Error opening COM1" & @CRLF)
endif

do
    $char = _CommReadByte(1)    ; Crash if set to 1 but doesn't if set to 0
    if $char = "" then
        if @error > 1 then
            FileWrite($log, "E" & @error & "E")
        endif
    else
        FileWrite($log, $char)
    endif
until $char = 13    ; @CR to end

_CommClosePort()
FileWrite($log, "App Stop" & @CRLF)

How can I solve this?

Thank you.

Link to comment
Share on other sites

To temporarily solve my crash, I have change the code for the function _CommReadByte to this:

Func _CommReadByte($wait = 0)
    Local $iCount, $vDllAns
    If Not $fPortOpen Then
        SetError(1)
        Return 0
    EndIf


    If Not $wait Then
        $iCount = _CommGetInputCount()
        If $iCount = 0 Then
            SetError(1)
            Return ''
        EndIf
    ;Patch for crash timeout
    ;EndIf
    else
        local $time = TimerInit()
        do
            $iCount = _CommGetInputCount()
        until (TimerDiff($time) >= $timeOut) OR ($iCount > 0)
        if ($iCount = 0) then 
            SetError(1)
            Return ''
        EndIf
    EndIf
    ;End patch

    $vDllAns = DllCall($hDll, 'str', 'GetByte')

    If @error <> 0 Then
        SetError(2)
        Return ''
    EndIf
    ;mgdebugCW('byte read was ' & $vDllAns[0] & @CRLF)
    Return $vDllAns[0]

EndFunc   ;==>_CommReadByte

And add a global variable (Global $timeOut = 0) to store the timeout set in function _CommSetTimeouts

Link to comment
Share on other sites

I don't know much about serial ports so please excuse me if this is a dumb question. Is the included example anything like a terminal emulator? If it isn't then how do I do things like set com ports and baud rates? Oh, I see commsetport.

Let me expand my question a little bit. I have an OBDII scan tool that hooks into a usb port. Can I use this UDF to talk to it? I need to be able to set the com port to 4 and the baud rate to 10400 something else to 8 and some other things which escape me. WOuld this be possible with this udf?

Edited by LaCastiglione
Link to comment
Share on other sites

To temporarily solve my crash, I have change the code for the function _CommReadByte to this:

Func _CommReadByte($wait = 0)
    Local $iCount, $vDllAns
    If Not $fPortOpen Then
        SetError(1)
        Return 0
    EndIf


    If Not $wait Then
        $iCount = _CommGetInputCount()
        If $iCount = 0 Then
            SetError(1)
            Return ''
        EndIf
    ;Patch for crash timeout
    ;EndIf
    else
        local $time = TimerInit()
        do
            $iCount = _CommGetInputCount()
        until (TimerDiff($time) >= $timeOut) OR ($iCount > 0)
        if ($iCount = 0) then 
            SetError(1)
            Return ''
        EndIf
    EndIf
    ;End patch

    $vDllAns = DllCall($hDll, 'str', 'GetByte')

    If @error <> 0 Then
        SetError(2)
        Return ''
    EndIf
    ;mgdebugCW('byte read was ' & $vDllAns[0] & @CRLF)
    Return $vDllAns[0]

EndFunc   ;==>_CommReadByte

And add a global variable (Global $timeOut = 0) to store the timeout set in function _CommSetTimeouts

jtredez,

You are correct that the _CommReadByte function was faulty if timeouts were set. I believe that I have now corrected this with a change to the dll and the UDF. These can now be downloaded from the link in the first post. The _commReadByte function returns a string which is normally 1 character long. If @error is set then the returned string will have details of the error, eg "Timeout".

Apologies for this mistake. I believe that _CommReadByteArray is already correctly written to avoid a crash on timeouts.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

I don't know much about serial ports so please excuse me if this is a dumb question. Is the included example anything like a terminal emulator? If it isn't then how do I do things like set com ports and baud rates? Oh, I see commsetport.

Let me expand my question a little bit. I have an OBDII scan tool that hooks into a usb port. Can I use this UDF to talk to it? I need to be able to set the com port to 4 and the baud rate to 10400 something else to 8 and some other things which escape me. WOuld this be possible with this udf?

This should work fine and people are already using the UDF for scanners.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Really?! I searched but only found one thread. I'll do it again.

Not so sure actually, it could be I'm thinking of discussions I've been involved in about barcodes and could be nothing to do with my COM port udf. I think many barcode scanners act like keyboard inputs don't they? In which case you wouldn't need to use my udf. Otherwise I would expect that my udf would be able to read the scanner input. The 10400 baud setting is an optional setting in the example with the udf download.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

I don't know much about barcode scanners. I believe this scan tool uses a serial to usb converter. Like I say I don't know much about this serial stuff. I set all of the settings correctly but I can't get it to communicate. Meh, I'll look into it and if any body has any info please fill me in. Thanks Martin.

Link to comment
Share on other sites

Thank you martin, now it works perfectly, I receive the timeout notification and it doesn't crash anymore.

jtredez,

You are correct that the _CommReadByte function was faulty if timeouts were set. I believe that I have now corrected this with a change to the dll and the UDF. These can now be downloaded from the link in the first post. The _commReadByte function returns a string which is normally 1 character long. If @error is set then the returned string will have details of the error, eg "Timeout".

Apologies for this mistake. I believe that _CommReadByteArray is already correctly written to avoid a crash on timeouts.

Link to comment
Share on other sites

I got it to communicate using your commgexample!

I realize that I was a little vague in my previous description. I was trying to communicate with an OBD scanner. OBD means On Board Diagnostics (I don't know if this is found outside of North America). OBD is a standard method of communicate with a vehicle's computer. This way you can retrieve Check Engine codes, see the RPMs, oxygen sensor readings, etc.

Anyway, my mistake was that I was trying to communicate with the OBD scanner at the same baud rate at which the scanner communicates with the car's computer!

Link to comment
Share on other sites

I got it to communicate using your commgexample!

I realize that I was a little vague in my previous description. I was trying to communicate with an OBD scanner. OBD means On Board Diagnostics (I don't know if this is found outside of North America). OBD is a standard method of communicate with a vehicle's computer. This way you can retrieve Check Engine codes, see the RPMs, oxygen sensor readings, etc.

Anyway, my mistake was that I was trying to communicate with the OBD scanner at the same baud rate at which the scanner communicates with the car's computer!

Glad you succeeded.

We have OBD in Europe too but I didn't realize what you meant because I homed in on the "scanner" word and my mind interpreted it as a barcode reader.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Hi Martin,

Finaly I got some error with the last version (2.84).

I send a string to the serial port with _CommSendString("message", 1) and wait the answer with $received = _CommGetLine(@LF, 100, 5000).

On the last version I doesn't receive anything, so I check what's wrong and found it works if I put in comment the end of _CommReadByte function like this :

#cs
    if StringLen($vDllAns[0]) > 1 then
        Return seterror(1,0,$vDllAns[0])
    EndIf
#ce

I don't see why you return an error if the len of the received string >1 (not present in the previous version) but without this it works.

Also I add "#include-once" at the first line of the file to avoid problem when used in my project (two different drivers that use the commg driver).

Just to informe you, I use the new _ComGetPortNames function (not present in the list of start of file) and it works fine.

Jerome

Edited by jtredez
Link to comment
Share on other sites

Hi Martin,

Finaly I got some error with the last version (2.84).

I send a string to the serial port with _CommSendString("message", 1) and wait the answer with $received = _CommGetLine(@LF, 100, 5000).

On the last version I doesn't receive anything, so I check what's wrong and found it works if I put in comment the end of _CommReadByte function like this :

#cs
    if StringLen($vDllAns[0]) > 1 then
        Return seterror(1,0,$vDllAns[0])
    EndIf
#ce

I don't see why you return an error if the len of the received string >1 (not present in the previous version) but without this it works.

Also I add "#include-once" at the first line of the file to avoid problem when used in my project (two different drivers that use the commg driver).

Just to informe you, I use the new _ComGetPortNames function (not present in the list of start of file) and it works fine.

Jerome

Hi Jerome,

I am not able to test things easily at the moment.

I think your mod might be the wrong thing to do. That makes the timeout error and return of the correct error message fail. I chnaged the dll so that it returned something to indicate the error so there was no need to check if the result was longer than one charactee before.

Perhaps the problem is more to do with _CommGetLine or _CommReadChar. I should have set the value of @error 3 on a timeout error in _CommReadByte rather than 1, and checked how other functions deal with it.

When I get a chance to investigate it I will get back.

I'll add the _ComGetPortNames to the list of functions, thanks for telling me it was missing. It was written by funkey.

I'll also add #include-once as well - another slip.

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Hi Martin, new to all this so learning as I go along. I've managed to use your UDF to communicate to an Arduino development board to control a Servo Motor using the _CommSendByte($Value) function.

My problem is I need to output to multiple servos, Leds etc (These are almost all of float type), Servos will be used for dials in the 0 to 270 degree range.

Hence the need for Float types as I require at least one decimal place resolution. :)

//Read values that need to be sent via serial
$Value = Read_Value ()
$Value1 = Read_Value2 ()
$Value2 = Read_Value2 ()
$Value3 = Read_Value3 ()
$Value4 = Read_Value4 ()
$Value5 = Read_Value5 ()
$Value6 = Read_Value6 ()
$Value7 = Read_Value7 ()
$Value8 = Read_Value8 ()
.......... // Upto 50 Values (Mostly Float)

//Send values via serial
_CommSendByte($Value, $Value1, $Value...... $Value50) <------ What to use here to send multiple float values???

Not sure what to use to send float values via your UDF would _CommSendByteArray work?

Thanks Martin

Edited by reaper7
Link to comment
Share on other sites

this had the text was messed up somehow.

It is replaced with post #399 below

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Hi reaper7,

I need to know more about how the Arduino board expects to receive data before I can answer your question. Maybe you can can provide a short explanation or a link which will give me a quick overview.

Can you send the values with a terminal emulator? If so then you only need _CommSendString which would make it much simpler.

If you do need to send bytes for each value then I assume that you need to send 4 bytes for each value. There must be some way to indicate the start and end as well.

You can send a single float value like this if the Arduino has the same way of storing a float

$sf = Dllstructcreate("float")
$psf = dllstructgetptr($sf)
$f1 = 26.9
dllstructsetdata($sf,1,$f1)
_CommSendByteArray($psf,4,1)

It could be you need to reverse the order of the bytes so you can do this

$sf = Dllstructcreate("float")
$psf = dllstructgetptr($sf)

$sb = DllStructCreate("byte;byte;byte;byte", $psf);array of bytes but in same memory location as the float

$srf = Dllstructcreate("byte;byte;byte;byte");to hold the reversed bytes<br>$psrf = DllStructGetPtr($srf)

for $h = 1 to 4
    DllStructSetData($srf,$h,dllstructgetdata($sb,5 - $h))
Next


_CommSendByteArray($psrf,4,1)

Or to send all 50 values at once you could have

$sf = Dllstructcreate("float[50]")
$psf = dllstructgetptr($sf)

for $n = 1 to 50
    dllstructsetdata($sf,1,$Value[$n],$n)
Next

_CommSendByteArray($psf,4*50,1)
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Hi Martin,

Sometime I have a popup window with title=Autoit3.exe and message=Timeout.

I doesn't have this message in my program, is it in the library?

Thank you

Whoops, yes, I thought I commented that out. Give me a few minutes and I'll fix it.

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...