November 21, 2024, 11:47:30 PM

News:

Be sure to checkout our Vixen interfaces in the Library forum -- if you want PC automation at near zero cost, EFX-TEK and Vixen is a great combination of tools.


Need a Program for Talking Skull

Started by brad g, April 12, 2007, 02:06:47 PM

Previous topic - Next topic

brad g

OK, when I started this topic on "Blending Servo Motion", Jon told me it was going to be complex, I just did'nt know HOW complex!
I'm muddling through programming, but at this rate I should be ready to attempt it in about 2 or 3 years, and it still wouldn't be half as good as anything you did.  I'm really good with hardware, not so hot with the software end. So, could I impose on you to write something that will make this thing work? What I'm "looking" to do is have the Prop1 turn on an mp3 player using a 12v relay, let it run it's course and have the program run two servos, left/right turn - up/down, to add a bit of "realism" to the skull. The jaw action and LED eyes will be run by an independant ST100 board that will be triggered when the mp3 comes on. The movements really don't need to be synchronized to the music, so any pattern will work fine.  I don't know if it can be done with the Prop1, but if possible, can two servos be run at the same time on this program, say left - up -center -down, or is this too complicated? The short of it is; Start the mp3,(song runs for exactly 2min., 28 sec.) run servos, shut off mp3.  The boards will be energized by a remote trigger, so I was hoping to get it to all come on as soon as it powered up, shut off at the end of it's run, and reset for the next power up. I'm starting to lose hair over this one, and I'd really appreciate the help!

JonnyMac

I told you that you were wading into tricky waters...  ;D

Okay, kidding aside, I already wrote you a program that you can modify in the "blending servos" thread; why won't that work?  The only change you need to make is on starting the audio.  I'm going to assume that since you're using a relay that you're hacking the MPJA player.  So, change the audio start section like this:

Start_Audio:
  HIGH Audio
  PAUSE 2000
  LOW Audio


This will kick-off that player.  You can use the same three lines (HIGH, PAUSE, LOW) of code to stop the player -- just put it under a separate label at the end of the sequence.

Look, I know that you're not yet a "software guy" but there's no reason you can't be -- it just takes a little practice.  Start easy, work your way up to the skull.
Jon McPhalen
EFX-TEK Hollywood Office

brad g

Okay, bear with me here a moment, I'll try not to sound too obtuse. On the first "Blending Servos" program you wrote, if I only want to run my two servos, I just delete the 3rd servo order from the program? Also, starting and stopping the mp3 I think I get, just place the start order at the beginning of the run, and the stop at the end, but I won't need to insert a pause as was discussed in the "Cheap MP3" thread, in it's place, I just run my servo program to the length I need and that will take the place of the pause command? Last, at least for the moment, after running the program, I will need to "trim" any excess servo moves from the program to fit the time of the song's running length of 2 min. and 28sec.s in order to get everything to shut down when I want it to? Sorry for all the questions, but I've been banging my head with this thing since late December!

JonnyMac

April 12, 2007, 07:56:59 PM #3 Last Edit: April 13, 2007, 02:55:31 PM by JonnyMac
Brad,

I don't think you're being obtuse, but I do kind of think that you've talked yourself into believing that this stuff (programming) is harder than it is.  It's really simple, I promise, and in the not-too-distance future you'll look back at this and laugh.  I'm certainly not the sharpest tool in the shed and I'm good at this stuff; you can be, too.

Below you find the updated program (two servos, MPJA MP3 player).  If you want it to run without a trigger then you'll need to remove the trigger test line and change

  GOTO Reset

to:

  END

Now, you'll have to take some time to work out the pan/tilt servo movements.  Make a timeline for yourself and and graph the movements on paper before entering numbers -- that will be far more interesting than just randomly tossing values into the program.  We actors don't like "unmotivated movement" and tossing numbers into the program would be just that.  Grab a beverage, sit down, and have fun!

' =========================================================================
'
'   File...... Servo_Blender-MP3.BS1
'   Purpose...
'   Author.... Jon Williams, EFX-TEK
'   E-mail.... jwilliams@efx-tek.com
'   Started...
'   Updated... 12 APR 2007
'
'   {$STAMP BS1}
'   {$PBASIC 1.0}
'
' =========================================================================


' -----[ Program Description ]---------------------------------------------
'
' Starts an external audio player and then controls the simultaneous
' movement of two (pan/tilt) servos.  Servo movement is stored in an EEPROM
' table with a "repeats" value for timing at the positions specified in the
' record (last byte).  The timing is approximately:
'
' 20 milliseconds x (repeats + 1)
'
' Mimimum: ~0.02 seconds
' Maximum: ~5.12 seconds
'
' Note that servos are mechanical and move slowly, so very small "repeats"
' values may expire before the servos reaches their target positions.


' -----[ Revision History ]------------------------------------------------


' -----[ I/O Definitions ]-------------------------------------------------

SYMBOL  Audio           = 7                     ' audio start/stop
SYMBOL  Trigger         = PIN6                  ' trigger input

SYMBOL  Servo2          = 1
SYMBOL  Servo1          = 0


' -----[ Constants ]-------------------------------------------------------

SYMBOL  IsOn            = 1
SYMBOL  IsOff           = 0

SYMBOL  RecLen          = 3                     ' record length (servos + 1)

SYMBOL  EOS             = 255                   ' end of show marker


' -----[ Variables ]-------------------------------------------------------

SYMBOL  record          = B0                    ' movement record
SYMBOL  pntr            = B1                    ' table byte pointer
SYMBOL  s1Pos           = B2                    ' servo 1 position
SYMBOL  s2Pos           = B3                    ' servo 2 position
SYMBOL  repeats         = B4                    ' repeats for record data


' -----[ Initialization ]--------------------------------------------------

Reset:
  PINS = %00000000
  DIRS = %10000011                              ' make servo pins outputs

  record = 0
  GOSUB Get_Servo_Pos                           ' get "home" positions


' -----[ Program Code ]----------------------------------------------------

Main:
  GOSUB Refresh_Servos
  IF Trigger = IsOff THEN Main                  ' wait for trigger

Start_Audio:
  HIGH Audio                                    ' "press" play button
  PAUSE 2000                                    '   for 2 seconds
  LOW Audio

Reset_Moves:
  record = 1                                    ' point to start of moves

Move_Engine:
  GOSUB Get_Servo_Pos                           ' get servo positions
  IF s1Pos = EOS THEN Show_End                  ' abort if at end

Servo_Hold:
  GOSUB Refresh_Servos
  IF repeats = 0 THEN New_Record                ' time left at this pos?
    repeats = repeats - 1                       ' yes, decrement timing
    GOTO Servo_Hold

New_Record:
  record = record + 1
  GOTO Move_Engine

Show_End:
  HIGH Audio                                    ' "press" play button
  PAUSE 2000                                    '   for 2 seconds
  LOW Audio

  GOTO Reset                                    ' clear everything


' -----[ Subroutines ]-----------------------------------------------------

' Call with "record" set to table line to read

Get_Servo_Pos:
  pntr = record * RecLen                        ' point into table
  READ pntr, s1Pos                              ' read servo 1 value
  pntr = pntr + 1                               ' point to servo 2
  READ pntr, s2Pos
  pntr = pntr + 1                               ' point to repeats
  READ pntr, repeats                            ' read repeats
  RETURN

' -------------------------------------------------------------------------

' Update servos -- time consumed is 19 to 21 ms

Refresh_Servos:
  PULSOUT Servo1, s1Pos
  PULSOUT Servo2, s2Pos
  PAUSE 17                                      ' pad for loop timing
  RETURN


' -----[ EEPROM Data ]-----------------------------------------------------

' Note on servo movement timing:
'
' Time spent on each record is 20 ms x (repeats + 1) so a repeats value
' of 0 is ~20 ms and a repeats value of 255 (max) is ~5.1 sseconds at that
' position.
'
'         s1   s2   rpts

Move_Table:
  EEPROM (150, 150, 255)                        ' home position
  EEPROM (100, 100,  50)                        ' start of movements
  EEPROM (100, 200,  50)
  EEPROM (200, 200,  50)
  EEPROM (200, 100,  50)
  EEPROM (EOS, 150, 255)                        ' end here

  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)
  EEPROM (EOS, 150, 255)                        ' last available EE space
Jon McPhalen
EFX-TEK Hollywood Office

brad g

Sincerest Thanks Jon! (By the way, it's Brad, not Bill!) Really, I appreciate the effort that went into this, and yes, like any new thing, this all seems very intimidating, but I will muddle on until it makes sense. Now I'm gonna go get that beverage and give this a shot.

JonnyMac

Sorry about the name mistake, Brad! (fixed now)  Be sure to post some video of your project when it's finished
Jon McPhalen
EFX-TEK Hollywood Office

livinlowe

Shawn
Scaring someone with a prop you built -- priceless!

brad g

I'm back again Jon (sorry!)  I've run into a problem getting the program to run, and I'm sure I'm doing something wrong, probably in the 'trigger' command.  What I am attempting to do is to use a remote outlet control to turn the system on and off, it's the same thing you see at Christmas to turn on lights using a keypad-style controller, that way, rather than using a PIR or something, I could just manually trigger the skull when I wanted it to run. Basically it would be a "light switch" operation, power on, the Prop1 goes into it's routine, comes to the end, I manually turn it off via the key pad device and the Prop1 resets and waits for the power to be turned back on to rerun it's program. It looks like there is a trigger command set for OUT6 in this program, do I delete this, or is what I want to do even possible? Again, just for clarity, what I'm trying to do is get the Prop1 to start doing it's thing as soon as power is applied to the board (which I will do manually with a hand-held remote), run it's program, and then at the conclusion, I will shut it down by turning all power off with the remote. I think I'm close to being finished here, I just can't get the routine to start!

brad g

April 22, 2007, 11:00:28 AM #8 Last Edit: April 22, 2007, 11:26:01 AM by brad g
And again, I jumped PIN 6 (P.6"w" to P.6"r") to get the program started, (I just touched them both with a wire to initiate triggering) and ran into something new. The mp3 came on as planned and the servo program kicked right in, it ran about 10 seconds into it's routine, then shut down the mp3, stopped moving, sat there for about 5 to 10 seconds and re-started the process all over again. The whole thing won't seem to run more than about 10 seconds or so. What am I doing wrong here? Do I need to add a PAUSE command into the mp3 trigger set up (roughly 3min, as discussed in the AUDIO forum section) to keep the player running for the duration of the song? Last, will using a jumper to connect the 'w' and 'r' pins on PIN 6 accomplish what I'm trying to do for a trigger?

JonnyMac

Brad,

A couple of messages ago I suggested you remove the trigger line.  Sorry, I should have been more specific.  In your program remove this line that looks for th trigger:

  IF Trigger = IsOff THEN Main                  ' wait for trigger

With that line you don't have to connect anything to fool the trigger.

I think the timing is your doing; send me your program (jwilliams at efx dash tek dot com) and I'll have a look.  Send a picture of your setup if you can as well so I can see how things are connected.
Jon McPhalen
EFX-TEK Hollywood Office

JonnyMac

If you don't mind running your skull from a PC (like the SkullTronix product) then we have another solution that lets you use your Prop-1:

-- http://www.efx-tek.com/php/smf/index.php?topic=96.0
Jon McPhalen
EFX-TEK Hollywood Office

ChrisBartram

Question on your sample program - the Move_Table: section never gets executed (I guess it's just static data loaded into memory?) - but where in the code is the pointer that knows where that data starts in memory? I see it appears your pointer "record" at byte0 is the memory pointer where servo positions get read, but I don't get how record gets "set" to the memory address where the Move_Table:/EEPROM statements store the servo data?

Thanks
-Chris

JonnyMac

Yes, the Move_Table section is data for the rest of the program and does not change.

Unless you specify an address in the EEPROM statement, user data starts at address $00 and builds up.  You program actually starts and address $FE and builds down -- hopefully, the two don't mean.  Since the BS1 has a WRITE instruction for storing data in the EEPROM, the compiler puts a value in $FF that specifies the highest address for user data -- writing beyond this address will corrupt and crash your program.

So... in the program I posted in this thread the Move_Table data starts at address $00.  When creating these kinds of "sequencer engine" programs I start with a simple data set, get my code working, then populate the data set (EEPROM statements) until the memory is full; you can check your progress with the Memory Map function in the BASIC Stamp IDE.

Another subtle note about BASIC Stamp controllers: all memory is cleared to zero on reset so you don't have to initialize variables to zero (unless you're going to jump back to that section for reinitialization while the program is running).
Jon McPhalen
EFX-TEK Hollywood Office

ChrisBartram

Thanks for that great explanation! Good info to know.

Quote from: JonnyMac on June 30, 2007, 01:07:34 PM
Another subtle note about BASIC Stamp controllers: all memory is cleared to zero on reset so you don't have to initialize variables to zero (unless you're going to jump back to that section for reinitialization while the program is running).

I assume the above doesn't include the EEPROM initialized stuff? If the code(program) and user data share the same memory, where/when does the code get refreshed "from" upon a reset?

JonnyMac

Correct; EEPROM is non-volatile -- it is not lost reset.  The only way to change EEPROM while the program is running is with the WRITE instruction; this is why address 255 exists: so that you don't WRITE into the space occupied by your program.  After a reset, the interpreter (running in a little PIC chip) knows to retrieve the code from EE address 254 and lower, and data (using READ) from address 0 and higher.
Jon McPhalen
EFX-TEK Hollywood Office