Jump to content
Sign in to follow this  
Keymaker

Chr(0) and rs232 communication

Recommended Posts

Keymaker

Hello forum,

Below is a script I have been writing to control a DirecTV satellite receiver Set Top Box (STB). The STB requires a sequence of Hex bytes be sent to it via rs232 serial. I am using the MScomm object to communicate with the STB.

The problem is the Chr(0) data character. I can send any other data byte fine and the STB responds accordingly. But for some reason Chr(0) does not transmit properly. I do not think it is the MScomm object, as I have tried NetCommX with the same results.

Has anyone found a workaround for this problem yet? I have scoured the AutoIT forums and found a couple of links where others have reported the same issue:

http://www.autoitscript.com/forum/index.ph...0&hl=chr(0).

Unfortunately they did not have have any solutions.

The relevant part of my code is included in this post. In the data array below, the "0x00" byte is not recognized by the STB but all other data bytes are. Also I can send 0x00" using 3rd party serial programs and the STB responds. SO I think it is some quirk with AutoIT.

Regards.

#include <Constants.au3>
#include <string.au3>
#include <Misc.au3>
#include <array.au3>


;----------------------------------------------;
; Make tray item
;----------------------------------------------;
Opt("TrayOnEventMode",1)
Opt("TrayMenuMode",1)
TraySetClick(16)
TraySetIcon(@ScriptDir & "\Images\Transmitting.ico")
$Exit = TrayCreateItem("Exit")
TrayItemSetOnEvent($Exit,"ExitEvent")

;----------------------------------------------;
; Setup Serial Port(s)
;----------------------------------------------;
Local $COM1 = 1
$MsComm1 = ObjCreate("MSCOMMLib.MsComm")
;$MsComm1 = ObjCreate("NETCommOCX.NETComm")
With $MsComm1
    .CommPort       = $COM1 ; Set COM1 port for ... 
    .Settings       = "9600,N,8,1"; 9600 Baud, 8 bits, 1 stop, No parity
    .InputMode      = 0     ; 0 = TEXT MODE, 1 = BINARY MODE
    .Handshaking    = 0
    .InBufferSize   = 512
    .InputLen       = 1
    .PortOpen       = 1
    .NullDiscard    = 0
EndWith 

Dim $satCMD[8]

;---------------------------------------------------------
; TEST program stars here
;---------------------------------------------------------

$satCMD[0] = 7  ; Ch244
$satCMD[1] = "0xFA"
$satCMD[2] = "0xA6"
$satCMD[3] = "0x00"
$satCMD[4] = "0xF4"
$satCMD[5] = "0xFF"
$satCMD[6] = "0xFF"
$satCMD[7] = "0x0D"

;SendSatCommand($satCMD) 
MsgBox(0, "OK", "Response from STB was : " & SendSatCommand($satCMD), 3)

Exit

;----------------------------------------------;
; Satellite receiver command function
;----------------------------------------------;
Func SendSatCommand($CommandArray)
    Local $SUCCESS = 244, $COMMAND_OK = 240, $PARAMETERS_OK = 242
    Local $response
    Const $CMD_TIMEOUT = 500; 500 milliseconds
    
    $i = 0
    Do
        $i = $i + 1
        SatSend($CommandArray[$i])
;MsgBox(0, "", "Command is : " & $CommandArray[$i], 2)
    Until $CommandArray[$i] = "0x0D" ;@CR 
    
; Wait for response 0xF0 = 240 = command acknowledged           
    $time = TimerInit()
    Do
        Sleep(5)
    Until $MsComm1.InBufferCount Or TimerDiff($time) > $CMD_TIMEOUT             
    $response = SatReceive()
    If $response <> $COMMAND_OK Then Return "Error 1  " & $response
            
; Wait for response 0xF2 or 0xF4 = parameters received
    $time = TimerInit()
    Do
        Sleep(5)
    Until $MsComm1.InBufferCount Or TimerDiff($time) > $CMD_TIMEOUT 
    $response = SatReceive()
    If $response = $SUCCESS Then Return "Success!"
    If $response <> $PARAMETERS_OK Then Return "Error 2 " & $response
    
; Wait for the 0xF4 response, "command successful".
    $time = TimerInit()
    Do                                      
        Sleep(5)
    Until $MsComm1.InBufferCount Or TimerDiff($time) > $CMD_TIMEOUT 
    $response = SatReceive()
    If $response = $SUCCESS Or $response = 0 Then Return "Success!"
    Return "Error 3 " & $response
    
EndFunc

;----------------------------------------------;
; Tray function
;----------------------------------------------;
Func ExitEvent()
    Exit
EndFunc

;------------------------------------------------------;
; Serial data ouput function to Satellite receiver
;------------------------------------------------------;
Func SatSend($data)
    With $MsComm1
        .OutBufferCount = 0
        .InBufferCount = 0
    If .PortOpen = True Then
        .Output = Chr($data)
    EndIf
    EndWith
EndFunc

;-----------------------------------------------------;
; Serial data input function from Satellite receiver
;-----------------------------------------------------;
Func SatReceive()
    $DataIn = ""
    With $MsComm1
        If .PortOpen = False Then
            .PortOpen = True
        EndIf
        If .InBufferCount Then
            $DataIn = .Input    ;Data
        EndIf
    EndWith
    Return Asc($DataIn)
EndFunc
Edited by Keymaker

Share this post


Link to post
Share on other sites
martin

Unfortunately they did not have have any solutions.

The link you gave was for a thread started by AutoitSteve, and he did get a solution, and it was from me. It was as a result of that thread that I produced my serial COMs UDF

commg.dll

There are possibly other solutions.

EDIT: Welcome to the forums!

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.

Share this post


Link to post
Share on other sites
Keymaker

Thanks for the reply Martin.

I tried to use your dll and UDfFs earlier. The send function (_CommSendByte() ) works and solves my Chr(0) problem. However, I have two problems with your UDF's and DLL:

1. My application will need to use two serial ports (COM1 controls the preamp, COM3 communicates withe the STB). Your UDFs make no provision for using more than one serial port. Whereas with the MScomm object, I can declare as many COMs as I need and address each one individually for reading and writing, e.g., $MsComm1.Ouput to write to COM1 and $MsComm2.Input to read from COM2. Your read and write UDFs are only applicable to the current open serial port declared in the _CommsetPort() function.

2. I can't seem to read any data FROM the Set Top Box using any of your read functions (_CommReadByte(), _CommReadChar(), _CommgetString() ). See my code below using your functions to help me determine what is wrong.

Regards,

Keymaker

#include <Constants.au3>
#include <CommMG.au3>
#include <string.au3>
#include <Misc.au3>
#include <array.au3>

;----------------------------------------------;
; Make tray item
;----------------------------------------------;
Opt("TrayOnEventMode",1)
Opt("TrayMenuMode",1)
TraySetClick(16)
TraySetIcon(@ScriptDir & "\Images\Transmitting.ico")
$Exit = TrayCreateItem("Exit")
TrayItemSetOnEvent($Exit,"ExitEvent")
Local $COM1 = 1, $COM3 = 242, $SuccessFlag, $response, $sErr
Const $CMD_TIMEOUT = 500    ; 500 milliseconds
Dim $command[6]

$command[0] = 0xFA      ; "0xFA"    = Command prefix
$command[1] = 0xA5      ; "0xA5" = user command
$command[2] = 0x00      ; "0x00" = switch toggle
$command[3] = 0x01      ; "0x01" = remote button
$command[4] = 0xF7      ; "0xF7 = menu command
$command[5] = 0x0D      ; "0D"  = @CR

;----------------------------------------------;
; Setup Serial Port(s)
;----------------------------------------------;
 _CommSetPort($COM1, $sErr, 9600, 8, 0, 1, 0)

;----------------------------------------------;
; Send MENU command
;----------------------------------------------;
MsgBox(0, "TEST", "Click OK to send MENU command ")

$i = -1
Do
    $i = $i + 1
    _CommSendByte($command[$i])
Until $command[$i] = 0x0D                   ;@CR 

Do
    Sleep(5)        
Until _CommGetInputcount() <> " "   ; Data available?
$response = _CommReadChar()
MsgBox(0, "OK", "Final return value was : " & $response)

Exit

;----------------------------------------------;
; Tray function
;----------------------------------------------;
Func ExitEvent()
    Exit
EndFunc

Share this post


Link to post
Share on other sites
martin

Thanks for the reply Martin.

I tried to use your dll and UDfFs earlier. The send function (_CommSendByte() ) works and solves my Chr(0) problem. However, I have two problems with your UDF's and DLL:

1. My application will need to use two serial ports (COM1 controls the preamp, COM3 communicates withe the STB). Your UDFs make no provision for using more than one serial port. Whereas with the MScomm object, I can declare as many COMs as I need and address each one individually for reading and writing, e.g., $MsComm1.Ouput to write to COM1 and $MsComm2.Input to read from COM2. Your read and write UDFs are only applicable to the current open serial port declared in the _CommsetPort() function.

2. I can't seem to read any data FROM the Set Top Box using any of your read functions (_CommReadByte(), _CommReadChar(), _CommgetString() ). See my code below using your functions to help me determine what is wrong.

Regards,

Keymaker

#include <Constants.au3>
#include <CommMG.au3>
#include <string.au3>
#include <Misc.au3>
#include <array.au3>

;----------------------------------------------;
; Make tray item
;----------------------------------------------;
Opt("TrayOnEventMode",1)
Opt("TrayMenuMode",1)
TraySetClick(16)
TraySetIcon(@ScriptDir & "\Images\Transmitting.ico")
$Exit = TrayCreateItem("Exit")
TrayItemSetOnEvent($Exit,"ExitEvent")
Local $COM1 = 1, $COM3 = 242, $SuccessFlag, $response, $sErr
Const $CMD_TIMEOUT = 500    ; 500 milliseconds
Dim $command[6]

$command[0] = 0xFA      ; "0xFA"    = Command prefix
$command[1] = 0xA5      ; "0xA5" = user command
$command[2] = 0x00      ; "0x00" = switch toggle
$command[3] = 0x01      ; "0x01" = remote button
$command[4] = 0xF7      ; "0xF7 = menu command
$command[5] = 0x0D      ; "0D"  = @CR

;----------------------------------------------;
; Setup Serial Port(s)
;----------------------------------------------;
 _CommSetPort($COM1, $sErr, 9600, 8, 0, 1, 0)

;----------------------------------------------;
; Send MENU command
;----------------------------------------------;
MsgBox(0, "TEST", "Click OK to send MENU command ")

$i = -1
Do
    $i = $i + 1
    _CommSendByte($command[$i])
Until $command[$i] = 0x0D                   ;@CR 

Do
    Sleep(5)        
Until _CommGetInputcount() <> " "   ; Data available?
$response = _CommReadChar()
MsgBox(0, "OK", "Final return value was : " & $response)

Exit

;----------------------------------------------;
; Tray function
;----------------------------------------------;
Func ExitEvent()
    Exit
EndFunc

Haven't tried your script but this bit is wrong

Do

Sleep(5)

Until _CommGetInputcount() <> " " ; Data available?

it should be

Do

Sleep(5)

Until _CommGetInputcount() <> "0" ; Data available?

But if you're going to wait until a character is available then you can just say

_CommReadChar(1);1 (or any value which is not 0) means wait until a character arrives then return it.

EDIT:Forgot your first point.

Yes you are correct that my UDF/dll only deals with one serial port at a time. I will see what is involved in dealing with more than one port. But even if I decide it's simple it will take me some time to produce a solution.

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.

Share this post


Link to post
Share on other sites
martin

Yes you are correct that my UDF/dll only deals with one serial port at a time. I will see what is involved in dealing with more than one port. But even if I decide it's simple it will take me some time to produce a solution.

I've had a look. To do it the way I would like will take a bit of time.

As a temporary method I could fairly quickly do this

Have two serial ports at once, that is you could use one or the other or both, but you are restricted to 2 ports.

Default is as now. I add a new function in my UDF Func switch($Channel) to switch to channel 1 or 2.

Then any function you use is talking to that channel, setport readbyte etc.

Would that be any help?


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.

Share this post


Link to post
Share on other sites
Keymaker

That would help greatly!

By the way, I've tried what you suggested in the previous post, but still no luck. The read functions all return "0" or "": The script hangs at that point because it never reads any data that is not "0" or "".

My previous method using $MsComm object reliably read the input and gave the correct data. Maybe there is something I'm missing. Also, your flow control choices are hardware or Xon/Xoff, but no choice for "None".

Thanks again for your efforts..

Keymaker.

Edited by Keymaker

Share this post


Link to post
Share on other sites
martin

That would help greatly!

By the way, I've tried what you suggested in the previous post, but still no luck. The read functions all return "0" or "": The script hangs at that point because it never reads any data that is not "0" or "".

My previous method using $MsComm object reliably read the input and gave the correct data. Maybe there is something I'm missing. Also, your flow control choices are hardware or Xon/Xoff, but no choice for "None".

Thanks again for your efforts..

Keymaker.

OK.

I've produced a version which has the switch idea and has flow = 2 in the setport for no flow control.

I'll PM you with a link.


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.

Share this post


Link to post
Share on other sites
Keymaker

Thanks for the prompt solution martin.

Regards,

Keyamker

Share this post


Link to post
Share on other sites
Keymaker

It works! No flow control ( Flow control = 2) fixed the problem.

Perhaps my DirecTV satellite application is the only one (so far) that needs a strict adherence to NO flow control.

Also, the files you sent me seem to work. I have NOT yet tried the new switch function. I will try it later. Do I implement the switch() function as follows? and is the function name preceded by an underscore (_)?:

_CommSetPort($COM1, $sErr, 9600, 8, 0, 1, 2) ; Set up COM1 for DirecTV STB
_CommSetPort($COM2, $sErr, 9600, 8, 0, 1, 2) ; Set up COM2 for Krell Preamp

Switch($COM2)
    _CommSendByte($data)    ; Write to COM1
Switch($COM1)
    _CommReadChar()         ; Read from COM2

Regards,

Keymaker

Share this post


Link to post
Share on other sites
martin

It works! No flow control ( Flow control = 2) fixed the problem.

Perhaps my DirecTV satellite application is the only one (so far) that needs a strict adherence to NO flow control.

Also, the files you sent me seem to work. I have NOT yet tried the new switch function. I will try it later.

Amazing!

Do I implement the switch() function as follows? and is the function name preceded by an underscore (_)?:

_CommSetPort($COM1, $sErr, 9600, 8, 0, 1, 2) ; Set up COM1 for DirecTV STB
_CommSetPort($COM2, $sErr, 9600, 8, 0, 1, 2) ; Set up COM2 for Krell Preamp

Switch($COM2)
    _CommSendByte($data)    ; Write to COM1
Switch($COM1)
    _CommReadChar()         ; Read from COM2

Regards,

Keymaker

Not quite, although it would be better if it was like that, however this is how you have to do it -

There are 2 channels in the new dll. Channel 1 and channel 2.

If you don't use the switch function then you are using channel 1. If yu use it with 2 as a parameter you are communicating with channel 2. The channel number is not related to the port number by which I mean channel 1 can be connected to COM9 and channel 2 can be COM3; it doesn't matter.

So here is a small example

$set = _CommSetport(2,$result,9600,8,0,1,0);we haven't used the switch so channel 1 is set for COM2

_CommSendByte($data);send a character to COM2

_CommSwitch(2); we are now talking to channel 2

$set = _CommSetport(9,$result,57600,8,0,1,0); so channel 2 is set for COM9

$c1 = _CommGetChar();get a character from channel2, ie from COM9

_CommSwitch(1); go back to channel 1, COM2

_CommSendString("It's 2.00am I.m going to bed!")

_CommClosePort(); closes both ports -(actually don't remember if I did anything in the dll about channel 2)

; and closes the dll

Hope that makes sense.


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.

Share this post


Link to post
Share on other sites
Keymaker

Martin,

I have not had a chance to test the new _CommSwitch function yet. I appear to be having a hardware issue with my COM2 port. I'll report back after I've resolved the problem.

Regards,

Keymaker

Share this post


Link to post
Share on other sites
martin

Martin,

I have not had a chance to test the new _CommSwitch function yet. I appear to be having a hardware issue with my COM2 port. I'll report back after I've resolved the problem.

Regards,

Keymaker

OK, I'm interested to find out.

I've done some test of my own and I'm feeling confidentish.


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.

Share this post


Link to post
Share on other sites
Keymaker

Martin,

I finally found and fixed my hardware problem and properly tested the _CommSwitch() function and it WORKS! It would be nice if you can add the ability to use more than 2 serial ports though.

In the meantime, I can get by with two ports. I sincerely thank you for all your efforts to help me resolve my problem.

Thanks again.

Regards,

Keymaker

Share this post


Link to post
Share on other sites
martin

Martin,

I finally found and fixed my hardware problem and properly tested the _CommSwitch() function and it WORKS! It would be nice if you can add the ability to use more than 2 serial ports though.

In the meantime, I can get by with two ports. I sincerely thank you for all your efforts to help me resolve my problem.

Thanks again.

Regards,

Keymaker

That's good to hear.

The method I used to add a second channel can be changed to add any number and would take me about 5 minutes, it just isn't the way I intend to do it eventually. So I'll make a new version for the moment with more channels and post that in the first post of my thread for the UDF. I prefer to keep the number of channels as low as I can while I'm using this present method, so if I say 4 will that be enough?


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.

Share this post


Link to post
Share on other sites
Keymaker

Yes, I think 4 channels would be enough...

Thanks again.

Share this post


Link to post
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
Sign in to follow this  

×