AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Serial ( COM ) Port Console Script
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
aobrien



Joined: 14 Feb 2008
Posts: 38

PostPosted: Wed Jul 23, 2008 7:00 am    Post subject: Reply with quote

Krisky,

I have reproduced your problem (script doesn't work with COM Port > 9). The section of the code that is causing the error is shown below.

Code:


;########################################################################
;###### Initialize COM Subroutine #######################################
;########################################################################
Initialize_COM(COM_Settings)
{
  Global COM_FileHandle

  ;###### Build COM DCB ######
  ;Creates the structure that contains the COM Port number, baud rate,...
  VarSetCapacity(DCB, 28)
  BCD_Result := DllCall("BuildCommDCB"   ;<--- Problem
       ,"str" , COM_Settings ;lpDef      ;<---   is
       ,"UInt", &DCB)        ;lpDCB      ;<---  here
  If (BCD_Result <> 1)
  {
    MsgBox, There is a problem with Serial Port communication. `nFailed Dll BuildCommDCB, BCD_Result=%BCD_Result% `nThe Script Will Now Exit.
    Exit
  }


The DllCall("BuildCommDCB"... is not happy with that extra character.

I don't believe that there is any way to fix this problem. However, there may be a work around. I am able to change the COM port number for my devices with the following procedure:
1. Right click "My Computer" -> select "Properties"
2. Click the "Hardware" tab
3. Click "Device Manager"
4. Expand "Ports (COM & LPT)"
5. Double click your device that has COM Port > 9.
6. Click the "Port Settings" tab
7. Click the "Advanced" button
8. Choose a different port number from the "COM Port Number" drop down menu. Just ignore all of the other settings (bits per second, parity, ...) they don't effect anything.
9. Click, OK, OK to finalize your new setting.

I'm using WinXP, but there should be something similar for Vista as well.

This should suffice for 98% of the population, which sucks because I'm probably one the 2% that will need more than 9 COM ports. Sad

If anyone has any suggestions on how to fix this bug, I'm all ears.

aobrien
Back to top
View user's profile Send private message
krisky68
Guest





PostPosted: Wed Jul 23, 2008 10:07 am    Post subject: found it Reply with quote

It relates to COM port numbers over 9, from the MS website CreateFile help:

Quote:

To specify a COM port number greater than 9, use the following syntax: "\\.\COM10". This syntax works for all port numbers and hardware that allows COM port numbers to be specified.


So for the CreateFile dll call, need to prepend the COM_Port var with "\\.\" if more than 4 chars. I tried it by just placing the string into the function, seems to work.

Smile
Back to top
krisky68
Guest





PostPosted: Wed Jul 23, 2008 10:17 am    Post subject: Reply with quote

I didn't see your last reply before I posted mine. I'm running XP, but the problem I was getting related to CreateFile, not the DBC

Code:
COM_Port    = COM17
COM_Baud     = 115200
COM_Parity   = N
COM_Data     = 8
COM_Stop     = 1
Console_Path =


And

Code:
COM_FileHandle := DllCall("CreateFile"
       ,"Str" , "\\.\COM17"     ;File Name         
       ,"UInt", 0xC0000000   ;Desired Access
       ,"UInt", 3            ;Safe Mode
       ,"UInt", 0            ;Security Attributes
       ,"UInt", 3            ;Creation Disposition
       ,"UInt", 0            ;Flags And Attributes
       ,"UInt", 0            ;Template File
       ,"Cdecl Int")


I haven't changed anything else, and it seems to work...
Back to top
aobrien



Joined: 14 Feb 2008
Posts: 38

PostPosted: Sat Jul 26, 2008 5:04 am    Post subject: Reply with quote

Krisky68, thanks for finding/fixing that bug! It is likely to not have been resolved otherwise.

I also put the fix in for the NULL (0x00) data.

Everyone (receiving email notifications) should update their functions to include these two important fixes. See the notes dated 7/23/08 on the second post for more information.
Back to top
View user's profile Send private message
Guest






PostPosted: Wed Oct 15, 2008 11:57 pm    Post subject: Reply with quote

How can the script be modified to send data instead of ASCII characters?
Back to top
aobrien



Joined: 14 Feb 2008
Posts: 38

PostPosted: Thu Oct 16, 2008 6:01 am    Post subject: Reply with quote

The script, by default, sends and receives only data. Look at the second post... in the header of the code you will find this following...

Code:

; The most useful subroutines are listed below. Take them and write your
; application around them.
;     Initialize_COM(COM_Settings)
;     Close_COM(COM_FileHandle)
;     Read_from_COM("0xFF") -- Size of receive buffer. This returns ASCII
;                                representation of the received HEX data.
;     Example: Read_Data := Read_from_COM("0xFF") ;if the RX buffer contained
;              0x11, 0x22, 0x00, 0x33, 0x44 then Read_Data will contain 1122003344
;     Write_to_COM(Hex_Data) -- Comma delimited hex data. If I wanted to
;                               send "Hello World" I would do the following:
;     ;ASCII DATA=  H    e    l    l    o   SP    W    o    r    l    d
;     Hex_Data = 0x48,0x65,0x6C,0x6C,0x6F,0x20,0x57,0x6F,0x72,0x6C,0x64
;     Write_to_COM(Hex_Data)


The Write_to_COM() and Read_from_COM() functions, by default, send/receive only data. What you want to do with the data is up to you.

The rest of the script was set up to send/receive ascii into a standard Notepad just for illustration purposes.

Simply copy the functions listed above and start writing your script around them.
Back to top
View user's profile Send private message
Guest






PostPosted: Thu Oct 16, 2008 12:48 pm    Post subject: Reply with quote

I need to send this:
-without the (begin) & (end) of course

(begin)
%

O8()

%
(end)

If could someone could show me how, I should be able to manage from here.
(thanks in advance)
Back to top
twhyman



Joined: 07 Dec 2005
Posts: 265

PostPosted: Thu Oct 16, 2008 9:05 pm    Post subject: Reply with quote

Hi,

Can someone upload the dll because the developer site is gone Rolling Eyes

Thanks
Twhyman
_________________
(\__/) This is Bunny.
(='.'=) Cut, copy, and paste bunny onto your sig.
(")_(") Help Bunny gain World Domination.
Back to top
View user's profile Send private message
Rabiator



Joined: 17 Apr 2005
Posts: 271
Location: Sauerland

PostPosted: Thu Oct 16, 2008 9:35 pm    Post subject: Reply with quote

http://www.elektronik-bastelecke.de/Port_dll.zip
Back to top
View user's profile Send private message
twhyman



Joined: 07 Dec 2005
Posts: 265

PostPosted: Fri Oct 17, 2008 2:44 pm    Post subject: Reply with quote

Rabiator wrote:
http://www.elektronik-bastelecke.de/Port_dll.zip


Thank you Very Happy
_________________
(\__/) This is Bunny.
(='.'=) Cut, copy, and paste bunny onto your sig.
(")_(") Help Bunny gain World Domination.
Back to top
View user's profile Send private message
aobrien



Joined: 14 Feb 2008
Posts: 38

PostPosted: Sat Oct 18, 2008 3:19 am    Post subject: Reply with quote

Guest,

Here is the code that will perform what you are asking. I don't have ability to test this at home, but it should work (famous last words).

0. Install ahk on your pc.
1. copy the entire code below and paste it into a text file
2. save it as .ahk
3. double click the file name
4. press the F4 key to send the characters on the serial port.

This is a good ASCII table that will tell you how to translate the ASCII characters to Decimal or Hex code which is what the script needs.
http://www.asciitable.com/

There are 2 different codes that can be used to send a {RETURN} 0x0A (New Line) and 0x0D (Carriage Return). Some text editors use one or the other or both. I'm not sure what your application requires so it might not be correct.

Good luck.

Code:


F4::

MsgBox, Begin COM Test

;########################################################################
;###### User Variables (Change these to match you needs) ################
;########################################################################
COM_Port     = COM4
COM_Baud     = 115200
COM_Parity   = N
COM_Data     = 8
COM_Stop     = 1

;########################################################################
;###### Script Variables (Don't touch these) ############################
;########################################################################
COM_Settings = %COM_Port%:baud=%COM_Baud% parity=%COM_Parity% data=%COM_Data% stop=%COM_Stop% dtr=Off

;########################################################################
;###### Main Routine ####################################################
;########################################################################
Initialize_COM(COM_Settings)

;NL = New Line
;            %   NL   NL    O    8    (    )   NL   NL    %
Message = 0x25,0x0A,0x0A,0x4F,0x38,0x28,0x29,0x0A,0x0A,0x25
Write_to_COM(Message)


Close_COM(COM_FileHandle)
Return


;########################################################################
;###### Subroutines (You don't really need to look below this line) #####
;########################################################################

;########################################################################
;###### Initialize COM Subroutine (Don't touch this routine) ############
;########################################################################
Initialize_COM(COM_Settings)
{
  Global COM_FileHandle

  ;###### Build COM DCB ######
  ;Creates the structure that contains the COM Port number, baud rate,...
  VarSetCapacity(DCB, 28)
  BCD_Result := DllCall("BuildCommDCB"
       ,"str" , COM_Settings ;lpDef
       ,"UInt", &DCB)        ;lpDCB
  If (BCD_Result <> 1)
  {
    MsgBox, There is a problem with Serial Port communication. `nFailed Dll BuildCommDCB, BCD_Result=%BCD_Result% `nThe Script Will Now Exit.
    Exit
  }

  ;###### Extract/Format the COM Port Number ######
  ;7/23/08 Thanks krisky68 for finding/solving the bug in which COM Ports greater than 9 didn't work.
  StringSplit, COM_Port_Temp, COM_Settings, `:
  COM_Port_Temp1_Len := StrLen(COM_Port_Temp1)  ;For COM Ports > 9 \\.\ needs to prepended to the COM Port name.
  If (COM_Port_Temp1_Len > 4)                   ;So the valid names are
    COM_Port = \\.\%COM_Port_Temp1%             ; ... COM8  COM9   \\.\COM10  \\.\COM11  \\.\COM12 and so on...
  Else                                          ;
    COM_Port = %COM_Port_Temp1%
  ;MsgBox, COM_Port=%COM_Port%

  ;###### Create COM File ######
  ;Creates the COM Port File Handle
  ;StringLeft, COM_Port, COM_Settings, 4  ; 7/23/08 This line is replaced by the "Extract/Format the COM Port Number" section above.
  COM_FileHandle := DllCall("CreateFile"
       ,"Str" , COM_Port     ;File Name         
       ,"UInt", 0xC0000000   ;Desired Access
       ,"UInt", 3            ;Safe Mode
       ,"UInt", 0            ;Security Attributes
       ,"UInt", 3            ;Creation Disposition
       ,"UInt", 0            ;Flags And Attributes
       ,"UInt", 0            ;Template File
       ,"Cdecl Int")
  If (COM_FileHandle < 1)
  {
    MsgBox, There is a problem with Serial Port communication. `nFailed Dll CreateFile, COM_FileHandle=%COM_FileHandle% `nThe Script Will Now Exit.
    Exit
  }

  ;###### Set COM State ######
  ;Sets the COM Port number, baud rate,...
  SCS_Result := DllCall("SetCommState"
       ,"UInt", COM_FileHandle ;File Handle
       ,"UInt", &DCB)          ;Pointer to DCB structure
  If (SCS_Result <> 1)
  {
    MsgBox, There is a problem with Serial Port communication. `nFailed Dll SetCommState, SCS_Result=%SCS_Result% `nThe Script Will Now Exit.
    Close_COM(COM_FileHandle)
    Exit
  }

  ;###### Create the SetCommTimeouts Structure ######
  ReadIntervalTimeout        = 0xffffffff
  ReadTotalTimeoutMultiplier = 0x00000000
  ReadTotalTimeoutConstant   = 0x00000000
  WriteTotalTimeoutMultiplier= 0x00000000
  WriteTotalTimeoutConstant  = 0x00000000

  VarSetCapacity(Data, 20, 0) ; 5 * sizeof(DWORD)
  NumPut(ReadIntervalTimeout,         Data,  0, "UInt")
  NumPut(ReadTotalTimeoutMultiplier,  Data,  4, "UInt")
  NumPut(ReadTotalTimeoutConstant,    Data,  8, "UInt")
  NumPut(WriteTotalTimeoutMultiplier, Data, 12, "UInt")
  NumPut(WriteTotalTimeoutConstant,   Data, 16, "UInt")

  ;###### Set the COM Timeouts ######
  SCT_result := DllCall("SetCommTimeouts"
     ,"UInt", COM_FileHandle ;File Handle
     ,"UInt", &Data)         ;Pointer to the data structure
  If (SCT_result <> 1)
  {
    MsgBox, There is a problem with Serial Port communication. `nFailed Dll SetCommState, SCT_result=%SCT_result% `nThe Script Will Now Exit.
    Close_COM(COM_FileHandle)
    Exit
  }

  Return %COM_FileHandle%
}

;########################################################################
;###### Close COM Subroutine (Don't touch this routine) #################
;########################################################################
Close_COM(COM_FileHandle)
{
  ;###### Close the COM File ######
  CH_result := DllCall("CloseHandle", "UInt", COM_FileHandle)
  If (CH_result <> 1)
    MsgBox, Failed Dll CloseHandle CH_result=%CH_result%

  Return
}

;########################################################################
;###### Write to COM Subroutines (Don't touch this routine) #############
;########################################################################
Write_to_COM(Message)
{
  Global COM_FileHandle
  Global COM_Port

  SetFormat, Integer, DEC

  ;Parse the Message. Byte0 is the number of bytes in the array.
  StringSplit, Byte, Message, `,
  Data_Length := Byte0
  ;msgbox, Data_Length=%Data_Length% b1=%Byte1% b2=%Byte2% b3=%Byte3% b4=%Byte4%

  ;Set the Data buffer size, prefill with 0xFF.
  VarSetCapacity(Data, Byte0, 0xFF)

  ;Write the Message into the Data buffer
  i=1
  Loop %Byte0%
  {
    NumPut(Byte%i%, Data, (i-1) , "UChar")
    ;msgbox, %i%
    i++
  }
  ;msgbox, Data string=%Data%

  ;###### Write the data to the COM Port ######
  WF_Result := DllCall("WriteFile"
       ,"UInt" , COM_FileHandle ;File Handle
       ,"UInt" , &Data          ;Pointer to string to send
       ,"UInt" , Data_Length    ;Data Length
       ,"UInt*", Bytes_Sent     ;Returns pointer to num bytes sent
       ,"Int"  , "NULL")
  If (WF_Result <> 1 or Bytes_Sent <> Data_Length)
    MsgBox, Failed Dll WriteFile to %COM_Port%, result=%WF_Result% `nData Length=%Data_Length% `nBytes_Sent=%Bytes_Sent%
}

;########################################################################
;###### Read from COM Subroutines (Don't touch this routine) ############
;########################################################################
Read_from_COM(Num_Bytes)
{
  Global COM_FileHandle
  Global COM_Port
  Global Bytes_Received
  SetFormat, Integer, HEX

  ;Set the Data buffer size, prefill with 0x55 = ASCII character "U"
  ;VarSetCapacity won't assign anything less than 3 bytes. Meaning: If you
  ;  tell it you want 1 or 2 byte size variable it will give you 3.
  Data_Length  := VarSetCapacity(Data, Num_Bytes, 0x55)
  ;msgbox, Data_Length=%Data_Length%

  ;###### Read the data from the COM Port ######
  ;msgbox, COM_FileHandle=%COM_FileHandle% `nNum_Bytes=%Num_Bytes%
  Read_Result := DllCall("ReadFile"
       ,"UInt" , COM_FileHandle   ; hFile
       ,"Str"  , Data             ; lpBuffer
       ,"Int"  , Num_Bytes        ; nNumberOfBytesToRead
       ,"UInt*", Bytes_Received   ; lpNumberOfBytesReceived
       ,"Int"  , 0)               ; lpOverlapped
  ;MsgBox, Read_Result=%Read_Result% `nBR=%Bytes_Received% ,`nData=%Data%
  If (Read_Result <> 1)
  {
    MsgBox, There is a problem with Serial Port communication. `nFailed Dll ReadFile on %COM_Port%, result=%Read_Result% - The Script Will Now Exit.
    Close_COM(COM_FileHandle)
    Exit
  }

  i = 0
  Data_HEX =
  Loop %Bytes_Received%
  {
    ;First byte into the Rx FIFO ends up at position 0

    Data_HEX_Temp := NumGet(Data, i, "UChar") ;Convert to HEX byte-by-byte
    StringTrimLeft, Data_HEX_Temp, Data_HEX_Temp, 2 ;Remove the 0x (added by the above line) from the front

    ;If there is only 1 character then add the leading "0'
    Length := StrLen(Data_HEX_Temp)
    If (Length =1)
      Data_HEX_Temp = 0%Data_HEX_Temp%

    i++

    ;Put it all together
    Data_HEX := Data_HEX . Data_HEX_Temp
  }
  ;MsgBox, Read_Result=%Read_Result% `nBR=%Bytes_Received% ,`nData_HEX=%Data_HEX%

  SetFormat, Integer, DEC
  Data := Data_HEX

  Return Data

}


Back to top
View user's profile Send private message
Max_Foster
Guest





PostPosted: Mon Oct 27, 2008 1:38 pm    Post subject: Reply with quote

I'm wondering if this script can be used for my needs, but unfortunatelly my AHK skills are still very basic...
So, this is the thing: I'm using this program (SuperLab) to perform some experiments on visual perception. So far, I've been using AHK to send the mouse cursor to the center of the screen after any mouse click (so to allow the mouse cursor to appear always at that position at the beginning of each trial). But for some stimuli I would need the mouse cursor to be send for specific coordinates on the screen. Since the stimuli appear in a random order, the only way I could manage this would be to have SuperLab sending an instruction to AHK to perform that positioning of the mouse cursor. Luckily, SuperLab has the option to send a Serial Output (Including sending a String or ASCII values). Also, and since both programs would be run in the same machine, I can use a virtual serial port.
My question is simply out to "translate" a given serial output from SuperLab into an action within the AHK script (specifically, move the mouse cursor to x,y)? Would this script allow me to do that?
I can antecipate that I would have to do something around this logic: IF serial output = X THEN [instruction for mouse cursor]. But I can't figure out where and how in the script I can do such...
Thanks in advance.
Back to top
aobrien



Joined: 14 Feb 2008
Posts: 38

PostPosted: Sat Nov 01, 2008 6:32 am    Post subject: Reply with quote

Hi Max,

The following script probably won't work straight out of the box, but is a good start.

Read and understand the script until you get to the subroutines (don't go any further than that) then begin testing.

Good luck!

[EDIT]Updated code snip[\EDIT]
Code:



F6::  ;Push F6 key to start script

;########################################################################
;###### User Variables ##################################################
;########################################################################
;COM Port Settings
COM_Port     = COM9
COM_Baud     = 115200
COM_Parity   = N
COM_Data     = 8
COM_Stop     = 1

;########################################################################
;###### Script Variables ################################################
;########################################################################
COM_Settings = %COM_Port%:baud=%COM_Baud% parity=%COM_Parity% data=%COM_Data% stop=%COM_Stop% dtr=Off



;########################################################################
;###### Main Routine ################################################
;########################################################################

;READ THIS!!! -- This script assums that:
;   the first byte of data received on the serial port is the X coordinate and
;   the second byte of data received on the serial port is the Y coordinate.
;Have your Superlab send 2 bytes of data over the serial port and you should see the mouse move.
;Use the MsgBox lines to help you debug. Remove the MsgBoxes when the script is working.


COM_FileHandle := Initialize_COM(COM_Settings) ;Initialize the COM port with the above settings
Data =
Loop   ;This is an infinite loop. To stop the script you will have to right click on the Green "H" icon and reload or exit.
{
    New_Data := Read_from_COM("0xFF") ;Get some data from the serial port - store it in New_Data - each byte of data will be represented by 2 characters which will make one hex byte
    New_Data_Length := StrLen(New_Data) ;Find out how many characters are in New_Data
    If (New_Data_Length > 1)
    {
        Data := Data + New_Data
        MsgBox, Data = %Data%      New_Data %New_Data% ;pop-up a message box to show what your data strings.
    }

    Data_Length := StrLen(New_Data)
    If (Data_Length > 3)
    {
        StringLeft, X, Data, 2  ;get the first hex byte - 2 characters
        StringTrimLeft, Data, Data, 2  ;remove the first hex byte from "Data" the second byte is now the shifted into the first byte position

        StringLeft, Y, Data, 2  ;get the Y hex byte
        StringTrimLeft, Data, Data, 2 ;remove it from the string.

;MouseMove will require a decimal number. You will need to have some sort of routine to convert the Hex X and Y values Decimal. I will leave this to you :)

        MouseMove, %X%, %Y%  ; move the mouse
        MsgBox, X = %X%    Y = %Y% ;pop-up a message box showing what your retrieved X,Y data is.
       
    }
}

;########################################################################
;###### Subroutines (You don't really need to look below this line) #####
;########################################################################

;########################################################################
;###### Initialize COM Subroutine #######################################
;########################################################################
Initialize_COM(COM_Settings)
{
  Global COM_FileHandle

  ;###### Build COM DCB ######
  ;Creates the structure that contains the COM Port number, baud rate,...
  VarSetCapacity(DCB, 28)
  BCD_Result := DllCall("BuildCommDCB"
       ,"str" , COM_Settings ;lpDef
       ,"UInt", &DCB)        ;lpDCB
  If (BCD_Result <> 1)
  {
    MsgBox, There is a problem with Serial Port communication. `nFailed Dll BuildCommDCB, BCD_Result=%BCD_Result% `nThe Script Will Now Exit.
    Exit
  }

  ;###### Extract/Format the COM Port Number ######
  ;7/23/08 Thanks krisky68 for finding/solving the bug in which COM Ports greater than 9 didn't work.
  StringSplit, COM_Port_Temp, COM_Settings, `: 
  COM_Port_Temp1_Len := StrLen(COM_Port_Temp1)  ;For COM Ports > 9 \\.\ needs to prepended to the COM Port name.
  If (COM_Port_Temp1_Len > 4)                   ;So the valid names are
    COM_Port = \\.\%COM_Port_Temp1%             ; ... COM8  COM9   \\.\COM10  \\.\COM11  \\.\COM12 and so on...
  Else                                          ;
    COM_Port = %COM_Port_Temp1%
  ;MsgBox, COM_Port=%COM_Port% 

  ;###### Create COM File ######
  ;Creates the COM Port File Handle
  ;StringLeft, COM_Port, COM_Settings, 4  ; 7/23/08 This line is replaced by the "Extract/Format the COM Port Number" section above.
  COM_FileHandle := DllCall("CreateFile"
       ,"Str" , COM_Port     ;File Name         
       ,"UInt", 0xC0000000   ;Desired Access
       ,"UInt", 3            ;Safe Mode
       ,"UInt", 0            ;Security Attributes
       ,"UInt", 3            ;Creation Disposition
       ,"UInt", 0            ;Flags And Attributes
       ,"UInt", 0            ;Template File
       ,"Cdecl Int")
  If (COM_FileHandle < 1)
  {
    MsgBox, There is a problem with Serial Port communication. `nFailed Dll CreateFile, COM_FileHandle=%COM_FileHandle% `nThe Script Will Now Exit.
    Exit
  }

  ;###### Set COM State ######
  ;Sets the COM Port number, baud rate,...
  SCS_Result := DllCall("SetCommState"
       ,"UInt", COM_FileHandle ;File Handle
       ,"UInt", &DCB)          ;Pointer to DCB structure
  If (SCS_Result <> 1)
  {
    MsgBox, There is a problem with Serial Port communication. `nFailed Dll SetCommState, SCS_Result=%SCS_Result% `nThe Script Will Now Exit.
    Close_COM(COM_FileHandle)
    Exit
  }

  ;###### Create the SetCommTimeouts Structure ######
  ReadIntervalTimeout        = 0xffffffff
  ReadTotalTimeoutMultiplier = 0x00000000
  ReadTotalTimeoutConstant   = 0x00000000
  WriteTotalTimeoutMultiplier= 0x00000000
  WriteTotalTimeoutConstant  = 0x00000000

  VarSetCapacity(Data, 20, 0) ; 5 * sizeof(DWORD)
  NumPut(ReadIntervalTimeout,         Data,  0, "UInt")
  NumPut(ReadTotalTimeoutMultiplier,  Data,  4, "UInt")
  NumPut(ReadTotalTimeoutConstant,    Data,  8, "UInt")
  NumPut(WriteTotalTimeoutMultiplier, Data, 12, "UInt")
  NumPut(WriteTotalTimeoutConstant,   Data, 16, "UInt")

  ;###### Set the COM Timeouts ######
  SCT_result := DllCall("SetCommTimeouts"
     ,"UInt", COM_FileHandle ;File Handle
     ,"UInt", &Data)         ;Pointer to the data structure
  If (SCT_result <> 1)
  {
    MsgBox, There is a problem with Serial Port communication. `nFailed Dll SetCommState, SCT_result=%SCT_result% `nThe Script Will Now Exit.
    Close_COM(COM_FileHandle)
    Exit
  }

  Return %COM_FileHandle%
}

;########################################################################
;###### Close COM Subroutine ############################################
;########################################################################
Close_COM(COM_FileHandle)
{
  ;###### Close the COM File ######
  CH_result := DllCall("CloseHandle", "UInt", COM_FileHandle)
  If (CH_result <> 1)
    MsgBox, Failed Dll CloseHandle CH_result=%CH_result%

  Return
}

;########################################################################
;###### Write to COM Subroutines ########################################
;########################################################################
Write_to_COM(Message)
{
  Global COM_FileHandle
  Global COM_Port

  SetFormat, Integer, DEC

  ;Parse the Message. Byte0 is the number of bytes in the array.
  StringSplit, Byte, Message, `,
  Data_Length := Byte0
  ;msgbox, Data_Length=%Data_Length% b1=%Byte1% b2=%Byte2% b3=%Byte3% b4=%Byte4%

  ;Set the Data buffer size, prefill with 0xFF.
  VarSetCapacity(Data, Byte0, 0xFF)

  ;Write the Message into the Data buffer
  i=1
  Loop %Byte0%
  {
    NumPut(Byte%i%, Data, (i-1) , "UChar")
    ;msgbox, %i%
    i++
  }
  ;msgbox, Data string=%Data%

  ;###### Write the data to the COM Port ######
  WF_Result := DllCall("WriteFile"
       ,"UInt" , COM_FileHandle ;File Handle
       ,"UInt" , &Data          ;Pointer to string to send
       ,"UInt" , Data_Length    ;Data Length
       ,"UInt*", Bytes_Sent     ;Returns pointer to num bytes sent
       ,"Int"  , "NULL")
  If (WF_Result <> 1 or Bytes_Sent <> Data_Length)
    MsgBox, Failed Dll WriteFile to %COM_Port%, result=%WF_Result% `nData Length=%Data_Length% `nBytes_Sent=%Bytes_Sent%
}

;########################################################################
;###### Read from COM Subroutines #######################################
;########################################################################
Read_from_COM(Num_Bytes)
{
  Global COM_FileHandle
  Global COM_Port
  Global Bytes_Received
  SetFormat, Integer, HEX

  ;Set the Data buffer size, prefill with 0x55 = ASCII character "U"
  ;VarSetCapacity won't assign anything less than 3 bytes. Meaning: If you
  ;  tell it you want 1 or 2 byte size variable it will give you 3.
  Data_Length  := VarSetCapacity(Data, Num_Bytes, 0x55)
  ;msgbox, Data_Length=%Data_Length%

  ;###### Read the data from the COM Port ######
  ;msgbox, COM_FileHandle=%COM_FileHandle% `nNum_Bytes=%Num_Bytes%
  Read_Result := DllCall("ReadFile"
       ,"UInt" , COM_FileHandle   ; hFile
       ,"Str"  , Data             ; lpBuffer
       ,"Int"  , Num_Bytes        ; nNumberOfBytesToRead
       ,"UInt*", Bytes_Received   ; lpNumberOfBytesReceived
       ,"Int"  , 0)               ; lpOverlapped
  ;MsgBox, Read_Result=%Read_Result% `nBR=%Bytes_Received% ,`nData=%Data%
  If (Read_Result <> 1)
  {
    MsgBox, There is a problem with Serial Port communication. `nFailed Dll ReadFile on %COM_Port%, result=%Read_Result% - The Script Will Now Exit.
    Close_COM(COM_FileHandle)
    Exit
  }

;;;;;;;; 7/23/08 This section is replaced by the code below ;;;;;;;;;;;;;
;  SetFormat, Integer, DEC
;
;  ;###### Format the received data ######
;  ;Return only the bytes that were received.
;  If (Bytes_Received = 0)
;    Return ""
;  Else
;    ;StringTrimRight, Data, Data, %Bytes_Received% ;5/22/08 This line is essentially useless and could potentially show up as a bug.
;    StringLeft, Data, Data, Bytes_Received ;5/22/08 This is what the above line should have been
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  ;###### Format the received data ######
  ;This loop is necessary because AHK doesn't handle NULL (0x00) characters very nicely.
  ;Quote from AHK documentation under DllCall:
  ;     "Any binary zero stored in a variable by a function will hide all data to the right
  ;     of the zero; that is, such data cannot be accessed or changed by most commands and
  ;     functions. However, such data can be manipulated by the address and dereference operators
  ;     (& and *), as well as DllCall itself."
  i = 0
  Data_HEX =
  Loop %Bytes_Received%
  {
    ;First byte into the Rx FIFO ends up at position 0

    Data_HEX_Temp := NumGet(Data, i, "UChar") ;Convert to HEX byte-by-byte
    StringTrimLeft, Data_HEX_Temp, Data_HEX_Temp, 2 ;Remove the 0x (added by the above line) from the front

    ;If there is only 1 character then add the leading "0'
    Length := StrLen(Data_HEX_Temp)
    If (Length =1)
      Data_HEX_Temp = 0%Data_HEX_Temp%

    i++

    ;Put it all together
    Data_HEX := Data_HEX . Data_HEX_Temp
  }
  ;MsgBox, Read_Result=%Read_Result% `nBR=%Bytes_Received% ,`nData_HEX=%Data_HEX%

  SetFormat, Integer, DEC
  Data := Data_HEX

  Return Data

}




Last edited by aobrien on Mon Nov 17, 2008 6:55 am; edited 1 time in total
Back to top
View user's profile Send private message
Max Foster
Guest





PostPosted: Thu Nov 13, 2008 2:49 pm    Post subject: Reply with quote

Hi aobrien!
First of all, thank you very much for the prompt reply along with the script.
However, I can't run the code. Everytime I try to it gives me an error message on a nonexistent function, namely Close_COM(COM_FileHandle). Moreover, it reports the error to be happening at the line 122.
Since this location is well below your comment "Don't touch this", I thought it would be better to ask you about this...
In the meanwhile, I've been looking through the rest of the code, and I'm pretty confident that it would work properly for my purposes. Smile
Anyway, if you can give me a tip on this error, I would appreciate.
Thanks again!
Back to top
A_Guest
Guest





PostPosted: Thu Nov 13, 2008 4:07 pm    Post subject: Reply with quote

hi

thanks for sharing this!

i got my plasma connected to my pc and use a software to switch it on/off. The software i use is kinda bloated/slow and i would like to try this script. Im a novis coder so i dont understand it fully. I want to send this:

"COM Settings","9600","O","8","1"
"C","Power On","9F 80 60 4E 00 CD","5"
"C","Power Off","9F 80 60 4F 00 CE","5"

*the 5 is some kind of delay i think 5ms ..?

Would it work to insert this data to your User Variables/Message section? If not could oyu please give me some help..?
Back to top
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group