Micromouse book
Categories
Recent Comments
Meta
Popular Posts
- Simple ADC use on the STM32 (4,106)
- STM32 Arm-Cortex bootloader (2,803)
- STM32 USART basics (2,704)
- All Japan Micromouse 2011 – finals (2,011)
- STM32F4 – the first taste of speed (1,690)
- Micromouse Book (1,588)
- Nokia 3410 LCD on the STM32 (1,337)
- CodeSourcery GNU Toolchain for the ARM on a Mac (1,145)
- Bit Banding in the STM32 (1,045)
- ARM STM32 JTAG (973)
Blogroll
-
Upcoming Events
Tag Archives: encoder
Encoder/Motor trouble
This micromouse thing is a bit tricky. I have not been happy with the accuracy of the results I have been getting with Decimus. Occasionally, a move is significantly shorter, or longer than intended. Looking at the code does not help – either the code is fine or I just follow the same thought process leading to the same errors every time I look. There is, however, something odd about the encoders.
If I set a distance (number of encoder counts) for the mouse to run and then measure how far it has moved on the ground, I get a value for the number of encoder counts per cell. This works out at about 4250 making about 23.6 counts per mm. This is fairly consistent and repeatable. There is some change in physical distance travelled when the acceleration is changed. I can explain this away in terms of wheel slippage and compensate accordingly although it is more than a bit of a fudge to do so.
Then I tried getting a value for the number of encoder counts per mm by pushing the mouse along by hand and recording the number of counts from the encoders. I had many goes at this and finally arranged to measure the same distance several times. To try and reduce experimental error, physical stops were used to ensure the mouse always started and stopped in the same place. Backlash in the gearing was eliminated for each trial. To eliminate variations caused by a curved path, the mouse was pushed along a straight edge. Care was taken not to push down too hard so that the tyre were not compressed. The average of ten trials was used for the result.
With all these precautions, I end up with upsetting values. First, there is the result of 23.1 counts per millimeter rather than the 23.6 from having the mouse do the driving. I have no idea why that would be. Second is the awful variability in the results. Each trial is over 706mm. The encoder counts vary over a range of 110 counts out of around 16,000. That is nearly 5mm. It is not nearly good enough.
I guess I shall have to try and see if there are spurious counts caused by the back-EMF of the motors. The results do not seem to be caused by the speed of the motors. I may try putting the counters into x4 decode mode to see if that makes any difference. Also, the index pin is left floating as there is a setting to ignore it. Perhaps better to tie that high or low as well.
While testing, it became apparent one of the motors is faulty. With the mouse set to hold its position, I can turn the left wheel by hand as far as I like. The motor output saturates and when I let go the wheel rapidly returns to its set position. Exactly as it should do. However, if I do that with the right wheel, the current drawn gets nowhere near as high when the motor drive saturates. Further, the encoder on that motor stops generating pulses. If I swap the motor connections around, the problem stays with the same wheel so it is not caused by either the drive circuit or the counter.
All in all, not a happy Easter bunny here. I just ordered a replacement motor. Painfully expensive those things are.
LS7366 quadrature counter
The LS7366 is a 32 bit counter with a direct interface for quadrature signals from incremental encoders. There is also an index channel for marker functions. The interface to the microcontroller is SPI mode 0 making it relatively easy to drive with a variety of common controllers. Decimus has one of these on each motor channel connected to the encoders on the back of the Faulhaber 2224 coreless motors. There is very little information about these chips available except the data sheet. This is how they are used on Decimus.Interface to the encoders is very easy as the phase inputs can be connected directly to the chip. A clock signal must be provided for the counter and I used the same 8MHz oscillator that drives the processor on Decimus. the clock will need to be less than 40MHz in a 5V system and must be greater than 4 times the maximum count frequency. Even at a speed of 5m/s Decimus will only be generating encoder pulses at about 140kHz so there is plenty of margin.The counter is very flexible and can be configured for x1, x2, x4 and non-quadrature counting and the counter register may be set to 8, 16, 24 or 32 bits in size. Selecting x1 decoding will give 512 counts per revolution of the motor shaft and 2048 counts per revolution of the wheel. For this application, the counter width will be set to 8 bits. This is the fastest to read back from the counter and has sufficient range for my needs. With a single byte counter, the maximum difference in counts that can be reliably detected between two reads is 127. Since each count on Decimus is 24mm * pi / 512 * 4 or about 0.04mm. The control loop runs at 1KHz so the maximum recordable speed would be 127 * 0.04mm / 1ms which is around 5m/s. Practically speaking, the mouse would almost never be able to reach such a speed in the maze and the top speed will be limited to no more than 4m/s by the control loop.Configuring the chip is a question of sending a number of values to internal registers over the SPI. Here is a code fragment for the mouse initialisation:
CNTR_LEFT_SEL = 0; // start a command
SPI_putc(WR + MDR0); // write MDR0
SPI_putc(CLOCK_DIV_2 + FREE_RUN + CNT_MODE_X1); // free-running, x1 decoding
CNTR_LEFT_SEL = 1; // end this command
asm("nop");asm("nop");asm("nop"); // delay between commands
CNTR_LEFT_SEL = 0; // start next command
SPI_putc(WR + MDR1); // write MDR1
SPI_putc(COUNT_ENABLE + CNTR_WIDTH_1); // enabled, single-byte
CNTR_LEFT_SEL = 1; // end command
asm("nop");asm("nop");asm("nop"); // delay between commands
CNTR_LEFT_SEL = 0; // start next command
SPI_putc(CLR + CNTR); // clear the counter
CNTR_LEFT_SEL = 1;
The only real ‘gotcha’ was not noticing that after each command the select line must be raised to complete the command then lowered again for the next command. There is a minimum time the line must be held high, hence the ‘NOP’ instructions. The setup and hold times for the select line are easily met by the overhead of the function call for the SPI_putc() function.Reading the counter is also quite straightforward. A command is sent to read the counter. This transfers the current counter value to the output register and the next write to the chip clocks out that register. You must perform as many reads as there are bytes. Remember that the data comes out MSB first so you can’t just read the low bytes and ignore the rest. Like all SPI systems, a byte has to be sent so that you can get a byte back as transfers occur simultaneously in both directions. So for example, if the counter were set up for a 16 bit width, the current value can be read with code like this:
CNTR_LEFT_SEL = 0; SPI_putc(RD + CNTR); // transfer CNTR to OTR and prepare to read temp1 = SPI_putc(0x00); // send a dummy byte to get the first byte back temp1 = (temp1 << 8); // we get the high byte first temp1 += SPI_putc(0x00); // another dummy byte gets the lower byte returned CNTR_LEFT_SEL = 1;
This is fairly quick. Reading both encoders in 16 bit mode takes just under 30us on Decimus with the SPI running a 4MHz clock. Continue reading
Add to Google