2016-09-18 09:57 AM
I am doing a project with the STM32F407VGT that has six small DC motors, each with a quadrature encoder built in. The plan is to use these signals for position and speed control; I was hoping to get some basic conceptual guidance on how to best do this.
The signal coming out of the encoders will max out at ~1kHz. Direction of movement is needed, but does not need to be known at all times and I'd been planning on hooking the second channel of the encoder up to a GPIO and simply poll the state of the two lines once in a while to verify that direction matches what has been set. As for the other encoder channel, I need to know both period and the number of rising edge events to determine position. (I don't need the precision of rising and falling due to some pretty aggressive gearing on the motors)I’ve spent a while working my way through the reference manual, cross-series timer overview, and general purpose timer cookbook documents. Thus far I’ve been able to come up with a few different ways to achieve this, but I’m not sure which is the most appropriate and will have the least overall performance impact.
1. Set one timer for each encoder in up counter mode; sample the count value at a known rate using another timer interrupt and calculate the average period over the sample time. This would be set up so all six counters were polled and calculated at the same time. My understanding is that this has the benefit of being pretty simple, but may lack in accuracy and the interrupt handler could take a significant amount of time. Also, this seems like it will fall apart when the motor is moving at very slow speed and it would require the use of seven total timers.2. Use the dedicated encoder mode, but my understanding of this is that only two motors can be used in this way. If this is correct then the method will not work.3. Use input capture mode. This seems like the most appropriate option from the reading I’ve done, but is also the method I have the most confusion about. It seems like the simple approach to this is to use four channels (or two? I’ve think I’ve seen talk of only being able to use two channels of a four channel timer in this method). Each rising edge event on each channel triggers an interrupt handler which calculates the delta between the previous event and the current one, stores that value, and increments a counter variable. This seems concerning having up to ~6000 interrupts happening per second.The other method with input capture seems to be using the same setup, but using a DMA request to store off the timer values. If I understand this correctly, which is questionable at best, these values would need to be polled by a flag set in a register whenever there was an event. The code executed when the flag is set would both read the current value, calculate the delta, and increment a counter.
Are these the only ways to approach this, and conceptually do I understand them correctly? Any guidance to which of these approaches is most appropriate, or if there is another that is better, would be greatly appreciated.Thank you,
Matthew