Synchronizing two BLDC motors powered by hobby ESCs

Go To Last Post
34 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello everyone. It's been a while since my last post. Many of you may remember my tachometer project that you AVR Freaks were so helpful with me completing:

https://www.avrfreaks.net/forum/my-digital-tachometer-putting-it-all-together

 

Since then, I've been busy with other projects; I made three custom tachometers (as noted at the end of the above thread), and have been converting the machine tools in my machine shop to use VFDs (Variable Frequency Drives). This involved making new drive mechanics and removing the mechanical vari-speed drive. Additionally, it gave me an application for the afore mentioned tachometer. I made a large digital display for one.... I've also been setting up a small in-house anodizing line.

 

I now have a new "micro" project... well... maybe resurrecting an older one:

https://www.avrfreaks.net/forum/syncronizing-2-rc-airplane-motors

 

I'm making a device that uses two motors with offset weights to cause vibration. This device is battery powered and uses BLDC motors normally used for R/C airplanes. To create the desired vibration, the motors counter-rotate and they need to be synchronized with the weights 180* out of phase. For the proof-of-concept prototype, I'm using an AVR with generic ESCs and controlling the motor speed the same way a hobby servo is controlled (PWM). A potentiometer is used so the operator can select the nominal RPM of the system.

 

I have some parts of the system working already.

 

I'm using an ATtiny261. I have the ADC routine working (8 bit) and can easily read the potentiometer position. Using this ADC reading, the PWM (for hobby servo control) is altered. I don't yet have the ESCs, so I am testing with a hobby servo. The PWM for two separate servos works great. The servo (or ESC) PWM is controlled from Timer1. Since it is an 8 bit timer, I used some tricks with the overflow interrupt to get decent resolution to the pulse width.

 

The next step is to determine how to sense RPM and angular position, and what strategy to use to measure them. I have some ideas and some questions.

 

I plan to use an opto-interrupter or hall sensor to get a once-per-rev pulse at the rotational position of the offset weight of EACH motor. Also, it's okay to take a second or two to get the motors synced at startup. Plus it's okay to have a tolerance in the phase angle of plus or minus 10 to 15 degrees.

 

One idea is to use the Timer0 Input Capture to measure the time from motor1 interrupt to motor2 interrupt, and then from motor2 to motor1. The object is to make the times equal each other.

 

Another idea is to use external INT0 and INT1 to time each motor interrupt and go from there.

 

The questions I have are mostly in regard to Input Capture.

 

First, what happens if the timer overflows between captures?

Second, since I'll be using Timer0 in 16 bit mode, do I need to deal with combining the two bytes or does the compiler take care of that for me?

 

It seems that using separate interrupts (INT0, INT1) for each motor makes it easier to know which motor is ahead of the other than using Input Capture (since there is only one). However, INT0 & INT2 have more overhead. Oh, this reminds me of another question.

 

Third, the data sheet says that Input Capture can be triggered by the ICP0 pin or alternatively, AC0. Could these two different inputs be used to help distinguish between which motor triggered the interrupt?

 

Do any of you have comments about one or both approaches... pros/cons....

 

Thanks!

 

Cris

 

 

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

Last Edited: Mon. Jan 18, 2016 - 11:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Since bldc motors are inherently synchronous, could you not just slave another set of drivers or even put two motors in parallel?

What you're proposing is a phase locked loop. Rather than an optical sensor, just sensing a phase should be more than adequate. You would adjust the slave pulse width to bring both motors into synchronism.

Would you need the input capture? Only to measure speed. What happens if the timer overflows between captures? Nothing - as long as the time between captures is less than the overflow period. If you do your captures as unsigned integers, it all works out. Try it on a piece of paper- 0x2000 - 0xe000. The result should be 0x4000. The magic of fixed precision binary math. Yes, most compilers take care of reading/writing the high and low byte registers in the correct order.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Since bldc motors are inherently synchronous, could you not just slave another set of drivers or even put two motors in parallel?

The motors are sensorless. Commutation is accomplished by sensing back EMF in the phase that is off in order to know position. Direction is sensed by starting the motor and if it turns the wrong way, it reverses. Your suggestions mess with this system and render it inoperative.

 

Kartman wrote:
What you're proposing is a phase locked loop.

Thanks. I don't know anything about phase locked loops, my cursory google only raised more questions.

 

Kartman wrote:
Rather than an optical sensor, just sensing a phase should be more than adequate.

Sensing phase only gets you the same RPM. Angular synchronization in not guaranteed.

 

Thanks for the other answers!wink

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

Last Edited: Tue. Jan 19, 2016 - 12:18 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A BLDC is a synchronous motor - thus rotor angle is tied to phase. The error is the slip angle. Depending on load, this angle may vary but it is that basis of how these motors are controlled. The permanent magnets set the reference. The ESC creates a magnetic vector along with the permanent magnet determines the rotor position. You rotate the magnetic vector and the rotor follows.

 

A separate set of drivers would not mess with the commutation sensing. Not an ideal setup for the slave motor, but depending on the exact setup, it may actually work in practice - especially if you're not extracting maximum performance from the motors. With the low cost of ESCs for radio control models, it's not an expensive or difficult test to set up.

 

Conceptually, a phase locked loop consists of three components - phase comparator, loop filter and voltage controlled oscillator. In your instance, the voltage controlled oscillator is the pwm generator.

 

The phase comparator gives a value depending on the error - 0= no error. The loop filter averages the error and provides the system response function. These can be done in analog or digital. Depending on the motor speed, it might be easier doing it in analog. 

 

What are you building? A super polisher or a double dildo:)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the motors have a number of poles, then the phase idea won't work - it will give you a match on a pole modulus. It was a good idea whilst it lasted. You want Selsyns! 

Last Edited: Tue. Jan 19, 2016 - 02:36 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
A BLDC is a synchronous motor - thus rotor angle is tied to phase.

We touched on some of this in my previous thread (mentioned in OP). The motors I'm using have 12 poles/coils, therefore you can be in any of four positions when using your method (assuming a 3 phase motor). I am very familiar with BLDC and stepper motors as I have been in the motor design and manufacturing industry for over four decades. In my previous thread, I had misunderstood your use of the word "slip" (I would call it lag) so we were saying the same thing (only I didn't know it).

 

EDIT: I just noticed your correction (above) after I posted this

 

Kartman wrote:
A separate set of drivers would not mess with the commutation sensing. Not an ideal setup for the slave motor, but depending on the exact setup, it may actually work in practice - especially if you're not extracting maximum performance from the motors. With the low cost of ESCs for radio control models, it's not an expensive or difficult test to set up.

When you say "A separate set of drivers", are you talking about MOSFETs? This would require some 'surgery', which is possible, but the circuit design is pushing my expertise.... Many tests have been conducted using various ESCs, some work with dual motors, most don't. I am hoping to get a more consistent outcome.

 

Kartman wrote:
The phase comparator gives a value depending on the error - 0= no error. The loop filter averages the error and provides the system response function. These can be done in analog or digital. Depending on the motor speed, it might be easier doing it in analog.

It sounds like I am planning on a phase locked loop without knowing what its called. Doing it in analog is likely beyond my pay grade....

 

Kartman wrote:
What are you building? A super polisher or a double dildo:)

Definately NOT the latter, but the former is close (I don't know if I'm able to elaborate).

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

Last Edited: Tue. Jan 19, 2016 - 02:45 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sounds like we're back to using two interrupts. What sort of rpm are we talking about? Cpu speed and interrupt service time are going to determine the angular precision you'll be able to achieve. Or you could use an XOR gate on the two pulse inputs and feed that into the capture to get better performance. You can then test the external interrupt flags to see which one caused the event.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
you could use an XOR gate on the two pulse inputs and feed that into the capture to get better performance. You can then test the external interrupt flags to see which one caused the event.

An XOR gate is not a problem. So are you suggesting using the external interrupts AND Input Capture? Use the Input Capture for timing and the interrupt to determine which motor? I like that.... Although it may not be necessary since the motors are turning 3000 RPM, max.

 

As I think about though, even if it isn't needed for performance reasons, it seems it may be easier to manage the timer that way.

 

Thanks Kartman! That sounds like a great idea.smileywink Sounds like fun!

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

At 3000 rpm, that's 55.5uS per degree, so you could expect better than a couple of degrees accuracy without too much trouble. If you use external interrupts, you have the delay between the event actually happening and getting into the isr then reading the timer value, so this gives you an error. Input capture avoids this. With a 16MHz AVR, it might take a couple of microseconds to respond to the external interrupt and read the timer, thus the error will be less than a degree. I'd say that would be acceptable, so no compelling reason to use input capture or need other shenanigans. As such, you don't need to 'manage' the timer - you just read it. To find the difference, just subtract the current timer value from the previous timer value - as long as you do it using unsigned integers, the calculation works.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
you don't need to 'manage' the timer - you just read it.

There you go... keeping me from making more work for myself again.... After your explanation, I see that there is no real difference in what happens with the timer - just how the 'read' is triggered. I was making more hoops to jump through. As of now, I'm using the internal oscillator at 8mHz. Even so, that should be fine. If not, it won't be hard to go with a 16mHz crystal.

My previous timer experience was as a timer or PWM. In this case it is really just counting, so I wasn't thinking about it correctly. Plus, my inexperience with unsigned integer math was having me make it more complicated.wink

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

Last Edited: Tue. Jan 19, 2016 - 04:53 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've been reading www.rcgroups.com for years and the idea of synchronizing BLDCs for a "twin" (or even a tri-motor or 4 motor) has been discussed ad-nauseum there. The bottom line of the general consensus is that it cannot be done because you are looking at things like the friction coefficients of the bearings and things like that. Both motors/props are "free to move" (which is kind of the whole point of brushless!) and the likelihood that for the same applied signal causing them to rotate at exactly the same speed is impossible. What you might do is add some kind of sensor (hall effect, optical) to each to be able to monitor their rotational speeds and then vary the signals from each ESC to match the RPMs using some kind of PID (obviously one motor is master then the other is a slave playing "catch up"). The ESC signals are almost bound to be different for any chosen RPM. In effect you have to turn your sensorless BLDC back to sensored ones.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You asked about input capture. The ATtiny261 has limited capabilities - the TCNT0 value is captured  when the ICP0 pin changes. You can also configure an interrupt if the counter overflows.

You have to choose between the ICP0 and AC0 triggers, you can't have both at the same time

The ATxmega chips are more flexible, and have typically 5 16-bit counters. The event system ensures accurate timing, and does not have timing problems with interrupt response times, one only has to remember that you can't have more than one input capture event per timer, even if there are four ICRs/counter

Jerry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
add some kind of sensor (hall effect, optical) to each to be able to monitor their rotational speeds and then vary the signals from each ESC to match the RPMs

Thanks Cliff. You perfectly summarized what I'm doing.

 

jerryr wrote:
You have to choose between the ICP0 and AC0 triggers, you can't have both at the same time

Thanks for the explanation Jerry. It doesn't appear the Input Capture is needed in this case. I'm getting more understanding about it though.

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

Last Edited: Tue. Jan 19, 2016 - 04:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
most compilers take care of reading/writing the high and low byte registers in the correct order

I'm using ImageCraft. Does someone know the syntax for having the compiler handle reading/writing both bytes of TCNT0? I found a tutorial online and it just uses TCNT1 (it's using timer1) and it seems to work fine for them. When I try it in ImageCraft, I get an error. Do I need an 'include' file or something?

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

Last Edited: Tue. Jan 19, 2016 - 08:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I made an interesting discovery. Since I had found the tutorial I mentioned above, and it uses TCNT1 as if it were an unsigned integer, I expected that the same would be true in my case using TCNT0 with an ATtiny261. The tutorial is for an ATmega32 and I assumed they would be similar. I got the idea to look at the include files of each device to see if there was a clue. There was.

 

This is part of the ATmega32 file:

#define TCNT1    (*(volatile unsigned int *)0x84)
#define TCNT1L    (*(volatile unsigned char *)0x84)
#define TCNT1H    (*(volatile unsigned char *)0x85)

This is the ATtiny261:

#define TCNT0H	(*(volatile unsigned char *)0x34)
#define TCNT0L	(*(volatile unsigned char *)0x52)

Since the ATmega32 registers are consecutive, the low byte register address can be used to define an unsigned int instead of char.

 

Unfortunately, the ATtiny261 registers are NOT consecutive. So the chip architecture prohibits the above method.

 

Bummer.sad

 

Does anyone know of a 'trick' that may get around this? I have some ideas but my ignorance of much of this keeps me from coming up with a solution.

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

Last Edited: Tue. Jan 19, 2016 - 10:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sort of.  You can create accessor funtions:

uint16_t TCNT0_read(void) {
  uint16_t tcnt0;
  tcnt0 = TCNT0L;
  tcnt0 = tcnt0 | (TCNT0H << 8);
  return tcnt0;
}

void TCNT0_write(uint16_t tcnt0) {
  TCNT0H = tcnt0 >> 8;
  TCNT0L = tcnt0 & 0xFF;
}

This ensures correct ordering of low and high bytes when reading and writing.

 

This is likely to be inefficient in ICC.  It might be just as well you do this yourself in your code.  At least try declaring the accessors as static inline, it may help.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Tue. Jan 19, 2016 - 10:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks JJ. That looks straightforward. I expected that I could solve the problem like that. I was trying to find a way to create a definition of some kind. Since I'm not using the register (OCR0A) who's address is just before TCNT0H, maybe something like this:

#define OCR0A = TCNT0L
#define TCNT0   (*(volatile unsigned int *)0x33)

 

[EDIT:] I now understand the above is incorrect, but what I was attempting looks like it can be done. All I have to do is learn a lot more about macros.wink

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

Last Edited: Tue. Jan 19, 2016 - 11:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That won't work - the compiler has no say where the registers are located in hardware.
It's only a couple of lines of code, just do it the 'classic' way.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
just do it the 'classic' way.

Thanks Kartman. More words of wisdom....wink

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've made some progress....

 

This is a plate with the two motors attached for testing and software development. There are two ESC (electronic speed controllers) that accept a 50 Hz PWM with 1 mSec to 2 mSec pulsewidth for speed control. So far, I only have one sensor for RPM. The LED facing the far motor is used as a strobe (like a timing light) to be able to see when/if the motors are syncronized and phased correctly when I get to that point in programming.

 

For this proof of concept, I'm using an extra PC board I had left over from my Manifold Pressure Gauge (mentioned in OP). The display is handy for "seeing" what may be going on by selecting various parameters to display. Here it is showing the PWM pulsewidth in milliseconds. The trimmer pot (top center) is used by the operator to select motor RPM.

 

The sensor I'm using is something I had already. It is an LED and phototransistor. The phototransistor is in the hole (as shown) to protect it from ambient light.

 

The red LED reflects off a small strip of aluminized mylar (from a potato chip bag) attached with double sided tape. The mylar reflects the LED into the sensor hole and generates an interrupt. It also turns on the LED used for a strobe.

 

I am successfully timing the period of each revolution and figuring the RPM. Kartman was right (of course) that timer overflow is not any problem as long as the time between captures is shorter than the overflow period.

 

So now I am looking into how to make sure the overflow period is longer than the time between captures. I can count overflow interrupts but that just gets close.

 

Is there a trick that makes this simple? Or do I just subtract the first capture from 64k and add it to the second capture and check to see if it is more than 64k?

 

Thanks!

 

Cris

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The overflow period determines the minimum rpm you can measure. So you balance resolution vs timer period. So, if you want to measure a wider range than 16 bits will allow, then you need to count overflows. So you can extend your timer to 24,32... Bits. The period measurement is the same. Period = current time - previous time. The funs comes in when a capture happens close to an overflow - what interrupt gets priority?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Kartman. I hadn't thought much about the interrupt priority, I didn't know that I had a choice with that (I understood the ATtiny has its own priority table). Though, after reading your response, I realize that I should have included more details.

 

MCU clock  freq. = 8 mHz

timer0 prescale = divide by 8

so it is 1 count every microsecond

overflow period = .065536 seconds

minimum RPM ~ 916 RPM

 

I don't need to worry about anything below 1300 RPM. So all I want to do is find a simple check to make sure the RPM is above that, before I use the timer count for anything.

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You'll need to check for max rpm. When the rom drops brlow 916, it will 'wrap around' as stupidly high rpm. To detect loss of rpm, i have a downcount in the overflow isr that gets reloaded when i get an input pulse. When i stop getting pulses, the downcount gets to 0. Then i clear the rpm value.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
a downcount in the overflow isr that gets reloaded when i get an input pulse.

 

Thanks Kartman. But isn't it possible for the count to still 'wrap around' before it gets to the next overflow....

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, what I'm finding is that there is apparently no 'trick' that I may be unaware of because of my inexperience.

 

This discussion has had me looking at the details (and my unconscious assumptions) and I found ways to simplify things. First, I don't need 1 microsecond resolution - far from it. By using 1024 prescaler I will get 128 microsecond resolution which translates to very close to 3 degrees of rotation at 4000 RPM. This makes the overflow period in excess of 8 seconds and makes this a much smaller issue.

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The downcount is just a simple timeout mechanism - I don't care about the actual timer count. If I don't get a pulse in X overflows, then I declare the motor not running and zero the rpm. It probably won't work too well if your overflows happen every 8 seconds! Do you really need to know the exact time the pulse exceeded the overflow time? For me, I'm usually measuring the rpm of a petrol engine and the readout is for a human, so he doesn't really care when the motor precisely stops.

As for the timer prescaler - it's a tradeoff of course, but based on your numbers, the overflow wasn't a problem as you could still measure your rpm range of interest. Having too much prescaler means your measurements are coarser, even though it is around 3 degrees, when you do your reciprocal the results may be 'lumpy' due to integer calcs - do a spreadsheet to visualise the potential issue.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just went out to lunch and had a little ponder. You're not really interested in rpm as such but more the difference between the two pulses. If the slave comes before the master, slave is too fast. If slave comes after the master, slave is too slow. Calculate the difference and filter the result . Then scale this to get your pwm out. Tweaking the control loop is the fun part.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nice project.

 

I think you will want an additional piece of clear cellophane tape over the top of the aluminum reflector.

The double sticky tape will fail with time, even though the reflector has very little mass.

 

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Building a stick shaker for a stall warning for your aircraft?

 

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
The downcount is just a simple timeout mechanism

I understand. With my first example (prescale = 1/8), as the RPM ramps up, I will have erroneous readings until it gets to 914 RPM - even though the overflow test may pass. I was looking for a way to disregard those readings.

Kartman wrote:
even though it is around 3 degrees, when you do your reciprocal the results may be 'lumpy' due to integer calcs

Very good point. I hadn't thought of that.

Kartman wrote:
You're not really interested in rpm as such but more the difference between the two pulses.

That is correct. I was merely using the terminology as a shorthand (although I did calculate actual RPM for debug purposes).

 

My plan is to read the ADC to determine the position of the pot. This will define the RPM (actually period of 1 rev.) of the master motor and will have a feedback loop to keep it constant. From that, I will adjust the slave motor to the same RPM and adjust for proper phasing.

 

I've never done this before so this is my first stab at the process. I hope you are right that "tweaking the control loop is the fun part".

DocJC wrote:
The double sticky tape will fail with time, even though the reflector has very little mass.

Thanks Doc. I agree that it will fail with time. This is only a temporary setup to develop software, and different hardware will be used in the actual part.

DocJC wrote:
Building a stick shaker for a stall warning for your aircraft?

LOL! No, my aircraft better have plenty of aerodynamic warning (or I did something wrong). This is a separate project independent of aircraft.

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

Last Edited: Tue. Feb 23, 2016 - 06:38 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So far, I'm finding it straightforward to get all the different features to work (ADC, Timer0, PWM, etc.). The thing that's really hurting my head is figuring out how to structure the program to have it all work together....indecision

 

I'm thinking I should use the 50 Hz PWM as a trigger to sync calculations of the motor control loop, since I won't be able to make changes any faster than that anyway.

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

aeroHAWK wrote:
The thing that's really hurting my head is figuring out how to structure the program to have it all work together...

I know it's old fashioned but something like a flowchart can help - it doesn't have to be a work of art - a simple sketch on a piece of paper with a pencil will do. It helps you to get your thoughts in order when you think about such a thing and it may make you think of some conditions you weren't previously catering for.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The structure should be pretty simple - the pwm timer overflow sets a flag. The main loop, waits for the flag, clears it then reads the adc, filters the adc value and updates the master pwm. Read the difference (error) between master and slave. If the error is not in the window, ramp the slave speed up and down at a given rate. When the error is within the window, then switch to lock mode where you determine the amount and sign of the error. Then do a fine adjust of the slave speed. Do other things then go back to waiting for the overflow.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
I know it's old fashioned but something like a flowchart can help

Kartman wrote:
The structure should be pretty simple -

Thanks Cliff and Kartman.

 

What you've shown me is that I need to get out of my head and use paper and make a hard copy of something. Even if it's not quite right to begin with... at least it gets something in front of me that I can see, and help me get my head around it. Kartman, you wrote down a structure that got me started and Cliff has the great suggestion to put it in the form of a flow chart. THANKS!

 

Cris

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. Antoine de Saint-Exupery (1900 - 1944)