As shown in circuit diagram (Figure 3), dsPIC30F2010 from Microchip is used as processor to accept the command, drive the LEDs and generate the encoder signals. This project is so simple that no external crystal or oscillator is needed. Instead we use the internal RC oscillator provided inside the dsPIC. In the diagram we omit some minor detail such as reset or program loader part.
Figure 3: Simplified emotor block diagram
The PWM command is averaged by a simple RC circuit and fed into analog channel AN0 (RB0), while the DIR command is interpreted as a digital input through RB1 pin. A command can be given manually by adjusting a pair of 3-pin jumpers and using VR and a 2-pin jumper. Turning VR clockwise increases the LEDs rotation speed. Jumper on sets DIR=0 (rotating clockwise). Jumper off pulls DIR=1 (rotating counter-clockwise). The quadrature and index signals QA,QB,Z are sent out of pins RB4, RB5, RD1, respectively. (On the prototype, I soldered 3 mini-LEDs to these pins.) There is also a tachometer output generated by passing the PWM signal at OC1 (RD0) pin, corresponding to rotation speed, through an RC filter, the same way we use at the PWM command input. A push-button switch SW1 is used to apply torque disturbance to the emotor
The prototype was tested (Figure 4) and eventually worked as I wanted it to (after a few bug fixes.) See also the videos at bottom of this article.
Figure 4: emotor standalone test
As simple as it reads, this emotor
project is a good exercise in programming ADC, timer, and PWM modules of dsPIC. The concept could be adapted to other microcontrollers if you wish. The complete C source file is provided. There is nothing too complicated in the code, so here I explain in words only the overall program structure.
is a naive multithread program consisting of 3 threads: main, TSR1, and TSR2 timer routines. After initializing all modules and variales, the main routine procceds into an infinite loop that handles speed commands via ADC0 (voltage related to PWM). The new ADC value is averaged with the three previous ones to reduce noise. Then the motor increment variable minc
is computed related to the speed command, which is used by TSR1 to update the global variablemangle
. The variable enloop
is also computed. This variable determines when the quadrature encoder signals change their states. Before computing these values, the main loop polls on SW1 to check whether it is pressed. In such case, the actual speed is reduced to 0.6 of its commanded value. This mimics a “torque disturbance” input, just like one tries to squeeze the real motor shaft using fingers to reduce its speed. This disturbance must be attenuated when the emotor
is put into feedback loop with a controller. Finally, the main loop sends the actual speed to PWM module, to be measured as speed tachometer output.
TSR1, which takes care of motor rotation, is the most demanding thread in this application. This timer routine is programmed to run every 100 microseconds, so not too much code could be put into it. The only tasks are updating the motor angle variable mangle
and generating QA,QB quadrature encoder signals relating to the state duration (encloop
, computed in main loop), and DIR logic (read from RB1). It is not necessary to update the rotation LEDs at this fast rate, so we leave such task to timer 2.
TSR2 updates the 6 LEDs that represents motor angle each 10 milliseconds. It also generates the index pulse Z every revolution. Well, the dsPIC30F2010 has 3 timers and it turns out I have used them all (timer3 is consumed in the PWM generation process.) in case you have some other job and want to allocate timer2 to it, you may try putting the LEDs update function into a software timer routine, whose tick is updated by timer 1. This makes the program somewhat more complicated. Since I don’t have anything else that needs timer2, I am happy with this structure.
Read more about multitasking program structure with timer interrputs.