FreeBasic SSC-32 Interpreter

This program was developed to operate Peter Penguin, an animatronic that I am building, through a Lynxmotion SSC-32 Servo controller. The objective was to allow me to write ‘scripts’ in a naturally descriptive manner. For example:

  1. Move eyes left
  2. Squint
  3. Turn head right
  4. Move eyes right slowly
  5. Open eyes
  6. Face forward

In the end, the project became a mini-programming like language, with directives such as Define Moves (creating a lookup table between the English description and the corresponding controller commands), Play Move, Start Script (to allow parallel execution of moves), Jump To {label}, Synchronize between scripts, Pause, etc…
The code is organized into three major sections:

  1. Define Moves
  2. Pre-Process all ‘scripts’ for a ‘show’
  3. Execute the scripts;

‘Define Moves’ reads the lookup table from a file (the ‘show’ data) and loads the description/controller commands into an array.

‘Pre-Process’ the scripts converts the natural language descriptions and moves, into integer codes and array indices to either the controller command or to another location within the script. Each line in a script consists of three values, some of which are optional depending on the action. Action is what the line does, for example “PlayMove” sends a command to the SSC-32. Description is a user-friendly name for the action or move, such as “Move Eyes Right Slowly”. The third value is a numeric value and in most cases represents time in ms, often to specify a delay after sending a command to the SSC-32. During this delay, the software can continue to process other actions.

‘Execute’ the scripts performs the actions defined in the show file, moving the penguin according to the defined script(s). The feature of being able to define multiple scripts is similar to having two GP players available on the SSC-32, only you can define more than two series of commands to execute in parallel (well, kinda in parallel… More like alternating commands from different scripts and using the delay time in the moves to execute other moves - timesharing). On my penguin, I can have one script moving the head, a second script moving the arms and a third script controlling the torso. The multi-tasking is done via software in this portion of the code. If you look at the source code attached, you also may note that moving the mouth – speaking – will be done in parallel with other moves; I will start an external process to play a .wav file and while it is running, the code will be performing A/D input from the circuit I developed (See my post viewtopic.php?f=2&t=6113) and moving the penguin mouth in synch.

Here is an example of the data file/script:

[code]Begin,Moves
Look ahead,#0P1500 #1P1500
Look right,#0P1100 #1P1100
Look left,#0P2000 #1P2000
Cross-eyed,#0P2000 #1P1100
Look right slowly,#0P1100 #1P1100 T1500
Look ahead slowly,#0P1500 #1P1500 T1500
Look left slowly,#0P2000 #1P2000 T1500
Open eyes,#2P750
Close eyes,#2P2000
Blink eyes,#2P1200
Squint eyes,#2P1000
Squint eyes slowly,#2P1000 T2000
Open eyes slowly,#2P750 T3000
Close eyes slowly,#2P2000 T3000
Close Mouth,#3P570
Open Mouth 1,#3P600
Open Mouth 2,#3P680
Open Mouth 3,#3P790
Open Mouth Wide,#3P1005
End,Moves

StartScript,Main,0
Label, Repeat moves,
PlayMove,Look right,20
PlayMove,Look ahead,100
PlayMove,Look right slowly,20
ScriptPause,-,2000
PlayMove,Look ahead,20
ScriptPause,-,2000
PlayMove,Blink eyes,10
PlayMove,Open eyes,200
PlayMove,Blink eyes,10
PlayMove,Open eyes,200
PlayMove,Blink eyes,10
PlayMove,Open eyes,200
PlayMove,Squint eyes slowly,2000
PlayMove,Look right slowly,2000
PlayMove,Look left slowly,2000
PlayMove,Look ahead,1000
PlayMove,Open eyes,30
JumpTo,Repeat Moves.
EndScript,Main,0
End,Scripts
[/code]

Eventually, I want to add additional sensors and conditional logic to the program, so that when alone or no one is near, the penguin will shift, flap his wings, blink and perform various bored movements seemingly at random. Then, when someone approaches, he will turn to look at them and react somehow… sometimes shyly… sometimes with a greeting… sometimes with a song!
Animatron.bas (6.85 KB)

This is a perfect example of how easy it is to make an animatronic show from simple off the shelf components and simple programming. Excellent work! 8)

Some additional details. I have been adding functionality to the program and debugged it once I had Peter assembled. For those of you who read code, the current version is attached. On request, I will supply sample data files…

“Animatron” has the following command set:

PlayMove = send commands to SSC-32
Say = play external sound file; will cause a servo (e.g. mouth servo) to synchronize to sound
PlayScript = execute multiple scripts in parallel; script must be defined in same file
ScriptPause = “Pause” or “Delay” command; pauses execution for n milliseconds
StartScript = define new script; main script MUST be last in file
EndScript = end of script routine definition
JumpTo = “goto” command; label MUST exist (is not checked for)
Label = definition of label used in “JumpTo” command
SyncPoint = definition of scripts which will synchronize with other script(s)
EndSync = definition of step in script at which to wait for synchronization

Right now, I am adding a “Random” command to this list, that will randomly pick from a selected group of actions to take, whether a single group move or a command (i.e., “Playscript”) to play a sequence. That way, Peter can loop his actions and not do the same thing every time.

Also, once Peter has sensors added, the software will include conditional execution and the scripting commands will by definition become a true programming language. One other option is to use the program to generate code for one or more of the microprocessors Lynxmotion sells.
Animatron.bas (10.7 KB)

this is a nice way of executing movement. nice work. :wink:

i like the “random” feature. looking to use something like this in my project.

Great work!

That is a pretty neat feature. I would guess this work only as long as the scripts doesn’t involve the same servo?

Thanks for sharing your code! :smiley:

It is written with the expectation that the multiple scripts would not use the same servo. If you did, the results would be unexpected as the scripts running in parallel would fight over control. Thinking about it, using the SyncPoint and EndSync commands, it might be possible for parallel scripts to cooperate. Theoretically of course. I’ll have to test that. :wink:

The random mode is good, you might also want to consider reading some sensors, such as proximity (a person is near), temperature, light (maybe he nods off when the lights drop!), etc. Basically, a shift in behaviors due to stimuli.

Maybe Peter likes a little sprinkle of water!

Alan KM6VV

*Once Peter has sensors added, the software will include conditional execution *and the scripting commands will by definition become a true programming language. Then he will react to his surroundings. Perhaps even eventually be able to respond to voice with appropriate responses.

Peter would probably like more than a “sprinkle” of water - more like a dive! Perhaps I can add an olfactory sensor so he can react when he smells mackerel :wink:

Below is a talking bird.

shopgadgetsandgizmos.com/product/2319/

That’s the stupidest thing I’ve seen in a long time.

Yes, but under the right circumstances even stupid sells.

I was able to get the random movement programming done in my Animatron basic program. Peter has been doing his own thing beside me while I type this description for you all. Here is my test script that has been running…

Startscript,Main,0 Label,DoItAgain,0 RandomMove,Head Fakes,12 Playmove,Look ahead,500 Playmove,Look right,500 Playmove,Look left,500 Playmove,Look right slowly,1500 Playmove,Look ahead slowly,1500 Playmove,Look left slowly,1500 Playmove,Face Right,500 Playmove,Face Forward,500 Playmove,Face Left,500 Playmove,Face Right Slow,2000 Playmove,Face Forward Slow,2000 Playmove,Face Left Slow,2000 JumpTo,DoItAgain,0 Endscript,Main,0

It was not too difficult to fit the logic into the structure of the existing program. Defining the command 'RandomMove" was similar to the SyncPoint, EndSync and Scriptpause commands; that is I only needed to define the action and a single value.

RandomMove only needs to know how many different commands it can select from when making a choice. It then uses a random number generator to pick one of them to execute next, and sets the script’s pointer to that command. The trick was to resume execution AFTER the block of commands (repeating the random selection process was easy, as the program already had a ‘Label’ and ‘JumpTo’ command). In order to do this, RandomMove also calculates the next step after the defined block of possible moves.

I defined a state variable that was then used when selecting the next command to execute. There are three defined states: No need to adjust the next step, within the random selection, so execute the current step, but set the state so that NEXT time, the command after the defined block of moves is executed.

Right now, the moves are purely random. The sample script I have included just moves his head and eyes back and forth – but it is enjoyable to see Peter move on his own - i.e. unscripted.
A current code listing follows…

[code]#include once “windows.bi”
#include once “win/mmsystem.bi”
’ ===========================================================================
’ ===========================================================================
’ ===========================================================================
’ ===========================================================================

Declare Function FindIt (array() As String, What As String) As Integer
Declare Function DisplayStep (i As Integer, j As Integer) As String

ReDim MoveDescription(0) As String ’ Move lookup table: description of move, e.g. “Move Eyes Left”
ReDim MoveCommand(0) As String ’ actual servo move command, e.g. “#0P2000 #1P2000 T100”
Dim MoveIndex As Integer =0 ’ array index of Move arrays

ReDim LabelDescription(0) As String ’ Label lookup table; name of label or script
ReDim LabelScriptIndex(0) As Integer ’ index to step after label in script arrays
Dim LabelIndex As Integer =0 ’ array index for Label arrays

ReDim PlayerStep(0) As Integer ’ Player properties: index to step in script to execute next
ReDim As Double PlayerEndWait(0) ’ array of time before next command is issued, by player
PlayerEndWait(0)=0
Dim As Double SoundEndWait=0 ’ timer value before next check of ADC for voice/sound input, ~12ms from last test.
Dim Player As Integer =0

ReDim ScriptAction(0) As Integer ’ Script properties: action to take
ReDim ScriptDescription(0) As Integer ’ Index to servo move table
ReDim ScriptOption(0) As Integer ’ value for action, i.e. pause length after command is issued
Dim ScriptStep As Integer =0, MainScript As Integer =0
Dim ErrorFound As Integer =0

’ Properties for executing a random move from a selection of ‘n’ commands
’ also, can be used for other non-linear execution plans for a script.
Const NoAdjustStepAction = 1 ’ constant values to indicate the state of processing a random move
Const InRandomSelection = 2
Const AdjustStepAction = 3
ReDim As Integer AdjustStep(0) ’ state variable for adjusting the step
’ while processing a random move
Dim As Integer Selections ’ variable to store the possible number of random moves from which to select
ReDim As Integer NextStep(0) ’ variable which will point to the step AFTER a random move block
Randomize

ReDim SyncPoints(0) As ULongInt ’ flags for sync points; bit encoded by associated players
Dim SyncPointStatus As ULongInt =0
Dim SyncPointIndex As Integer =0

Dim IndexPlayers As Integer = 0, MaxPlayers As Integer =0, NotDone As Integer =-1 ’ script player definitions

'Speech variables
Dim As String dat, ssc32cmd, PW, qs, cr
Dim As Integer level
Dim soundFile As String

'Control variables
Dim As String ControlKey
Dim SingleStep As Integer = 0
Const PauseKey=""
Const Esc = Chr(27)

'SSC-32 constants
Const scbase="#3P"
qs = “VA” + Chr(13)
cr = Chr(13)

’ Prepare Show
Dim CommPort As String ’ serial port connected to servo controller (SSC-32)
Dim Animatron As String ’ name of file containing mapping between move descriptions and SSC-32 commands
Dim ShowName As String ’ name of file containing a script for a given “show”
Const dfltCommPort = “com4:”
Const dfltMoves = “peter.csv”
Const dfltScript = “Peter-Live.csv”

’ connection to servo controller (SSC-32)
Print "Comm port “;dfltCommPort;”]: ";
Input CommPort
If CommPort = “” Then CommPort = dfltCommPort

’ short description to servo controller (SSC-32) commands mappings
Print “Character/Move file name “;dfltMoves;”]:”;
Input Animatron
If Animatron = “” Then Animatron = dfltMoves
Open Animatron For Input As #1

’ script file
Print "Show file name “;dfltScript;”]: ";
Input ShowName
If ShowName = “” Then ShowName = dfltScript

’ ===========================================================================
’ ===========================================================================
’ Define Moves (lookup table)
’ ===========================================================================
’ ===========================================================================

’ read in short description and corresponding SSC-32 command
Dim Move As String , CtrlrCmd As String
Do While Not Eof(1)And ErrorFound =0
Input #1, Move, CtrlrCmd
If UCase(Move) = “END” Then Exit Do
MoveIndex += 1
ReDim Preserve MoveDescription(MoveIndex)As String, MoveCommand(MoveIndex)As String
MoveDescription(MoveIndex) = Move
MoveCommand(MoveIndex) = CtrlrCmd+cr
Loop
Close #1

’ ===========================================================================
’ ===========================================================================
’ Define Script(s)
’ ===========================================================================
’ ===========================================================================

Open ShowName For Input As #1

Dim Action As String, Description As String, OptionValue As Integer, LocalIndex As Integer
Const PlayMove As Integer =0 ’ send commands to SSC-32
Const PlayScript As Integer =1 ’ execute script in parallel; script must be defined in same file
Const StartScript As Integer=2 ’ define new script; main script MUST be last in file
Const EndScript As Integer =3 ’ end of script routine definition
Const JumpTo As Integer =4 ’ “goto” command; label MUST exist (is not checked for)
Const Label As Integer =5 ’ definition of label used in “JumpTo” command
Const SyncPoint As Integer =6 ’ definition of scripts which will synchronize with other script(s)
Const EndSync As Integer =7 ’ definition of step in script at which to wait for synchronization
Const ScriptPause As Integer=8 ’ “Pause” or “Delay” command; pauses execution for n milliseconds
Const Say As Integer=9 ’ play external sound file; will cause servo defined in “scbase” (e.g. mouth servo) to synchronize to sound
Const RandomMove As Integer=10 ’ Randomly perform on of the following ‘n’ actions; n is the option value

Do While Not Eof(1) And ErrorFound =0
Input #1, Action, Description, OptionValue
Print Action, Description, OptionValue

Select Case UCase(Action)
	
	Case "PLAYMOVE"
		ScriptStep +=1
		ReDim Preserve ScriptAction(ScriptStep), ScriptDescription(ScriptStep), ScriptOption(ScriptStep) 
		ScriptAction(ScriptStep) = PlayMove
		LocalIndex = FindIt(MoveDescription(), Description)
		If LocalIndex < 0 Then
			Print "Cannot find move ";Description
			ErrorFound=1
			Exit Do 
		Else 
			ScriptDescription(ScriptStep) = LocalIndex
		EndIf
		ScriptOption(ScriptStep) = OptionValue
	
	Case "STARTSCRIPT", "LABEL"
		LabelIndex +=1
		ReDim Preserve LabelDescription(LabelIndex) As String, LabelScriptIndex(LabelIndex)As Integer
		LabelDescription(LabelIndex) = Description
		LabelScriptIndex(LabelIndex)=ScriptStep+1
		If UCase(Action) = "STARTSCRIPT" Then MainScript=ScriptStep+1
		
	Case "PLAYSCRIPT", "JUMPTO"
		ScriptStep+=1
		ReDim Preserve ScriptAction(ScriptStep) As Integer, ScriptDescription(ScriptStep) As Integer, ScriptOption(ScriptStep) As Integer 
		If UCase(Action) = "PLAYSCRIPT" Then
			ScriptAction(ScriptStep)=PlayScript
		Else
			ScriptAction(ScriptStep)=JumpTo
		EndIf
		LocalIndex = FindIt(LabelDescription(), Description)
		If LocalIndex < 0 Then
			Print "Cannot find script or label ";Description
			ErrorFound=2
			Exit Do 
		Else 
			ScriptDescription(ScriptStep) = LabelScriptIndex(LocalIndex)
		EndIf
	
	Case "SAY"
		LabelIndex +=1
		ReDim Preserve LabelDescription(LabelIndex) As String, LabelScriptIndex(LabelIndex)As Integer
		LabelDescription(LabelIndex) = Description
		LabelScriptIndex(LabelIndex)=ScriptStep+1
		ScriptStep +=1
		ReDim Preserve ScriptAction(ScriptStep) As Integer, ScriptDescription(ScriptStep) As Integer, ScriptOption(ScriptStep) As Integer 
		ScriptAction(ScriptStep) = Say
		ScriptDescription(ScriptStep) = LabelIndex

	Case "ENDSCRIPT"
		ScriptStep +=1
		ReDim Preserve ScriptAction(ScriptStep) As Integer, ScriptDescription(ScriptStep) As Integer, ScriptOption(ScriptStep) As Integer 
		ScriptAction(ScriptStep) = EndScript
		
	Case "SYNCPOINT", "ENDSYNC", "SCRIPTPAUSE", "RANDOMMOVE"
		ScriptStep+=1
		ReDim Preserve ScriptAction(ScriptStep) As Integer, ScriptDescription(ScriptStep) As Integer, ScriptOption(ScriptStep) As Integer 
		If UCase(Action)="SYNCPOINT" Then
			If OptionValue>SyncPointIndex Then SyncPointIndex=OptionValue
			ScriptAction(ScriptStep)=SyncPoint
		ElseIf UCase(Action)="ENDSYNC" Then
			ScriptAction(ScriptStep)=EndSync
		ElseIf  UCase(Action)="RANDOMMOVE" Then 
			ScriptAction(ScriptStep)=RandomMove
		Else
			ScriptAction(ScriptStep)=ScriptPause
		EndIf
		ScriptDescription(ScriptStep)=OptionValue
		ScriptOption(ScriptStep)=OptionValue

	Case Else
		Print "Unrecognized script command"
		ErrorFound=4
		Sleep
		Exit Do 			

End Select

Loop

Close #1
If ErrorFound Then End ErrorFound

’ ===========================================================================
’ ===========================================================================
’ Execute processed Script(s)
’ ===========================================================================
’ ===========================================================================

If timeBeginPeriod( 1 ) = TIMERR_NOCANDO Then
Print “Specified period is out of range”
ErrorFound=3
End If
If ErrorFound Then End ErrorFound

Open Com CommPort+" 115200,N,8,1,BIN,CD,CS,DS,RS" For Binary As #1
If Err Then
Print "Could not open ";CommPort
EndIf

’ initialize sound subsystem
Put #1,qs
Sleep 12
dat=Input$(Loc(1),#1)

’ define first step
MaxPlayers=0
ControlKey=""
PlayerStep(MaxPlayers) = MainScript
AdjustStep(MaxPlayers)=NoAdjustStepAction
ReDim SyncPoints(SyncPointIndex) As ULongInt

Print “Starting to play script at “;Mainscript
Print UBound(ScriptAction);” steps in script”
Print
Print “Press any key to start”;
Sleep
ControlKey=InKey

Print “”
Print “Press <> key to pause, key to resume,”
Print " to enter/leave single step mode,"
Print " to step through script,"
Print " key to stop execution and leave the program."
Print “3…”
Sleep 1000
Print “2…”
Sleep 1000
Print “1…”
Sleep 1000
Print “!”
ControlKey=“x”

Do While ControlKey <> ""
	ControlKey=InKey 
	Sleep 1
Loop

Do While NotDone ’ “NotDone” is true until the main script executes an “EndScript” command
For Player=0 To MaxPlayers ’ “Player = 0” is the main script

’ Speech processing …
If (SoundEndWait-Timer <0) Then
dat = Input$(Loc(1), #1)

		If dat = "" Then
			' Print "No data"
		Else
			level = Asc(dat)
			' Print "Level ";level
			Select Case level
				Case 0 To 12
					PW="600"
				Case 13 To 25
					PW="700"
				Case 25 To 255
					PW="800"
			End Select
	
			ssc32cmd=scbase+PW+cr
			'Print "Command = ";ssc32cmd
			Put #1,, ssc32cmd 
		End If 

		Put #1,,qs
		SoundEndWait=Timer+.012
	EndIf
	
	
	If ((PlayerEndWait(Player)-Timer)< 0) And (PlayerStep(Player)<>0) Then
		PlayerEndWait(Player)=0
		Select Case AdjustStep(Player)
			Case NoAdjustStepAction
				ScriptStep=PlayerStep(Player)
			Case InRandomSelection
				ScriptStep=PlayerStep(Player)
				AdjustStep(Player)=AdjustStepAction
			Case AdjustStepAction
				PlayerStep(Player)=NextStep(Player)
				ScriptStep=NextStep(Player)
				AdjustStep(Player)=NoAdjustStepAction
		End Select
		
	' Pause/Single Step script on request
	ControlKey=InKey 
	If ControlKey = PauseKey Then
		Print "Script paused per request"
		Sleep
		Print "Continuing..."
	ElseIf ControlKey = cr Then
		SingleStep = Not SingleStep
	ElseIf ControlKey = Esc Then
		NotDone=0
		Exit For 
	EndIf 
	If SingleStep Then 
		Print "Single ";
		Sleep
	EndIf


	
		Select Case ScriptAction(ScriptStep)
			
			Case PlayMove
				MoveIndex=ScriptDescription(ScriptStep)
				Print "Step ";DisplayStep(Player,ScriptStep);":  ";MoveDescription(MoveIndex),MoveCommand(MoveIndex)
				Put #1,,MoveCommand(MoveIndex)
				PlayerEndWait(Player)=Timer+ScriptOption(ScriptStep)/1000
				PlayerStep(Player)=ScriptStep+1

			Case ScriptPause
				Print "Step ";DisplayStep(Player,ScriptStep);":  ";
				Print Using "Pause #.###";(ScriptOption(ScriptStep)/1000)
				PlayerEndWait(Player)=Timer+ScriptOption(ScriptStep)/1000
				PlayerStep(Player)=ScriptStep+1

			Case PlayScript
				IndexPlayers=1
				Do While IndexPlayers <= MaxPlayers
					If PlayerStep(IndexPlayers)=0 Then Exit Do
					IndexPlayers+=1
				Loop
				If IndexPlayers>MaxPlayers Then 
					MaxPlayers+=1
					ReDim Preserve PlayerStep(MaxPlayers) As Integer, PlayerEndWait(MaxPlayers) As Double
					ReDim Preserve As Integer AdjustStep(MaxPlayers), NextStep(MaxPlayers)
				EndIf
				PlayerStep(IndexPlayers)=ScriptDescription(ScriptStep)
				PlayerEndWait(IndexPlayers)=0
				AdjustStep(IndexPlayers)=NoAdjustStepAction
				PlayerStep(Player)=ScriptStep+1
				Print "Step ";DisplayStep(Player,ScriptStep);":  Starting script on Player ";IndexPlayers
				
			Case EndScript
				PlayerStep(Player)=0
				NotDone = (Player<>0) ' main script has ended
				Print "Step ";DisplayStep(Player,ScriptStep);":  Scripts have completed on ";Player

			Case JumpTo
				Print "Step ";DisplayStep(Player,ScriptStep);":  Jump to";ScriptDescription(ScriptStep)
				PlayerStep(Player)=ScriptDescription(ScriptStep)
				
			Case SyncPoint
				SyncPointIndex=ScriptDescription(ScriptStep)
				Print "Step ";DisplayStep(Player,ScriptStep);":  Defining synchronization point ";SyncPointIndex
				If Player > 63 Then
					Print "Too many simultaneous Players...";Player
					Exit Do 
				EndIf
				SyncPoints(SyncPointIndex)=SyncPoints(SyncPointIndex) Or (2^Player)
				PlayerStep(Player)=ScriptStep+1
				
			Case EndSync
				SyncPointIndex=ScriptDescription(ScriptStep)
				If Player > 63 Then
					Print "Too many simultaneous Players...";Player
					Exit Do 
				EndIf
				SyncPointStatus= SyncPoints(SyncPointIndex) And (Not 2^Player)
				If SyncPointStatus <> SyncPoints(SyncPointIndex) Then
					Print "Step ";DisplayStep(Player,ScriptStep);":  Sync'ing to";SyncPointIndex;"  ";SyncPoints(SyncPointIndex);"]"
				EndIf
				SyncPoints(SyncPointIndex)= SyncPointStatus
				If SyncPoints(SyncPointIndex) = 0 Then 
					PlayerStep(Player)=ScriptStep+1
				EndIf

			Case RandomMove
				Selections=ScriptDescription(ScriptStep)
				NextStep(Player)=ScriptStep+Selections+1
				MoveIndex=Int(Rnd()*Selections)+1
				PlayerStep(Player)=ScriptStep+MoveIndex
				AdjustStep(Player)=InRandomSelection
				Print "Step ";DisplayStep(Player,ScriptStep);":  RandomMove of";Selections
			
			Case Say
				soundFile=LabelDescription(ScriptDescription(ScriptStep))
				Print "Step ";DisplayStep(Player,ScriptStep);":  Saying ";soundFile
				PlaySound(soundFile, NULL, SND_ASYNC Or SND_FILENAME)
				PlayerStep(Player)=ScriptStep+1
			
		End Select
	EndIf
	
Next
Sleep 1

Loop

timeEndPeriod( 1 )
Print “Press any key to finish”;
Print
Sleep

End

Function FindIt (AnArray() As String, What As String) As Integer
Dim i As Integer
For i=0 To UBound(AnArray)
If AnArray(I) = What Then Exit For
Next
If i > ubound(AnArray) Then i=-16384
Return i
End Function

Function DisplayStep(i As Integer, j As Integer) As String
Dim Display_Number As String =""
Display_Number = Right(" " & Str(i),2) & “-”+Left(Str(j) & " ",3)
Return Display_Number
End Function
[/code]
Edit 1-5-11: updated code after some bug fixes; the random selection can now successfully call other scripts and has been tested with up to six scripts/players running in parallel. Had to limit the number of players/simultaneous scripts to 64; more than the amount of servos available, so is not a limit practically! Also changed the display to show the player AND step being executed…
Animatron2.zip (4.21 KB)

The RandomMove command was so successful, I added a RandomPause command. When running multiple scripts, sometimes it seemed as if Peter had had too much coffee :open_mouth: . A pause command added to the random move selection helped, but a random pause command made his actions less predictable.

Hope to have a new video this weekend; still tweaking my show script.

Also, code has been added to accept commands over a TCP socket, in preparation for connecting an iPhone. I just need to parse the command like the pre-processor section of code does, in order to send the results to the SSC-32. Initially, it will accept just play move and play script commands from the iPhone or a telnet client. I can use the latter to test and also control Peter from another computer in the house. (If I had a fixed public IP address, he could be controlled over the Internet as well :bulb:.)

Dynamic ip services like below can fix that problem. I use the no-ip service.

no-ip.com/services/managed_d … c_dns.html
dyndns.com/services/dns/dyndns/

Thanks to zoomkat, I connected with dyndns.org.

After configuring my router, my son was able to use his iPad and control Peter over the Internet. 8)

Way cool

So I have been thinking about naming the scripting language that Animatron.bas implements.

I was thinking of “Animasic” combining animatron and BASIC. Someone on the BASIC forum told me about “gcode” for CNC; that made me think of acode or scode (for servo code), but both sounded boring…

Any other ideas?
dj

I like Gcode!

Yes, Acode could work for your efforts.

Alan KM6VV

I know this is an old post, but an article describing the program in more detail was just published in the online magazine Back2BASIC. If you’re interested, please check it out.

I hope Alan (KM6VV) notices that I agreed with his thoughts on using “A-code” for the name of the interpretive language.

dj

Nice work DJ!

It feels great to be published!

Alan KM6VV