Jump to content

Serial Port /COM Port UDF


martin
 Share

Recommended Posts

I'm in a hotel room with a very slow link, so forgive me if I'm posting this to the wrong place. I'm not near my code nor an AutoIt3 installation, so I can't reproduce my exact code or even the exact Commg function name.

I'm using commg in an application working with a Redbee RFID reader, and everything is working just fine except my .exe file keeps hogging all the cpu time (shown in Task Monitor/Services.

Code snippet:

--------------

while 1

sleep(200)

$data = _commg_getline(...,2000) ; I know this isn't the actual syntax except for the last parameter.

"parse data"

wend

--------------

The rest of the code is all event driven from GUI controls. I've played with the sleep() parameter which doesn't change the CPU utilization. I'm guessing the getline is the problem, since the utilization is a problem with no incoming traffic.

My goal is to process whole "lines" of asynchronous input.

Is there a better way to handle this? My next try is to read strings instead of lines, contcatenate them, and wait for a @CR within the string?

In the UDF have a look at the _CommGetLine function. There is a while loop where the next character is read until either the end character is read or the maximum length string is reached or the maximum time has elapsed. This is the only place I imagine the CPU usage might be high, so try adding a sleep at the end of the while loop, say sleep(20), and see if it helps.

If that does help please let me know because I wasn't aware that the _CommGetLine function caused a problem and I'll change 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

I'll be able to try that today. What would be really cool (for this app) would be a Comm_getstring "event"

I put a sleep(20) just before the "wend" line, and things are much better. Can't see any CPU utilization at all. Thanks Martin!

Link to comment
Share on other sites

I put a sleep(20) just before the "wend" line, and things are much better. Can't see any CPU utilization at all. Thanks Martin!

OK. Thanks for letting me know jimg. I'll make that change to the UDF and see if the same needs to be done in other functions.

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'll be able to try that today. What would be really cool (for this app) would be a Comm_getstring "event"

Yes, an event driven version of the UDF would be nice. Maybe next year:).

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

To anyone running x64 OS you will need to right click on your script and select to run in x86 mode. If you compile your script you can also right click and compile in x86 mode.

For anyone running Windows 7 you will need to right click on the .dll and select UNBLOCK.

Now that I got that out of the way I am having a slight issue.

I noticed when running my app grabbing an input from the serial port every 1 second there appears to be a large amount of CPU use needed (25%).

Now 25% might not seem like that much but this is 25% on a Phenom II Quad 965, so 25% is insane for a script like this. I changed my script to read from a text file instead and I have another script writing values into that text file every minutes to simulate similar actions without the .dll. The CPU was normal and didn't even blip 1%.

I then ran the Demo app that the original poster made and same thing, 25% cpu usage. Maybe this is just an x64 thing I don't know, I am going to run it in my XP mode VM later today and see what happens. I didn't know in the mean time if anyone has noticed this or checked into it.

~~--Feel Free to Steal my Sigs --~~FLAT LOOK____________________________________ROUNDED LOOK

Link to comment
Share on other sites

Looks like someone right before posted the same thing, I will check to see if the sleep has been added to the file I have and if not I will add it to see if it makes a difference.

~~--Feel Free to Steal my Sigs --~~FLAT LOOK____________________________________ROUNDED LOOK

Link to comment
Share on other sites

To anyone running x64 OS you will need to right click on your script and select to run in x86 mode. If you compile your script you can also right click and compile in x86 mode.

For anyone running Windows 7 you will need to right click on the .dll and select UNBLOCK.

Thanks for those notes burners. I'll add a loink in the first post.

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

Martin I added the sleep to the CommMG file and that didn't solve the issue with the example but after adding a sleep 20 to the Example file you supplied on line 20 I was able to get the CPU usage down to 3%.

If I increase the sleep to 200 it will drop to 0% CPU. I have ran my test file after the change in the CommMG file and it appears to be a TON better with the minor sleep added. I dont even see my app go over 0% which is correct.

I know before the change was made this would have killed an older single threaded processor.

Now the next annoying issue is to figure out a way to get the app to NOT crash when it tries to return an Array variable thats no longer an array because the value didn't update in the time it was REGEX'd.

In other words here is my input

$serialstringin = _CommGetLine('þ„',0,1000)
$serialstringout = StringRegExp($serialstringin, "(?<=þ„)....", 2)
Global $input1 = $serialstringout[0]

But AIT gets ANGRY when _CommGetLine returns null and then StringRegExp fails which then makes $serialstringout[0] no longer an array ;)

Edited by burners

~~--Feel Free to Steal my Sigs --~~FLAT LOOK____________________________________ROUNDED LOOK

Link to comment
Share on other sites

Ah I was able to resolve the error issue with this, not that this is related at all but figured I'd give an update

Do
$serialstringin = _CommGetLine('þ„',0,1000)
$serialstringout = StringRegExp($serialstringin, "(?<=þ„)....", 2)
sleep(10)
Until @error <> 1

Global $input1 = $serialstringout[0]
Edited by burners

~~--Feel Free to Steal my Sigs --~~FLAT LOOK____________________________________ROUNDED LOOK

Link to comment
Share on other sites

Ah I was able to resolve the error issue with this, not that this is related at all but figured I'd give an update

Do
$serialstringin = _CommGetLine('þ„',0,1000)
$serialstringout = StringRegExp($serialstringin, "(?<=þ„)....", 2)
sleep(10)
Until @error <> 1

Global $input1 = $serialstringout[0]

_CommGetLine returns a string which ends in the character given in the first parameter, or the maximum length or maximum time is reached. If you supply a string longer than a single character then it won't ever trigger the end of the line so the function will return when the maximum length or time is reached. If you want to detect a group of characters like "b,," you will need to modify the _CommGetLine function.

In your code @error will never be 1 because sleep(10) will reset @error to 0 so the Do/Until loop is doing nothing. It would be better to test for $serialstringin being an empty string before using stringregexp perhaps.

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

_CommGetLine returns a string which ends in the character given in the first parameter, or the maximum length or maximum time is reached. If you supply a string longer than a single character then it won't ever trigger the end of the line so the function will return when the maximum length or time is reached. If you want to detect a group of characters like "b,," you will need to modify the _CommGetLine function.

In your code @error will never be 1 because sleep(10) will reset @error to 0 so the Do/Until loop is doing nothing. It would be better to test for $serialstringin being an empty string before using stringregexp perhaps.

Yeah I caught that shortly after I posted it, the sleep was in the wrong spot. Everything is working good now

Do
sleep(10)
$serialstringin = _CommGetLine('þ„',0,1000)
$serialstringout = StringRegExp($serialstringin, "(?<=þ„)....", 2)
Until @error <> 1

Global $input1 = $serialstringout[0]

Whats going on is I grab the serial input which is "þ„" followed by 3-4 digits from a PC fan read by an Arduino like so "þ„1983",

The reason for the "þ„" is because this is the serial command used to reset the screen on the LCD. I am going to change the LCD so its on a different pin to get rid of this in the future, I seen Arduino has a library which does this, it looks like it just bit bangs output / input pins for serial communication since the model I am using only has 1 set of serial communication pins.

So basically I had to find a way to chop the "þ„" from the serial input while keeping the 3-4 digit numbers which is what the StringRegExp is used for. Now if for some reason the _CommGetLine didn't return the input in time the StringRegExp would fail and return 0 which is not an array so the variable "$serialstringout[0]" is no longer valid and it would crash the app completely. I first ran into this when parsing Fortinet config files and when the wrong String was returned it would do the same thing.

To see what I used this for so far check out this thread.

http://www.autoitscript.com/forum/index.php?showtopic=121086

I have much bigger plans in the future, I need to get an Arduino Mega and a few other things and then I can complete my 12 Fan / 12 Sensor PC Fan Speed Controller with automated temperature monitoring and action based on temps and user settings.

Their will be monitoring and control available through both the LCD and 6-way touch pad + the PC software I am making.

A quick run down of the capabilities and what makes the device I am making different than what you can buy right now

-High power mosfets, maximum wattage draw of outputs will support multiple high power water pumps

-Monitoring of RPM on 6 devices including Fans & Water pumps

-Speed control through PWM on up to 14 devices (Fans, Lights, Water Pumps)

-Monitoring of temperature on up to 16 devices

-Additional On/Off action based (temp, rpm, user input, PC power supply) switching for up to 10 devices

-Serial to USB output for control and monitoring on PC

-Serial output to 2 or 4 line LCD for monitoring and control of sensors and fans

-6-way or 7-way touchpad for external control of the setup through the LCD

I have most things done

RPM Reading

LCD display

Temp Reading

PWM Control with circuits designed

Serial Communication with PC

~~--Feel Free to Steal my Sigs --~~FLAT LOOK____________________________________ROUNDED LOOK

Link to comment
Share on other sites

  • 3 weeks later...

Hi,

I have a problem with that UDF. I find the note to unblock the .dll but I have no Button in the file attributes. When I try to set a Port or do something else I get the error "Failed to open commg.dll". I have put a copy of it in the Incude folder of AutoIt and in the ScriptDir as backup. Maybe someone can help me with that issue, it seems to be the only way to COM-Port.

OS: Win7 64 bit

MfG DaRe

Link to comment
Share on other sites

There is no 'unblock' menu item (or attribute for that matter) available for DLL files.. not sure where the heck that idea came from.

Link to comment
Share on other sites

Okay nice to know but what can I do instead to make it run? =/

In W7 maybe a dll which is not registered and not installed in a program folder might get blocked by the OS, so unblocking it makes sense to me, though my knowledge of W7 is low. But I assume that if there is no unblock button then either it doesn't need to be unblocked or it can't be unblocked.

My small experience of W7 has shown some strange characteristics of the inbuilt safety features. If a program can't be run without the user being asked for confirmation that you want to allow the program to make changes, then all you have to do is to rename the program and confirm that you want to do that and it can be run without any prompts. So try the same with the dll. Copy it to a program folder say, then rename it to something like CommgB.dll and use the function _CommSetDllPath to specify the dll full path BUT I see there is an error in the SetPort function. You must replace

$hDll = DllOpen('commg.dll')

with

$hDll = DllOpen($DLLNAME)

or the _CommSetDllPath function won't work.

The dll is 32 bit so you must compile your script for 32 bit as stated in the first post so maybe that is the problem.

If you still have problems post some sample code.

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

*edit: I just realized the COM functions are part of the standard API functions (here on MSDN: 'Communication Functions (Windows)'). No need to do much other than recompile the DLL as 64-bit to give that functionality. (make sure everything is not hardcoded for certain sizes though of course)

Edited by Ascend4nt
Link to comment
Share on other sites

Hi Martin,

Started to look at this as I need to talk to some production tools at work.

Found a bug.

Scenario. Open 2 COM ports. Shut down 1 COM port, _CommReadByte from the remaining COM port.

This causes AutoIt to crash.

This works. Open 2 COM ports. Shut down 1 COM port, try and _CommGetString from the remaining COM port.

So the issue seems to be with the _CommReadByte

#include "CommMG.au3"
;2 ports COM 5 and COM 6
$Err = ""
$newsFile = @Scriptdir & "\debug.log"
News("Availble ports :" & _CommListPorts() )
;setup com port 5
_CommSwitch(5)
_CommSetPort(5, $Err)
If $Err = "" Then
    News("Com port " & "5" & " opened correctly")
Else
    News("Error opening port :" & $Err)
EndIf
_CommSwitch(6)
_CommSetPort(6, $Err)
If $Err = "" Then
    News("Com port " & "6" & " opened correctly")
Else
    News("Error opening port :" & $Err)
EndIf
;OK we now have ports set up correctly lets do a poll for data
_CommSwitch(5)
News("Start to read byte from Com 5")
 $rtn =  _CommReadByte() ; expecting a blank return - that is OK - I have got nothing connected up
 news("Return from Com 5:" & $rtn)

_CommSwitch(6)
News("Start to read byte from Com 6")
 $rtn =  _CommReadByte() ; expecting a blank return - that is OK - I have got nothing connected up
 news("Return from Com 6:" & $rtn)
 ;I am expecting script to still be alive.
News("Close down Com 5")
_CommSwitch(5)
_CommClosePort()
News("Availble ports :" & _CommListPorts() )
;now read data from Com 6
_CommSwitch(6)
News("Start to read byte from Com 6")
 $rtn =  _CommReadByte() ; expecting a blank return - that is OK - I have got nothing connected up
 news("Return from Com 6:" & $rtn)

Func News($x)
    FileWriteLine($newsFile, @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & ":" & @MSEC & " :" & $x)
EndFunc

Log files from my test.

2010/11/11 13:25:35:453 :Availble ports :COM1|COM3|COM5|COM6

2010/11/11 13:25:35:468 :Com port 5 opened correctly

2010/11/11 13:25:35:468 :Com port 6 opened correctly

2010/11/11 13:25:35:468 :Start to read byte from Com 5

2010/11/11 13:25:35:468 :Return from Com 5:

2010/11/11 13:25:35:468 :Start to read byte from Com 5

2010/11/11 13:25:35:468 :Return from Com 6:

2010/11/11 13:25:35:484 :Close down Com 5

2010/11/11 13:25:35:484 :Availble ports :COM1|COM3|COM5|COM6

2010/11/11 13:25:35:484 :Start to read byte from Com 6

At this point AutoIt will crash.

Any thoughts.

Thanks

Steve

Link to comment
Share on other sites

Hi steve8tch,

I've had a quick look and I can see that the function closedown which is called in the dll is completely wrong. It closes all ports one at a time instead of just the currently selected port.

here is a quick attempt at a fix.Can you try it and let me know if it fixes the problem? I don't have the time at the moment.

martin

Edit.

I can't add an attachment for some reason, I'll try sending it to you in a PM.

Edit 2.

No, I can't attach anything to a PM either. I'll put some link in th efirst post.I'll add a link to this post later.

Try this

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

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...