Hoverboard main board with simpleFOC

I only checked the first three hex chars, but they look perfectly ok (Sen). Also the ending with 0D 0A is perfectly fine…. You seem to be sending correctly. Problems may still exist if sender and receiver expect different baud rate or start/stop bits.

Test your ftdi by connecting RX and TX together and check if you get what you send

1 Like

Common problems are:

RX and TX need to be crossed once, somewhere along the line. Not crossing or crossing twice are things I’ve managed to do frequently.

Setting the wrong baud rate or com port options - though usually some gibberish shows up on the terminal to clue you in that the baud rates are set differently.

Terminal connecting to some other com port (my Mac seems to have three useless ones, two of them Bluetooth related that platformio just loves to connect to instead of my MCUs :rofl:

I had that in mind all the time and made sure MCU-TX was connected to FTDI-RX.
Just for fun I connected TX-TX and now it works?! :rofl:
Just to clarify, I’m using a ESP8266 WEMOS-D1 module with reset pinned to GND. That way the CH340 chip acts like a USB-Serial interface for external devices.

TBH, there were several things I had wrong regarding activation of the second UART:
When you wake up UART2, you also have to use Serial2 in the pin definitions.
BTW, it works with both: MCU pin numbers and port-numbers

#define SERIAL_UART_INSTANCE    2
 #define PIN_SERIAL2_RX           PA3 //  13 
 #define PIN_SERIAL2_TX           PA2 //  12

Now I have to figure out if the RX-pin also works by adding Commander-stuff and motor/driver definitions.
I’m a bit worried, because on MCU-RX-side is an RC-circuit with 100R resistor in line and Capacitor to GND between header and MCU.
I wonder, if they added that, because it was the long connection between the two splitboards.

1 Like

One step forward, two steps back…
I tried to flash velocity control with commander and motor.monitor, but it doesn’t fit in 64k flash.
So I set target.velocity to 5 and commented out all the commander-stuff. Now it fit’s, yeah!

After powering the 40V supply up, I got some messages from serial and heard a clunk sound from the motor.
But the initialisation failed.
That was the last sign of life. For some reason the 3.3V LDO onboard only shows 0.8V.
How did I kill it? The ST-link was unplugged at that moment.
Here’s the complete code:

/* 
  10" hoverboard splitboard with STM32F030C8T6 MCU and hall sensors
*/

#include <SimpleFOC.h>
#define SERIAL_UART_INSTANCE    2
 #define PIN_SERIAL2_RX           PA3 //  13 
 #define PIN_SERIAL2_TX           PA2 //  12

#define SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH true //  for Fortior FD2133S gate drivers
#define SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH false

BLDCMotor motor = BLDCMotor(15);
// BLDCDriver6PWM driver = BLDCDriver6PWM(A_PHASE_UH, A_PHASE_UL, A_PHASE_VH, A_PHASE_VL, A_PHASE_WH, A_PHASE_WL);
BLDCDriver6PWM driver = BLDCDriver6PWM(PA8,PB13,PA9,PB14,PA10,PB15);  //  blue, green, yellow gate driver pins

// Hall sensor instance
//  - hallA, hallB, hallC    - HallSensor A, B and C pins
//  - pp                     - pole pairs
HallSensor sensor = HallSensor(PA0, PF1, PC15, 15); //  blue, green, yellow, 15PP

// Interrupt routine intialisation
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}

// instantiate the commander
float target_velocity = 5;
//Commander command = Commander(Serial2);
//void doTarget(char* cmd) { command.scalar(&target_velocity, cmd); }

void setup() {
  pinMode(PB9,OUTPUT);  //  onboard LED for heartbeat signal

    // monitoring port
  Serial2.begin(115200);
  digitalWrite(PB9,HIGH);

  // initialise encoder hardware
  sensor.init();
  // hardware interrupt enable
  sensor.enableInterrupts(doA, doB, doC);

  // link the motor to the sensor
  motor.linkSensor(&sensor);
  
  // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 40;
  driver.init();
  // link the motor and the driver
  motor.linkDriver(&driver);

  // aligning voltage [V]
  motor.voltage_sensor_align = 6;
    
  // set motion control loop to be used
  motor.controller = MotionControlType::velocity;

  // controller configuration 
  // default parameters in defaults.h

  // velocity PI controller parameters
  motor.PID_velocity.P = 0.2f;
  motor.PID_velocity.I = 2;
  motor.PID_velocity.D = 0;
  // default voltage_power_supply
  motor.voltage_limit = 20;
  // jerk control using voltage voltage ramp
  // default value is 300 volts per sec  ~ 0.3V per millisecond
  motor.PID_velocity.output_ramp = 1000;

  // velocity low pass filtering time constant
  motor.LPF_velocity.Tf = 0.01f;

  // comment out if not needed
  motor.useMonitoring(Serial2);

  // 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 velocity using serial terminal:"));

   _delay(1000);
   */
 }

void loop() {
  motor.loopFOC();
  motor.move(target_velocity);
  motor.monitor();

  // user communication
  //command.run();
  
  digitalWrite(PB9,LOW);
  delay(100);
  digitalWrite(PB9,HIGH);
  
}

You could use my “poor man’s commander” Programming the Lepton from start to finish - #35 by dekutree64

1 Like

Yeah, it fit’s in and only takes 2% more flash. I can reduce the options a lot to make it even smaller.
That should be the new commander standard for 8-biters with 64k flash mem :+1:

Hmmm… hard to say from the description what happened, but some thoughts:

  • don’t test with 40V until you’re confident its all correct. Usually you can get motion with a lower voltage like 10V also… I assume you’re using a PSU with current limiting? Set a low limit.

  • but above all, don’t test with power until you’re sure its working. You can test the driver stage by looking at the PWM signals before running the motor. Then next you can test it with power but no motor connected…

  • loose cables/connections. Make sure everything is soldered well, and wobbly cables are held in place by a spot of sugru, hot-glue or similar. Loose cables and connections can make it quite impossible to progress even if you got everything right. And they have potential for shorting out things they should not be touching, in the worst case this can destroy the board.

Do you have another board you can try with?

I’ve set motor.voltage_sensor_align to 6V to make sure it wouldn’t jump off the table.
Maybe that was too low?
I’m also not sure, if the place to put
#define SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH false

in the maincode is correct? Maybe include a build_option.h file and put those compiler directives there?

Hey,

In C, C++ the compiler compiles C/C++ files into object files. Each compilation unit (1 .c or .cpp file) goes through the preprocessor, where all the #defines and #includes are resolved.
The result is one massive string of c/c++ code, which the compiler turns into the object file for that c/cpp file. These different object files are then linked together in a second step, by the linker, to build the binary file loaded onto the MCU.
There may be some additional steps, but in essence this is how it works.

When you put a #define in some .c or .h file of your project, it never gets included by the .c/c++ files of the libraries or the framework. Of course not, how can they know about what’s in your project? They are supposed to be general, re-usable for all projects…

So when you want to make build-flags, i.e. #defines that affect the entire compilation, they cannot go in any .c/.cpp or .h/.hpp file of your project. They have to be defined at a global level, so they also affect the compilation of the libraries and the framework.

So you have to put them in a place where they act globally. In platformIO, this can be your platformio.ini file. In ArduinoIDE, you have to modify some framework files like the boards.cfg or platform.cfg to add the flags to some part of the configuration.

1 Like

I think, I get what you’re saying, but I don’t invent these defines in my code, I overwrite them.
If I’d try to #define Rumpelstilzchen I’d get an error.

Anyway, the good news is, the board isn’t damaged. I flashed the working hall-sensor test file and it was back in the race.
I then flashed the 6PWM driver test and could scope the H_in and L_in signals for the gate-driver.
Yellow is H_in; green is L_in


Does that look OK? It should be 3V-PWM with a 12V PSU

12V might not work well later when you want to get the motor moving.
Mosfets need more than that I think.

You can #define whatever you like, it does not have to over-write anything. Try adding #define Rumpelstilzchen!

The reasons that some defines change program behaviour is because the code is written using them as control statements to change what parts of code are compiled.

OK, but it would only be valid after that line (locally)

If you want to globally define Rumpelstilzchen (during and after compilation) you can add it in the build flags, like this:
-D Rumpelstilzchen
Which is more what @runger was talking about earlier with the compliler/ linker.

OK, now what about the gate signals? The H_in is high active, the L_in is low active. To me it looks like I get a through-shoot with that pattern?

If they are inverted logic (which you said they are?) then it looks fine, although the time between switching (dead time) does look a little short, but this could be an artifact of the oscilloscope too. I might just hook a motor up and give that a try, with a low max current.

Yes, you need to globally define the low side active-high flag to false…

However, your fortior driver will prevent the shoot-through, normally. Best not to stress it out too much though :wink:

That’s what I read from this graphic. They always reference LIN with an * which is also a sign of being inverted

You are right, I tried to overwrite it in my code, but it doesn’t change… :blush:
Time to dig deeper
Found the definition in hardware_api.h and boldy set it to false. Et voilá

I also increased the dead-time and reduced PWM-frequency to 25kHz
Do we have a winner?

1 Like