This is a guide to setup the AVR PWM for updating a servo in the background. This demo is for sweeping a regular servo through it's motion or a continous servo backwords, neutral, and forward. The long waits are used to measure the PWM pulse width values.
#chip mega328, 16
'**********
'step 1: pick TIMER, and PWM pin, which will be timer1 for it is a 16
'bit timer, and OC1A for the pin.
#define Servo1 PortB.1
Dir Servo1 OUT 'pin OC1A or Pin 9 on the UNO board
'step 2: set the MODE wanted, which is phase correct and a TOP of ICR1
'so we can set the 20ms update frequency/period accurately. From table
'16-4, mode 10 is required:
Set WGM13 ON
Set WGM12 OFF
Set WGM11 ON
Set WGM10 OFF
'step 3: pick the PRESCALE for reasonable step resolution, say 250
'(over 2ms) steps. Since 2ms is 10% of the 50 Hz (i.e. 20ms update) we
'will look for a TOP value (ICR1) of 2500. Using the formula from the
'data sheet, and available prescales. TOP or ICR1 = (16000000 / 2 *
'50 * 64)- 1 = 2499; so 250 is the duty cycle for 2ms with the prescale
'at 64. Set clock select or prescale bits:
Set CS12 OFF
Set CS11 ON
Set CS10 ON
'step 4: set the PERIOD or frequency per previous TOP/ICR1 calculation:
'Servo Update = 2499 for 50Hz/20ms
ICR1H = 9
ICR1L = 195
'step 5: Start DUTY CYCLE at servo center, using OC1A pin of Timer1.
'1.5ms or approximately 3/4 * 250 = 187:
'test neutral for continous servo
Dim ServoPeriod1 as Word
OCR1AH = 0
OCR1AL = 187
'step 6: set PWM MODE BITS to startup the module.
Set COM1A1 On
Set COM1A0 Off
'**********
Dim steps as Word
wait 5 s
Main:
steps = 90
SetDuty (steps)
wait 5 s
For steps = 90 to 187
SetDuty (steps)
wait 20 ms
Next
wait 5 s
For steps = 187 to 290
SetDuty (steps)
wait 20 ms
Next
wait 5 s
goto Main
sub SetDuty (ServoPeriod1)
OCR1AH = ServoPeriod1_H
OCR1AL = ServoPeriod1
end sub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I copy pasted that to gcb and saved. I'll give ita try...well scope and mess with. All those silly register bit names...if tey are...like arduino guide to timers and pwm/cmmp.
I'll see now what it does,
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Not familiar with xloader, but I just did a copy and paste, make hex and no compiler problems. Reflash with avrisp Mark ii and super bloated atmel studio 7. Getting PWM period of 50Hz, and pulse widths of 0.720ms, 1.496ms, and 2.321ms as expected with DVM.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
maybe not the rightt bits for uno Set WGM13 ON
Set WGM12 OFF
Set WGM11 ON
Set WGM10 OFF
I'm just guessing cos the arduino guide says not uno but I'm not certain...baffled by science
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sub works, otherwise would not get correct pulse widths. Period and duty cycle word values need to be loaded in correct order for the "timer" which is the high register first, then low register, per recent conversation with William. "HAVE TO USE THAT SUB" for the duty cycle values, otherwise gcb will try and load the low register first, which is no bueno.
Should work as unmodified, so I think it may be the tool chain. You have been using xloader all along with no problems? Xloader works with a specific bootloader, is it the correct one? If not, then try a different version of xloader, or the required bootloader? I use 328p device with Studio 7 programming tool. I am currently on gcb 95.008, I'll try on 97.01 and see what happens, seems like I did this before.
Just reflashed once again from cut and paste, with 95.008, and still good results. The WGM3:WGM0 bits are correctly set for the TC1 PWM mode 10.
EDIT: said WGM3:WGM0 meant WGM13:WGM10 bits.
Last edit: kent_twt4 2017-05-31
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi again. My cheapo dso managed to trigger but the signal is swamped with other signals.! KHz is dominant.. It won't drive a servo. Why am I getting non result. I'm using v.97 and came with it pwm in include/lowlevel not test pwm but tried that to.
I've been looking at https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM fo insight.
Looksl ike mains hum. I put a do loop at line 51.
Looks like you are getting the Hantek DSO sorted out? Sometimes when chasing 1's and 0's the results can be inexplicable :). Don't have that tool, so no help here on how to run it. Try the pulse width setting for ms timing? Here is a pic of the Saleae clone logic tool zoomed in.
Sorry to distract you but could you run 3 servos off this routine by stopping and starting similar code cos there's time for 3 routines. Sorry if that's a dumb question. Is there a gcb pic version of hpwm servo or method for pic with hpwm? All the new timer and now hpwm new dev I get lost keeping up.. Brill this complicated stuff is being made easier.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Yes on using three servos with AVR hardware PWM, but I think it would have to be a large pinout AVR device like the atmeg2560. The '2560 has four 16bit timers, with each timer having 3 PWM channels OCRxA, OCRxB, and OCRxC. The '328p 16 bit timer only has two PWM channels OCR1A, and OCR1B connected to the 16 bit timer1.
In order to get the three servos using the 328p, I would probably us the above method to control two servo's like for robot drive and use the PWM period interrupt to update a third servo. start a timer2, turn on a pin for third servo, wait for timer2 compare match to fire another interrupt to set the third servo pin off. Sounds complicated, there is probably a better way of thinking on this others may want to elaborate.
Not aware of gcb servo command, or similar PIC HPWM routine, but servo's have been discussed in the past, so a search can lead to some demo code for more servos?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I haven't checked all pics compare and hpwm capabilities. I would think some pis might be similar to 2560
I like simple robots and built a line follower that used two fitec 9g servos modded for continuous. It used 50hz interrupt pulseouts and worked. I want another normal servo for a distance sensor holder.I'll wire scope it and see what happens without another solutin. Maybe I'm hoping too much and why they sell servo controller boards :)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am sure the 50Hz interrupt is a good strategy, it is the way it is mostly done?
I have used the PIC16f1572 before for driving leds, it has four 16bit PWM, kind of rediculous really for an eight pin device. That could do four servos in hardware PWM. You probably need more pins though, so look for one using Microchip MAPS found here http://www.microchip.com/maps/microcontroller.aspx to find what you need.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This is a guide to setup the AVR PWM for updating a servo in the background. This demo is for sweeping a regular servo through it's motion or a continous servo backwords, neutral, and forward. The long waits are used to measure the PWM pulse width values.
I copy pasted that to gcb and saved. I'll give ita try...well scope and mess with. All those silly register bit names...if tey are...like arduino guide to timers and pwm/cmmp.
I'll see now what it does,
It crashed gcb when I flashed hex.on it. avrdude errors. I get back sir l8r
GCB hex file crashed xloader. cntrl/alt/del job. No compile errors.No make hex errors.
The p in #chip mega328, 16 but now scoping it won't trigger
Not familiar with xloader, but I just did a copy and paste, make hex and no compiler problems. Reflash with avrisp Mark ii and super bloated atmel studio 7. Getting PWM period of 50Hz, and pulse widths of 0.720ms, 1.496ms, and 2.321ms as expected with DVM.
Is the sub working ... 8 bit val to lo hi or moi not with it?? complicated stuff on pic to.
I stuck the p in mega328 and hexflash from GCB ok but nowt solid on portb.1 pin 9 arduino uno on scope
It's a works for me thing. Please re check, I send stuff and missed a bit lots.
maybe not the rightt bits for uno Set WGM13 ON
Set WGM12 OFF
Set WGM11 ON
Set WGM10 OFF
I'm just guessing cos the arduino guide says not uno but I'm not certain...baffled by science
there's activity on several pwm pins. My scope won't trigger though
Sub works, otherwise would not get correct pulse widths. Period and duty cycle word values need to be loaded in correct order for the "timer" which is the high register first, then low register, per recent conversation with William. "HAVE TO USE THAT SUB" for the duty cycle values, otherwise gcb will try and load the low register first, which is no bueno.
Should work as unmodified, so I think it may be the tool chain. You have been using xloader all along with no problems? Xloader works with a specific bootloader, is it the correct one? If not, then try a different version of xloader, or the required bootloader? I use 328p device with Studio 7 programming tool. I am currently on gcb 95.008, I'll try on 97.01 and see what happens, seems like I did this before.
Just reflashed once again from cut and paste, with 95.008, and still good results. The WGM3:WGM0 bits are correctly set for the TC1 PWM mode 10.
EDIT: said WGM3:WGM0 meant WGM13:WGM10 bits.
Last edit: kent_twt4 2017-05-31
Separate power supply for servo I hope,.... if it is hooked up? grounds need to be connected too.
Hi again. My cheapo dso managed to trigger but the signal is swamped with other signals.! KHz is dominant.. It won't drive a servo. Why am I getting non result. I'm using v.97 and came with it pwm in include/lowlevel not test pwm but tried that to.
I've been looking at https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM fo insight.
Looksl ike mains hum. I put a do loop at line 51.
Last edit: stan cartwright 2017-06-01
Sorted.Works ok. Dunno why didn't work. Nice work Kent.
Looks like you are getting the Hantek DSO sorted out? Sometimes when chasing 1's and 0's the results can be inexplicable :). Don't have that tool, so no help here on how to run it. Try the pulse width setting for ms timing? Here is a pic of the Saleae clone logic tool zoomed in.
Cheapo dso is not a substitute for old analogue scope I found. I wouldn't have sorted all that code you did myself. Great job.
Sorry to distract you but could you run 3 servos off this routine by stopping and starting similar code cos there's time for 3 routines. Sorry if that's a dumb question. Is there a gcb pic version of hpwm servo or method for pic with hpwm? All the new timer and now hpwm new dev I get lost keeping up.. Brill this complicated stuff is being made easier.
Yes on using three servos with AVR hardware PWM, but I think it would have to be a large pinout AVR device like the atmeg2560. The '2560 has four 16bit timers, with each timer having 3 PWM channels OCRxA, OCRxB, and OCRxC. The '328p 16 bit timer only has two PWM channels OCR1A, and OCR1B connected to the 16 bit timer1.
In order to get the three servos using the 328p, I would probably us the above method to control two servo's like for robot drive and use the PWM period interrupt to update a third servo. start a timer2, turn on a pin for third servo, wait for timer2 compare match to fire another interrupt to set the third servo pin off. Sounds complicated, there is probably a better way of thinking on this others may want to elaborate.
Not aware of gcb servo command, or similar PIC HPWM routine, but servo's have been discussed in the past, so a search can lead to some demo code for more servos?
I haven't checked all pics compare and hpwm capabilities. I would think some pis might be similar to 2560
I like simple robots and built a line follower that used two fitec 9g servos modded for continuous. It used 50hz interrupt pulseouts and worked. I want another normal servo for a distance sensor holder.I'll wire scope it and see what happens without another solutin. Maybe I'm hoping too much and why they sell servo controller boards :)
I am sure the 50Hz interrupt is a good strategy, it is the way it is mostly done?
I have used the PIC16f1572 before for driving leds, it has four 16bit PWM, kind of rediculous really for an eight pin device. That could do four servos in hardware PWM. You probably need more pins though, so look for one using Microchip MAPS found here http://www.microchip.com/maps/microcontroller.aspx to find what you need.
I didn't know about that. Thank you.