While I was experimenting with controlling the speed of the H/B drive wheels, I realized that really slow speed control was difficult to achieve with reasonable torque. This is unfortunate, because I'm anticipating needing slow (safe) speeds, but I still want to be able to drag a heavy device and child around.
The mainstream control method is to look at the hall effect sensors to determine the current phase, and then drive the desired (next) phase with a PWM signal. The duty cycle of the PWM signal controls the "strength" of the rotational torque which effects the speed of rotation. So to get a very slow speed, the PWM duty cycle must be very low, and then so is the torque.
I started researching other brushless drive strategies, and came across several articled that described how to run a BLDC (Brush Less DC) motor like a stepper motor. Anyone who has used a stepper motor knows that the torque is very high, and you can move them slowly, but they are very "cog-y".
The speed of a stepper motor is set by manually stepping the drive phases through their sequence at the desired rate. This essentially ignores the normal system of letting the motor free-run, and holds each step for the desired duration.
Since you are effectively holding the motor in stall, you do need to worry about heating. But you can still use the PWM to vary the amount of current/torque available. Unfortunately, this type of drive strategy produces a very noisy and "shaky" wheel motion. This is because the hoverboard wheel is divided into 90 "steps", so each phase jump corresponds to about 1/4" of forward motion.
I finally came upon a more elegant way to run the motors in Stepper Mode. If you have the processing power available, you can switch from square waves to sine waves for driving the phase coils. Technically this is called micro-stepping.
In this mode, instead of jumping from one phase to the next, the wheel does a smooth transfer (in micro steps). It's not perfect, but it's much quieter. I also discovered that instead of using a pure sinusoid, you can use a different curve (called a constant power curve) which is apparently smoother. I tried both methods and eventually decided on the constant power curve. To implement this, I used a spreadsheet to determine the curve values, and then I coded them as a lookup table with 1 degree steps. Since my PWM values go from 0-1000 that's how I scaled the table, but eventually I decided to scale these values down to 1/8th of this to limit self-heating of the motor.
Having discovered and implemented this new drive strategy, I ran some tests. I discovered:
1) I could accelerate very slowly a stop to a preset velocity with a substantial amount of torque.
2) Rather than using a pure sinusoid, there is a modified "constant power" cure that can provide a smoother motion.
3) If you are not careful you can overheat the wheel (and probably the drive FETs) if you don't scale down the overall voltage when applying the drive curve.
4) Once the rotational speed reaches a certain point (about 5% of full speed for me) the motor will start to jump and skip steps if it's put under load. I suspect this is because I'm not able to run through the Sine wave power curve fast enough.
So, I had a dilemma. The classic drive method works great for high speeds but lousy at slow speeds, and the new stepper method is great for slow speeds but lousy at high speeds.
My solution was to create a hybrid mode that switches between the two drive methods at a certain drive speed. The chosen "shifting" speed is the top speed that the stepper method works well. The final implementation of this strategy can be found in my hoverboard repo. Check out the bldc.c code.
My code can run the drive in several modes:
0) Open loop constant power (traditional)
1) Closed loop PID speed control (traditional)
2) Stepper motor mode
3) Hybrid Stepper/PID (Automatic shifting at MAX_STEP_SPEED)
Note: It took a lot of experimentation to get a smooth "shift" when shifting down to the stepper mode.