PIC32MK MC QEI example

nsaspook

Joined Aug 27, 2009
7,494
Needed to build a tester for some high resolution QEI encoders. The speed and number of counts per revolution favored a hardware motor control solution for the A/B/Index signals vs a software solution. I had a PIC32MK GP board but needed the MC chip on the board so first the first step was to swap controllers on the board without destroying it.

Used a hot air gun to remove the GP and install the MC. Used polyimide tape to protect other components
from the heat.

Modded dev MC board with TTL 7433N (from the junk box) level converter in mikro bus socket for the encoder signals.
https://www.celeramotion.com/sites/default/files/LP-Data_Sheet-Packaged_DRC-M35.pdf

The test software just updates a few leds, and outputs the qei position count register to uart #3.

C:
// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************

/* redirect printf to uart3 */
void _mon_putc(char c)
{
while (DRV_USART0_TransmitBufferIsFull()) {
}; //Wait till transmission is complete
DRV_USART0_WriteByte(c);
}

int main(void)
{
int32_t itest, update_count = 0;
/* Initialize all MPLAB Harmony modules, including application(s). */
SYS_Initialize(NULL);

/* serial clock is off, this is actually 76.8 kb/s */
DRV_USART0_BaudSet(115200);

while (true) {
/* Maintain state machines of all polled MPLAB Harmony modules. */

/* update local value of the position counter */
itest = POS1CNT;

if (update_count++ > 20480) {
/* flash the board leds using the position counter bits */
LATGbits.LATG12 = itest >> 10;
LATGbits.LATG13 = itest >> 12;
LATGbits.LATG14 = itest >> 14;
/* send to uart3 the current POS1CNT value */
printf("count %8i\r\n", itest);
update_count = 0;
}
}

/* Execution should not come here during normal operation */

return( EXIT_FAILURE);
}
https://github.com/nsaspook/m35_pic32mk_mc

The QEI device easily tracks the >320,000 counts per turn of the encoder knob with only a few config values in module SFR registers.
C:
int32_t m35_init_qei(void)
{
/* port pin numbers from port_p32mk1024mcf100.h */
QEA1R = 0x00;
QEB1R = 0x0D;
INDX1R = 0x00;
HOME1R = 0x04;
QEI1CON = 0;
QEI1IOC = 0;
QEI1IOCbits.QEAPOL = 1;
QEI1IOCbits.QEBPOL = 1;
QEI1IOCbits.IDXPOL = 1;
QEI1IOCbits.SWPAB = 1;
QEI1CONbits.PIMOD = 0;
QEI1CONbits.QEIEN = 1;
POS1CNT = 0;
return 0;
}

nsaspook

Joined Aug 27, 2009
7,494
MandM control board prototype with PIC32MK MC controller, QEI control, PWM and dual twin H-bridge controllers to control four motors.

https://github.com/nsaspook/vcan

Testing the 24vdc gear motor with a 9v battery. One (of six) 32-bit QEI channel reads the input encoder while the other reads the motor position encoder. Nothing fancy, just testing the
new prototype board for bugs.

nsaspook

Joined Aug 27, 2009
7,494
XYZ motor control testing. I don't want to smoke my proto test board yet so the motor(s) PS is a current limited 12v dc supply.

nsaspook

Joined Aug 27, 2009
7,494
I've completed modifying and testing the prototype PCB for another and last board spin of this project. One of the reasons for using a 32-bit motor controller is the ability to handle three-phase drive and position calculations in real-time. The PWM on the uC has 8.33ns resolution. That's needed to generate the slow tracking drive frequencies using high-resolution PWM sine-wave stepping for direct motor drive tracking with encoder ring position feedback. A specialized, very low speed VFD.
https://www.professional-telescopes.com/Product-Line/Mountings/Direct-Drive-Mount
https://global.vixen.co.jp/en/product/37913_2/

https://www.mathworks.com/solutions/power-electronics-control/clarke-and-park-transforms.html?s_eid=PSM_15028

Last edited:

nsaspook

Joined Aug 27, 2009
7,494
This is the type of motor the controller/output driver is being designed for. A co-worker is building a new telescope.

Tracking motor(s).

The test-bed tracker motor and encoder for software development.

360,000 counts per turn with internal interpolation and external quadrature.

BLDC motor using 3-phase centered-symmetrical PWM from the controller board.

My test direct-drive setup is about 10X less tracking resolution than the telescope RA encoder but it should be OK to tune for the required slow tracking profiles.
The bottom left number is the encoder read-back slowly changing as the shaft moves due to motor control from the controller.

nsaspook

Joined Aug 27, 2009
7,494
Updated 4 layer PCB with LCD graphic display using a custom driver for the PIC32MK@120MHz clock. 8MHz spi clock with interrupt driven I/O updates the graphics memory in about 3.6ms per screen draw.

From JCLPCB.

Raw update speed.

SPI datastream:
Top 2 lines MOSI and SCK screen updates between gaps.
Bottom 2 lines: Scope zoom to each byte transferred@8 MHZ SCK with interrupt processing gaps of 3us between bytes.

Last edited:

jpanhalt

Joined Jan 18, 2008
10,110
Thanks for the update. Pretty impressive display stats.

What is your display driver? I am using an ST7567 that is able to drive a 132x65 screen; although, it is only used at 132x64. It works great with SPI at 8 MHz too. I split the screen into two, 66x64 palettes with data on the right and gragh on the left. Simply erasing DDRAM for both sides is 2.451 ms total. When I redraw the graph screen, it takes longer as I recalculate each byte from data in linear RAM (PIC16F1783 @ 32 MHz). Somewhere I have that number, but couldn't find it. There is a noticeable blink, but it's not too bad.

ci139

Joined Jul 11, 2016
1,684
i can't detect any motion (other than camera) from the video ?
. . .
so it's encoder read-back ... not that the sys. gives you (allows you to control) an absolute shaft pos.
tough - as i understand - (the one) relative to the phase windings
? how efficient
? how linear
? how "stable" (relative to any rotation angle)
Space Vector PWM

atferrari

Joined Jan 6, 2004
4,071
Hola @nsaspook

I have been reading a lot about BLDCs but have no hands-on experience.

My questions, actually not focused on the main subject of the OP and sorry for that:

a) Find puzzling the motor's "parallel" wiring. What is the advantage?

b) What is the micro's Fosc? The PWM 8,33 ns resolution at what frequency?

c) Suppose the four motors turning continuously; what would be their"cruising speed"?

d) Other than azimuth and elevation, what are the others two for?

nsaspook

Joined Aug 27, 2009
7,494
i can't detect any motion (other than camera) from the video ?
. . .
so it's encoder read-back ... not that the sys. gives you (allows you to control) an absolute shaft pos.
tough - as i understand - (the one) relative to the phase windings
? how efficient
? how linear
? how "stable" (relative to any rotation angle)

No, you can't detect the motion. This version (other versions will be for general motor control of DC, stepper and BLDC servo motors) of board software is being designed as a direct drive motor star tracker for telescope long exposure imaging so it needs to move the motor shaft very slowly with high torque and accuracy over long periods of time. Hall sensors can't deliver the need positional data, only commutation data. First the motor is trained by homing to a rotation electrical position zero by applying DC currents to the proper motor leads and zero the encoder counts, then we rotate the motor using a standard BLDC commutation pattern for one electrical rotation (depending on the number of poles there will be several electrical rotations for one mechanical rotation).

From the one electrical rotation we can then calculate the pole offsets and the values needed for proper shaft position (we know the number of encoder counts for one shaft rotation) to three phase sine-wave (calculated on the fly) angles (offset by 120 degrees) for moving the motor to X rotational position with the needed torque (X current PID feedback loop at the correct rotor offset at X position) using electrical current feedback from two of the PWM drivers. The velocity data and position used encoder counts and data between encoder counts is extrapolated using a 32-bit timer that resets and counts up a every QEI A/B signal from the drive motor. This gives rotational speed fine control to adjust the fractional Hz sine-wave frequency using a PID velocity error loop.

https://m.eet.com/media/1112634/f-wescot.pdf
https://en.wikipedia.org/wiki/PID_controller#PI_controller

I only use the PI parts for motor control.

Last edited:

nsaspook

Joined Aug 27, 2009
7,494
Hola @nsaspook

I have been reading a lot about BLDCs but have no hands-on experience.

My questions, actually not focused on the main subject of the OP and sorry for that:

a) Find puzzling the motor's "parallel" wiring. What is the advantage?

b) What is the micro's Fosc? The PWM 8,33 ns resolution at what frequency?

c) Suppose the four motors turning continuously; what would be their"cruising speed"?

d) Other than azimuth and elevation, what are the others two for?

The FOSC is 120MHz but actually more important here is the hardware floating point co-processor.

The controller has four H-bridges that can be configured in many different ways. One of the pictured testing configurations was the one DC motor per H-bridge (three used with one extra), the other pictured configuration is a three phase motor setup with a H-bridge per phase (3 used with one extra)

nsaspook

Joined Aug 27, 2009
7,494
Thanks for the update. Pretty impressive display stats.

What is your display driver? I am using an ST7567 that is able to drive a 132x65 screen; although, it is only used at 132x64. It works great with SPI at 8 MHz too. I split the screen into two, 66x64 palettes with data on the right and gragh on the left. Simply erasing DDRAM for both sides is 2.451 ms total. When I redraw the graph screen, it takes longer as I recalculate each byte from data in linear RAM (PIC16F1783 @ 32 MHz). Somewhere I have that number, but couldn't find it. There is a noticeable blink, but it's not too bad.
It's a DOGS102-6 LCD (102x64 PIXELS) that uses the UC1701x 65x132 STN LCD Controller-Driver.
https://www.lcd-module.de/eng/pdf/zubehoer/uc1701.pdf

The other graphics display is a DOGXL240-7 with a UC1611S 160COM x 256SEG Matrix LCD Controller-Driver w/ 16-shade per pixel but that's on the back burner.

https://www.crystalfontz.com/controllers/UltraChip/UC1611S/

The driver is a pretty vanilla buffered ram version built from pieces of several drivers. (the controller board needs to also drive a 4*20 character display as an option) Parts of one does the hardware setup, parts of the other does the actual graphics into a ram buffer for fonts, pixels and lines while the last part is the Microchip MPLAB Harmony V3 generic SPI interrupt driver using some of the enhanced FIFO modes of the chips SPI module.

The speed is mainly a function of brute power and fast interrupts. If I do decide to use the larger screen then a DMA mode driver will be used to reduce the inter-char spacing due to interrupt latency.

OledDriver.c -- Graphics Driver Library for SSD1306 Display
C:
void OledUpdate(void)
{
int32_t ipag;
uint8_t* pb;

pb = rgbOledBmp;

for (ipag = 0; ipag < cpagOledMax; ipag++) {
*/
//Set page command
//page number
/* Start at the left column
*/
//set low nibble of column
//set high nibble of column
lcd_moveto_xy(ipag, 0);
/* Copy this memory page of display data.
*/
OledPutBuffer(ccolOledMax, pb);
pb += ccolOledMax;
}
}
Parts from here: https://github.com/mueschel/lcdlib
C:
/******************************************************************************
* Moves the cursor to the given position
* pages         - page to move to
* columns       - column to move to
*/
void lcd_moveto_xy(uint8_t page, uint8_t column)
{
lcd_current_column = column;
lcd_current_page = page;
}

Last edited:

jpanhalt

Joined Jan 18, 2008
10,110
Thanks. The user interface for that controller is the same as mine has. There is no read with serial SPI and column select is 2 bytes. The latter is not too important, but I think being able to read would be an advantage for scrolling and such. Of course, my processor is only 8-bit at 32 MHz.

ci139

Joined Jul 11, 2016
1,684
current PID feedback loop at the correct rotor offset at X position) using electrical current feedback from two of the PWM drivers. The velocity data and position used encoder counts and data between encoder counts is extrapolated using a 32-bit timer that resets and counts up a every QEI A/B signal from the drive motor.
long story of something that happens fast -- hard to grasp what it's about until i read
https://en.wikipedia.org/wiki/PID_controller
(a way over my head ... the math side)

nsaspook

Joined Aug 27, 2009
7,494
That MDA810A is a nice toy!

One of the functions of the controller LCD graphics display is to show a 3-phase Vector Display of the driver wave-forms. It won't be fancy like the LeCroy display.

nsaspook

Joined Aug 27, 2009
7,494
Hacked a simple three phase vector display demo for the LCD. Set to update every 15ms, full speed is about 4ms but is hard to see on the small display with a single line per vector.
Code fragment.
C:
    double theta1 = 0.0, theta2 = 120.0, theta3 = 240.0;

OledSetCursor(0, 1);
OledPutString("3PH VECTOR");
//Starting point
xn1 = x1;
yn1 = y1;

r = x2 - x1;
ra = 0.0175 * theta1;
si = sin(ra);
co = cos(ra);
//second point
xn2 = x1 + r * co + 1;
yn2 = y1 + r * si + 1;

line_rot(xn1, yn1, xn2, yn2);
ra = 0.0175 * theta2;
si = sin(ra);
co = cos(ra);
//second point
xn2 = x1 + r * co + 1;
yn2 = y1 + r * si + 1;

line_rot(xn1, yn1, xn2, yn2);
ra = 0.0175 * theta3;
si = sin(ra);
co = cos(ra);
//second point
xn2 = x1 + r * co + 1;
yn2 = y1 + r * si + 1;

line_rot(xn1, yn1, xn2, yn2);
OledUpdate();

irow++;
theta1 = theta1 + 1.0; // rotate
if (theta1 > 360.0)
theta1 = 0.0;
theta2 = theta2 + 1.0; // rotate
if (theta2 > 360.0)
theta2 = 0.0;
theta3 = theta3 + 1.0; // rotate
if (theta3 > 360.0)
theta3 = 0.0;

ci139

Joined Jul 11, 2016
1,684
? are you alone in this - as i get it gonna be tough task to reach the reliable anything ? and it'll be quite expensive one

nsaspook

Joined Aug 27, 2009
7,494
? are you alone in this - as i get it gonna be tough task to reach the reliable anything ? and it'll be quite expensive one
It's not my first Rodeo for this type of project (this one is actually easy as most motor driver software is a simple extension of induction principles) and the target systems for the regular software motor drivers/testers are multi-million dollar semiconductor production tools. The expense is relative.

Example: This little device saved a large amount of money. The high speed (needed for variable reluctance speed sensors) vacuum feed-through (Brass devices in the picture) would fail causing catastrophic damage of the vacuum turbo pump (\$60,000 each new) and beam line components. The cure was to slow down (using Hall sensors) the rotation to the point they never fail but to still provide the needed rotational speed information to the machine.

Last edited:

ci139

Joined Jul 11, 2016
1,684
The expense is relative.
Long ago "we" were the local representative of the https://www.scanvaegt.com/en/ , sold mostly the weighing equipment (somewhat to the price scale you mention above) . The scale circuitry was not more complex than the one in the "black-box" at your link - but the ting was stable at it's specified working T-range, had 33ppm internal accuracy and 333ppm display/legal accuracy, auto tracking zero, etc. ...
... so -- you could enter the raw accuracy display with the service PW -- so such enabled (in emergency , for as short period as possible) to calibrate a floor scale on site for the customer if he had another working one avail.

(looks like they're still in service) -- before i left they moved some of the production to China - so we had to finish the "chinese work" at the local device building factory (the scales should have been waterproof but you could see the daylight passing through from were there should have been a weld . . . ) . . . makes me wonder if the China and the Virus are synonymes ...

Last edited: