Simple "Time-out" routine


+ Reply to Thread
Results 1 to 5 of 5
  1. #1
    Join Date
    Mar 2010
    Posts
    2

    Default Simple "Time-out" routine

    I have a project where I have to move a small trolley on a rail forwards until it reach a proximity switch A. I then need to move the trolley backwards until it reach proximity switch B. Once again, I have to change the direction to move the trolley forwards. Because of the weight of the trolley I have used PWM to accelerate the trolley rather than to switch it hard on or off. This has to run continuously for weeks in order to test a laser scanner.

    Everything works fine but I would like to add a time out function should the next proximity switch not be reached in 20 seconds. It should then just stop motor and the application.

    Code:
    '****************************************************************
    '*  Name    : 12F675_Motor_Control_SoftStart_and Brake          *
    '*  Author  : Jaco Muller                                       *
    '*  Notice  : Copyright (c) 2010 Jaco Muller                    *
    '*          : All Rights Reserved                               *
    '*  Date    : 01/04/10                                          *
    '*  Version : 1.0                                               *
    '*  Notes   :                                                   *
    '*          :                                                   *
    '****************************************************************
    @ DEVICE PIC12F675,MCLR_OFF,INTRC_OSC_NOCLKOUT,WDT_OFF,BOD_OFF
    Include "modedefs.bas"		' Mode definitions for Serout
    
    '-------------------------------------------------------------------
    ' PIC12F675 on Transtoll Motor Control Board Part Number 4410A
    '-------------------------------------------------------------------
    ' PIN  NAME     USE/CONNECTION
    '  1   Vdd      +5VDC
    '  2   GPIO.5   Q3  +24V on Output +
    '  3   GPIO.4   Input IN1
    '  4   GPIO.3   Input IN2
    '  5   GPIO.2   Q8  0V on Output -
    '  6   GPIO.1   Q4  +24V on Output - 
    '  7   GPIO.0   Q7  0V on Output +
    '  8   VSS       GROUND
    '-------------------------------------------------------------------
    
        DEFINE OSC 4     ' Internal Clock to 4 Mhz
    
        ANSEL.0=0  ' AN0 to digital
        ANSEL.1=0  ' AN1 to digital
        ANSEL.2=0  ' AN2 to digital
        ANSEL.3=0  ' AN3 to digital
        ANSEL.4=0  '\
        ANSEL.5=0  ' clock derived from a dedicated internal oscillator
        ANSEL.6=0  '/
        ANSEL.7=0  ' Unimplemented
        
        TRISIO.0  = 0    ' GPIO.0  Output
        TRISIO.1  = 0    ' GPIO.1  Output
        TRISIO.2  = 0    ' GPIO.2  Output
        TRISIO.3  = 1    ' GPIO.3  Input
        TRISIO.4  = 1    ' GPIO.4  Input
        TRISIO.5  = 0    ' GPIO.5  Output
        TRISIO.6  = 0    ' Unimplemented
        TRISIO.7  = 0    ' Unimplemented
    
    	ADCON0.0 = 0		' ADON: A/D Conversion STATUS bit
    	ADCON0.1 = 0		' GO/DONE: A/D Conversion Status bit
    	ADCON0.2 = 0		' \   AN 0
    	ADCON0.3 = 0		' /   AN 0
    	ADCON0.4 = 0		' Unimplemented
    	ADCON0.5 = 0		' Unimplemented
    	ADCON0.6 = 0		' Reference to Vdd
    	ADCON0.7 = 1		' Right justify result
    
        CMCON = 7   ' Analog comparators off
    
    
        Q3 Var GPIO.5   ' High side Power MOSFET Switch for Direction 1 (IPS511)   
        Q4 var GPIO.1   ' High side Power MOSFET Switch for Direction 2 (IPS511)
        Q7 var GPIO.0   ' Low side Power MOSFET for Direction 2  (VNP5N07)
        Q8 var GPIO.2   ' Low side Power MOSFET for Direction 1  (VNP5N07)
        IN1 var GPIO.4  ' Input of Limit Switch 1
        IN2 VAR GPIO.3  ' Input of Limit Switch 2
        Direct1 var bit ' Movement away from switch 1
        Direct2 VAR bit ' Movement away from switch 2
        Stat var byte
        DutyC var byte     ' Byte size variable for Duty cycle
        Cycles var byte ' Byte size variable for number of cycles per duty cycle
    
        stat=0    
        
        '   Stat=0 when no switch is pressed and there is no movement
        '   Stat=1 when switch 1 is pressed and there is no movement
        '   Stat=2 when switch 2 is pressed and there is no movement
        '   Stat=3 when switch 1 & switch 2 are pressed and there is no movement
        '   Stat=4 when no switch is pressed and there is movement in direction 1
        '   Stat=5 when switch 1 is pressed and there is movement in direction 1
        '   Stat=6 when switch 2 is pressed and there is movement in direction 1
        '   Stat=7 when switch 1 & switch 2 are pressed and there is movement in direction 1
        '   Stat=8 when no switch is pressed and there is movement in direction 2
        '   Stat=9 when switch 1 is pressed and there is movement in direction 2
        '   Stat=10 when switch 2 is pressed and there is movement in direction 2
        '   Stat=11 when switch 1 & switch 2 are pressed and there is movement in direction 2
        
            
        low q3
        low q4
        low q7
        low q8
    
        pause 50
    
        high q8
        pwm q3,127,8            ' Pulse Width Modulate High side, dc% for cycles
    
        pause 50
    
        low q3
        low q8
        
        pause 50
    
        high q7
        pwm q4,127,8            ' Pulse Width Modulate High side, dc% for cycles
    
        pause 50
        low q4
        low q7
    
        
        cycles = 10  ' Set cycles per duty cycle 
         
        
    MAIN:
        if in1=1 then
            stat.0=0
        else
            stat.0=1
        endif
        if in2=1 then
            stat.1=0
        else
            stat.1=1
        endif
        stat.2=Direct1    
        stat.3=Direct2
    
    
        select case stat
            case 0
                'do nothing
            case 1
                goto left
            case 2
                goto right
            case 3
                'do nothing
            case 4
                'do nothing
            case 5
                'do nothing
            case 6
                goto right
            case 7
                goto brake
            case 8
                'do nothing
            case 9
                goto left
            case 10
                'do nothing
            case 11
                goto brake
        end select
        GOTO MAIN	  ' DO IT AGAIN
        end
    
    left:
        low q4                         ' Set High side Right off
        low q7                         ' Set Low side Right off
        pause 1                        ' Wait for Switch
    
        high q8                        ' Set Low side Left on
        high q7                        ' Set Low side Right on
        pause 300                      ' Wait for System to stop
    
        low q8                         ' Set Low side Left off
        low q7                         ' Set Low side Right off
        pause 1                        ' Wait for Switch
    
        high q8                        ' Set Low side Left on
        for DutyC = 0 to 255 step 4    ' Step duty cycle from 0% to 100%
            pwm q3,DutyC,cycles        ' Pulse Width Modulate High side, dc% for cycles
            if in2=0 and in1 = 0 then  ' Check if both switches were pressed
                DutyC = 255            ' If true, set DC = 255
                goto brake             ' exit sub goto brake
            endif
        next DutyC
        Direct1=1
        direct2=0
        high q3                        ' Set High side to 100%
        goto main
        end   
        
    right:
        low q3                         ' Set High side Left off
        low q8                         ' Set Low side Left off
        pause 1                        ' Wait for Switch
        
        high q8                        ' Set Low side Left on
        high q7                        ' Set Low side Right on
        pause 300                      ' Wait for System to stop
    
        low q8                         ' Set Low side Left off
        low q7                         ' Set Low side Right off
        pause 1                        ' Wait for Switch
        
        
        
        high q7
        for DutyC = 0 to 255 step 4    ' Step duty cycle from 0% to 100%
            pwm q4,DutyC,cycles        ' Pulse Width Modulate High side, dc% for cycles
            if in2=0 and in1 = 0 then  ' Check if both switches were pressed
                DutyC = 255            ' If true, set DC = 255
                goto brake             ' exit sub goto brake
            endif
         next DutyC
        Direct1=0
        direct2=1
        high q4
        goto main
        END		  ' END PROGRAM
    
    Brake:
        Direct1=0
        direct2=0
        low q3
        low q8
        low q7
        low q4
        pause 5000
        goto main
        END		  ' END PROGRAM

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,253

    Default

    Hi Jaco,
    I haven't looked into your code very deeply but here's an idea that might work.
    Have a "counter" variable that you increment in each of the states where you have movement but not yet detected "the other" switch.

    Figure out the magic number that matches ~20 seconds and if the "counter" ever reaches that number you abort the whole thing. When you go from a state of movement but no switch to a state where you detect a s switch you reset the "counter".

    The timing may not be super accurate depending on how long your various subroutines takes but for a "simple timeout" it may suffice?

    /Henrik.

  3. #3
    Join Date
    Mar 2010
    Posts
    2

    Default Time-out routine

    Hi Hendrik

    Thanks for the response. I have used two variables, Micro VAR WORD and Milli VAR WORD. For each cycle in the main loop where no switch was activated, the Micro (~micro second) increased by 1 until 999 by which time the Milli is increased by 1 and the micro is reset to 0. I had to do this because of the the varaible type word max 65 535 and that is not long enough. It just seemed very clumsy. I though it will be more elegant to use an internal timer which is reset each time the switch is activated. If a switch is not activated within 20 seconds, the system must stop the motor and end the application.

    Does that make sense?

    The reason why I am after a good solution, is that I might use this circuit in another application where timing is a bit more critical.


    Quote Originally Posted by HenrikOlsson View Post
    Hi Jaco,
    I haven't looked into your code very deeply but here's an idea that might work.
    Have a "counter" variable that you increment in each of the states where you have movement but not yet detected "the other" switch.

    Figure out the magic number that matches ~20 seconds and if the "counter" ever reaches that number you abort the whole thing. When you go from a state of movement but no switch to a state where you detect a s switch you reset the "counter".

    The timing may not be super accurate depending on how long your various subroutines takes but for a "simple timeout" it may suffice?

    /Henrik.

  4. #4
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,253

    Default

    Hi,
    Sure, it makes sense. If you need accurate timing you'll have to resort to a timer based interrupt. However, if timing isn't that critical you can set up the hardware timer and just check the interrupt flag in software (ie. not actaully enabling the interrupt).

    You can use TMR1 of the 12F675, with a 1:8 prescaler and 4Mhz clock it will overflow at a rate of (4000000/4/8/65536) = ~1.9Hz. Unfortunately the highest prescaler ratio is 1:8 so that's as "slow" as it gets. Having it "time" 20 seconds intervals would require an external clock x-tal for the timer oscillator which would cost you two I/O pins that you don't have.... :-(

    For accurate timing, as already been said, you'll have to resort to an interrupt based routine. In this case you set up the timer so it overflows at a rate high enough for your timing purposes, lets say 100Hz. Then you keep track of the time pretty much as you already did - with variables like Days, Hours, Minutes, Seconds, ms.

    Have a look at Darrel Taylors Elapsed Time routine I think it pretty much fits your need perfectly.

    /Henrik.

  5. #5
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    2,938

    Default ~20 sec hardware timer

    In the attached file, you can use the Timer1 with Interrupts. Just Start Timer1 by setting t1con.0 bit and then either check flag or stop whatevere your are doing in the ISR routine, inside the IF-THEN.

    Thanks to Darrel once again for his DT-INTS.

    Don't forget to include the files in the directory of your code and use MPASM as an assembler.

    Ioannis
    Attached Files Attached Files

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts