Adruino Uno + DRV8302 + hoverboard 36v 360 w

The resistance appears to be the resistance per phase, which is half of the resistance that you measure across any of the two terminals of the motor.

I would like to take this opportunity to say that I don’t think the way things are organized in the code base is the best, it leads to this kind of thing a lot. Motor.target should imo mean the same thing all the time. No one thing in one mode and another thing in another mode. It makes it a lot harder to figure out the code, and mistakes like this happen a lot. One thing changes in one place, like setting the phase resistance, and everything breaks everywhere.

Setting the phase resistance should not really prevent you from using the voltage mode for open loop. You should have to deliberately set the current mode, and the attribute/variable/whatever should be different for both. One for current, one for voltage. One of them gets ignored. This code base is used a lot by people like me who have no clue and I think a straightforward approach would help a lot.

The resistance appears to be the resistance per phase, which is half of the resistance that you measure across any of the two terminals of the motor.
I’m a bit new to phase resistance. do you mean that i need to devide the measured resistance by 2?

anyway i measured my phase resistance wrong as i measured the resistance with the driver connected to the motor :sweat_smile:. I measured a resistance of around 1.4 ohm when the motor is disconnected from everything.

I think i got everything working well with the open_loop examples so now i wanted to try close_loop examples.

Im trying to get a closed_loop torque mode using voltage as torque control type. the problem i’m having is that when the motor.initFOC(); starts it seems to get stuck on MOT: alignsensor. it gives power to the motor, but it locks the motor and does not wants to turn. This has been great to confirm the amount of polar is indeed 15 :grin:.

the motor works fine using the open_loop example and the hall sensors also work great in a seperate code. Do you guys now what the cause might be?

No, this depends on the winding type of your motor. For Wye wound motors, the phase resistance is 1/2 the measured phase-to-phase resistance. For Delta wound motors, the phase resistance is 3/2 the measured phase-to-phase resistance.

Usually this means the sensor is not working right yet, for one reason or another - or the pole pairs is set wrong, though usually this results in motion rather than the motor locking up.

Do you mind sharing again the current state of your code?

its not incredibly well organised sorry :sweat_smile:

/**
 * 
 * Torque control example using voltage control loop.
 * 
 * Most of the low-end BLDC driver boards doesn't have current measurement therefore SimpleFOC offers 
 * you a way to control motor torque by setting the voltage to the motor instead of the current. 
 * 
 * This makes the BLDC motor effectively a DC motor, and you can use it in a same way.
 */
 // for creating a software interrupt pin
  #include <PciListenerImp.h>
  #include <PciManager.h>
  #include <SimpleFOC.h>

// set up pins on arduino board
#define HallA  2 // yellow
#define HallB  3 // blue
#define HallC  4 // green

//InH PWM pins
#define INHA   9
#define INHB   10
#define INHC   11
//miscellaneous pins
#define En_Gate  8 //Enable gate driver and current shunt amplifiers.
#define OC_ADJ   A0 //analog input adjusting the over-current limit - if you don’t care you can put it to high
#define M_OC     12 //Mode selection pin for over-current protection options. LOW = cycle by cycle. HIGH = overcurrent shutdown 
#define M_PWM    7 //Mode selection pin for PWM input configuration. LOW = 6PWM. HIGH = 3PWM

// polar pairs
int pp = 15; // motor has 30 outer magnets
//phase resistance value of the motor A B and C wires.
//float RPhase = 1.4;

// BLDC motor & driver instance
// BLDCMotor motor = BLDCMotor(pole pair number);
BLDCMotor motor = BLDCMotor(pp);
// BLDCDriver3PWM driver = BLDCDriver3PWM(pwmA, pwmB, pwmC, Enable(optional));
BLDCDriver3PWM driver = BLDCDriver3PWM(INHA, INHB, INHC, En_Gate);

// hall sensor instance
HallSensor sensor = HallSensor(HallA, HallB, HallC, pp);

// Interrupt routine intialisation
// channel A and B callbacks
void doA(){
  sensor.handleA();
  }
void doB(){
  sensor.handleB();
  }
void doC(){
  sensor.handleC();
  }

/* 
HallA and B are on the arduino uno hardware intterrupt pins which are pin 2 and 3.
because the arduino uno only has 2 hardware intterrupt pins Hall C needs to be
placed on a software intterupt pin.
this is what this does.
*/
PciListenerImp listenC(sensor.pinC, doC);

// voltage set point variable
float target_voltage = 1;
// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_voltage, cmd); }

void setup() { 
  
  // initialize Hall sensor hardware
  sensor.pullup = Pullup::USE_EXTERN;
  sensor.velocity_max = 1000; // 1000 rad/s is around 10,000 rpm
  //simplefoc activate sensor
  sensor.init();
  sensor.enableInterrupts(doA, doB);
  //extra step for HallC
  PciManager.registerListener(&listenC);
  // link the motor to the sensor
  motor.linkSensor(&sensor);

  // driver config
  //DRV802 driver specific code
  //3 or 6 PWM put on high for 3 pwm driver
  pinMode(M_PWM, OUTPUT);
  digitalWrite(M_PWM, HIGH);
  //over current protection
  pinMode(M_OC, OUTPUT);
  digitalWrite(M_OC, LOW);
  pinMode(OC_ADJ, OUTPUT); //adjuster voltage limit for M_OC
  digitalWrite(OC_ADJ, HIGH); // for now put on high to give maximum over current limit but better to connect it with a pot meter.

  driver.voltage_power_supply = 36; // power supply voltage [V]
  driver.init(); //start driver
  motor.linkDriver(&driver); // link driver
  motor.voltage_limit = 5;   //voltage limit
  motor.voltage_sensor_align = 1;   // aligning voltage limit
  
  //motor mode selection
  // choose FOC modulation (optional)
  motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
  //set torque mode:
  motor.torque_controller = TorqueControlType::voltage;
  // set motion control loop to be used
  motor.controller = MotionControlType::torque;

  // use monitoring with serial 
  Serial.begin(115200);
  // comment out if not needed
  motor.useMonitoring(Serial);
  motor.monitor_variables = _MON_TARGET | _MON_VEL | _MON_ANGLE; 
  // downsampling
  motor.monitor_downsample = 10; // default 10
  
  // initialize motor
  motor.init();
  // align sensor and start FOC
  motor.initFOC();

  // add target command T
  command.add('T', doTarget, "target_voltage");

  Serial.println(F("Motor ready."));
  Serial.println(F("Set the target voltage using serial terminal:"));
  _delay(1000);
}


void loop() {

  // main FOC algorithm function
  // the faster you run this function the better
  // Arduino UNO loop  ~1kHz
  // Bluepill loop ~10kHz 
  motor.loopFOC();

  // Motion control function
  // velocity, position or voltage (defined in motor.controller)
  // this function can be run at much lower frequency than loopFOC() function
  // You can also use motor.move() and set the motor.target in the code
  motor.move(target_voltage);
  motor.monitor();
  // user communication
  command.run();
}

This is likely totally wrong, but just remembering the code for the align sensor thing, I don’t know if it works for hall sensors. That’s not likely your problem, though. When I had a similar problem, the motor was actually turning but very very slowly. What was happening was that the I2C line lacked pullup resistors, and that caused it to stop working when motor power was applied, but it worked fine otherwise. The system was waiting for the sensor information before changing the angle with each tiny step. The communication timed out eventually, and it would move very slightly, almost too slow to notice.

If you open up the .cpp file that is being run and stick print statements in the right place that helps a lot to track down what’s up.

Speaking of pullup resistors, do you have any on the hall sensor lines? I see you have Pullup::USE_EXTERN set. At least on my hoverboard motors, the hall PCB inside the motor is only used for wire routing, no resistors or other components on the board. The CPU’s internal pullups are weaker than ideal, but Pullup::USE_INTERN has been working for me with U1881 hall sensors on small motors. My hoverboard motors have 41F hall sensors and I haven’t tried internal pullups with that kind yet, but most likely will work.

15 pole pairs should be correct if you counted 30 magnets. My motors are the same. find_pole_pair_number won’t work with hall sensors because there’s nothing that detects when a full mechanical revolution has completed.

As for voltage or current limiting, it doesn’t really matter for low speed testing. Easier to get up and running with voltage only. But for higher speed (which requires higher voltage limit), you need current limiting. Otherwise you get excessively high current at low speed when there’s no back-EMF to oppose the applied voltage.

@Anthony_Douglas

This is new to me. do you mean the library file where the .align reference is stated? so go to definition?

@dekutree64
ive used them both and for both the motor seems to lock itself in place. For Pullup::USE_EXTERN extern i didn’t add any resistor. i am pretty sure the hoverboard itself doesn’t have any resistors. maybe i need to buy some 5k ohm resistors to see if that’s improves anything. I don’t think so because the hall sensors work fine when using them in this code:

// for creating a software interrupt pin
#include <PciListenerImp.h>
#include <PciManager.h>

//for reading hall sensors
#include <SimpleFOC.h>

// set up pins on arduino board
int HallA = 2; // yellow
int HallB = 3; // blue
int HallC = 4; // green
int pp = 15; // motor has 30 outer magnets

//set up sensor in SimpleFOC library code
HallSensor sensor = HallSensor(HallA, HallB, HallC, pp);
void doA(){
  sensor.handleA();
  }
void doB(){
  sensor.handleB();
}
void doC(){
  sensor.handleC();    
}

/* 
HallA and B are on the arduino uno hardware intterrupt pins which are pin 2 and 3.
because the arduino uno only has 2 hardware intterrupt pins Hall C needs to be
placed on a software intterupt pin.
this is what this does.
*/
PciListenerImp listenC(sensor.pinC, doC);

void setup() {
  // put your setup code here, to run once:
sensor.pullup = Pullup::USE_INTERN;
sensor.velocity_max = 1000; // 1000 rad/s is around 10,000 rpm

//simplefoc activate sensor
sensor.init();
sensor.enableInterrupts(doA, doB);

//extra step for HallC
PciManager.registerListener(&listenC);
Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:
  // IMPORTANT - call as frequently as possible
  // set frequency at which to update encoder values
  sensor.min_elapsed_time = 0.0001; // 0.0001 by default
  // update the sensor values 
  sensor.update();
  // display the angle and the angular velocity to the terminal
  Serial.print("angle: ");
  Serial.print(sensor.getAngle());
  Serial.print("\t");
  Serial.print("velocity: ");
  Serial.println(sensor.getVelocity());
}

I thought it could maybe be the arduino uno not able to process the code. its already at 91% of its storage space and uses 75% of its dynamic memory.

I think here you can’t use voltage limits if you don’t include the phase resistance and KV rating of motor, maybe this is the issue? It needs to know phase resistance in order to know this voltage.
BLDCMotor(pp,Rp,KV)

@VIPQualityPost
I thought you need to add the phase resistance for when you are using a current limit.
I added it but the same thing happens the motor locks when it wants to align.

the serial print seems to get stuck went it wants to align which i think is strange. Also interestingly enough when the psu is turned off its able to continue with its calibration but states that it “failed to notice movement”

I don’t want to be unhelpful or repeat the same message, unfortunately I am noticing a prominent pattern on this forum. The issues rapidly become so complex that people over the forum kind of get overwhelmed and they can’t help much from afar with a lot of things.

The best advice I think is to get in there and look at how things are working. Look at the library documentation here:
http://source.simplefoc.com/foc__utils_8cpp_source.html#l00053

Browse. Try to follow the flow of the program. Come up with a hypothesis as to where it is getting stuck and add some print statements to sneak diagnostic information out. Use the serial monitor and plotter as suitable. Then tweak things and see if you can get to the next stage. There are probably more issues waiting after you solve this one, so budget the time and you have to be doing something worth doing, unfortunately, if my experience is any indication. I also had to do a little crash course on how arduino and C++ compiling works a little bit.

I think anything more than a trivial undertaking may benefit from proper debugging tools, my plan is to use Atmel Studio if I have such a problem again, who knows how that will go.

That’s normal, if the MCU is powered from USB, for example, then the MCU can run SimpleFOC but the motor can’t move because the driver isn’t powered. Then the alignment “fails to notice movement”.

What’s weird is that you say it gets stuck when it has power? I would also try external pull-ups as a first measure…
Another thing I note is that you’re using 1V out of 36V on the alignment… that’s really low. Is it possible to lower the PSU voltage? Otherwise I think the PWM won’t have much resolution left, although I don’t know if this can be the problem.

What’s weird is that you say it gets stuck when it has power?

when the alginment starts it starts to power the motor in such a way that it “locks” when you try to turn the motor with you hand you can feel resistance (friction?) from the magnets and you the motor jumping from magnet to magnet.

From what i understand is that the when the initFOC starts it wants to move the with one “electrical revolution” (. I think when its tries do the “electrical revolotion” it locks up.

Another thing I note is that you’re using 1V out of 36V on the alignment… that’s really low. Is it possible to lower the PSU voltage? Otherwise I think the PWM won’t have much resolution left, although I don’t know if this can be the problem.

I’m not sure if thats the problem for the openloop examples i have also used 1 to 8 voltage and it seems to work fine for me.

Got it working :grin:.

i set the driver.pwmfrequency from 32 khz to 4khz and that seems to do the trick (thank you for v2.3 :grin:). it now is able to align the sensor and able to turn, although there is a high pitch noice coming from the motor. Does anyone know what might be the cause of that?

That’s why we normally use PWM frequencies outside human hearing range :slight_smile: If you can’t get it to work with 32KHz, you’ll just have to ignore it or try a different driver. Do you know what kind of mosfets are on that board? We can look up their switching times and see if that’s the problem.

oh wow i’m glad that it is just an annoyance to the ears.

The mosfets are from Nce
NCE82H110D 1GL02
datasheet: https://datasheetspdf.com/pdf/1273220/NCEPowerSemiconductor/NCE82H110D/1


ive got a whole lot of switching characteristics but no idea what to do with it :sweat_smile:. I assume i can use one of these values to see at which pwm frequency i need to set the driver.

is it possible that the adruino uno is just not powerfull enough to handle closed_loop simplefoc well?

Hmm, that looks plenty fast. 32KHz is 31250ns per cycle. With target set to 1 volt out of 36, that’s 868ns on, 30382ns off. So the turn-on delay+rise is about 6% of the total on time. I wouldn’t think that would cause it to lock up entirely. But if you have a lower voltage power supply, give it a try and see if it helps.

Agreed on the FETs

But this is a Vq and will correspond to half that in terms of PWM range since the Vq can also be negative.
Then the PWM will only be at the 1V peak a small amount of the time, the rest of the time the duty cycles will be less than this.
But also the modulation is centred at 50% of the driver.voltage_limit so if I’m not totally confused this means the PWM is actually higher than 1/36 duty cycle…

ive lowered the voltage of the psu from 36v to 23.1v but that doesn’t seem to improve much.
Would the driver work better if i change it from 3 PWM to 6 PWM? I assume so, but i dont know what would change.

from what i understand i need to lower the voltage to around 5 volt in order to make the motor spin with 32KHz. My thought is that 4kHz is 250,000 ns per cycle so this means 1/36 volt is 6944 ns. 1/5 volt is 6250 ns per cycle when using a pwm.frequency of 32kHz.
I could also increase the driver.voltage_limit to 5 volt as 5/23.1v gives but im reluctant to do that as that would increase the current aswell. Im unsure how if that’s a bad, maybe its not.

But this is a Vq and will correspond to half that in terms of PWM range since the Vq can also be negative.
what does Vq stands for?

I have the feeling this is going in the wrong direction… both the DRV8302 and your MOSFETs should be able to handle PWM faster than 4kHz.

Doing your tests with a low PSU voltage (but not too low, or motor won’t turn and/or driver can’t work) is just a good idea in principle. If you’re only using 1/36V or 5/36V, why not reduce the input voltage and make things easier for the system. But with a hoverboard motor you’re going to need a certain amount of voltage or things just won’t move.

I think this is much more likely to be a source of problems. The UNO is quite a slow MCU, generally performance is much improved when you use a ESP32 or STM32 MCU with more power.

Another thing to check, but this will need an oscilloscope, is the switching behaviour of the FETs. We think they should be switching quickly, but this also depends on things like the drive voltage, gate resistance, and other factors. If this is a self-made driver, it can be worth checking that the power stage is indeed switching as expected.

I actually bought an adruino mega 2560 which is an improvement over the adruino uno i believe. So i hope it might work with that, because i have never worked with an ESP32 or STM32 before :sweat_smile:

i actually lowered the voltage already to 4/23.1 V. It mostly resulted in more noice from the motor though.

I don’t have a oscilloscope but I might barrow one somewhere. Never used one before so could be fun to check it out :grin:.