Cant get good data from sensor/can't turn the motor

The l6234 has thermal protection, you might be lucky. Regarding voltage limits, i think it doesn’t get used in voltage mode. After all, when you call motor.move(1) - you are asking for 1v to be supplied to the motor. I’d call motor.move(0.1) and increase slowly to motor.move(1). At 1v you’ll be drawing ~2A (if winding is 0.5ohms). This will be too hot for continuous use. Hopefully your motor will spin at less than 0.5v.
One non conclusive test as to whether you’ve killed your shield is to check how much current it draws when no motor is attached. I think mine is 7mA at 12v. If it pulls a lot more it’s dead.

1 Like

Hi guys, it 's a great discussion in here! :smiley:

@Owen_Williams thanks for the fix for the find_pole_pairs example I have included it to the new version of the code.

@breef Unfortunately, both of your motors are a bit to much for the shield. The board is designed for the motors closer to resistance of 10 ohms, and for currents under 5A peak. And if you would be planning to run this motor with 2A+ you should consider cooling, a heat sink or something similar.

I will try to document this better when I am back, but for now I would like to provide you guys with an example code of the open motor control and one example of how exactly to limit the voltages.

Open loop motor control - motor test

 // Open loop motor control example 
 #include <SimpleFOC.h>

// motor instance
BLDCMotor motor = BLDCMotor(3, 10, 6, 11, 7);

void setup() {
  
  // power supply voltage
  // default 12V
  motor.voltage_power_supply = 12;
  
  // choose FOC modulation (optional)
  motor.foc_modulation = FOCModulationType::SpaceVectorPWM;

  // init motor hardware
  motor.init();

  Serial.begin(115200);
  Serial.println("Motor ready!");
  _delay(1000);
}

// target voltage to be set to the motor
float target_voltage = 2;
// target voltage to be set to the motor
float target_angle = 2;

void loop() {
  // integratiing the angle in real time
  // the larger the constant added the faster the movement
  target_angle += 0.001;
  
  // set open loop voltage
  motor.setPhaseVoltage(target_voltage, target_angle);
}

With this code you can test your driver and you can easily set the limiting voltage you are setting to the motor. Just make sure you change the target_voltage value. (this value can be negative as well).
In case of your motors you can start form 0.1V and then grow the values.

If you wish to change the velocity of the movement you just add a larger number instead of 0.001. You can put something like:
target_angle += 0.1;

Voltage limiting

Now when you want to limit the voltage there are 4 things you should know:

  1. First thing you should make sure to change is set is the motor.voltage_power_supply if you don’t put the real power supply voltage (doesn’t have to be dead on, but at least close) then all of your limiting in future steps will have an error proportional to the error of the motor.voltage_power_supply .

  2. First thing to limit is the variable motor.PI_velocity.voltage_limit = yourVoltageLimit; as suggestedd by @David_Gonzalez. This is very important.

  3. When you are running the voltage control then you don’t need any other limits, other than not setting the target voltage higher than you limit.

  4. When running position/velocity motion control then you need to set the
    motor.PI_velocity.voltage_limit = yourVoltageLimit; this variable is only used for position and velocity control, not for open loop and voltage control. You can see this on the diagrams in the Motion Control | Arduino-FOC

Here is a voltage control code with voltage limiting:

#include <SimpleFOC.h>

// Magnetic sensor
MagneticSensorI2C sensor = MagneticSensorI2C(0x36, 12, 0x0E, 4);

// Motor instance
BLDCMotor motor = BLDCMotor(9, 5, 6, 11, 8);

void setup() {

  // initialise magnetic sensor hardware
  sensor.init();
  // link the motor to the sensor
  motor.linkSensor(&sensor);

  // power supply voltage
  // default 12V
  motor.voltage_power_supply = your power supply;     
  // aligning voltage
  motor.voltage_sensor_align = your limit; 
  
  // choose FOC modulation (optional)
  motor.foc_modulation = FOCModulationType::SpaceVectorPWM;

  // set motion control loop to be used
  motor.controller = ControlType::voltage;

  // use monitoring with serial 
  Serial.begin(115200);
  // comment out if not needed
  motor.useMonitoring(Serial);

  // initialize motor
  motor.init();
  // align sensor and start FOC
  motor.initFOC();

  Serial.println("Motor ready.");
  Serial.println("Set the target voltage using serial terminal:");
  Serial.println("But dont exceed your limit");
  _delay(1000);
}

// target voltage to be set to the motor
float target_voltage = 0;

void loop() {

  // main FOC algorithm function
  motor.loopFOC();

  target_voltage = 

  // Motion control function
  motor.move(target_voltage);
  
  // communicate with the user
  serialReceiveUserCommand();
}


// utility function enabling serial communication with the user to set the target values
// this function can be implemented in serialEvent function as well
void serialReceiveUserCommand() {
  
  // a string to hold incoming data
  static String received_chars;
  
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the string buffer:
    received_chars += inChar;
    // end of user input
    if (inChar == '\n') {
      
      // change the motor target
      target_voltage = constrain(received_chars.toFloat();, -your limit, your limit)
      Serial.print("Target voltage: ");
      Serial.println(target_voltage);
      
      // reset the command buffer 
      received_chars = "";
    }
  }
}

And here is a simple example of a velocity control (the limiting part is the same as for the position loop):

// Voltage motion control will placeholders for voltage limit
#include <SimpleFOC.h>

// magnetic sensor instance
MagneticSensorI2C sensor = MagneticSensorI2C(0x36, 12, 0x0E, 4);

// Motor instance
BLDCMotor motor = BLDCMotor(9, 5, 6, 11, 8);

void setup() {
 
  // initialise magnetic sensor hardware
  sensor.init();
  // link the motor to the sensor
  motor.linkSensor(&sensor);

  // power supply voltage
  // default 12V
  motor.voltage_power_supply = your power supply;
  // aligning voltage
  motor.voltage_sensor_align = your limit; 

  // set motion control loop to be used
  motor.controller = ControlType::velocity;

  // velocity PI controller parameters
  motor.PI_velocity.P = 0.2;
  motor.PI_velocity.I = 20;
  // default voltage_power_supply
  motor.PI_velocity.voltage_limit = your limit;

  // use monitoring with serial 
  Serial.begin(115200);
  // comment out if not needed
  motor.useMonitoring(Serial);

  // initialize motor
  motor.init();
  // align sensor and start FOC
  motor.initFOC();

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

// velocity set point variable
float target_velocity = 0;

void loop() {
  // main FOC algorithm function
  motor.loopFOC();

  // Motion control function
  motor.move(target_velocity);
  
  // user communication
  serialReceiveUserCommand();
}

// utility function enabling serial communication with the user to set the target values
// this function can be implemented in serialEvent function as well
void serialReceiveUserCommand() {
  
  // a string to hold incoming data
  static String received_chars;
  
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the string buffer:
    received_chars += inChar;
    // end of user input
    if (inChar == '\n') {
      
      // change the motor target
      target_velocity = received_chars.toFloat();
      Serial.print("Target velocity: ");
      Serial.println(target_velocity);
      
      // reset the command buffer 
      received_chars = "";
    }
  }
}

I hope it helps, let me know how it goes!

I have released the new version of the library 1.4.1 which has a bit smaller memory footprint so please make sure to use the newest version. This might help with the find_pole_pairs issue.

I also have one quesstion

@Juxo, you say you are running the i2c sensor with the Nucleo boards, did you need to use pull-ups.

1 Like

Antun,
I made the tests “quick and dirty”. I placed two magnets on the shaft. One at the front and one at the end of a motor. Than I run the motor and compare the output at different speeds and at different stop angles.
Up to now I used the predefined pins for I²C and SPI (from the pin-out diagram, not the arduino headers). I guess the basic configuration of this pins are pull-up if there should be for proper operations. I haven’t went through the documentation. Just women are reading manuals :wink: . Sorry, wasn’t political correct.
If I will ever get in trouble with the sensor I will check this again. For now it works fine what it should not do when pull-up is not enabled.

Antun,
this discussion brings me to an idea/question.
Provided, I have a motor that can’t run the zero_electric_angle search because of limited precision in low speed or anything else.
But I could figure out the correct zero_electric_angle by setting the value and try a ramp-up. The more efficient this run would be the more precise I hit the right angle.
This would provide that I can adjust the zero_electric_angle in the main loop (for evaluating), or at least in the setup function (for the next operations with the same motor).
What would your suggestion to realize this.
When I create an instance of the BLDCmotor, the value is set to 0 by:

// electric angle of the zero angle
zero_electric_angle = 0;

And for my understanding there is no property that can be set to override the value.
For sure I could add some code to the library but this is not my intention.

Is there a backdoor?

Edit: I guess zero_electric_angle isn’t the right variable but you know what I mean.

If you don’t have the precision to calibrate the sensor (motor) angle to electrical angle, then the same lack of precision will hit you at speed. You don’t really know where the motor is so even if you had a really good zero offset you’d have a crappy calculated electrical angle.

You can run in openloop mode without any sensor. It kind of works like a stepper motor. You spin the field with a certain speed and torque and ‘hope’ the rotor follows. It’s likely to be more obediant if you ramp up voltage (torque) but the beauty of closed loop is that torque adjusts to load, a well tuned closed loop is really efficient.

I’ve got 3 hall sensors on a 15 pole pair motor. That gives me a resolution of 90 steps per mechanical 360, or putting it another way i can expect one or the hall sensors to change state every 4 degrees. Not great, but velocity control will be fine and might still be possible to do position control. I’m not sure what 6 steps per electrical revolution will do to simplefoc algorithm! But i plan to explore.
Was your question hypothetical or do you have a motor with limited precision?

It was not really hypothetical.
Bad precision is just one example of the need to put in a fixed value of zero offset. Imagine a situation where a motor is part of a complex machine. Then it would be problem to adjust electrical 0-offset every time you start. This is the real source of my thoughts. The question of breef was just another trigger for my idea.
As long as we playing around it is nice to search for zero. But when I’m going to test it in real environment the things are changing.

Hey @Juxo, you are absolutely right. At the moment I have not implemeted this, but I will in the next version of the library. Basically my plan is to skip the init prices if you supply zero offset to the initFOC function.

motor.initFOC(offset);

At the moment you can do it by hand. You can run the code one time and do a serial print of motor.zero_electric_angle
And one time you have it you can comment out the call of motor.initFOC()
And add:
motor.zero_electric_angle = your value.

This should work as well.

I may done some typos since I’m typing from my phone, but I think you get the idea.

Also, this will work only for magnetic sensors!

1 Like

Very good implementation!
Probably this method is also useful for future implementation of hall sensors. If they are misaligned you are faced with a similar problem.

Antun,
it happend as you have predicted. Under real conditions the I²C connection is not stable without pull-ups.
So I went back to SPI where no additional hardware is needed (and the AS5048a has a better resolution).
BTW: I can see examples where the instance of the sensor was made with the resolution in cpr (i.e. 16xxx) and other with bits (i.e. 14). Referred to the code it should be in byte. Has something changed and the code was not modified or is both valid?

Hey @Juxo,
I was hoping this was just me and it won’t happen to anyone else :slight_smile:

You’ve spotted well, I’ve actually updated the library examples today (master branch). I have not well refactored the code before. You should use the number of bits* not the CPR anymore, this makes more sense for magnetic sensors.

Hey!

It took a while but I just got back to doing stuff again with SimpleFOC :slight_smile: I got some new parts but still have some problems. Or I don’t get how to set everything haha.

I got a new motor with correct resistance, >10 - its something like 15 if I remember correctly - its a 5208-12, 12N14P - the product says 20V.
Also got a new SimpleFocShield - Thanks @Antun_Skuric! :slight_smile: The old one did still turn a bit but maybe I didn’t have everything set up correctly, if I get the new shield running I’ll test the old one again - if its fried I’ll order a new chip and repair it. Doesn’t hurt I need multiple either way.

But I still haven’t really got it running. Sensor data seems good but just can’t get find_pole_pairs to run. I got the newest Version of the Library. I changed around the motor wires but its more often than not negative. Well, I know the pole pair number in theory - 12N14P - that means 14 pole pairs right? After reading in the forum I found that it should be halved from that specification? For everything I tried I took 14 and 7 - both didn’t really work - maybe one better than the other but I think 7 is correct. Its rocking a couple mm front and back (and that rather smooth) but fails or gets something >1000

With that 7 I tried running open_loop_velocity_example first with 12V and voltage_limit I tried everything from 3-12V, later tried with 20V power supply and 3-12V voltage limit which changes the behaviors but I dont get what is wrong. Its like its missing a phase - kinda like missing steps. It sometimes just back and fourth a couple mm or it turns but really badly and not smooth.
I made sure it doesn’t pull more than 1A this time :wink:

this is my motor code:

//  open_loop_velocity_example  

  BLDCMotor motor = BLDCMotor(9, 5, 6, 7, 8);
    .
    .
    .
  motor.voltage_power_supply = 12;

  // limiting motor movements
  motor.voltage_limit = 7;   // rad/s
  motor.velocity_limit = 20; // rad/s

I made two videos if its needed, but haven’t a fast way to attach them right now :slight_smile:
But either way I’m exited to try again!

Edit: The other code in this thread I haven’t tried yet, I wanted to get the tutorial basically working but I see you use voltage alignment settings. It feels like that what’s missing to turn the motor correctly.

Just to make sure - with the open_velocity_example - I’m expected to see the motor continuously turn right?

edit2: I was running the velocity example at around 3-5 velocity - if that helps to know

Edit3: I just tried the open loop code in a post from @Antun_Skuric in a post more on top here, first I thought its the same as the example but its not, its using SpectorPWM and the example code defines a ControlType. I tried to compile that but it says setPhaseVoltage is private. That might be old code? I could change SimpleFOC to call this here but I think that’s not intended anymore?

A video would help a lot!

In the meanwhile, you should be able to spin your motor with no problems with the open_loop_control example. Try lowering the velocity_limit to something around 2 rad/s since 20rad/s is actually pretty fast and might be too fast for your motor.

Hey thanks!
I always ran it with 2-5 rad/s, the maximum of 20 was just the default in the example file

But I wouldn’t say I’m able to spin it without problems - any ideas? Or is it to be expected that way?

here are two videos: :slight_smile:

I see from your video that you’re using an Arduino UNO with the shield, have you double checked the solder jumpers on the backside of the shied that you’re using the correct pins for the PWM signals? You could also try removing the conductive ink (black dots) that come with the shield and make a solder bridge.

The first video looks like the voltage limit is too small. The second video doesn’t seem too bad, but the clicking sound is weird.

1 Like

Oh wow thanks for the tipp. I was sure the pins where correct but I already thought today might as well resolder them - just resoldered the pads now its working like I would expect it to! Thanks a lot! :smiley:

Now I can start real playing around! :slight_smile:

1 Like

Hey Benjamin!

I am happy that you found a solution :smiley:
There is also a getting started page which might be helpful for problems like this one, it doesn’t cover all the things but it is a good place to start.
https://docs.simplefoc.com/arduino_simplefoc_shield_getting_started

Keep us posted about your cool projects :smiley:

Getting Started = Page not found

1 Like