Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Timer controlled movement of RC servo strange
Goto page 1, 2  Next
 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR
View previous topic :: View next topic  
Author Message
autoguider

Bascom Member



Joined: 24 Sep 2007
Posts: 82
Location: Aachen

germany.gif
PostPosted: Fri Dec 11, 2020 1:15 pm    Post subject: Timer controlled movement of RC servo strange Reply with quote

Dear All, I kindly ask for your advice.
I want to control 2 RC servos (KUMAN , 270°) named servo_2 and servo_3.
Length of pulses is between 500µs and 2500 µs.
As movement needs to be slow I do an update of the pulse length every 40ms. With 20ms it was the same.
Servo 3 runs smoothly the whole way. Only Servo 2 is stuttering in the final 30% of the movement in and from the working position.

Update: I get the first hickups at a value of 215 for timer2. This correponds to 2.24 ms pulse length.

Changing the servo hardware did not help. So it seems to be in the software. Either of the servo or in the Atmel.

Pulse generation is done via 2 timers.
Timer0 generates the 20ms frame.
The ISR of timer0 calculates the new values for the interrupt generation of timer 2 and stores them into the array B_Impulsdauer.

For each servo there is a reserved time frame determined by the value of pulseframe.
I set pulsframe to 253. This means 2640 µs for each pulse which is sufficient for the 2500µs and allows to extend the ON- time of the pulse in case of tolerances with the servos.
So the 20ms frame is kept for each of the servos.
Impulsdauer(3) contains the value for the ON –time for the pulse for servo2
Impulsdauer(4) contains the value for the OFF –time for the pulse for servo2
Impulsdauer(5); Impulsdauer(6) does the same for servo 3.

How the new values are changed depends on the value of B_Fahrzustand.
These values are:
1 ( forward), 0 (standstill), &HFF (backward). So timer0 can run permanently.
Timer0 triggers timer2. Timer2 generates the pulses for both servos. Servo 2 is served first. The ISR Servopuls_isr_t2 is executed 5 times and then shuts off timer2. Timer2 remains inactive until it is re-triggered by timer0.
B_Servonr is a counter to address the correct time period. Values range from 2 to 7. When value 7 is reached B_Servonr is reset to 2 (see label Reset_servo_count)

Parameters for the Timers:
Code:

Config Timer0 = Ctc , Clear_timer = 1 , Prescale = 1024
On Compare0a 20ms_timer0_isr Nosave


'CTC Mode, Outputs disconnected

   ' TCCR0A
   '   'Bit        7                 6            5         4        3 2     1         0
   '   '(0xB0) COM02A1 COM0A0 COM0B1 COM0B0 – – WGM01 WGM00
Tccr0a = &B00000010

   '   'TCCR0B
   '   'Bit           7          6    5 4     3         2     1        0
   '   '(0xB1) FOC0A FOC0B – – WGM02 CS02 CS01 CS00

'Tccr0b = &B00000101
Tccr0b = &B00000000     ' Timer stopped. Started in Sub init
 


Timer2
Code:

Config Timer2 = Timer, Prescale = 64


On Compare2a Servopuls_isr_t2 Nosave


Tccr2a = &B00000010                     'CTC Mode, Output disconnected

Tccr2b = &B00000000                     'Timer 2 triggered by Timer0 so-> STOP here



'Tccr2b = &B00000100                 'prescaling 64 only!; 1 required to start Timer2

      ' ' TCCR2A
   '   'Bit        7     6     5        4  3 2   1     0
   '   '(0xB0) COM2A1 COM2A0 COM2B1 COM2B0 – – WGM21 WGM20

   '   'TCCR2B
   '   'Bit      7     6   5 4  3     2     1      0
   '   '(0xB1) FOC2A FOC2B – – WGM22 CS22 CS21 CS20
   '             0    0    0 0   0    1     0    0


  '@ 6,144 MHz and prescale 64 240 increments for 2500µs and 48 incr. for 500µs
 



Here the code of the ISR Timer0

Code:

20ms_Timer0_isr:                        'Starts 20ms frame

'Executed operations
'B_Impulsdauer(3) = B_Impulsdauer(2) + B_Fahrzustand(2)
'B_Impulsdauer(5) = B_Impulsdauer(3) + B_Fahrzustand(3)
'start Timer 2
'Runtime ISR appr.11 us , 69 cycles
     '




$asm
      push r15                          'r 15 to Stack
      in r15,sreg                       'Read Statusregister  R15
      push r15                          'Statusregister to Stack
      push r20                          'r 20 to Stack
      push r19                          'r 19 to Stack
      push r28                          'Y Register
      push r29
      push r30                          'Z- Register
      push r31


      Loadadr B_alarmcounter,Z          '20ms timebase for increment alarmcounter ;
      ld r20,z
      inc r20
      st z,r20
      andi r20,2                        'calculate length of puls every 2 x 20 ms
      cpi r20,2
      brne Jumplabel


      Loadadr B_impulsdauer(3) , Z      'Duration of "ON" phase addressed via Z register
      ld r20,z                          'Duration in r20
      Loadadr B_fahrzustand(2) , Y      'Y adresses mode of movement in-/decrement of 1 results in 10.4 µs pulse length
      ld r19 ,y                         'value in r19
      ADD r20,r19                       'Addition, result in r20
      st z,r20                          'save in Impulsdauer(3)


      ldi r19,pulsframe                       'Calculate time gap to meet pulseframe of servo 1
      !Sub R19 , R20
      st z+1,r19                        'Save in Impulsdauer(4)

      Loadadr B_fahrzustand(3) , Y      'Y adresses mode of movement

      ld r19,y                         'R 19 contains Fahrzustand(3)
      ld r20,z+2                        'R 20 contains Impulsdauer(5) = ON time servo 2
      add r20,r19                       'Addition Ergebnis in R20
      st z+2,r20                        'store new value of "ON" time servo 2 in Impulsdauer(5)
      'Loadadr Maxpuls, y
      'ld r19,y


      ldi r19,Pulsframe                 'calculate new value for "OFF" time servo 2
      !SUB R19 , R20
      st z+3,r19


     jumplabel:
      ldi r20,3                         'R20 now used as general register
      !Out Ocr2a , R20              'Set OCR2A to 3 to have a time distance between ISRs 64 = clock cycles sufficient to finalize this ISR before Servopuls_isr_t2 is executed the 1st time

      ldi R20,0
      !out tcnt2,R20                    'Set Counter register to 0 setzen
      ldi r20,&B00000100              'Configuration Timer 2 with pre scale etc..
      Out Tccr2b , R20                  'Load Timer2 register Starts Timer 2

     


      Pop r31                           'Stack clean up
      Pop r30
      Pop r29
      Pop r28
      Pop r19
      Pop r20
      Pop r15
      Out Sreg , R15
      pop r15



 $end Asm

 Return
 

And the code for the Timer2 ISR
Code:

Servopuls_isr_t2:                       'Creates pulses for the servos


   $asm

      push r20                          'save content r20 to stack
      in r20,sreg                       'load statusregister in r 20
      push r20                          'save status register to stack
      push r19                          'save content r19 to stack
      push r26                          'save contentX register
      push r27                          'save content X register

      cbi portc,1                       'Clear C1 = Pulse Servo 2 =0
      cbi Portc,2                       'Clear C2 = Pulse Servo 3 =0

      Loadadr B_servonr , X
      Ld r20 , X                        'ServoNr in r20; Start Value =2
      inc r20                           'Increment B_servoNr



     '--------------- "ON" time servo 2

         cpi r20,3                      'Equal to 3 ?
         brne OFF_time_servo_2          'if value =4  jump
         st X , R20                     'store incremented B_ServoNr =3
         SBI portc,1                    'set pin c1 =1. "ON" time servo 2
         Loadadr B_impulsdauer(3) , X   'Load duration of switch "on" phase
         ld r19,x                       'in register 19
         !Out Ocr2a , R19               'Set value for next ocr2a interrupt
         ldi r19,0                      'load value 0 to r19
         !out tcnt2, r19                'Set counter value of timer2 to 0

      jmp End_ISR_t2                    'JMP to exit procedure ISR

    '---------------- "OFF" time servo 2

    Off_time_servo_2:                   'Fill time gap so that servos get their signals in the 20ms frame

     cpi r20,4                          'check if value =4
     brne ON_Time_Servo_3               'if 5 Goto "ON" phase servo 3

     st x , r20                         'store value 4 to B_servonr
     Loadadr B_impulsdauer(4) , X       'load value for filling remaining time gap
     ld r19,x                           'Load duration of switch "off" phase servo 1
     !Out Ocr2a , R19                   'Set value for next ocr2a interrupt
     ldi r19,0
     !out tcnt2, r19                    'Set counter value of timer2 to 0


    jmp End_ISR_t2                      'JMP to exit procedure ISR



   On_time_servo_3:

     cpi r20,5                          'Check if value =5
     brne OFF_time_servo_3              'Goto OFF time servo 3

  '--------------- "ON" time servo 3
     st x , r20                         'store value 5 to B_servonr

     sbi portc,2                        'set pin c2 "ON" time servo 3
     Loadadr B_impulsdauer(5) , X       'Load duration of switch "on" phase servo 2
     ld r19,x
     !Out Ocr2a , R19                   'Set value for "ON" time servo 3
     ldi r19,0
     !Out Tcnt2 , R19                    'Set counter value of timer to 0
     jmp End_ISR_t2                     'JMP to exit procedure ISR

  '--------------- "OFF" time servo 3
 Off_time_servo_3:

     cpi r20,6                          'Check if value =6
     brne Reset_Servo_Count             'jmp if b_servonr has normally value 7
     st x , r20                         ' B_Servonr = 6; Save value
     Loadadr B_impulsdauer(6) , X       'Fetch value for "OFF" time servo 3
     ld r19,x                           'load value for "OFF" time servo 2 to r19
     !Out Ocr2a , R19                   'Set timer register to OFF time value
     ldi r19,0
     !out tcnt2, r19                    'Set counter value of timer2 to 0
     jmp End_ISR_t2                     'JMP to exit procedure ISR


Reset_servo_count:

     Loadadr B_servonr , X
     ldi r20,2
     st x ,r20                          'Set B_Servonr to 2; Is prepared for the next cycle of this ISR
     ldi r19, 0
     !Out Tccr2b , R19                  'Timer2 is stopped
     !out tcnt2 , r19                   'Timer 2 counter register =0



 End_isr_t2:

      pop r27
      pop r26
      pop r19
      pop r20                           'X Register High to Stack
      !out sreg,r20
      pop r20

 $end Asm
 'max 53 cycles = 9µs
Return
 


After days of testing I have no clue why it works with servo3 and not with servo2.
Please let me have your advice.

Best regards
Christian

(BASCOM-AVR version : 2.0.8.3 )
Back to top
View user's profile
hgrueneis

Bascom Member



Joined: 04 Apr 2009
Posts: 902
Location: A-4786 Brunnenthal

austria.gif
PostPosted: Sat Dec 12, 2020 8:22 pm    Post subject: Reply with quote

If you use RC-servos, then you are driving these servos out of range!
Most Servos can accept pulses from 0.9 milliseconds to 2.1 milliseconds.
If you need more than 60 degrees of movement, then you have to modify the servo with additional resistors at the potentiometer.
In practical applications it can be extended to about 180 degrees of servo movement.
Slow movement can be done by loops or certain interrupt routines, which can be called at fixed times.
Reverse movement requires to switch sides on the potentiometer.
If you do not write your own routine, then you can use Bascom commands.
I control 18 servos with just AT168 with a resolution of 1 microsecond. Proven with a scope.

Regards
Hubert
Back to top
View user's profile
laborratte

Bascom Expert



Joined: 27 Jul 2005
Posts: 299
Location: Berlin

germany.gif
PostPosted: Sun Dec 13, 2020 5:19 pm    Post subject: Reply with quote

Hi,
I'm not familiar with RC Servos, but here some notes to your code:

- I don't see any overflow control in your on-off-time calculation. How do you avoid values >255 or <0?

- When writing asm code in "no save" interrupt routines you should use the $notransform compiler directive. Depending to your MCU Bascom may change instructions like CBI, SBI, OUT with use of R23 (see help: mixing ASM/Bascom) - which you are not saving to stack. This can produce very nasty and difficult to find errors.

- I try to avoid the use of Y pointer - it is too important to Bascom. I the case shown above it is OK, but if you somehow later reuse the code in mainloop this can cause serious problems.

- Instead of using
Code:
Loadadr B_servonr , X
Ld r20 , X
you can use
Code:
lds r20,{B_servonr}
Saves time and space.

- Why do you not use the PWM generation capabilities of the timers directly?
Back to top
View user's profile
Duval JP

Bascom Member



Joined: 22 Jun 2004
Posts: 1161
Location: France

france.gif
PostPosted: Sun Dec 13, 2020 5:36 pm    Post subject: Reply with quote

Mark does a lot for us :

see https://wiki.mcselec.com/bavr/CONFIG_SERVOS

JP Wink

_________________
pleasure to learn, to teach, to create
Back to top
View user's profile Visit poster's website
hgrueneis

Bascom Member



Joined: 04 Apr 2009
Posts: 902
Location: A-4786 Brunnenthal

austria.gif
PostPosted: Sun Dec 13, 2020 9:21 pm    Post subject: Reply with quote

JP,
yes, that is right, but Bascom , as good as it is,
can not handle 18 Rc-Servos at a resolution of one microsecond.
In order to have a smooth movement for a high number of servos, you need to write your own routines....in Bascom.
At least, if you want a reasonable repeat time of 40 times a second.
With my system and change of processor I could expand to over 30 servos per controller at the same resolution.
It is not rocket building knowledge.

Best regards
Hubert
Back to top
View user's profile
hgrueneis

Bascom Member



Joined: 04 Apr 2009
Posts: 902
Location: A-4786 Brunnenthal

austria.gif
PostPosted: Sun Dec 13, 2020 9:47 pm    Post subject: Reply with quote

I did not go through your program, but you need to check the limits of your servos first,
and I am sure that you are out of range. Like I wrote before, most servos can handle 0.9 to 2.1 milliseconds, but there are some that can only handle a lot less. If a servo starts to jitter above 2.1 milliseconds or 1.9, this means that it is at its limits. Driving these servos further can result in damage and loss of servo and much higher power consumption (the end is near).

Best regards
Hubert
Back to top
View user's profile
Evert :-)

Bascom Expert



Joined: 18 Feb 2005
Posts: 2156

netherlands.gif
PostPosted: Mon Dec 14, 2020 9:12 pm    Post subject: Reply with quote

hgrueneis wrote:
JP,
yes, that is right, but Bascom , as good as it is,
can not handle 18 Rc-Servos at a resolution of one microsecond.


TS is talking about 2 servo's, not 18.
Btw The help text is talking about 14 servo's are supported by Bascom.

_________________
www.evertdekker.com Bascom code vault
Back to top
View user's profile Visit poster's website
autoguider

Bascom Member



Joined: 24 Sep 2007
Posts: 82
Location: Aachen

germany.gif
PostPosted: Wed Dec 16, 2020 8:00 pm    Post subject: Reply with quote

Dear All,
many thanks for your replies and advice.
@ Hubert: The servo is designed for 270 control angle. According to the information from the supplier the length of the control pulse can vary between 500µs and 2500 µs. So hacking of these servos is not required. That is the reason for me to choose them.
@ laborratte: I was not aware of the $notransform directive and I will put it into my code. Also the lds command is very useful. I will implement it as well
I did not see how to use the PWM capabilities of the timer. I need to serve 2 servos, maybe 3 in a later stage. For timer 0 I have OC0A and OCOB. Changing the trigger values to execute the ISR is essential for each movement. I you can help me with a code snippet or a link?
@JP: Tkanks for the link. I do not understand how I can run the feature that Mark has provided for a 270° control angle servo. How is the pulse generation synchronized to the 20ms frame for all servos?
How can I do the slow movement ?
Also the question of overflows arised.
To avoid overflow of the trigger values for timer2 is control them in the sub that coordinates the movement.
Code:

Case 2 : B_fahrzustand(2) = Vor            ' swivel to working position
                While B_impulsdauer(3) < Maxpuls   ' Wait until working position is reached
                 Wend
                 B_fahrzustand(2) =Steht  ' position reached. Add 0 to the value for counter register
 

And here the definitions:
Code:

 'State of movement

.equ Vor = 1                           'forward
.equ steht = 0  '        neutral, no changes
.equ Back = &HFF '   backward, subtraction
 

In the ISR of timer0 the values are always added. Most of the time it will be the value 0. Adding &HFF causes a subtraction which means counting down.

When the target value is reached the state of moving is set to Steht, which adds the value 0 to impulsdauer. So the length of the control pulse is not changed anymory. This is at the working position and at the standby position.
Additionally I do have implemented a limitation in the main loop.

In the meantime I did some further investigation using an oscilloscope.
The pulse generation looks smooth and continuous.
I measured 1V amplitude for the control pulse. As I read that servos need TTL level I installed 1k pullup resistors connect to the 7805 that provides power to the MCU circuit. As soon as I connect the servo to the circuit board voltage drops from 5V to 1V again.
Disconnecting brought the voltage of the control pulse back to 5 V.
I expect the servos to have a high impedance and not to drop the voltage.

Then I installed a 220µF capacitor at the supply voltage of the servo close to the servo. The supply voltage is generated by another 7805.
Still the hiccups. But not always.
Sometimes I can operate the servo 4-5 times absolutely smooth. Then , there are 2-3 hiccups that I can see and also feel at the body of the servo when moving forward and also when moving backward at the same positions.
The strange thing is that the second servo runs smoothly. Only the servo that is served first in the ISR has the hiccups. Changing the servos does not change the behavior of the servo that is served first.
So it could be the software or it is something wrong with the connection.

Occasionally it can happen that I turn off the electric power when the servo is in working position.
On powering up again I set the length of the control pulse to 500µs. As I shut down the power when the servo was in working position the actual pulse does not match the physical position.
Then I can feel some vibration in the servo'as body. Pushing the button to bring the pulse length matching the physical position works. Just when the pulse fits I get a short fast movement backwards and immediately forward. After this logical and physcal positons match an I am back in normal operation.
Is this typical to servos?

If you have some ideas please let me know.
Best regards
Christian
Back to top
View user's profile
autoguider

Bascom Member



Joined: 24 Sep 2007
Posts: 82
Location: Aachen

germany.gif
PostPosted: Thu Dec 17, 2020 3:02 pm    Post subject: Reply with quote

Update.
When I disconnect the 2nd, smooth running, servo from the circuit board I have no hiccups in the movement of servo 1.
I do not see bursts, spikes or voltage drops on the suppy voltage for the servos.

Now it looks that most probably the software is not the issue but some interference.
control pulse of servo 1 is over before the pulse for servo 2 starts.
It remains strange.
Back to top
View user's profile
hgrueneis

Bascom Member



Joined: 04 Apr 2009
Posts: 902
Location: A-4786 Brunnenthal

austria.gif
PostPosted: Sat Dec 19, 2020 6:49 pm    Post subject: Reply with quote

How many Kg/cm do the servos do?
Regards
Hubert
Back to top
View user's profile
autoguider

Bascom Member



Joined: 24 Sep 2007
Posts: 82
Location: Aachen

germany.gif
PostPosted: Mon Dec 21, 2020 2:05 pm    Post subject: Reply with quote

It is 17 kg cm. KUMAN KY72-1
I think that they are oversized.
When plugging in I measure 30mA at the entry of the 7805 on 12V level per servo.
In movement it takes less than 100mA.
The ripples in the movement do not occure when the movement starts but in between.

I will do a measurement of the 5V level that I use for the supply of the servos.

The control voltage is generated by a separate 7805 that supplies the Atmel.
The strange behaviour is that the output voltage at PORTC.1 / C.2 is 5V when servos are disconnected.
As soon as I plug in one servo this voltage drops down to 1V. Pull up rsisitors did not help.
I contacted KUMAN to check on the impedance.
It also may be possible that these servos need 6V or 7V for operating properly.
Then I will install a 7806.
To my feeling the impedance of the servos has to be in the kOhms area at least. I am not the 1st one to connect servos to an Atmel.

best regards
Christian
Back to top
View user's profile
hgrueneis

Bascom Member



Joined: 04 Apr 2009
Posts: 902
Location: A-4786 Brunnenthal

austria.gif
PostPosted: Mon Dec 21, 2020 3:04 pm    Post subject: Reply with quote

I use 10K servos, but on a 5 Amp. supply for the 18 servos.
Your problem might be the control voltage output from the ports.
or one servo input might be defective.
One way to find out, put an mA-meter in the control line or better a 1 or 10 ohm resistor and scope the voltage to find out the drain.
It should be less than 20mA and at least show 4,5V at the port.
If it is less than 20 mA, then your Atmel is shot with the port at 1V.
You might also try to switch the servos on the ports.

Best regards
Hubert
Back to top
View user's profile
autoguider

Bascom Member



Joined: 24 Sep 2007
Posts: 82
Location: Aachen

germany.gif
PostPosted: Mon Dec 21, 2020 6:12 pm    Post subject: Reply with quote

Dear Hubert,
this is what I expected. Max. 20 mA.
I have the voltage drop on both servos.
To avoid interference from the motors to the Atmel I installed the separate 7805 + free wheeling diode on the 5V side.
My strong feeling is too that the 1Vpulse level is much too low for the servos.

This morning I got a contact to the supplier and asked for information about the impedance.
Maybe the servos' control circuit is damaged.
I also found performance data based on 6V and 7V operation voltage.

Can servos run on this high voltage. To my experience 5V is the normal case.

If 6V or 7V is nominal voltage then it may happen that the servos' control circuits doe not operate properly.
Did you experience such voltage issues on servos?

best regards
Christian
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Mon Dec 21, 2020 7:36 pm    Post subject: Reply with quote

autoguider wrote:
To avoid interference from the motors to the Atmel I installed the separate 7805 + free wheeling diode on the 5V side.

You never had the idea, that RC servos may pull pulsating current and the few mA you've measured are averaged by your DMM?
The poor little 7805 tries to handle these pulses and has to do a hell of a job.
Try a few 1,5V batteries and report back.
Here:
http://www.kumantech.com/kuman-17kg-270-degree-metal-gear-digital-servo-with-u-bracket-amp-side-mount-for-rc-robot-helicopter-airplane-car-boat-ky72-1_p0398.html
the talk is about a current of 100mA unloaded, I guess they pull 1.5 to 2.5 amps while stalling.
Back to top
View user's profile
hgrueneis

Bascom Member



Joined: 04 Apr 2009
Posts: 902
Location: A-4786 Brunnenthal

austria.gif
PostPosted: Mon Dec 21, 2020 9:45 pm    Post subject: Reply with quote

The minimum voltage for your Servo is obviously 6V, max. 7V.
No mention of the control voltage drive (Voltage/Amp.)at WMS's link.
Regular servos need 4.8V to 5V. and the control pulse is within TTL specs.
I would ask sales for a valid datasheet per email.
Good luck.

Regards Hubert
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum