I need help with a new actuator in an old configuration

I am at my wits end - I am attempting to control a really nice Hudson motor which is part of a telescope mount - it has 8 poles and an integrated quadrature encoder - The part number indicates that it has 4000 cpr encoder, however it also parenthetically states (post-quadrature) - and in fact it fails the PP Check if I use 4000, it passes with 2000 cpr but the reported angle only changes PI radians for a full rotation vs 2PI radians. Oh I am using angle mode and when I turn the system on it starts spinning like a motor. I looked at the quadrature signals on an oscilloscope and they are nice and clean with less than 100 nsec rise and fall times.

Now the setup is running on a Teensy 4.0 with an Infineon board that I have used in the past with no issues at all (different motor and encoder) - the cabling and pinouts are identical - this WAS with an older version of Simple FOC - one thing I notice now is some messages during compile related to something with the Teensy as follows, I tried looking at the code - its a bit cryptic and the warnings aren’t very specific as to what pins might be “wrong”???

c:\Users\dolph\OneDrive\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\teensy\teensy4_mcu.cpp:12:54: note: ‘#pragma message: SimpleFOC: compiling for Teensy 4.x’
12 | #pragma message(“SimpleFOC: compiling for Teensy 4.x”)
| ^
c:\Users\dolph\OneDrive\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\teensy\teensy4_mcu.cpp: In function ‘int get_submodule(uint8_t, uint8_t)’:
c:\Users\dolph\OneDrive\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\teensy\teensy4_mcu.cpp:93:47: warning: ’ not in same submodule!’ directive writing 23 bytes into a region of size between 21 and 23 [-Wformat-overflow=]
93 | sprintf (s, “TEENSY-DRV: ERR: Pins: %d, %d not in same submodule!”, pin, pin1);
| ^~~~~~~~~~~~~~~~~~~~~~~
c:\Users\dolph\OneDrive\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\teensy\teensy4_mcu.cpp:93:13: note: ‘sprintf’ output between 51 and 53 bytes into a destination of size 50
93 | sprintf (s, “TEENSY-DRV: ERR: Pins: %d, %d not in same submodule!”, pin, pin1);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
c:\Users\dolph\OneDrive\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\teensy\teensy4_mcu.cpp: In function ‘int get_inverted_channel(uint8_t, uint8_t)’:
c:\Users\dolph\OneDrive\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\teensy\teensy4_mcu.cpp:130:80: warning: ’ - only B supported’ directive writing 19 bytes into a region of size between 14 and 15 [-Wformat-overflow=]
130 | sprintf (s, “TEENSY-DRV: ERR: Inverted pin: %d on channel %s - only B supported”, pin1, ch2==1 ? “A” : “X”);
| ~^~
c:\Users\dolph\OneDrive\Documents\Arduino\libraries\Simple_FOC\src\drivers\hardware_specific\teensy\teensy4_mcu.cpp:130:13: note: ‘sprintf’ output between 65 and 66 bytes into a destination of size 60
130 | sprintf (s, “TEENSY-DRV: ERR: Inverted pin: %d on channel %s - only B supported”, pin1, ch2==1 ? “A” : “X”);
| ^
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

is this a problem ? It seems to move the motor fine during alignment checks which always seem to yield the same Zero Electric angle of 6.28 (<< 2PI ??)

MOT: Monitor enabled!
MOT: Init
MOT: Enable driver.
MOT: Align sensor.
MOT: sensor_direction==CW
MOT: PP check: OK!
MOT: Zero elec. angle: 6.26
MOT: No current sense.
MOT: Ready.

Here is the motor/encoder setup code (although still a little bit odd about the 2000 cpr vs 4000 cpr:

// BLDC motor instance BLDCMotor(polepairs, (R), (KV))
BLDCMotor motor = BLDCMotor(8, 2.87, 9.28);

// BLDC driver instance BLDCDriver3PWM(phA, phB, phC, (en))
BLDCDriver3PWM driver = BLDCDriver3PWM(4, 5, 6, 7, 8, 9);

// position / angle sensor instance Encoder(encA, encB , cpr, (index))
Encoder sensor = Encoder(15, 14, 2000);
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}

The correct PPR setting for 4000 CPR in quadrature mode is 1000PPR. CPR = 4 x PPR

This should fix the angle changing by only 1xPI per turn.

For the motor PP check, what setting are you using for the PP? If the motor has 8 poles, then the correct setting would be 4PP.

Let us know how it goes with a setting of 1000PPR and 4PP.

I can’t say for sure about the warning you’re seeing, but there have been some changes to the teensy PWM driver. Please let us know if it works for you once you’ve found the right settings…

1 Like

Thank you runger, So I verified the encoder is producing 1000 cpr, I wrote a quick program to key off the index output and count the A and B counts - they are almost always exactly 1000 counts but sometimes could be up to 1014, they both always seem to be the same amount so I suspect its just the ambiguity of the index pulse (I am polling the input pins and spinning by hand) - I changed the PP to 4 and now everything seems good there - 2 Pi radians per rev measured by the FOC software. The remaining issue at present is that immediately after motor init the motor starts spinning - and it is in angle mode so it should be stationary until I give it a new target angle. - it does spin smoothly with stable velocity which seems to indicate that the PWM signals are clean - its also pretty quiet. Its almost like the control loop error signal is inverted - I tried swapping the encoder pins and I also tried swapping the phases but I’m guessing that the calibration routine probably figures all that out in software so it may not matter. Any suggested next steps to check ? I just noticed that the direction it spins at startup is completely random - one more bit of information, I put the thing in openloop mode - and commanded it 6.28 radians - the motor moved a small amount - in fact to get the motor to go 1 revolution I had to command it to ~1200 radians, now it is open loop so I guess it is only going on the number of pole pairs to do that - but it seems WAY off.

One more new piece of information - if I make the motor.voltage_limit = 0.5 the controller actually works as an angle controller but when it is at the set point it is “buzzing” - I notice it also fails the PP check when this value is small. If I give it a target of 6.28 radians it makes one complete rotation - if I make it 12.56 it overshoots the target by about 0.5 rotations and then slowly moves back to 12.56 - so weird…

Wish I could help in a more tactical manner, but this is too complicated and unfamiliar territory for me :(. I just want to say that this sort of stuff happens a lot. People are trying to make a fairly sophisticated piece of equipment from components and libraries, but it’s not easy. It’s far from plug and play. Stuff like this seems to be extremely common, and if they ever say “ok, it’s working now!” that only means it’s working to a very basic degree on one count.

We need to solve all these types of scenarios well ahead of time all at once by moving in an organized way to at least one (to start with) flagship board, and build out the code base with modules for various features, then knit them together into examples, test with various motors, debug… then people can plug and play to make one off devices with reasonable efficiency.

To try to give slightly more tactically useful advice, this is such a hairball that honestly I think the most efficient approach is to laboriously proceed to inspect and verify things from the bottom up. Get open loop working, verify the angle increments and decrements, then the other layers, you may need to tune the PID loops as well. There is a SOP but it’s laborious and slow and we all try to skip it but end up floundering.

The crazy thing is that 2 years ago I used SImpleFOC for a pretty complex integration of a new motor, I added my own absolute encoder (an Orbis SPI unit) and got it all up in running in a day - with this setup I was able to do individual rotor position control on a 100 lb coaxial helicopter - operating as a virtual swashplate - I happened to have one of the controller/teesny setups and figured a simple low speed BLDC motor with an integrated quadrature encoder would be a simple task - I think part of this may be related to the major re-architecture of simple FOC since that time - I’ll keep plugging away !

1 Like

I found the problem !!! When I wrote the code I had all the motor data including the winding resistance and the KV value, so I put it in - by just entering the PP number, and nothing else, the design works - including the winding resistance and KV number breaks it. AND its my fault, the number I put in was the back EMF value NOT the KV rating - lol !!

BLDCMotor motor = BLDCMotor(4, 2.87, 9.28); << This didn’t work because 9.28 is NOT the KV rating

BLDCMotor motor = BLDCMotor(4); << This DOES work !