Posts about brushless-controller


YBrushless Motor Controller


Brushless Motor Controller

Moving rover is the most important thing followed only by the ability to steer and control it. Our idea is to use gimbal brushless motors (like these) in the wheel hubs to the drive rover. Brushless motors are quite fast which helps a lot, but also the ones we selected are gimbal motors they are supposed to be able to move very precisely for minute changes in camera movements.

The idea was to start with something like BLheli programmable ESCs but the software inside of them wasn't good enough to drive them slowly. Normally drone ESCs (Electronic Speed Controllers) are made for fine control of speed when props are already rotating quite quickly.

So, the other option was to make a homebrew brushless controller like this: Spining BLDC(Gimbal) motors at super slooooooow speeds with Arduino and L6234. That particular article was the main inspiration - especially as ATmega chips with nRF24L01 were the original idea to sit in side of wheels and drive each wheel. Quite an exciting little side-project...

So, the controller is going to be the L6234 chip - three phase motor drivers with a 5A peak current through it. The original rover had four motors that each has a stall current at around 800-900mAh. With the rover that might now be twice the weight it shouldn't really go over twice that, so 5 amps seems quite sufficient.

Moving Motor

Brushless at club

To start with a homebrew brushless ESC we decided to use a Raspberry Pi for prototyping as setting up three PWM pins (and another three just for 'enable' of each phase) is dead easy. Our "prototyping" Pi was our "Pi on a stick" - a Raspberry Pi Zero with USB connector set up to work as ethernet device.

Pi Stick and Brushless Rig

The code to start with is really simple - all that is needed to move motor is to set one of three 'phases' to positive potential ('1') and other two to negative ('0') in H bridges:

#!/usr/bin/env python3
from time import sleep
import RPi.GPIO as GPIO

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)


GPIO.setup(17, GPIO.OUT)
GPIO.setup(27, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)

o = GPIO.output

p = 0.2

while True:
        o(17, 0)
        o(22, 0)
        o(27, 1)
        sleep(p)

        o(17, 0)
        o(22, 1)
        o(27, 0)
        sleep(p)

        o(17, 1)
        o(22, 0)
        o(27, 0)
        sleep(p)

        p = p * 0.99

Moving Brushless Motor Slowly

Since our motor has 12 coils and 14 magnets (official designation 12N14P - "Common for higher torque applications. Noted commonly for its smooth and quiet operation." as per Wikipedia) that kind of program is not good for smooth operation. It would drive the motor 12 steps for whole circle - 30º per step. Since the wheels we'll have are going to be roughly 200mm in circumference, 12th part of it would be 16.6mm - quite a coarse movement. As per article mentioned above (Driving BLDC Slowly) we decided to use PWM and sinusoidal waves shifted 1/3 (120º in electricians' terms) apart. Sine waves were generated by open office's spreadsheet (as per article above) and embedded in code.

For instance:

PWM = [
[49, 93, 6], [50, 92, 6], [51, 92, 5], [52, 91, 5], [53, 91, 4], [54, 90, 4], [55, 90, 4], [55, 89, 3],
[56, 89, 3], [57, 88, 3], [58, 88, 2], [59, 87, 2], [60, 86, 2], [61, 86, 1], [61, 85, 1], [62, 85, 1],
[63, 84, 1], [64, 83, 1], [65, 83, 0], [66, 82, 0], [66, 81, 0], [67, 81, 0], [68, 80, 0], [69, 79, 0],
[70, 79, 0], [70, 78, 0], [71, 77, 0], [72, 77, 0], [73, 76, 0], [74, 75, 0], [74, 74, 0], [75, 74, 0],
[76, 73, 0], [77, 72, 0], [77, 71, 0], [78, 70, 0], [79, 70, 0], [79, 69, 0], [80, 68, 0], [81, 67, 0],
[81, 66, 0], [82, 66, 0], [83, 65, 0], [83, 64, 1], [84, 63, 1], [85, 62, 1], [85, 61, 1], [86, 61, 1],
[86, 60, 2], [87, 59, 2], [88, 58, 2], [88, 57, 3], [89, 56, 3], [89, 55, 3], [90, 55, 4], [90, 54, 4],
[91, 53, 4], [91, 52, 5], [92, 51, 5], [92, 50, 6], [93, 49, 6], [93, 48, 6], [93, 48, 7], [94, 47, 7],
[94, 46, 8], [95, 45, 8], [95, 44, 9], [95, 43, 9], [96, 42, 10], [96, 41, 10], [96, 41, 11], [97, 40, 12],
[97, 39, 12], [97, 38, 13], [97, 37, 13], [98, 36, 14], [98, 36, 15], [98, 35, 15], [98, 34, 16], [98, 33, 17],
[99, 32, 17], [99, 31, 18], [99, 31, 19], [99, 30, 19], [99, 29, 20], [99, 28, 21], [99, 27, 21], [99, 27, 22],
[99, 26, 23], [99, 25, 24], [99, 24, 24], [99, 24, 25], [99, 23, 26], [99, 22, 27], [99, 21, 27], [99, 21, 28],
[99, 20, 29], [99, 19, 30], [99, 19, 31], [99, 18, 31], [99, 17, 32], [98, 17, 33], [98, 16, 34], [98, 15, 35],
[98, 15, 36], [98, 14, 36], [97, 13, 37], [97, 13, 38], [97, 12, 39], [97, 12, 40], [96, 11, 41], [96, 10, 41],
[96, 10, 42], [95, 9, 43], [95, 9, 44], [95, 8, 45], [94, 8, 46], [94, 7, 47], [93, 7, 48], [93, 6, 48],
[93, 6, 49], [92, 6, 49], [92, 5, 50], [91, 5, 51], [91, 4, 52], [90, 4, 53], [90, 4, 54], [89, 3, 55],
[89, 3, 55], [88, 3, 56], [88, 2, 57], [87, 2, 58], [86, 2, 59], [86, 1, 60], [85, 1, 61], [85, 1, 61],
[84, 1, 62], [83, 1, 63], [83, 0, 64], [82, 0, 65], [81, 0, 66], [81, 0, 66], [80, 0, 67], [79, 0, 68],
[79, 0, 69], [78, 0, 70], [77, 0, 70], [77, 0, 71], [76, 0, 72], [75, 0, 73], [74, 0, 74], [74, 0, 74],
[73, 0, 75], [72, 0, 76], [71, 0, 77], [70, 0, 77], [70, 0, 78], [69, 0, 79], [68, 0, 79], [67, 0, 80],
[66, 0, 81], [66, 0, 81], [65, 0, 82], [64, 1, 83], [63, 1, 83], [62, 1, 84], [61, 1, 85], [61, 1, 85],
[60, 2, 86], [59, 2, 86], [58, 2, 87], [57, 3, 88], [56, 3, 88], [55, 3, 89], [55, 4, 89], [54, 4, 90],
[53, 4, 90], [52, 5, 91], [51, 5, 91], [50, 6, 92], [49, 6, 92], [48, 6, 93], [48, 7, 93], [47, 7, 93],
[46, 8, 94], [45, 8, 94], [44, 9, 95], [43, 9, 95], [42, 10, 95], [41, 10, 96], [41, 11, 96], [40, 12, 96],
[39, 12, 97], [38, 13, 97], [37, 13, 97], [36, 14, 97], [36, 15, 98], [35, 15, 98], [34, 16, 98], [33, 17, 98],
[32, 17, 98], [31, 18, 99], [31, 19, 99], [30, 19, 99], [29, 20, 99], [28, 21, 99], [27, 21, 99], [27, 22, 99],
[26, 23, 99], [25, 24, 99], [24, 24, 99], [24, 25, 99], [23, 26, 99], [22, 27, 99], [21, 27, 99], [21, 28, 99],
[20, 29, 99], [19, 30, 99], [19, 31, 99], [18, 31, 99], [17, 32, 99], [17, 33, 99], [16, 34, 98], [15, 35, 98],
[15, 36, 98], [14, 36, 98], [13, 37, 98], [13, 38, 97], [12, 39, 97], [12, 40, 97], [11, 41, 97], [10, 41, 96],
[10, 42, 96], [9, 43, 96], [9, 44, 95], [8, 45, 95], [8, 46, 95], [7, 47, 94], [7, 48, 94], [6, 48, 93],
[6, 49, 93], [6, 49, 93], [5, 50, 92], [5, 51, 92], [4, 52, 91], [4, 53, 91], [4, 54, 90], [3, 55, 90],
[3, 55, 89], [3, 56, 89], [2, 57, 88], [2, 58, 88], [2, 59, 87], [1, 60, 86], [1, 61, 86], [1, 61, 85],
[1, 62, 85], [1, 63, 84], [0, 64, 83], [0, 65, 83], [0, 66, 82], [0, 66, 81], [0, 67, 81], [0, 68, 80],
[0, 69, 79], [0, 70, 79], [0, 70, 78], [0, 71, 77], [0, 72, 77], [0, 73, 76], [0, 74, 75], [0, 74, 74],
[0, 75, 74], [0, 76, 73], [0, 77, 72], [0, 77, 71], [0, 78, 70], [0, 79, 70], [0, 79, 69], [0, 80, 68],
[0, 81, 67], [0, 81, 66], [0, 82, 66], [1, 83, 65], [1, 83, 64], [1, 84, 63], [1, 85, 62], [1, 85, 61],
[2, 86, 61], [2, 86, 60], [2, 87, 59], [3, 88, 58], [3, 88, 57], [3, 89, 56], [4, 89, 55], [4, 90, 55],
[4, 90, 54], [5, 91, 53], [5, 91, 52], [6, 92, 51], [6, 92, 50], [6, 93, 49], [7, 93, 48], [7, 93, 48],
[8, 94, 47], [8, 94, 46], [9, 95, 45], [9, 95, 44], [10, 95, 43], [10, 96, 42], [11, 96, 41], [12, 96, 41],
[12, 97, 40], [13, 97, 39], [13, 97, 38], [14, 97, 37], [15, 98, 36], [15, 98, 36], [16, 98, 35], [17, 98, 34],
[17, 98, 33], [18, 99, 32], [19, 99, 31], [19, 99, 31], [20, 99, 30], [21, 99, 29], [21, 99, 28], [22, 99, 27],
[23, 99, 27], [24, 99, 26], [24, 99, 25], [25, 99, 24], [26, 99, 24], [27, 99, 23], [27, 99, 22], [28, 99, 21],
[29, 99, 21], [30, 99, 20], [31, 99, 19], [31, 99, 19], [32, 99, 18], [33, 99, 17], [34, 98, 17], [35, 98, 16],
[36, 98, 15], [36, 98, 15], [37, 98, 14], [38, 97, 13], [39, 97, 13], [40, 97, 12], [41, 97, 12], [41, 96, 11],
[42, 96, 10], [43, 96, 10], [44, 95, 9], [45, 95, 9], [46, 95, 8], [47, 94, 8], [48, 94, 7], [48, 93, 7],
[49, 93, 6]]

All that is needed now is to send PWM to three pins from 3 places from above array, three places that are 1/3 of array length apart. Here is how it looks like moving brushless motor smoothly:

Controller

ATmega328p pinout

For a controller that can fit in wheel hub we have chosen the ATmega328p - there are enough free pins to cover 6 pins needed for L6234, 6 for nRF24L01 (more about it later) and a few spare for ADC and such. Also, it has three timers (two 8bit and one 16bit) all with two PWM outputs. Two eight bit timers with their corresponding PWM outputs work perfectly in this situation. Remaining 16 bit timer can be, then, used for internal timing.

Controller on breadboard

Conclusion

That week or two was really interesting and we learnt a lot about 3 phase motors, about PWM on Raspberry Pi, finding out how to check speed of the motor by counting the number of frames on videos that it takes the motor to make one revolution and such.

Happy Crew at the Club