Go Down

Topic: Frequency Question (Read 6382 times) previous topic - next topic

retrolefty


My idea was to make another library, which had to be more efficient in terms of cpu usage.

What I have designed is a testing board (which I'll post after I finish the 1st stage, the motors and the equilibrium library). To start, I've used just 2 of the 4 motors I have for testing. Later, I'll make a quadcopter having a maximum of 550-600 grams. And my target is to make the quadcopter super responsive to stimuli.
That's why I wasn't thinking at the Servo library. I thought it was too slow.

Well the ESC cannot accept new valid speed commands faster then it's 50Hz frame rate allows so the servo library will not be the limiting factor of how responsive motor commands will be, your sketch loop rate will probably be the limiting factor.

I'll post later the results of using the Servo library.

Good luck on your project.

Lefty


Thanks,
RobertEagle

dhenry

Quote
1.My ESCs are Roxxy Robbe BL Control 710 and work with Roxxy Robbe 2216/25 Motors.


Unless your ESCs are some strange beasts, they are not going to run at 10Khz. They usually take 20ms signal (20hz).

If that is the case, you can easily replicate such a thing via software. A few possibilities:

1) the simplest would be polling: set up a free running 20ms timer. in the loop, read the timer and set / clear output pins based on the value of the timer and your desired duty cycle. This is the simplest to code but sucks all processor power and may have some jitter.
2) or you can use software timers. st up a timer to run the duty cycle; on up the isr, reload the timer with 20ms - duty cycle, and then set / clear pins.
3) use three hardware timers. You can use either the OCnA/B/C pins, or user-specified pins.

The last approach is the best but requires 3 timers.


retrolefty


Quote
1.My ESCs are Roxxy Robbe BL Control 710 and work with Roxxy Robbe 2216/25 Motors.


Unless your ESCs are some strange beasts, they are not going to run at 10Khz. They usually take 20ms signal (20hz).

If that is the case, you can easily replicate such a thing via software. A few possibilities:

1) the simplest would be polling: set up a free running 20ms timer. in the loop, read the timer and set / clear output pins based on the value of the timer and your desired duty cycle. This is the simplest to code but sucks all processor power and may have some jitter.
2) or you can use software timers. st up a timer to run the duty cycle; on up the isr, reload the timer with 20ms - duty cycle, and then set / clear pins.
3) use three hardware timers. You can use either the OCnA/B/C pins, or user-specified pins.

The last approach is the best but requires 3 timers.




And why would not just using the standard Arduino servo library not be the best solution? Curious minds would like to know.  ;)

Lefty

Erni

#18
Sep 29, 2012, 08:16 pm Last Edit: Sep 29, 2012, 08:18 pm by Erni Reason: 1
Quote
And why would not just using the standard Arduino servo library not be the best solution? Curious minds would like to know


I can see one reason, which by the way do not aplly to this ESC, and that is the fact that some servo's and ESC's are designed for faster refresh rates than the 50Hz used by most standard servos.

For example servos to control the tailrotor on helicopters, and ESC's to multicopters use a higher resfreshrate (200-400 HZ), because they have to respond more quickly

RobertEagle

#19
Sep 29, 2012, 08:35 pm Last Edit: Sep 29, 2012, 08:36 pm by RobertEagle Reason: 1
Can you give me an example of these? Like a project of somebody's..or something like that?
And if you're proving that you're right, how far can it go with the frequencies?

dhenry

Quote
how far can it go with the frequencies?


Many of those cheap ESCs use a mcu (mega8 in many cases) to control 3 windings, at 10khz. I think they incorporate a closed loop control for the motors.

What you are trying to do is much simpler than what the ESC does so 10khz, if you want to push for it, is quite doable - assuming you have complete hardware control.

If your hardware is restricted - for example, if hardware PWM is not possible, you have to use software and that reduces the speed (but provides more flexibility).

I can write a simple piece of code to get you started if you want.

RobertEagle

Yes. If you please :)

By the way, I wonder at what frequencies are these quadcopters running.
http://www.youtube.com/watch?v=MvRTALJp8DM&

Erni

Quote
And if you're proving that you're right


I don't want to prove anything, I just wanted to point out that the refreshrate in some applications are higher than when using standard servos.

For example the ESC's used in this multi-wii copter use a refresharate at 490Hz
You can look up any high end tailrotor servo to see the spec's

http://www.multiwii.com/faq#Be_sure_your_ESC_can_support_PPM_with_490Hz_refresh_rate


RobertEagle

Get it. And the quadcopter found in the video posted by me earlier, the frequency is around 1Khz.
Is there any chance of verifying my ESC's maximum frequency?

DuaneB

I can confirm that none of my rc equipment refreshes at 50hz, the slowest is 61 and the fastest is 91. I have been interchanging this equipment for years with no ill effect. there are a lot of people out there convinced that they are running 50hz equipment, very few of them are.

Just for completeness, my gear is all low to mid range surface radio.

Duane B

rcarduino.blogspot.com
Read this
http://rcarduino.blogspot.com/2012/04/servo-problems-with-arduino-part-1.html
then watch this
http://rcarduino.blogspot.com/2012/04/servo-problems-part-2-demonstration.html

Rcarduino.blogspot.com

dhenry

To come back, here is a little piece that may be of use to you.

Code: [Select]
//compa match isr
ISR(TIMER1_COMPA_vect) {
    //clear the output pins for ch a
}

//compb match vector
ISR(TIMER1_COMPB_vect) {
    //clear the output pins for ch b
}

//overflow isr
ISR(TIMER1_OVF_vect) {
    //set the output pins for ch a/b
}

//timer1 init
//oc1a/b disconnected
//fast pwm, 8-bit
//prescaler = 8
//pwm frequency = F_CPU (1Mhz) / prescaler / 256
//@ F_CPU = 1Mhz / 8, prescaler = 8, -> pwm period = 16ms
//@ F_CPU = 16Mhz, prescaler = 1024, -> pwm period = 16ms
void tmr1_init(void) {
    TCCR1B = TCCR1B & ~0x0f; //turn off timer1
    TCCR1A = (0<<COM1A1) | (0<<COM1A0) | //0b00 -> oc1a disconnected / normal operation
                (0<<COM1B1) | (0<<COM1B0) | //0b00 -> oc1b disconnected / normal operation
                (0<<WGM11) | (1<<WGM10); //wgm13..0 -> 0b0101 -> fast pwm 8-bit, top at 0x00ff
    TCCR1B = (0<<ICNC1) | //input capture nonise canceller off
                (0<<ICES1) | //input capture edge select: falling edge
                (0<<WGM13) | (1<<WGM12) | //wgm13..0 -> 0b0101 -> fast pwm 8-bit, top at 0x00ff
                (1<<CS12) | (0<<CS11) | (1<<CS10); //cs12..0 -> 0b111 -> ps = xyz
TCCR1C = 0; //not applicable
TIMSK1 = (TIMSK1 & ~0x07) | //presercing other bits
(1<<OCIE1B) | //enable output compare on b
(1<<OCIE1A) | //enable output compare on a
(1<<TOIE1); //enable overflow

}

//macros to set pwm duty cycle
//dc = 0 -> 0xff
#define tmr1a_setdc(dc) OCR1A = (dc)
#define tmr1b_setdc(dc) OCR1B = (dc)

//to initialize in  your application code
    //set up the pin here

    //set up the duty cycle
    tmr1a_setdc(0xff / 10); //set channel a's duty cycle
    tmr1b_setdc(0xff/2); //set channel b's duty cycle

    //set up the timer here
    tmr1_init(); //initialize tmr1

    //enable interrupt


So you set up the timer1 to run - in this case, 8-bit fast pwm. You may need to pick your parameters to yield the desired pwm frequency. After that, you can adjust the duty cycle with tmr1a/b for two channels.

The piece utilizes hardware pwm, except for its output pins (OCnA and OCnB), where the user can specify the output pins - you can have multiple pins here.

I picked 8-bit pwm so that you can configure other timers to produce multiple channels of pwm signals.

Hope it helps.

DuaneB

That looks over complicated to me.

Does anyone know if the high refresh rate ESCs use a different pulse width ? or is it still 1 to 2 ms ?

I have a small fast and simple servo library that allows an adjustable refresh rate, but it currently uses 1 to 2 ms for the ouput pulses so is limited to 125 hz for a single timer channel with four escs or 250 hz if i use two timer channels with two escs on each.

To go higher than this it would be possible to interlace channels, but that has its own problems, so if anyone can answer the question, does a 250hz or higher refresh rate ESC use a different pulse width ? I can put something together.

Duane B

rcarduino.blogspot.com




Read this
http://rcarduino.blogspot.com/2012/04/servo-problems-with-arduino-part-1.html
then watch this
http://rcarduino.blogspot.com/2012/04/servo-problems-part-2-demonstration.html

Rcarduino.blogspot.com

RobertEagle

Wow....looks very complex. It surely needs hours of reading and thinking to know the way it works.
Honestly, I understand few of what you have written there.

Can you show me how would it looked like if it was in an Arduino sketch (void setup(){} and void loop(){})?
Showing me this way, just makes me more confused.

1.Is this example of yours outputting the frequency on pins 3 and 11 (OCR2A/B)?
2.At a prescaler of 8 with the FCPU@1Mhz, the period wouldn't be 2ms, rather than 16ms?
3.Is this meaning that the pins are working at 61Hz?
4.Should I understand that I have to change the duty cycle here "tmr1a/b_setdc()" at every 16ms?
5.When you refer at setting up the pins (supposing in the setup()) , you're saying that I should initialize them with ISR(TIMER1_OVF_vect) function? If I have to initialize them this way, what should I write in this function?
6.It crystal clear that you know much more than me in this area.

If you please,and if it's possible, can you show me an example with this kind of behavior on the motors?
Code: [Select]
void setup()
{
  //enabling pins + timer functions
}

void loop()
{
  for(byte i=0; i<=255; i+=2)
  {
    //writing the duty cycle to both pins (3 and 11)
  }
}


Thank you,
RobertEagle


dhenry

That's about 10 lines of code so if you still think it is complicated, ...

Here is a complete piece:

Code: [Select]
//output pins
#define PWM_A      8
#define PWM_B      9
//end output

//compa match isr
ISR(TIMER1_COMPA_vect) {
    //clear pwm_a
    digitalWrite(PWM_A, LOW);
}

//compb match vector
ISR(TIMER1_COMPB_vect) {
    //clera pwm_b
    digitalWrite(PWM_B, LOW);
}

//overflow isr
ISR(TIMER1_OVF_vect) {
    //set pwm_abc
    digitalWrite(PWM_A, HIGH);
    digitalWrite(PWM_B, HIGH);
}

//timer1 init
//oc1a/b disconnected
//fast pwm, 8-bit
//prescaler = 8
//pwm frequency = F_CPU (1Mhz) / prescaler / 256
//@ F_CPU = 1Mhz / 8, prescaler = 8, -> pwm period = 16ms
//@ F_CPU = 16Mhz, prescaler = 1024, -> pwm period = 16ms
void tmr1_init(void) {
    TCCR1B = TCCR1B & ~0x0f; //turn off timer1
    TCCR1A = (0<<COM1A1) | (0<<COM1A0) | //0b00 -> oc1a disconnected / normal operation
                (0<<COM1B1) | (0<<COM1B0) | //0b00 -> oc1b disconnected / normal operation
                (0<<WGM11) | (1<<WGM10); //wgm13..0 -> 0b0101 -> fast pwm 8-bit, top at 0x00ff
    TCCR1B = (0<<ICNC1) | //input capture nonise canceller off
                (0<<ICES1) | //input capture edge select: falling edge
                (0<<WGM13) | (1<<WGM12) | //wgm13..0 -> 0b0101 -> fast pwm 8-bit, top at 0x00ff
                (1<<CS12) | (0<<CS11) | (1<<CS10); //cs12..0 -> 0b111 -> ps = xyz
TCCR1C = 0; //not applicable
TIMSK1 = (TIMSK1 & ~0x07) | //presercing other bits
(1<<OCIE1B) | //enable output compare on b
(1<<OCIE1A) | //enable output compare on a
(1<<TOIE1); //enable overflow

}

//macros to set pwm duty cycle
//dc = 0 -> 0xff
#define tmr1a_setdc(dc) OCR1A = (dc)
#define tmr1b_setdc(dc) OCR1B = (dc)


void setup(void) {
  //configure the output pins
  pinMode(PWM_A, OUTPUT);
  pinMode(PWM_B, OUTPUT);
 
  //configure the timer
  tmr1_init();                                  //initialize timer
  tmr1a_setdc(0xff / 2);                        //set dc to 50%
  tmr1b_setdc(0xff / 4);                        //set dc to 25%
 
  //enable interrupt
  interrupts();
}

void loop(void) {
}


This is essentially the hardware PWM + software output. As such, once it is set-up, it will run by itself, without any intervention by the user  (and the mcu, other than the isr portion).

The two macros are provided as a means for the user to change duty cycles on the two channels.

As is, it will output PWM on pin 8/9, based on timer1.

Moving to different pins require change the definitions of PWM_A/B and recompile. Moving to a different timer requires changing the timer1-specific registers - read the datasheet for that.

dhenry

Quote
As such, once it is set-up, it will run by itself, without any intervention by the user


Notice that the loop() section is completely empty. Conceivably, you can implement code there to receive data and then change duty cycles based on the commands / new data.

Go Up