Problem with 12F629, servo and EEPROM


Closed Thread
Results 1 to 14 of 14
  1. #1
    Join Date
    Sep 2006
    Location
    Florida, USA
    Posts
    88

    Default Problem with 12F629, servo and EEPROM

    Hello - I am trying to get this VERY simple program to work, but after hours of banging my head on it, I can't see what I am doing wrong. I'm sure that I will be embarrased when someone points out what I need to do...

    What I want to do is use a 12F629 to drive a servo via a pot. There are 2 pushbuttons to set the minimum and maximum travel limits for the servo and a switch to enable the user to enter the min and max settings. I can drive the servo with the pot without any problem. The problem arises when I try to set the min and max limits. This process consists of switching the Limit Set Enable slide switch to ON, which pulls GPIO.1 high. This tells the PIC to start monitoring the Min and Max pushbuttons. When the user presses one of the buttons, the PIC takes the current position of the servo and stores it in the appropriate variable and then writes the value to internal EEPROM. After setting the Min and Max values and the Limit Set Enable switch is switched off, the servo movement should be limited to between the min and max limits that were just set. Seems simple enough... What is happening when I set a min or max limit is that the servo will not move from that position. For example, I have the total range of movement set from 100 to 250 (1 to 2.5 ms). I get nice movement over this range. If I move the servo to the middle position (let's say 125) and then enable limit setting and then press the Min button, the movement should then be limited to 125 - 250. Well, it acts as though the min and max limits were both set to 125 - the servo won't move from this position. I'm baffled... Another problem that I am having is that the values for the min and max positions are not being written to the internal memory. I do this so that the PIC will remember the last min/max settings. But when I cycle the power, the settings go back to the original min max values (100 & 250). Following is my code and I have attached my circuit. I would appreciate any insight - again, I fully expect to be embarrased....

    @ DEVICE pic12F629, INTRC_OSC_NOCLKOUT ; Using Internal Clock, no clock out
    @ DEVICE pic12F629, WDT_ON ; Enable Watch dog timer
    @ DEVICE pic12F629, PWRT_ON ; Enable Power-up timer
    @ DEVICE pic12F629, MCLR_OFF ; Disable MCLR pin
    @ DEVICE pic12F629, BOD_ON ; Enable Brown-out detect
    @ DEVICE pic12F629, CPD_OFF ; EEPROM Protect
    @ DEVICE pic12F629, PROTECT_OFF ; Code Protect off

    TRISIO = %11111110
    INTCON.6=0 ' Disable all unmasked Interrupts
    INTCON.7=0 ' Disable Global Interrupts
    CMCON = 7 ' Disable analog comparator

    ServoOut var GPIO.0
    SetLimitSw var GPIO.1
    PotIn var GPIO.2
    MinSw var GPIO.4
    MaxSw var GPIO.5

    Posit var word
    MinPosit var word
    MaxPosit var word

    'load starting min and max positions at program time
    data @ 0, 0, 100
    data @ 2, 0, 250

    '************************************************* ***************
    low Servoout

    'read in stored min and max limits
    read 0, MinPosit.byte0
    read 1, minposit.byte1
    read 2, MaxPosit.byte0
    read 3, maxposit.byte1

    Start:
    gosub GetServoPosition
    pulsout servoout, posit
    pause 20

    if setlimitsw = 1 then 'check min max buttons
    if minsw = 1 then
    MinPosit = Posit
    write 0, MinPosit.byte0
    write 1, minposit.byte1
    pause 250
    endif

    if maxsw = 1 then
    MaxPosit = Posit
    write 2, MaxPosit.byte0
    write 3, maxposit.byte1
    pause 250
    endif
    endif

    goto start

    '************************************************* ***************
    GetServoPosition:
    high potin
    pause 1
    rctime potin, 1, Posit 'at 4 mhz, returns 0 - 120

    'adjust posit to get values between 75 and 250
    posit = posit + 75 + (posit / 2)

    'now limit posit to 100 - 250 (1 ms - 2.5 ms)
    if posit < 100 then posit = 100
    if posit > 250 then posit = 250

    if setlimitsw = 0 then 'apply limits
    if Posit < MinPosit then Posit = MinPosit
    if Posit > MaxPosit then Posit = MaxPosit
    endif

    return

    '************************************************* ***************

    End
    Attached Images Attached Images

  2. #2
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Code:
    @ DEVICE pic12F629, INTRC_OSC_NOCLKOUT  ; Using Internal Clock, no clock out
    @ DEVICE pic12F629, WDT_ON              ; Enable Watch dog timer
    @ DEVICE pic12F629, PWRT_ON             ; Enable Power-up timer
    @ DEVICE pic12F629, MCLR_OFF            ; Disable MCLR pin  
    @ DEVICE pic12F629, BOD_ON              ; Enable Brown-out detect
    @ DEVICE pic12F629, CPD_OFF             ; EEPROM Protect
    @ DEVICE pic12F629, PROTECT_OFF         ; Code Protect off
    data 0, 100 , 250
    trisio=$fe:intcon=0:cmcon=7:servoout var gpio.0:serlimitsw var gpio.1
    potin var gpio.2:minsw var gpio.4:maxsw var gpio.5:posit var byte
    minposit var byte:maxposit var byte:low servout
    read 0,MinPosit:read 1,MaxPosit
    Start:     gosub GetServoPosition : pulsout servoout, posit : pause 20
    if setlimitsw = 1 then 'check min max buttons
            if minsw = 1 then MinPosit = Posit : write 0, MinPosit : pause 25
            if maxsw = 1 then MaxPosit = Posit : write 1, MaxPosit : pause 25
    endif
    goto start
    GetServoPosition:     high potin:pause 1:rctime potin,1,Posit:posit=posit*2
    if posit < 100 then posit = 100
    if posit > 250 then posit = 250
    if setlimitsw = 0 then 'apply limits
            if Posit < MinPosit then Posit = MinPosit
            if Posit > MaxPosit then Posit = MaxPosit
    endif 
    return
    Give that a shot, see what happens. The scaling is 'fixed' for now, and needs to be worked on...

  3. #3
    Join Date
    Sep 2006
    Location
    Florida, USA
    Posts
    88


    Did you find this post helpful? Yes | No

    Default

    Skimask - Thanks for the reply. I tried your code but am getting the same result. If the Set Limit Enable switch is on, I can control the servo movement with the pot (I had to change the scaling back to what I originally had, first). When it is at this point, it is not applying the limits (100 & 250). As soon as I turn off the switch (applying the limits), the servo does not move from the current position. It is acting like the minposit and maxposit variables are the same number. And the memory stuff still doesn't work either. This is such a simple design, I am truly baffled... Any other thoughts?

  4. #4
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,615


    Did you find this post helpful? Yes | No

    Wink

    Quote Originally Posted by Atom058 View Post
    Any other thoughts?

    Yes !

    Elektor Magazine published such a device ... lots of years ago !!! Was April 1999 issue ...
    But the processor was a ST62T65B.

    Now you want that with a Pic ans PbP Written ...

    I just have one question : Why do you use a 12F629 instead of a 12F675 ??? ... that would give you a nice pot following servo position ...

    or do you intend to add a retrieving table ti linearize the RCTime result ???

    While you look at those lines ... I look at your code - OR - Organigram failure.

    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  5. #5
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Atom058 View Post
    Skimask - Thanks for the reply. I tried your code but am getting the same result. If the Set Limit Enable switch is on, I can control the servo movement with the pot (I had to change the scaling back to what I originally had, first). When it is at this point, it is not applying the limits (100 & 250). As soon as I turn off the switch (applying the limits), the servo does not move from the current position. It is acting like the minposit and maxposit variables are the same number. And the memory stuff still doesn't work either. This is such a simple design, I am truly baffled... Any other thoughts?
    The data statement is wrong-ish...
    data @0,100,250
    The original would put: 0,100,250 into eeprom, this way puts 100,250 starting at location 0.

    And you might want to try 'unrolling' your code, put it all in-line, get rid of the gosub. I believe if you 'unroll' your code, you may find your logic problem. Then you can put it back into a more modular format.

  6. #6
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,615


    Did you find this post helpful? Yes | No

    Default

    Hi, Atom

    Those lines Have Passed the MPSIM Test ...

    Code:
    @ DEVICE pic12F629, INTRC_OSC_NOCLKOUT ; Using Internal Clock, no clock out
    @ DEVICE pic12F629, WDT_ON ; Enable Watch dog timer
    @ DEVICE pic12F629, PWRT_ON ; Enable Power-up timer
    @ DEVICE pic12F629, MCLR_OFF ; Disable MCLR pin 
    @ DEVICE pic12F629, BOD_ON ; Enable Brown-out detect
    @ DEVICE pic12F629, CPD_OFF ; EEPROM Protect
    @ DEVICE pic12F629, PROTECT_OFF ; Code Protect off
    
    '@ __CONFIG _INTRC_OSC_NOCLKOUT &  _WDT_ON & _PWRTE_ON & _BODEN_ON & _MCLRE_OFF
    
    DEFINE OSCCAL_1K 1
    DEFINE BUTTON_PAUSE 20
    
    GPIO	= %00000000
    TRISIO 	= %11111110
    
    INTCON.6=0 ' Disable all unmasked Interrupts
    INTCON.7=0 ' Disable Global Interrupts
    CMCON = 7 ' Disable analog comparator
    
    ServoOut 	var GPIO.0
    SetLimitSw 	var GPIO.1
    PotIn 		var GPIO.2
    MinSw 		var GPIO.4
    MaxSw 		var GPIO.5
    
    Delay		var Byte
    
    Posit 		var Byte
    MinPosit 	var Byte
    MaxPosit 	var Byte
    
    'load starting min and max positions at program time
    data @ 0,100 
    data @ 2,250 
    
    '************************************************* ***************
    low Servoout
    
    'read in stored min and max limits
    
    read 0, MinPosit
    read 2, MaxPosit
    
    Start:
    
    gosub GetServoPosition
    
    Low 	servoout
    pulsout servoout, posit
    
    
    
    Delay = 0
    BUTTON setlimitsw, 0, 255, 0, Delay, 1, Start
    
    	Delay = 0
    	BUTTON minsw, 1, 255, 0, Delay, 1, MinL		'20 ms
    	Delay = 0
    	BUTTON maxsw, 1, 255, 0, Delay, 1, MaxL		' 20 ms
    	
    	pause 20					' no button pushed
    	Goto Start					
    	
    MinL:
    	IF maxsw = 1 THEN Start		'1 Button pushed at a Time !!!
    	
    	IF Posit <> MinPosit THEN
    	
    		MinPosit = Posit
    		write 0, MinPosit						'10 ms
    	
    	ENDIF
    	
    goto start
    
    MaxL:
    	
    	IF minsw = 1 THEN Start		'1 Button pushed at a Time !!!
    	
    	IF Posit <> Maxposit THEN
    	
    		MaxPosit = Posit
    		write 2, MaxPosit						' 10 ms
    		
    	ENDIF
    
    goto start
    
    '************************************************* ***************
    GetServoPosition:
    
    high potin
    pause 1
    rctime potin, 1, Posit 'at 4 mhz, returns 3 - 123 :: 1.23 ms max
    
    'adjust posit to get values between 75 and 250
    posit = posit + 75 + (posit / 2)
    
    'now limit posit to 100 - 250 (1 ms - 2.5 ms)
    
    if posit < 100 then posit = 100
    if posit > 250 then posit = 250
    
    if setlimitsw = 0 then 'apply limits
    
    	if Posit < MinPosit then Posit = MinPosit
    	if Posit > MaxPosit then Posit = MaxPosit
    	
    endif 
    
    return 
    
    '************************************************* ***************
    
    End
    Try those lines ... should work !!!

    Alain
    Last edited by Acetronics2; - 29th February 2008 at 19:32.
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  7. #7
    Join Date
    Sep 2006
    Location
    Florida, USA
    Posts
    88


    Did you find this post helpful? Yes | No

    Default

    Alain - Thanks for your suggestion. I tried it and got different results. Still getting good servo response to the pot, but it does not seem to be registering the min and max values when the buttons are pressed. The servo continues to move to the full limits.

    Just to be clear, the SetLimitSw is a slide switch. When it is slid to the On position, the program will monitor for the pressing of either the min or max pushbuttons (momentary). When the SetLimitSw is slid to Off, the program will apply the limits that were set.

    The concept is so simple (at least should be) that I am embarassed that I can't get this to work - I have done projects that are a hundred times more complex than this. I know the answer is staring me in the face - I just can't see it!

    I appreciate all the comments and encourage more!

  8. #8
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    You're reading EEPROM values into your word vars in reverse.

    data @0, 0, 100
    read 0, MinPosit.byte0 ' low byte now = 0
    read 1, minposit.byte1 ' high byte now = 100

    Then if Posit < MinPosit then Posit = MinPosit will always = true
    since MinPosit starts out at 25,600 or 6400h.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  9. #9
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,615


    Did you find this post helpful? Yes | No

    Post

    Hi,

    Did you check ( W/Multimeter ) GPIO 4 and 5 state when your Min and Max Buttons are pushed ???

    stupid question , ehhhh ???

    MPSIM shows memory is well written ... so, I do suspect a harware problem !!!

    I'll give a try with a '675 ... to be sure ( no 629 home ! )

    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  10. #10
    Join Date
    Sep 2006
    Location
    Florida, USA
    Posts
    88


    Did you find this post helpful? Yes | No

    Default

    Bruce - Good catch on the Data statement (DUH!)! However, if I run my original code as in my first post (with the change in the data statement), I still get the same results: perfect servo movement when first booted up, but when I move the servo to the center position, switch on the SetLimitSw, press the Min button and then switch off the SetLimitSw, the servo no longer responds to the pot - as though both the min and max buttons were pressed at the same position.

    I am beginning to think I have some underlying hardware issue (as Alain suggests). I will do some metering to see if I see anything fishy. If I don't, I'm going to rebuild the board with new components. If it still does it after all that, I'll shoot myself! (just kidding!).

    Thanks guys - let me know if you think of anything else!

  11. #11
    Join Date
    Sep 2006
    Location
    Florida, USA
    Posts
    88


    Did you find this post helpful? Yes | No

    Default Problem Solved!

    Well, just as I expected, it was me and yes, I'm embarassed! I started metering the min and max buttons and noticed that if I pressed either button, both pins went high - explaining why the servo just stayed in one spot when either the min or max button was pressed. After scratching my head over how that could possibly be happening, I noticed that my pull-down resistors were put in vertically instead of horizontally. If you look at the circuit diagram in my first post, you will see what I mean. How stupid was that! Anyway, I rotated the resistors and everything works perfectly! Go figure!

    I'd like to thank those who helped me and apologize for wasting their time. I knew it would be something like this...

    Well, I made a few changes to the code and here it is in it's final form:

    @ DEVICE pic12F629, INTRC_OSC_NOCLKOUT ; Using Internal Clock, no clock out
    @ DEVICE pic12F629, WDT_ON ; Enable Watch dog timer
    @ DEVICE pic12F629, PWRT_ON ; Enable Power-up timer
    @ DEVICE pic12F629, MCLR_OFF ; Disable MCLR pin
    @ DEVICE pic12F629, BOD_ON ; Enable Brown-out detect
    @ DEVICE pic12F629, CPD_OFF ; EEPROM Protect
    @ DEVICE pic12F629, PROTECT_OFF ; Code Protect off

    TRISIO = %11111110
    INTCON.6=0 ' Disable all unmasked Interrupts
    INTCON.7=0 ' Disable Global Interrupts
    CMCON = 7 ' Disable analog comparator

    ServoOut var GPIO.0
    SetLimitSw var GPIO.1
    PotIn var GPIO.2
    MinSw var GPIO.4
    MaxSw var GPIO.5

    wPosit var word
    Posit var byte
    MinPosit var byte
    MaxPosit var byte

    'load starting min and max positions
    data @ 0, 100
    data @ 1, 250

    '************************************************* ***************
    low Servoout

    'read in stored min and max limits
    read 0, MinPosit
    read 1, MaxPosit

    'for power-on reset of positions:
    if minsw = 1 then
    minposit = 100
    write 0, minposit
    endif
    if maxsw = 1 then
    maxposit = 250
    write 1, maxposit
    endif
    pause 1000

    Start:
    gosub GetServoPosition
    pulsout servoout, posit
    pause 20

    if setlimitsw = 1 then 'check min max buttons
    if minsw = 1 then
    MinPosit = Posit
    write 0, MinPosit
    pause 250
    endif

    if maxsw = 1 then
    MaxPosit = Posit
    write 1, MaxPosit
    pause 250
    endif
    endif

    goto start

    '************************************************* ***************
    GetServoPosition:
    high potin
    pause 1
    rctime potin, 1, wPosit 'at 4 mhz, returns 0 - 120

    'adjust posit to get values between 75 and 250
    'use word-sized variable because calculation might exceed 255
    wposit = wposit + 75 + (wposit / 2)

    'now limit posit to 100 - 250 (1 ms - 2.5 ms)
    'and put into byte-sized variable
    if wposit > 250 then
    posit = 250
    else
    posit = wposit
    endif

    if posit < 100 then posit = 100

    if setlimitsw = 0 then 'apply limits
    if Posit < MinPosit then Posit = MinPosit
    if Posit > MaxPosit then Posit = MaxPosit
    endif

    return

    '************************************************* ***************

    End

  12. #12


    Did you find this post helpful? Yes | No

    Default Beware the PULSOUT inversion problem

    PULSOUT is a toggle. Sooner or later you will get some interference that flips the state of the SERVOOUT line and your system will be off in the weeds.

    To guarantee correct working of the PULSOUT command you should first force the SERVOOUT line to a defined state.

    For example, put
    SERVOOUT = 0
    or
    LOW SERVOOUT
    before calling the Pulsout command.

    One of my RC aircraft went berserk because of that little oversight.

    HTH
    Brian

  13. #13
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by BrianT View Post
    One of my RC aircraft went berserk because of that little oversight.
    HTH
    Brian
    You mean like pulling UP out of an inverted low pass?
    I lost a hopped-up clipped wing (+an extra bay) Goldberg Cub that way....(sigh)....

  14. #14
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,615


    Did you find this post helpful? Yes | No

    Default

    Hi, BrianT

    To fullfill your Pulsout knowledge ...

    You are to use LOW Output ...

    with some Hot plugged servos ( Graupner i.e.) or High capacitive loads ( some µF ) , Output = 0 is not enough to have a neat O level prior to Pulsin.
    I know it's not supposed to happen in flight ... but, ...

    Service,Sir ...

    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

Similar Threads

  1. Problem with I2C EEPROM addressing
    By Atom058 in forum General
    Replies: 14
    Last Post: - 3rd November 2009, 03:17
  2. Writing to a table.
    By Rhatidbwoy in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 24th December 2005, 16:20
  3. Servo Recording
    By kenpo in forum General
    Replies: 3
    Last Post: - 2nd September 2005, 16:03

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

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