Jump to content


Photo

[some code] Arduino.ahk beta .01


  • Please log in to reply
5 replies to this topic

#1 ahklerner

ahklerner
  • Members
  • 1382 posts

Posted 14 March 2011 - 08:32 PM

Example: Moving a servo with a slider control
;
; AutoHotkey Version: 1.x
; Language:       English
; Platform:       Windows XP +??
; Author:         ahklerner / kruzan
;
; Script Function:
;	Arduino GUI Example
;
; set some defaults
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
; serial settings
ARDUINO_Port     = COM2 ; change accordingly
ARDUINO_Baud     = 115200
ARDUINO_Parity   = N
ARDUINO_Data     = 8
ARDUINO_Stop     = 1
; setup arduino serial communication
arduino_setup(start_polling_serial:=false)
; *****************GUI CODE***************
; add first button
Gui, Add, Slider, vServoSlider gServoSlider range0-180 AltSubmit, 90
Gui, Add, Text,, Current Servo Position (as reported by Arduino):
Gui, Add, Text, vPosition,**NO DATA RECEIVED YET**

; show the gui (it will be auto sized and positioned)
Gui, Show
; *****************************************
Gosub, ServoSlider
return
; ******button action code ******

ServoSlider:
	Gui, Submit, NoHide
	UpdateSliderToolTip(ServoSlider)
	GuiControl,,Position, % arduino_send(ServoSlider)
return

UpdateSliderToolTip(val){
	SetFormat, Integer, DEC
	val += 0
	ToolTip % val
	SetTimer, tooltip_close, -500
}

tooltip_close:
	ToolTip
return

;*************************************************************************************
; *****Do not edit below this line unless you want to change the core functionality of the script*****
;*************************************************************************************
; called when the gui is closed
;also called when program exits
GuiClose:
OnExit:
	; make sure to cleanly shut down serial port on exit
	arduino_close()
; this is important!! or else theprogram does not end when closed
ExitApp
#include %A_ScriptDir%\Arduino.ahk


code sould use some cleanup, its the initial release ... i have not decided exactly how im doing this, so code subject to major changes

Requires Arduino.ahk
#include %A_ScriptDir%\Serial.ahk
; Arduino AHK Library
arduino_setup(start_polling_serial=true,ping_device=true){
	global
	ARDUINO_Settings = %ARDUINO_Port%:baud=%ARDUINO_Baud% parity=%ARDUINO_Parity% data=%ARDUINO_Data% stop=%ARDUINO_Stop% dtr=off ;to=off  xon=off odsr=off octs=off rts=off idsr=off
	ARDUINO_Handle := Serial_Initialize(ARDUINO_Settings)
	if ping_device {
		arduino_send("")
	}
	if (arduino_poll_serial_enabled := start_polling_serial) {
		SetTimer, arduino_poll_serial, -1
	}
}

arduino_send(data){
	global ARDUINO_Handle
	Serial_Write(ARDUINO_Handle, data)
	sleep, 50
	return arduino_read_raw()
}

arduino_read(){
	global ARDUINO_Handle
	return Serial_Read(ARDUINO_Handle, "0xFF", Bytes_Received)
}

arduino_read_raw(){
	global ARDUINO_Handle
	return Serial_Read_Raw(ARDUINO_Handle, "0xFF", "raw",Bytes_Received)
}

arduino_close(){
	global ARDUINO_Handle, arduino_poll_serial
	; turn off timer if it is running
	SetTimer, arduino_poll_serial, Off
	; wait a bit for timer to finished if it happened
	Sleep, 100
	Serial_Close(ARDUINO_Handle)
}

arduino_poll_serial:
	if (IsFunc(f:="OnSerialData")&&(arduino_poll_serial_enabled == true)){
		SerialData := arduino_read_raw()
		if SerialData {
				%f%(SerialData)
			}
		SetTimer, arduino_poll_serial, -1
	}else{
		MsgBox, OnSerialData function not defined. 
		SetTimer, arduino_poll_serial, Off
		arduino_poll_serial_enabled = false
		}
return
Requires Serial.ahk
; from here: http://www.autohotkey.com/forum/viewtopic.php?p=290253#290253
;########################################################################
;###### Initialize COM Subroutine #######################################
;########################################################################
Serial_Initialize(SERIAL_Settings){
  ;Global SERIAL_FileHandle      ;uncomment this if there is a problem

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

  ;###### Extract/Format the COM Port Number ######
  StringSplit, SERIAL_Port_Temp, SERIAL_Settings, `:
  SERIAL_Port_Temp1_Len := StrLen(SERIAL_Port_Temp1)  ;For COM Ports > 9 \\.\ needs to prepended to the COM Port name.
  If (SERIAL_Port_Temp1_Len > 4)                   ;So the valid names are
    SERIAL_Port = \\.\%SERIAL_Port_Temp1%             ; ... COM8  COM9   \\.\COM10  \\.\COM11  \\.\COM12 and so on...
  Else                                          ;
    SERIAL_Port = %SERIAL_Port_Temp1%
  ;MsgBox, SERIAL_Port=%SERIAL_Port%

  ;###### Create COM File ######
  ;Creates the COM Port File Handle
  ;StringLeft, SERIAL_Port, SERIAL_Settings, 4  ; 7/23/08 This line is replaced by the "Extract/Format the COM Port Number" section above.
  SERIAL_FileHandle := DllCall("CreateFile"
       ,"Str" , SERIAL_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 (SERIAL_FileHandle < 1){
    error := DllCall("GetLastError")
    MsgBox, There is a problem with Serial Port communication. `nFailed Dll CreateFile, SERIAL_FileHandle=%SERIAL_FileHandle% `nLasterror=%error%`nThe Script Will Now Exit.
    ExitApp
  }

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

  ;###### 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", SERIAL_FileHandle ;File Handle
     ,"UInt", &Data)         ;Pointer to the data structure
  If (SCT_result <> 1){
    error := DllCall("GetLastError")
    MsgBox, There is a problem with Serial Port communication. `nFailed Dll SetCommState, SCT_result=%SCT_result% `nLasterror=%error%`nThe Script Will Now Exit.
    Serial_Close(SERIAL_FileHandle)
    ExitApp
  }

  Return SERIAL_FileHandle
}

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

;########################################################################
;###### Write to COM Subroutines ########################################
;########################################################################
Serial_Write(SERIAL_FileHandle, Message){
  ;Global SERIAL_FileHandle
	OldIntegerFormat := A_FormatInteger

  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" , SERIAL_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%
   	SetFormat, Integer, %OldIntegerFormat%

    Return Bytes_Sent
}

;########################################################################
;###### Read from COM Subroutines #######################################
;########################################################################
Serial_Read(SERIAL_FileHandle, Num_Bytes, byref Bytes_Received = ""){
  ;Global SERIAL_FileHandle
  ;Global SERIAL_Port
  ;Global Bytes_Received
  	OldIntegerFormat := A_FormatInteger

  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, 0)
  ;msgbox, Data_Length=%Data_Length%
	;Bytes_Received := 0

  ;###### Read the data from the COM Port ######
  ;msgbox, SERIAL_FileHandle=%SERIAL_FileHandle% `nNum_Bytes=%Num_Bytes%
  Read_Result := DllCall("ReadFile"
       ,"UInt" , SERIAL_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.
    Serial_Close(SERIAL_FileHandle)
    Exit
  }

  ;###### 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_Temp
  }
  ;MsgBox, Read_Result=%Read_Result% `nBR=%Bytes_Received% ,`nData_HEX=%Data_HEX%

  SetFormat, Integer, DEC
  Data := Data_HEX
  SetFormat, Integer, %OldIntegerFormat%

  Return Data

}

;########################################################################
;###### Read from COM Subroutines #######################################
;########################################################################
Serial_Read_Raw(SERIAL_FileHandle, Num_Bytes, mode = "",byref Bytes_Received = ""){
  ;Global SERIAL_FileHandle
  ;Global SERIAL_Port
  ;Global Bytes_Received
    	OldIntegerFormat := A_FormatInteger

  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, 0)
  ;msgbox, Data_Length=%Data_Length%


  ;###### Read the data from the COM Port ######
  ;msgbox, SERIAL_FileHandle=%SERIAL_FileHandle% `nNum_Bytes=%Num_Bytes%
  Read_Result := DllCall("ReadFile"
       ,"UInt" , SERIAL_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.
    Serial_Close(SERIAL_FileHandle)
    Exit
  }

  ;if you know the data coming back will not contain any binary zeros (0x00), you can request the 'raw' response
  If (mode = "raw")
    Return Data

  ;###### 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_Temp
  }
  ;MsgBox, Read_Result=%Read_Result% `nBR=%Bytes_Received% ,`nData_HEX=%Data_HEX%
	SetFormat, Integer, DEC
	Data := Data_HEX
	SetFormat, Integer, %OldIntegerFormat%
  
  Return Data

}

Arduino sketch - Servo.pde:



// Controlling a servo position using a slider in autohotkey
// by ahklerner / kruzan
// based on:
// Controlling a servo position using a potentiometer (variable resistor) 
// by Michal Rinott <http://people.interaction-ivrea.it/m.rinott> 

#include <Servo.h> 
 
Servo myservo;  // create servo object to control a servo 
 
int pos;    // variable to read the value from the analog pin 
 
void setup() 
{ 
  delay(1000);          // wait a bit before starting
  Serial.begin(115200);   // set up Serial library at 9600 bps
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
} 
 
void loop() 
{ 
  if (Serial.available() > 0) {
	pos = Serial.read();
	myservo.write(pos);                  // sets the servo position according to the scaled value 
	Serial.println(pos);
	delay(15);                           // waits for the servo to get there 
  }
}

The example GUI:
Posted Image :)

#2 MasterFocus

MasterFocus
  • Moderators
  • 4126 posts

Posted 15 March 2011 - 02:47 AM

Thanks!

#3 ahklerner

ahklerner
  • Members
  • 1382 posts

Posted 15 March 2011 - 03:01 AM

Do you have Arduino?

#4 MasterFocus

MasterFocus
  • Moderators
  • 4126 posts

Posted 15 March 2011 - 03:06 AM

No, but this may be very helpful in the future, since I'm studying Electronic Engineering.

#5 Randomlydunn

Randomlydunn
  • Members
  • 1 posts

Posted 31 January 2013 - 02:31 PM

Hi all
I'm a newbie, and have just started with this, I'm having a tough time finding help with a project involving an arduino. I kind of have a deadline .
been looking at AHK scripts to connect to an Arduino via COM3 and just tell it (the arduino) "on". Most of what I found is far more involved than what i need to do, just turn on/off an LED.
I've been taking tutorials and things but I think it will take longer to get results that way than I have.
Can some one modify a AHK script to work with this (below) Arduino script for me? I'm probably asking allot, I will share the results with all the other message boards and give credit where do.

Thanks

Randy

 



    //el sequencer channels
    #define A_Chan  2
    #define B_Chan  3
    #define C_Chan  4
    #define D_Chan  5
    #define E_Chan  6
    #define F_Chan  7
    #define G_Chan  8
    #define H_Chan  9


    char serialIn[20];
    char holder = -1;
    // the setup routine runs once when you press reset:


    void setup() {               
      pinMode(A_Chan, OUTPUT);
      pinMode(B_Chan, OUTPUT);
      pinMode(C_Chan, OUTPUT);
      pinMode(D_Chan, OUTPUT);
      pinMode(E_Chan, OUTPUT);
      pinMode(F_Chan, OUTPUT);
      pinMode(G_Chan, OUTPUT);
      pinMode(H_Chan, OUTPUT);
     
      delay(2000);

      digitalWrite(A_Chan, LOW);
      digitalWrite(B_Chan, LOW);
      digitalWrite(C_Chan, LOW);
      digitalWrite(D_Chan, LOW);
      digitalWrite(E_Chan, LOW);
      digitalWrite(F_Chan, LOW);
      digitalWrite(G_Chan, LOW);
      digitalWrite(H_Chan, LOW); 

      delay(500);
      Serial.begin(9600);
    }

    // the loop routine runs over and over again forever:
    void loop() {

      int index = 0;

      //this reads the serial incoming
      while (Serial.available() > 0){
        if (index < 19){
          holder = Serial.read();
          serialIn[index] = holder;
          index++;
          serialIn[index] = '\0';
        }
      }

      //this prints the serial out
      Serial.println(serialIn);

      if (strcmp(serialIn, "on") == 0){ 
        digitalWrite(A_Chan, HIGH);
        delay(1000);               // wait for a second
      }else{
        digitalWrite(A_Chan, LOW);
        delay(1000);               // wait for a second
      }
    }





#6 None

None
  • Members
  • 3199 posts

Posted 01 February 2013 - 02:35 AM

See my post here for an example of sending serial to an Arduino

http://www.autohotke...elays/?p=561196