ROBODYSSEY SYSTEMS LLC

Product Catalog
Code Page
Policies
Gallery
Whats New
Press Releases
Resources
Links
Contact Us
About Us
Press

Home Product Catalog Shopping Cart Resources Links
Code Page Policies Gallery

This Project saves Servo Position Data to an external EEPROM and plays it back to syncronized sound. The sound is played through a modified sound recorder from Radio Shack. The three servos can be recorded while the sound is being played. Selection of the servo to record is done with a resistor on pins 0,1 and 2 of PortC. Playback uses pin 3 and the sound is controlled on pin 4 of PortC

I2C protocols allow for easy transfer of information to an external device. the syntax in as follows
I2COUT Control, Address, ( Value{,Value})

I2COUT being the command
Control being the chip setup info.
1xxxxxxx, 16bit chip - 0xxxxxxxx, 8bit chip.
x1010xxx, chip specific. Look it up, the 24LC256 was 1010.
xxxxxXXX, device select bits.

Address being the memory location.

Values being the variable your playing with.

I2CIN is pretty much the same but reversed in function.
I2CIN Control, Address, Var{,Var}
One important consideration, it takes about 10ms for it to occur. Thus the pause after.

This project Requires the modification of the include file "PBL.INC". It should be located in your compilers directory. Since I wanted to do both analog and digital signals on PortA, I decided it would be best to relocate the I2C protocols from the standard pins 0 and 1 to pins 4 and 5. This way I could use pin 0 as an analog input.

Doing this is really quite easy. Simply open up pbl.inc with any text editor. Scroll down to the I2C stuff (as shown)

Then change the port pins to whatever you want. In this case 4 and 5.

'******** Saving servo positions to an  ***************
'************** External EEPROM *********************** 
'****************************************************** 
'@ Platform: PicBasic 
'@ Version: 1.0
'@ Author: Brian Patton (brianp@robodyssey.com)
'     Robodyssey Systems, LLC. - www.robodyssey.com
'@ Last Updated: Feb, 20, 2004
'******************************************************
' This Program uses the 16F876 
'*********Materials**************************************
' 1 Robodyssey PicPac MotherBoard
' 1 Pic16F876 or similar
' 1 Voltage Divider board
' 1 Variable Resistor (pot)or photoresistor
' 1 10k resistor to act as switch 
' 1 I2C EEPROM (I used the 24LC256)
' PicBasic Compiler and a programmer
'******************************************************
' Register Locations
Symbol  TRISA  = $85 ' Register Location of TRISA
Symbol  ADCON0 = $1F ' Register location of ADCON0
Symbol  ADCON1 = $9F ' Register Location of ADCON1
Symbol  ADRESH = $1E ' Register Location of ADRESH
Symbol  TRISC  = $87 ' Register Location of TRISC
Symbol  PortC  = 7  ' Register Location of PortC
 
'***** Variables *****************************************
Symbol addr = w0   ' The bigger EEPROMs need 16 bit addresses
Symbol addr2 = w1   ' The bigger EEPROMs need 16 bit addresses
Symbol addr3 = w2
Symbol cont = %11010000 ' EEPROM control byte
 
Symbol RPot = b7   'Range between Min and Max
Symbol ServoPos = b8 'Pulse the servos will use
symbol Nvalue = b9  'variable to hand off to
Symbol x = b10   'just a counter
Symbol MinMax = b11
Symbol value = b12    ' Place for the data
Symbol ADcon = b13  ' storag spot for A to D functions
Symbol ServoPos2 = b14
Symbol rec = b15
Symbol Cstatus = b16   ' Check state of Port C variable
Symbol MinPot = b17  'Value for the minimum of the pot
Symbol MaxPot = b18  'Value for the maximum of the pot
Symbol ServoPos3 = b19
'***** Initiation *****************************************
Init:
 Dirs = %11111111   ' Set all Port B to output
 Poke ADCON1,%00000100  '  Pins 0,1 and 3 analog input. Pins 2,4 and 5 digital.
         ' 0xxxxxxx Sets result to Left justified
         ' 1xxxxxxx Sets result to Right justified  
 Poke TRISC, %00001111 ' Set all PortC Input
 Poke PortC, %00010000 'Keep sound off till ready.
 
'**********Main Code Block Area***************************
 Pause 1000
rec = 0
' This works by grounding resistors that hold pins high on Port c
' Grounding different pins selects playback, record 1,2 or 3.  

chk1:
Peek PortC,Cstatus  'Get the status of Port C
If Cstatus =  %00011111 Then chk1  'If closed then Gather Data
         'If open then Recall Data
If Cstatus =  %00010111 Then recall  'If closed then Gather Data
         'If open then Recall Data
If Cstatus =  %00011011 Then recswitch  'If closed then Gather Data
         'If open then Recall Data
If Cstatus =  %00011101 Then recswitch  'If closed then Gather Data
         'If open then Recall Data
If Cstatus =  %00011110 Then recswitch  'If closed then Gather Data
         'If open then Recall Data
goto chk1
 
'********** Sample and store Data **************************
recswitch:
If  rec = 1 Then choose 'If already done once then don't bother to do it again
 rec = 1 ' Darn, Gotta calibrate the pot
 Pause 1000
 high 2
 Poke TRISA, %00000001  'Set pin0, PortA Input
 MinMax = 1  'give it some start points
Maxmod:
 MaxPot = MinMax 'give it some start points
MinMod:
 MinPot = MinMax 'give it some start points
for x = 1 to 20 'Give you time to turn the pot
pause 100
     poke ADCON0, %11000001  'Set A/D to RC Osc, Channel 0, A/D converter ready
        'xx000xxx-Chan 0(RA0), xx001xxx-Chan 1(RA1),
        'xx010xxx-Chan 2(RA2), xx011xxx-Chan 3(RA3),
        'xx100xxx-Chan 4(RA4), xx101xxx-Chan 5(RA5),
        'xx110xxx-Chan 6(RA6), xx111xxx-Chan 7(RA7),
 
     ADcon = %11000101   'xxxxx1xx - on, xxxxx0xx - off
        Poke ADCON0,ADcon   ' Turn on the conversion at Bit 2
 
calfin: 
  Pause 5
        Peek ADCON0,ADcon
   If ADcon = %11000101 Then calfin   ' Wait for low on bit-2 of ADCON0, conversion finished
     Peek ADRESH, MinMax 
  If MinMax > MaxPot Then MaxMod  'Collect min and max values
   
  If MinMax < MinPot then MinMod  'Collect min and max values  
 next
 RPot = MaxPot - MinPot       'Calculate the range
 RPot = 1200/RPot 'The 1200 comes from differece of the min pulse width and max pulse width recomended by the
      'Servo manufacture time 10 in 10uSec units. The 10X is to keep the answer a 8 bit integer.
      'So, a servo with a rated pulse of 0.0009 to 0.0021 is 90 to 210 ten uSec units.
      'That is a difference of 120 uSec units. Times 10 is 1200.     
 Low 2
 Pause 1000
'******************************************************
'******** Choosing the rec chan. ********************************
choose:
Poke PortC, %00010000
pause 100
Peek PortC,Cstatus  'Get the status of Port C
If Cstatus =  %00011101 Then Servo2  'If closed then  Servo1
          'If open then Servo2
If Cstatus =  %00011110 Then Servo3  'If closed then  Servo1
          'If open then Servo2
' If neither then must be Servo1
'*******************************************************
Servo1:
 
 Pause 1000
 addr2 = 3000
 Poke PortC, %00100000
For addr = 1 to 2000  'addr is a 16 bit variable
 
     Poke ADCON0, %11000001  'Set A/D to RC Osc, Channel 0, A/D converter ready
        'xx000xxx-Chan 0(RA0), xx001xxx-Chan 1(RA1),
        'xx010xxx-Chan 2(RA2), xx011xxx-Chan 3(RA3),
        'xx100xxx-Chan 4(RA4), xx101xxx-Chan 5(RA5),
        'xx110xxx-Chan 6(RA6), xx111xxx-Chan 7(RA7),
 
     ADcon = %11000101   'xxxxx1xx - on, xxxxx0xx - off
        Poke ADCON0,ADcon   ' Turn on the conversion at Bit 2
 
Ser1fin: 
        Peek ADCON0,ADcon
   If ADcon = %11000101 Then Ser1fin   ' Wait for low on bit-2 of ADCON0, conversion finished
     Peek ADRESH,value
'************ convert value and ******************        
'************ drive the Servo ********************
 Nvalue = MaxPot + 10   'Hand over the value and keep it from ever becoming 0
 ServoPos = Nvalue - value  'Subtract found value from the Max possible
 ServoPos = ServoPos / 10 'Correct the 10x thing from above
 ServoPos = ServoPos * RPot 'Multiply it by the range
 ServoPos = 240 - ServoPos '210 is the longest pulse in 10uSec intervals my servo will handle
  Pulsout 4, ServoPos   'Pulse the Servo
'********** Play Memory and Write New************
  addr2 = addr2 + 1
  I2Cin cont,addr2,ServoPos2 
  Pulsout 5, ServoPos2   'Pulse the Servo
  I2Cout cont,addr,(ServoPos)
  Pause 10    'Need time to write
Next
Poke PortC, %00010000
goto chk1
 End
'*******************************************************
Servo2:
 
 Pause 2000
 addr = 1
 Poke PortC, %01000000
For addr2 = 3000 to 5000  'addr is a 16 bit variable
 
     Poke ADCON0, %11000001  'Set A/D to RC Osc, Channel 0, A/D converter ready
        'xx000xxx-Chan 0(RA0), xx001xxx-Chan 1(RA1),
        'xx010xxx-Chan 2(RA2), xx011xxx-Chan 3(RA3),
        'xx100xxx-Chan 4(RA4), xx101xxx-Chan 5(RA5),
        'xx110xxx-Chan 6(RA6), xx111xxx-Chan 7(RA7),
 
     ADcon = %11000101   'xxxxx1xx - on, xxxxx0xx - off
        Poke ADCON0,ADcon   ' Turn on the conversion at Bit 2
 
Ser2fin: 
        Peek ADCON0,ADcon
   If ADcon = %11000101 Then Ser2fin   ' Wait for low on bit-2 of ADCON0, conversion finished
     Peek ADRESH,value
'************ convert value and ******************        
'************ drive the Servo ********************
 Nvalue = MaxPot + 10   'Hand over the value and keep it from ever becoming 0
 ServoPos2 = Nvalue - value  'Subtract found value from the Max possible
 ServoPos2 = ServoPos2 / 10 'Correct the 10x thing from above
 ServoPos2 = ServoPos2 * RPot 'Multiply it by the range
 ServoPos2 = 240 - ServoPos2 '210 is the longest pulse in 10uSec intervals my servo will handle
  Pulsout 5, ServoPos2   'Pulse the Servo
'*****************************************************
  addr = addr + 1
  I2Cin cont,addr,ServoPos 
  Pulsout 4, ServoPos   'Pulse the Servo
  I2Cout cont,addr2,(ServoPos2)
  Pause 10    'Need time to write
Next
Poke PortC, %00010000
goto chk1
 End
'************ Servo 3 ***********************************
Servo3:
 Pause 1000
 addr = 1
 Poke PortC, %10000000
For addr3 = 6000 to 8000  'addr is a 16 bit variable
 
     Poke ADCON0, %11000001  'Set A/D to RC Osc, Channel 0, A/D converter ready
        'xx000xxx-Chan 0(RA0), xx001xxx-Chan 1(RA1),
        'xx010xxx-Chan 2(RA2), xx011xxx-Chan 3(RA3),
        'xx100xxx-Chan 4(RA4), xx101xxx-Chan 5(RA5),
        'xx110xxx-Chan 6(RA6), xx111xxx-Chan 7(RA7),
 
     ADcon = %11000101   'xxxxx1xx - on, xxxxx0xx - off
        Poke ADCON0,ADcon   ' Turn on the conversion at Bit 2
 
Ser3fin: 
        Peek ADCON0,ADcon
   If ADcon = %11000101 Then Ser3fin   ' Wait for low on bit-2 of ADCON0, conversion finished
     Peek ADRESH,value
'************ convert value and ******************        
'************ drive the Servo ********************
 Nvalue = MaxPot + 10   'Hand over the value and keep it from ever becoming 0
 ServoPos3 = Nvalue - value  'Subtract found value from the Max possible
 ServoPos3 = ServoPos3 / 10 'Correct the 10x thing from above
 ServoPos3 = ServoPos3 * RPot 'Multiply it by the range
 ServoPos3 = 240 - ServoPos3 '210 is the longest pulse in 10uSec intervals my servo will handle
  Pulsout 6, ServoPos3   'Pulse the Servo
'*****************************************************
  addr = addr + 1
  I2Cin cont,addr,ServoPos 
  Pulsout 4, ServoPos   'Pulse the Servo
  I2Cout cont,addr3,(ServoPos3)
  Pause 10    'Need time to write
Next
Poke PortC, %00010000
goto chk1
 End
'*********** Get Data Back Out ****************************
recall:
 Pause 1000
addr2 = 3000
addr3 = 6000
Poke PortC, %11100000
For addr=1 to 2000
 addr2 = addr2 + 1
 addr3 = addr3 + 1
 I2Cin cont,addr,ServoPos
 I2Cin cont,addr2,ServoPos2
 I2Cin cont,addr3,ServoPos3
 For x = 1 to 17
 high 2
 next
 low 2
 Pulsout 4, ServoPos   'Pulse the Servo
 Pulsout 5, ServoPos2   'Pulse the Servo
 Pulsout 6, ServoPos3   'Pulse the Servo
 Pause 7
Next
Poke PortC, %00010000
goto chk1
 End
 
 


Home Product Catalog Shopping Cart Resources Links
Code Page Policies Gallery

Robodyssey Systems manufactures Robot Kits including Autonomous Mobile Walking Robots, Wheeled Robots, Talking Robots, Expressive Robots, and Social Robots. We also sell Robotics Accessories including Nexcell NiMH AA Rechargeable Batteries, Nexcell NiMH AAA Rechargeable Batteries, Battery Holders, Velcro Straps for Battery Packs, Battery Chargers, Robot Grippers, Hobby Servos, Servos Modified for Continuous Rotation, Tail Wheels for all Rolling Robotic Platforms, Polyurethane Skate Wheels with Servo Adapter Hubs, Sharp IR Sensors and Adjustable Sensor Brackets, Sensor Cables, and Programming Cables. All of our Robot Kits can be purchased as easy to assemble robot kits or as fully assembled stationary or mobile robots. Robodyssey uses 1/8 inch aluminum and acetyl for most all of our mobile robot components and robotics accessories. We provide classroom training for teachers interested in integrating robotics, computer programming and electronics into the classroom.

We hope you enjoy our web site. Feel free to use any robotic resources. Robodyssey is your complete solution for Educational Robotics as well as Hobby Robotics.