| VB Robot Truck Example Last Modified: 2007-03-22 | | |
| Acroname Robotics | PDF webpage version | ||
| Overview This example is an application for controlling a small robot truck. The truck carries a small host computer that runs a Visual Basic program. This program communicates with two BrainStem GP 1.0 modules that act as slave controllers. Sending command packets to a BrainStem controller are covered in detail in other examples. Block Diagram The system has the following topology: ![]() Block diagram and the relationship between components.
BrainStem #1 with Address 2 controls five IO devices:
BrainStem #2 with Address 4 controls seven IO devices:
The VB Form defines a GUI for looking at sensor data. A button command is provided in order to take a reading from each input device. The code includes routines for formatting values (decimal, binary, hex) along with IO routines for managing all the devices. Most IO routines require the transfer of one packet to a BrainStem and reception of a reply packet. Some routines are generalized and have a parameter for selecting a specific BrainStem module. The routines that take readings from the SRF08 and CMPS03 require some extra command packets since these devices are connected to the I2C bus and need extra initialization. There are routines for reading the first echo from the SRF08, taking a light intensity reading from the SRF08, and getting the current heading from the CMPS03. Source Code The following source code was used for this example: VERSION 5.00
Object = "{648A5603-2C6E-101B-82B6-000000000014}#1.1#0"; "MSCOMM32.OCX"
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 4665
ClientLeft = 60
ClientTop = 345
ClientWidth = 8400
LinkTopic = "Form1"
ScaleHeight = 4665
ScaleWidth = 8400
StartUpPosition = 3 'Windows Default
Begin VB.TextBox CMPS03Buff
Height = 285
Left = 5280
TabIndex = 17
Text = "Text1"
Top = 1920
Width = 1455
End
Begin VB.TextBox SRF08Buff
Height = 285
Left = 5280
TabIndex = 16
Text = "Text1"
Top = 840
Width = 1455
End
Begin VB.TextBox GP2D12SXBuff
Height = 285
Left = 3600
TabIndex = 15
Text = "Text1"
Top = 2760
Width = 1095
End
Begin VB.TextBox GP2D12DXBuff
Height = 285
Left = 3600
TabIndex = 14
Text = "Text1"
Top = 120
Width = 1095
End
Begin VB.TextBox GP2D120Buff
Height = 285
Left = 1200
TabIndex = 13
Text = "Text1"
Top = 1920
Width = 1095
End
Begin VB.TextBox GP2D02Buff
Height = 285
Left = 1200
TabIndex = 12
Text = "Text1"
Top = 840
Width = 1095
End
Begin VB.Timer Scan
Left = 7680
Top = 720
End
Begin VB.CommandButton cmdCMPS03
Caption = "CMPS03"
Height = 255
Left = 3960
TabIndex = 11
Top = 2280
Width = 1215
End
Begin VB.TextBox CMPS03
Height = 285
Left = 3960
TabIndex = 10
Text = "CMPS03"
Top = 1920
Width = 1215
End
Begin VB.CommandButton cmdSRF08
Caption = "SRF08"
Height = 255
Left = 3960
TabIndex = 9
Top = 1200
Width = 1215
End
Begin VB.TextBox SRF08
Height = 285
Left = 3960
TabIndex = 8
Text = "SRF08"
Top = 840
Width = 1215
End
Begin VB.CommandButton cmdGP2D12_SX
Caption = "GP2D12SX"
Height = 255
Left = 2520
TabIndex = 7
Top = 3120
Width = 975
End
Begin VB.TextBox GP2D12SX
Height = 285
Left = 2520
TabIndex = 6
Text = "GP2D12SX"
Top = 2760
Width = 975
End
Begin VB.CommandButton cmdGP2D12_DX
Caption = "GP2D12DX"
Height = 255
Left = 2520
TabIndex = 5
Top = 480
Width = 975
End
Begin VB.TextBox GP2D12DX
Height = 285
Left = 2520
TabIndex = 4
Text = "GP2D12 DX"
Top = 120
Width = 975
End
Begin VB.CommandButton cmdGP2D120
Caption = "GP2D120"
Height = 255
Left = 240
TabIndex = 3
Top = 2280
Width = 855
End
Begin VB.TextBox GP2D120
Height = 285
Left = 240
TabIndex = 2
Text = "GP2D120"
Top = 1920
Width = 855
End
Begin VB.CommandButton cmdGP2D02
Caption = "GP2D02"
Height = 255
Left = 240
TabIndex = 1
Top = 1200
Width = 855
End
Begin VB.TextBox GP2D02
Height = 285
Left = 240
TabIndex = 0
Text = "GP2D02"
Top = 840
Width = 855
End
Begin MSCommLib.MSComm MSComm1
Left = 7680
Top = 0
_ExtentX = 1005
_ExtentY = 1005
_Version = 393216
DTREnable = -1 'True
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)
Option Explicit
' __________ Add-ons __________
Const SRF08_Ad = 224 ' The default address of the SRF08 Device
Const CMPS03_Ad = 192 ' The default address of the CMPS03 Device
Dim Buff_STR As String
Dim Distance_SRF08 As Integer
Dim Distance_GP2D12FW As Integer
' __________ __________
' Programma originale
Public BSTEM As Byte ' bstem is a variable because
' I use 2 modules
Dim bbuff(0 To 12) As Byte ' Arrays and ...
Const cmdDEV_VAL As Byte = 4 ' constants can not be declared "Public"
Const cmdVAL_GET As Byte = 17 ' on object-modul level in VB
Const cmdVAL_SET As Byte = 18
Const cmdVAL_SAV As Byte = 19
Const cmdSRV_SAV As Byte = 20
Const cmdVM_RUN As Byte = 21
Const cmdVM_KILL As Byte = 22
Const cmdDEBUG As Byte = 23
Const cmdRESET As Byte = 24
Const cmdDIG_CFG As Byte = 26
Const cmdDIG_RST As Byte = 28
Const cmdPTIME_RD As Byte = 29
Const cmdSRV_CFG As Byte = 31
Const cmdSRV_LMT As Byte = 32
Const cmdSRV_REL As Byte = 34
Const cmdSRV_RFLX As Byte = 35
Const cmdSRV_STOP As Byte = 36
Const cmdRAW_INPUT As Byte = 38
Const cmdTMR_SET As Byte = 39
Const cmdRFLXE_CFG As Byte = 40
Const cmdRFLXE_CHK As Byte = 41
Const cmdCTR_SET As Byte = 42
Const cmdCTR_CT As Byte = 43
Const cmdRAIL As Byte = 44
Const cmdFUNC As Byte = 45
Const cmdMPD_SET As Byte = 46
Const cmdMPD_CHK As Byte = 47
Const cmdWINDOW As Byte = 48
Const cmdERRAMP As Byte = 49
Const cmdERRATT As Byte = 50
Const cmdPAD_IO As Byte = 51
Const cmdPAD_INPUT As Byte = 52
Const cmdPWINDOW As Byte = 53
Const cmdPERRAMP As Byte = 54
Const cmdPERRATT As Byte = 55
Const cmdPTMR_SET As Byte = 56
Const cmdPCTR_SET As Byte = 57
Const cmdPCTR_WR As Byte = 58
Const cmdA2D_RD As Byte = 25
Const cmdDIG_IO As Byte = 27
Const cmdIR02_RD As Byte = 30
Const cmdSRV_ABS As Byte = 33
Const cmdIIC_RD As Byte = 37
Const cmdIIC_XMIT As Byte = 2
' MAIN
Private Sub Form_Load()
' Initialization routines for the 2 brainstem card
InitMSComm1
InitBrainStem2
InitBrainStem4
End Sub
' RS232 IO
Private Sub InitMSComm1()
'The program uses the MSComm-Control default property settings:
MSComm1.DTREnable = False
MSComm1.EOFEnable = False
MSComm1.Handshaking = comNone
MSComm1.InBufferSize = 1024
MSComm1.InputLen = 0
MSComm1.InputMode = comInputModeText
MSComm1.NullDiscard = False
MSComm1.OutBufferSize = 512
MSComm1.RTSEnable = False
MSComm1.SThreshold = 0
' MSComm1.RThreshold = 0 'this value should be different from
'default value 0 when using an OnComm event
MSComm1.RThreshold = 1
MSComm1.Settings = "9600,N,8,1"
MSComm1.CommPort = 1 'select COM-Port
If MSComm1.PortOpen = False Then MSComm1.PortOpen = True
End Sub
' Even if already set-up, a confirmation
Private Sub InitBrainStem2()
' IIC bus baud rate 100 Khz
BSTEM = 2
bbuff(0) = 3
bbuff(1) = cmdVAL_SET
bbuff(2) = 3
bbuff(3) = 0
Call sendPacketVB
' Set Internal HeartBeat
bbuff(0) = 3
bbuff(1) = cmdVAL_SET
bbuff(2) = 5
bbuff(3) = 1
Call sendPacketVB
' DIG 0 I/O Input
bbuff(0) = 3
bbuff(1) = cmdDIG_CFG
bbuff(2) = 0
bbuff(3) = 0
Call sendPacketVB
' DIG 1 I/O Input
bbuff(0) = 3
bbuff(1) = cmdDIG_CFG
bbuff(2) = 1
bbuff(3) = 0
Call sendPacketVB
' DIG 2 I/O Input
bbuff(0) = 3
bbuff(1) = cmdDIG_CFG
bbuff(2) = 2
bbuff(3) = 0
Call sendPacketVB
' DIG 3 I/O Input
bbuff(0) = 3
bbuff(1) = cmdDIG_CFG
bbuff(2) = 3
bbuff(3) = 0
Call sendPacketVB
' DIG 4 I/O Input
bbuff(0) = 3
bbuff(1) = cmdDIG_CFG
bbuff(2) = 4
bbuff(3) = 0
Call sendPacketVB
End Sub
Private Sub InitBrainStem4()
' IIC bus baud rate 100 Khz
BSTEM = 4
bbuff(0) = 3
bbuff(1) = cmdVAL_SET
bbuff(2) = 3
bbuff(3) = 0
Call sendPacketVB
' Set Internal HeartBeat
bbuff(0) = 3
bbuff(1) = cmdVAL_SET
bbuff(2) = 5
bbuff(3) = 1
Call sendPacketVB
' DIG 0 I/O Input
bbuff(0) = 3
bbuff(1) = cmdDIG_CFG
bbuff(2) = 0
bbuff(3) = 0
Call sendPacketVB
' DIG 1 I/O Input
bbuff(0) = 3
bbuff(1) = cmdDIG_CFG
bbuff(2) = 1
bbuff(3) = 0
Call sendPacketVB
' DIG 2 I/O Input
bbuff(0) = 3
bbuff(1) = cmdDIG_CFG
bbuff(2) = 2
bbuff(3) = 0
Call sendPacketVB
' DIG 3 I/O Input
bbuff(0) = 3
bbuff(1) = cmdDIG_CFG
bbuff(2) = 3
bbuff(3) = 0
Call sendPacketVB
' DIG 4 I/O Input
bbuff(0) = 3
bbuff(1) = cmdDIG_CFG
bbuff(2) = 4
bbuff(3) = 0
Call sendPacketVB
End Sub
' a cmd button to initialize the BrainStem cards and save the bits
Private Sub cmdINITBrainStem_Click()
InizializzazioneBrainStem2
bbuff(0) = 1
bbuff(1) = cmdVAL_SAV
Call sendPacketVB
InizializzazioneBrainStem4
bbuff(0) = 1
bbuff(1) = cmdVAL_SAV
Call sendPacketVB
End Sub
' Get Packet as it is
Private Sub sendPacketVB()
Dim i As Integer
Dim SendString As String
SendString = ""
SendString = Chr(BSTEM)
SendString = SendString & Chr(bbuff(0))
For i = 1 To bbuff(0)
SendString = SendString & Chr(bbuff(i))
Next
MSComm1.Output = SendString
End Sub
' Get Packet with added the readiong of the complete input string from the device
Private Sub getPacketVB()
Dim txtBuff As String
Dim i As Integer
Dim c As Long
Dim BuffLength
Dim Len_txtBuff As Integer
MSComm1.InBufferCount = 0 ' clear inBuffer
Do ' wait for incoming bytes
DoEvents
Loop Until MSComm1.InBufferCount > 0
txtBuff = MSComm1.Input
BuffLength = Len(txtBuff) ' number of received bytes
' (<= 4 bytes)
BSTEM = Asc(Mid(txtBuff, 1, 1)) ' get module number
bbuff(0) = Asc(Mid(txtBuff, 2, 1)) ' get packet size
If BuffLength < 2 + bbuff(0) Then ' if received bytes < packet size
MSComm1.InBufferCount = 0 ' do it again
Do
DoEvents
Loop Until MSComm1.InBufferCount > 0
txtBuff = txtBuff & MSComm1.Input
End If
For i = 3 To Len(txtBuff) ' write received data
c = Asc(Mid(txtBuff, i, 1)) ' to array bbuff()
bbuff(i - 2) = c
Next
Buff_STR = ""
For i = 1 To Len(txtBuff)
Buff_STR = Buff_STR + Str(Asc(Mid(txtBuff, i, 1)))
Next
End Sub
' readIR02_VB as it is
Function readIR02_VB(moduleNR) As Byte ' just an example
BSTEM = moduleNR
bbuff(0) = 2
bbuff(1) = cmdIR02_RD
bbuff(2) = 128
Call sendPacketVB
Call getPacketVB
readIR02_VB = bbuff(3)
End Function
' Routine to pilot servos on cards
Sub servoabs(moduleNR As Byte, ByVal bnum As Byte, ByVal babs As Byte)
BSTEM = moduleNR
bbuff(0) = 3
bbuff(1) = cmdSRV_ABS
bbuff(2) = bnum
bbuff(3) = babs
Call sendPacketVB
End Sub
' to reading A2D 10 bits inputs on cards
Function A2D(moduleNR As Byte, ByVal bnum As Byte) As Integer
BSTEM = moduleNR
bbuff(0) = 2
bbuff(1) = cmdA2D_RD
bbuff(2) = bnum
Call sendPacketVB
Call getPacketVB
A2D = DecToHex(CDbl(bbuff(3)), CDbl(bbuff(4)))
End Function
' to reading Digital inputs on cards
Function DIG_RD(moduleNR As Byte, ByVal bnum As Byte) As Byte
BSTEM = moduleNR
bbuff(0) = 2
bbuff(1) = cmdDIG_IO
bbuff(2) = bnum
Call sendPacketVB
Call getPacketVB
DIG_RD = bbuff(3)
End Function
' to writing Digital inputs on cards
Sub DIG_WR(moduleNR As Byte, ByVal bnum As Byte, babs As Byte)
BSTEM = moduleNR
bbuff(0) = 2
bbuff(1) = cmdDIG_IO
bbuff(2) = bnum
bbuff(3) = babs
Call sendPacketVB
End Sub
' to reading the SRF08 from By Register #
' Register Number 2 for reading the first echo
Function SRF08_(Register_Num As Integer)
Dim i As Integer
BSTEM = SRF08_Ad
bbuff(0) = 2
bbuff(1) = 0
bbuff(2) = 81
Call sendPacketVB
Sleep 80
bbuff(0) = 1
bbuff(1) = Register_Num
Call sendPacketVB
BSTEM = 2
bbuff(0) = 4
bbuff(1) = 37
bbuff(2) = 128
bbuff(3) = 225
bbuff(4) = 2
Call sendPacketVB
SRF08_ = SRF08_RD
End Function
' to reading the light sensor
Function SRF08_Light_()
Dim i As Integer
BSTEM = SRF08_Ad
bbuff(0) = 2
bbuff(1) = 0
bbuff(2) = 81
Call sendPacketVB
Sleep 80
bbuff(0) = 1
bbuff(1) = 0
Call sendPacketVB
BSTEM = 2
bbuff(0) = 4
bbuff(1) = 37
bbuff(2) = 128
bbuff(3) = 225
bbuff(4) = 2
Call sendPacketVB
SRF08_Light_ = SRF08_Light_RD
End Function
' To reading the Compass
Function CMPS03_()
BSTEM = CMPS03_Ad
bbuff(0) = 1
bbuff(1) = 2
Call sendPacketVB
BSTEM = 2
bbuff(0) = 4
bbuff(1) = 37
bbuff(2) = 128
bbuff(3) = 193
bbuff(4) = 2
Call sendPacketVB
CMPS03_ = CMPS03_RD
End Function
' Cmd Buttons on the form to run the reading
' and showing the full string and the measurement
Private Sub cmdGP2D02DX_Click()
GP2D02DX.Text = readIR02_VB(2)
GP2D02DXBuff.Text = Buff_STR
End Sub
Private Sub cmdGP2D02SX_Click()
GP2D02SX.Text = readIR02_VB(4)
GP2D02SXBuff.Text = Buff_STR
End Sub
Private Sub cmdGP2D120_Click()
GP2D120.Text = A2D(4, 129)
GP2D120Buff.Text = Buff_STR
End Sub
Private Sub cmdGP2D12_FW_Click()
Distance_GP2D12FW = A2D(4, 128)
GP2D12FW.Text = Distance_GP2D12FW
GP2D12FWBuff.Text = Buff_STR
End Sub
Private Sub cmdGP2D12_BW_Click()
GP2D12BW.Text = A2D(2, 128)
GP2D12BWBuff.Text = Buff_STR
End Sub
Private Sub cmdSRF08_Click()
Distance_SRF08 = SRF08_(2)
SRF08.Text = Distance_SRF08
SRF08Buff.Text = Buff_STR
End Sub
Private Sub cmdSRF08_Light_Click()
SRF08_Light.Text = SRF08_Light_
SRF08_Light_Buff.Text = Buff_STR
End Sub
Private Sub cmdCMPS03_Click()
CMPS03.Text = CMPS03_
CMPS03Buff.Text = Buff_STR
End Sub
' Scanning Timer for repetitive readings
Private Sub Scan_timer()
Sleep 100
cmdGP2D02DX_Click
Sleep 100
cmdGP2D02SX_Click
Sleep 100
cmdGP2D120_Click
Sleep 100
cmdGP2D12_FW_Click
Sleep 100
cmdGP2D12_BW_Click
Sleep 100
cmdSRF08_Click
Sleep 100
cmdSRF08_Light_Click
Sleep 100
cmdCMPS03_Click
End Sub
' Supporting function to reading the SRF08 (similar to GetPacketVB)
Function SRF08_RD()
Dim txtBuff As String
Dim i As Integer
Dim c As Long
Dim BuffLength
Dim Len_txtBuff As Integer
MSComm1.InBufferCount = 0 ' clear inBuffer
Do ' wait for incoming bytes
DoEvents
Loop Until MSComm1.InBufferCount > 0
txtBuff = MSComm1.Input
BuffLength = Len(txtBuff) ' number of received bytes
' (<= 4 bytes)
BSTEM = Asc(Mid(txtBuff, 1, 1)) ' get module number
bbuff(0) = Asc(Mid(txtBuff, 2, 1)) ' get packet size
If BuffLength < 2 + bbuff(0) Then ' if received bytes < packet size
MSComm1.InBufferCount = 0 ' do it again
Do
DoEvents
Loop Until MSComm1.InBufferCount > 0
txtBuff = txtBuff & MSComm1.Input
End If
Buff_STR = ""
For i = 1 To Len(txtBuff)
Buff_STR = Buff_STR + Str(Asc(Mid(txtBuff, i, 1)))
Next
If Len(txtBuff) = 6 Then
SRF08_RD = Asc(Mid(txtBuff, 5, 1)) * 256 + Asc(Mid(txtBuff, 6, 1))
End If
End Function
' Supporting function to reading the SRF08 Light Sensor (similar to GetPacketVB)
Function SRF08_Light_RD()
Dim txtBuff As String
Dim i As Integer
Dim c As Long
Dim BuffLength
Dim Len_txtBuff As Integer
MSComm1.InBufferCount = 0 ' clear inBuffer
Do ' wait for incoming bytes
DoEvents
Loop Until MSComm1.InBufferCount > 0
txtBuff = MSComm1.Input
BuffLength = Len(txtBuff) ' number of received bytes
' (<= 4 bytes)
BSTEM = Asc(Mid(txtBuff, 1, 1)) ' get module number
bbuff(0) = Asc(Mid(txtBuff, 2, 1)) ' get packet size
If BuffLength < 2 + bbuff(0) Then ' if received bytes < packet size
MSComm1.InBufferCount = 0 ' do it again
Do
DoEvents
Loop Until MSComm1.InBufferCount > 0
txtBuff = txtBuff & MSComm1.Input
End If
Buff_STR = ""
For i = 1 To Len(txtBuff)
Buff_STR = Buff_STR + Str(Asc(Mid(txtBuff, i, 1)))
Next
If Len(txtBuff) = 6 Then
SRF08_Light_RD = Asc(Mid(txtBuff, 6, 1))
End If
End Function
' Supporting function to reading the CMPS03 angular value into
' degrees (similar to GetPacketVB)
Function CMPS03_RD()
Dim txtBuff As String
Dim i As Integer
Dim c As Long
Dim BuffLength
Dim Len_txtBuff As Integer
MSComm1.InBufferCount = 0 ' clear inBuffer
Do ' wait for incoming bytes
DoEvents
Loop Until MSComm1.InBufferCount > 0
txtBuff = MSComm1.Input
BuffLength = Len(txtBuff) ' number of received bytes
' (<= 4 bytes)
BSTEM = Asc(Mid(txtBuff, 1, 1)) ' get module number
bbuff(0) = Asc(Mid(txtBuff, 2, 1)) ' get packet size
If BuffLength < 2 + bbuff(0) Then ' if received bytes < packet size
MSComm1.InBufferCount = 0 ' do it again
Do
DoEvents
Loop Until MSComm1.InBufferCount > 0
txtBuff = txtBuff & MSComm1.Input
End If
Buff_STR = ""
For i = 1 To Len(txtBuff)
Buff_STR = Buff_STR + Str(Asc(Mid(txtBuff, i, 1)))
Next
If Len(txtBuff) = 6 Then
CMPS03_RD = (Asc(Mid(txtBuff, 5, 1)) * 256 + Asc(Mid(txtBuff, 6, 1))) / 10
End If
End Function
' 10 bit A2D reading supporting function routine
Private Function DecToHex(Byte_1 As Integer, Byte_2 As Integer)
Dim A2D_String_Reading As String
Dim Most_Byte_1 As String
Dim Least_Byte_1 As String
Dim Most_Byte_2 As String
If Byte_1 < 16 Then
Most_Byte_1 = BinValue_(0)
Least_Byte_1 = BinValue_(Mid(Hex(Byte_1), 1, 1))
Else
Most_Byte_1 = BinValue_(Mid(Hex(Byte_1), 1, 1))
Least_Byte_1 = BinValue_(Mid(Hex(Byte_1), 2, 1))
End If
If Byte_2 < 16 Then
Most_Byte_2 = BinValue_(0)
Else
Most_Byte_2 = BinValue_(Mid(Hex(Byte_2), 1, 1))
End If
A2D_String_Reading = Most_Byte_1 + Least_Byte_1 + Most_Byte_2
DecToHex = Decimalvalue(A2D_String_Reading)
End Function
' 10 bit A2D reading supporting function routine
Private Function Decimalvalue(Value As String) As Integer
Dim de_power As Integer
Dim i As Integer
de_power = 0
For i = Len(Value) To 1 Step -1
de_power = Mid(Value, i, 1) * 2 ^ (Len(Value) - i) + de_power
Next
Decimalvalue = de_power
End Function
' 10 bit A2D reading supporting function routine
Private Function BinValue_(Value As String) As String
Select Case Value
Case "0"
BinValue_ = "0000"
Case "1"
BinValue_ = "0001"
Case "2"
BinValue_ = "0010"
Case "3"
BinValue_ = "0011"
Case "4"
BinValue_ = "0100"
Case "5"
BinValue_ = "0101"
Case "6"
BinValue_ = "0110"
Case "7"
BinValue_ = "0111"
Case "8"
BinValue_ = "1000"
Case "9"
BinValue_ = "1001"
Case "A"
BinValue_ = "1010"
Case "B"
BinValue_ = "1011"
Case "C"
BinValue_ = "1100"
Case "D"
BinValue_ = "1101"
Case "E"
BinValue_ = "1110"
Case "F"
BinValue_ = "1111"
End Select
End Function
Additional Information Claudio Concilio put together additional supplemental information about this example that covers the example robot's evolution, the project's overview and Visual Basic 5 code with detailed explanation.
Revision History:
| |||||||||||
Related Examples: Using a BrainStem as a Serial Slave Device with a BasicX Controller Slave Control of BrainStem with a BasicX and Microsfot Visual Basic Example | ||||||||||||
| voice: 720-564-0373, email: sales@acroname.com, address: 4822 Sterling Dr., Boulder CO, 80301-2350, privacy © Copyright 1994-2008 Acroname, Inc., Boulder, Colorado. All rights reserved. | ||||||||||||