[home]

Timer for Motor Driven
Animations
revised 2-19-09  d. bodnar
 

Many animations can be created by utilizing simple geared DC motors.  A PIC based timer can make the movements realistic by controlling how long the motor runs in one direction and how long it pauses before reversing and returning to its start position.

This timer can be triggered by a NO (normally open) reed or push button switch or by an infrared sensor that notes when a train or other object moves near it.

The time that the motor runs and the pause time before reversing can be set by adjusting two potentiometers.

LEDs show the status of the system and the time remaining before the next motor event.

For motors that do not reliably run at the same rate forward and backward there is an option to stop the motor at a specific point with switches.

Design

To expedite development of this project the timer will be based on an existing circuit board that is being used for the BARC (Blinking Auto-Reverse Controller)

The only major rewiring will be to add an Infrared detecting capability.  The unit's relay and other control components will be replaced by three external SPDT relay that will be used to control the motor.  In addition there are two pots that can be used to adjust the time.

An array of 4 LEDs will be used to show timing and two push button switches will be used during setup.

Schematic - original BARC schematic

Revised schematic for Animation timer with PNA44602 sensor & an isolated set of relays.:

 

Modifications

The original BARC circuit has been modified in a number of ways.  The most significant change is the use of three external SPDT relays.  Two of these relays are wired together to act as a DPDT relay that reverses the polarity of the power that goes to the motor.  The other SPDT relay is used to turn power to the motor on or off.  The 2N2222 transistors are used to activate the relays. 

Software
 

 
'  Date    : 2/04/2009
'TODO:
'    OK add sensor button start
'    OK test with IR sensor
'    OK add random function
'    OK test / adjust time accuracy
'    OK redo for non-inverted IR sensor
'       note on above - 1K resistor must be inserted between pin 1(+) and 
'       pin 3 (data) on IR Sensor plug to remove sensor
'   major revision - use buttons (buttn1 / buttn2) to stop motor at top and end
'     just set time to something greater than what it normally would take travel

rem - seems to program more reliably with MCLR_OFF removed
'  @ DEVICE  PIC16F88, INTRC_OSC_NOCLKOUT, WDT_OFF, LVP_OFF, PWRT_ON, PROTECT_OFF, BOD_ON, MCLR_OFF
    @ DEVICE  PIC16F88, INTRC_OSC_NOCLKOUT, WDT_OFF, LVP_OFF, PWRT_ON, PROTECT_OFF, BOD_ON
DEFINE OSC 8
OSCCON = $70
DEFINE DEBUG_REG PORTb  
DEFINE DEBUG_BIT 2                  ' PIN 8 on 16f88
DEFINE DEBUG_BAUD 9600 
DEFINE DEBUG_MODE 1                 ' Set Debug mode: 0 = true, 1 = inverted
LED0                VAR portb.4
LED1                VAR portb.5
LED2                VAR portb.6
LED3                VAR portb.7
MotorDirection      VAR portb.3     'pin 9       'relay to control direction pin 2
Motoron             VAR porta.7     'pin 16
TimeAdjusterD       CON 4           'porta.2         'pot to read for time delay pin 1
ButtnMotor          VAR portb.1     'pull low w/ jumper for random function on
ButtnPause          VAR porta.3     'button to start deceleration
TimeAdjusterM       CON 2           'porta.4         'pot to read for Delay pin 3
IRSensor            VAR porta.6     'pin 15 - IR sensor       
ManualStartButton   VAR porta.0     'pin 17 - normally high - pull low to start
TimeMotor           VAR WORD
TimeDelay           VAR WORD
TimeTemp            VAR WORD
rndOn               VAR BYTE 
loop4               VAR WORD
RNDtime             VAR WORD
temp                VAR WORD
temp1               VAR WORD
temp2               VAR WORD
temp5               VAR BYTE
dd                  VAR WORD
hundreds            VAR BYTE
tens                VAR BYTE
ones                VAR BYTE
ptime               VAR WORD
ptime2              VAR WORD
RndmOn              VAR BIT     'set to 1 if true, 0 if not
InvertedSensor      VAR BIT     'set to 1 if inverted IR sensor, =0 if not
ExitFlag            VAR BIT     'shows that end-of-run button hit
DirectionFlag       VAR BIT     '=0 if forward / =1 if backward
SubVar1             VAR WORD    'temp variable for subroutine
SubVar2             VAR WORD    'temp variable for subroutine
VER_Whole           VAR BYTE    'version whole number
VER_Decimal         VAR BYTE    'version decimal
InvertedSensor      =0
VER_Whole           =2
VER_Decimal         =3
ptime=100                       'was 160
ptime2=90
ansel = 0
trisa=%01011101 '  pots & button inputs, serial output
trisb=%00000010 '  leds outputs, button input
DEFINE  ADC_BITS        8     	' Set number of bits in result
DEFINE  ADC_CLOCK       3     	' Set clock source (3=rc)
DEFINE  ADC_SAMPLEUS    500    	' Set sampling time in uS
ADCON0 = %100001000		' Set PORTA analog and right justify result    
LOW motoron:LOW motordirection:GOSUB low3leds:LOW led3:ExitFlag=0
'store @0, rndOn, speedtop , deceltime, speedstepdivisor
DATA @0, 0  
READ 0, RndmOn       'stores value once it is set at boot
HPWM 3,  127,38000  '38 KHz on pin 6
Verytop:
RANDOM temp
DEBUG 13,10,13,10,13,10:PAUSE 30
DEBUG 13,10,"(C) 2009 - d. bodnar - ver ",DEC VER_Whole,"."
DEBUG DEC VER_Decimal,13,10,"TrainElectronics.com",13,10

LOW motoron:LOW motordirection:DirectionFlag=0
FOR temp=1 TO VER_Whole
 GOSUB showver
NEXT temp
PAUSE 500
IF VER_Decimal=0 THEN GOTO start
FOR temp=1 TO VER_Decimal
 GOSUB showver
NEXT temp
PAUSE 500

Start:
IF RndmOn=1 THEN 
    HIGH led3
    ELSE
    LOW led3
ENDIF
LOW motoron:LOW motordirection:DirectionFlag=0
DEBUG "at Start",10,13
ADCIN TimeAdjusterM, TimeMotor:IF TimeMotor<2 THEN TimeMotor=2
ADCIN TimeAdjusterD, TimeDelay:IF TimeDelay<1 THEN TimeDelay=2

Wait4StartButton:
DEBUG "waiting... "
ADCIN TimeAdjusterM, TimeMotor:IF TimeMotor<2 THEN TimeMotor=2
ADCIN TimeAdjusterD, TimeDelay:IF TimeDelay<1 THEN TimeDelay=2
IF ButtnPause=1 AND ButtnMotor=1 THEN
    RndmOn=NOT(RndmOn)
    PAUSE 1500
    WRITE 0, RndmOn
    GOTO start
ENDIF
IF ButtnMotor=1 THEN
    ADCIN TimeAdjusterM, TimeMotor:IF TimeMotor<2 THEN TimeMotor=2
    SubVar1=TimeMotor
    TimeTemp=TimeMotor
    PAUSE 500
    GOSUB report
    PAUSE 500
    GOTO start
ENDIF
IF ButtnPause=1 THEN
    ADCIN TimeAdjusterD, TimeDelay:IF TimeDelay<1 THEN TimeDelay=2
    SubVar1=TimeDelay
    TimeTemp=TimeDelay
    PAUSE 500
    GOSUB report
    PAUSE 500
    GOTO start
ENDIF
    
GOSUB flashled1
FOR temp=1 TO 5
    IF ManualStartButton=0 THEN ButtonHit:
    DEBUG "Temp= ",#temp,10,13
    IF irsensor=InvertedSensor  THEN 
        DEBUG "Sensor hit",#temp,10,13
        TOGGLE led0:TOGGLE led1:TOGGLE led2
    ENDIF
    IF irsensor<>InvertedSensor  THEN Wait4StartButton:
NEXT temp
ButtonHit:
GOSUB Low3LEDs
'goto Wait4StartButton:
SubVar1=TimeMotor
LOW MotorOn
LOW MotorDirection:DirectionFlag=0
GOSUB RunMotor:
ExitFlag=0

StartPause:
IF RndmOn=1 THEN
    HIGH led3 
    RANDOM temp2
    temp1=TimeDelay/2
    RNDtime = temp2 & temp1
    SubVar1=RNDtime+temp1
    DEBUG "random time = ",#SubVar1," max time = ", #TimeDelay,10,13
    ELSE
    SubVar1=TimeDelay
ENDIF

DEBUG "at StartPause",10,13
loop2:
IF ButtnPause=1 THEN  'abort on button press
     SubVar1=1
     DEBUG "aborting delay... restarting" ,10,13
ENDIF
LOW motoron
TimeTemp=SubVar1:GOSUB report
'next few lines adjust for time it takes to flash time out
again2:
IF dd>1000 THEN 
    IF SubVar1<>0 THEN
    SubVar1=SubVar1-1
    ENDIF
     dd=dd-1000
ENDIF
IF dd> 1000 THEN again2:
PAUSE 900
    IF SubVar1<>0 THEN
    SubVar1=SubVar1-1
    ENDIF
IF SubVar1=0 THEN
    LOW MotorOn
    dd=0
    GOTO startReverse
ENDIF
GOTO loop2

StartReverse:
HIGH motordirection::DirectionFlag=1
GOSUB RunMotor:
    HIGH led0:LOW led1:HIGH led2
Wait_for_IR_Sensor_to_Clear:
    TOGGLE LED0:TOGGLE LED1:TOGGLE led2
    FOR temp= 1 TO 10 
        PAUSE 200
        IF irsensor=InvertedSensor OR ManualStartButton=0 THEN wait_for_IR_sensor_to_clear:
    NEXT temp
    GOTO start:
''endif
''goto loop3

report:
DEBUG "at report - time = ",#(TimeTemp-SubVar1),"/",#TimeTemp, " ",#dd,10,13
    hundreds=SubVar1/100
    tens=(SubVar1-(hundreds*100))/10
    ones=SubVar1- (hundreds*100)-(tens*10) 
    IF hundreds<>0 THEN
      FOR loop4= 1 TO hundreds
      HIGH led2:GOSUB RWBC:LOW led2:GOSUB RWBC:dd=dd+(ptime2*2)     
      NEXT loop4:GOSUB RWBC :dd=dd+(ptime2*2)
      IF ExitFlag=1 THEN RETURN      
    ENDIF
    IF tens<>0 THEN
      FOR loop4= 1 TO tens
      HIGH led1:GOSUB RWBC:LOW led1:GOSUB RWBC:dd=dd+(ptime2*2)     
      IF ExitFlag=1 THEN RETURN
      NEXT loop4:GOSUB RWBC :dd=dd+(ptime2*2)      
      IF ExitFlag=1 THEN RETURN
    ENDIF
    IF ones <>0 THEN
      FOR loop4= 1 TO ones          
      HIGH led0:GOSUB RWBC:LOW led0:GOSUB RWBC:dd=dd+(ptime2*2)      
      IF ExitFlag=1 THEN RETURN
      NEXT loop4:GOSUB RWBC :dd=dd+(ptime2*2)      
      IF ExitFlag=1 THEN RETURN
    ENDIF
RETURN

ShowVer:
GOSUB high3leds:PAUSE 200:GOSUB low3leds:PAUSE 200
RETURN

Low3LEDs:
LOW led0:LOW led1:LOW led2
RETURN

High3LEDs:
HIGH led0:HIGH led1:HIGH led2
RETURN

FlashLED1:
HIGH led0:PAUSE 15:LOW led0:PAUSE 30:HIGH led1:PAUSE 40
LOW led1:PAUSE 30:HIGH led2:PAUSE 60:LOW led2:PAUSE 30
RETURN

DecelLED:
HIGH led2:PAUSE 50:LOW led2:PAUSE 20:HIGH led1:PAUSE 30
LOW led1:PAUSE 20:HIGH led0:PAUSE 15:LOW led0
RETURN

'ReportWithButtonCheck
RWBC
    FOR temp5=1 TO ptime 
        PAUSE 1
       IF (ButtnMotor=1 AND DirectionFlag=0) OR (Buttnpause=1 AND DirectionFlag=1)THEN
         DEBUG "aborting - restart",10,13
         ExitFlag=1
         RETURN
       ENDIF
    NEXT temp5
RETURN

RunMotor:
ExitFlag=0
dd=0
SubVar1=TimeMotor
loop1:
HIGH motoron
IF (ButtnMotor=1 AND DirectionFlag=0) OR (Buttnpause=1 AND DirectionFlag=1)THEN
    DEBUG "aborting - restart",10,13
    ExitFlag=1
    LOW motoron
    RETURN
ENDIF
TimeTemp=TimeMotor:GOSUB report
IF ExitFlag=1 THEN 
    LOW motoron:
    RETURN
ENDIF
'next few lines adjust for time it takes to flash time out
again:
IF dd>1000 THEN 
    IF SubVar1<>0 THEN
    SubVar1=SubVar1-1
    ENDIF
     dd=dd-1000
ENDIF
IF dd> 1000 THEN again:
PAUSE 900
    IF SubVar1<>0 THEN
    SubVar1=SubVar1-1
    ENDIF
IF SubVar1=0 THEN
    LOW MotorOn
    DEBUG "DD= ",#dd, 10,13
    dd=0
    RETURN
ENDIF
GOTO loop1 



RETURN
Prototype

The prototype is shown below.  The three relays are at the bottom under the Animation Controller label.  The main circuit board is at the top.  There are two potentiometers that are used for setting motor run and delay times.  The two push button switches to the left and right are used for initial setup and testing.  The yellow wires connect to the motor and the white ones to its separate power source.  The red/black wires go to a 12 volt DC power source for the circuit.  The IR sensor is in the upper right.  The START button starts the motor just as the sensor does.  Note that the sensor must be plugged in to operate.

Here is a bottom view of the two boards.  The relays are on the white board at the bottom.

Here is an inside view of the reflective IR sensor.  The IR emitter is at the top of the head, beyond view.  The IR detector module is marked B774.  The circuit board inverts the output from the unit so that the detector shows a low output when no reflection is noted and high when it reflects.

 

Operation

When turned on the unit will flash out the software version number.  It will then flash the 1's, 10's and 100's LEDs as it waits for the IR sensor to be activated or a button to be pressed.

The two potentiometers set the time that the motor will be on and the delay time before the motor reverses.  To see the current setting of "motor on" time press the Motor button.  To adjust that time turn the Motor pot.  Similarly the Delay button and Delay pot shows or adjusts the delay time.  The time range is from 2 seconds to 255 seconds for both motor on & delay.  (Note that there is a switch control option that is described below.)

Times are reported by the 1's, 10's and 100's LEDs.  A time of 125 seconds would have the 100's LED flash once, the 10's LED twice and the 1's LED five times.

-Random
To activate the random function hold both the Motor and Delay buttons till the LEDs stop flashing.  If the random LED was off it will be on and visa versa.  Make sure you do not hold the two buttons - just press both of till the flashing stops then release them.

When random is active the time for the delay is random.  The range of time that is selected is a random number of seconds between 1/2 of the set time and the full set time.  For example, if the set time is 150 seconds the random time will be no less than 75 and no more than 150.

-During operation
When the IR sensor is activated the motor will turn on for the set number of seconds.  The LEDs will flash out the remaining time as the motor runs.  Note that each second will not be reported as some time reports take more than a second to display.

-IR Sensor must clear
If the IR sensor continues to be active after the motor sequence is completed the unit will wait until the sensor is cleared for several seconds before resetting.  During this time the three number LEDs will flash slowly.

-Using the buttons during operation
The buttons can be used to control the motor as follows:

  1. When the motor is going forward (when it first starts up) pressing the MOTOR button will stop it immediately and move into the delay phase of operation.
  2. When the motor is going backward (when it runs after the delay) pressing the DELAY button will stop the motor immediately and move to the part of the program where it pauses for a few seconds to make sure that there is nothing in front of the IR sensor

Any type of SPST Normally Open switch can be wired in parallel with the MOTOR and DELAY buttons and used to stop the motor;s forward or backward operation.  Micro switches and reed switches would be good choices.

The Motor timer needs to be set to a time longer than what is needed to trip the switches.  Turning the MOTOR pot all the way up is the easiest way to do this. 

The MOTOR and DELAY buttons cannot be used to show time if one of the external switches is held closed.  The software checks to see if one of the switches may be held down and skips the time reporting mode so that the lights don't continuously report time.

Latest Revision (2-18-09)

The completed unit is shown here along with the IR sensor.  Power is supplied through the red / black wires in the upper left.
The yellow pair of wires goes to the motor power and the pair of white wires goes to the motor.

The three switches around the board are Motor, Delay and Start.  External switches can be added in parallel with the small switches.

The IR sensor units can be connected directly to the four wire cable that is soldered to the circuit board or an extension can be made using the other end of the cable that is shown here.  Just make sure that the red wire goes to the pin on the sensor that is marked "+".  The other wires must be connected in the same order that they are in on the cable.

To attach external switches solder in parallel with the switches on the circuit board.  In this view of the bottom of the circiut board the START switch is on the bottom edge towards the right, the MOTOR switch is bottom left and the DELAY switch is on the right edge.  You can solder to the terminals on the board that are circled.  The connections are close together so be sure there are no solder bridges.  You can also solder to the unconnected pins (also circled) coming off of the switches.