Programming the Lepton from start to finish

Hey guys, I am trying to gear up to test the Lepton. Programming it is quite baffling. I generally gather I use an STlink device and connect it to the SWD connector on the board. I have the connectors etc. for that. However, actually creating an arduino bootloader specific to the STM32G031G8U6 for 64 MHz with the internal clock, and uploading it is the sticking point. I have read instructions for programming the bluepill, but am rather aware it is not the same MCU. Can STM32Cube be used to produce this? And load it on?

I was able to get SimpleFOC working with the uno and shield.
I think I will probably also need to know the pin configurations, ideally some exact code known to work with the Lepton? Valentine, do you have some code that you used during testing that I could also use?
edit: the bluepill has jumpers for enabling flashing, we don’t have to worry about that?

Wait, I also have to be able to communicate over usb, I suppose I can use the uart port of the board with an FTDI converter?
Edit: I’d rather use exactly whatever you are using, Valentine, I am sure there are several approaches. Unless it is expensive or hard…

Hey,

Regarding serial output the ST-Link V3 models have a built-in serial to usb converter. So you can just connect the RX/TX lines to the ST-Link and only need one device and USB port.

Regarding the bootloader, you don’t need one, unless you want some kind of custom boot-up behaviour. The STM32G0 has a built-in boot loader which is perfectly good for programming via serial, and SWD is built into the chip.

What you do need is a working configuration based on “Generic STM32G0” which includes a clock configuration, otherwise your Leptons will run with an unreasonably slow default config. There was a thread on that topic recently in the forums here…

Will check for the thread. I’m not clear exactly on the process of compiling and uploading the config when done getting the C code sorted. do I use the Arduino IDE, then?

Use Arduino IDE. Install the STM Cube. Connect the programmer to the SWD pins, then just hit upload. No need for any bootloader, or anything. It’s a really straightforward process.

I created a user’s guide for the Mosquito, the LEPTON is using the same MCU, please read the programing section [2.5.5].

Add the clock config (simple copy/paste) to the beginning of your code. I don’t have it now, there was another thread as @runger said.

Cheers,
Valentine

Here is the clock code (generated by STM32CubeIDE). You can put in a separate .cpp file if you don’t want to clutter your main .ino file

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
  RCC_OscInitStruct.PLL.PLLN = 8;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

To make sure it’s working, Serial.println(F_CPU);
Without clock config should print 16000000, with clock config is 64000000.

You need to call Serial.setRx(PA15) and Serial.setTx(PA2) before calling Serial.begin. I use an FTDI adapter for serial communication, and ebay ST-Link v2 mini for programming via STM32CubeProgrammer. I think ST-Link v3minie can do both, but it does not supply 3.3v power, which is a bit annoying.

The Arduino IDE needs to be configured to save the build files in a place where you can get at them. In preferences.txt, add a line build.path=C:\Arduino\build or whatever folder you want it to output to. It should put a .ino.bin file in that folder when you compile, and that’s what you flash to the Lepton with STM32CubeProgrammer.

1 Like

Getting some slight contradictions here, deku… I think the Arduino IDE inserts most of that stuff for me when I select the right board and so on? The stuff regarding pins is why I wanted the sample code. That takes care of the serial pins, but the pwm pins could also be different, I can check I guess but it takes quite a bit of doing to peer through the documents and ascertain what the pins are actually called in the arduino code etc. Sample code that already has that stuff in it is the best thing.

Is there some known working sample code like there is for the mosquito as shown in the guide? Or can I just use that code for the mosquito in the guide?

It does not. In fact no IDE does this.

Could you please explain what stuff about pins you need?

No, the Mosquito uses different pins.

Cheers,
Vaentine

The PWM pins are on the board silkscreen so you don’t even have to check the schematic :slight_smile: BLDCDriver6PWM driver = BLDCDriver6PWM(PA8, PA7, PB3, PB0, PB6, PB1);

For I2C, call Wire.setSDA(PB7) and Wire.setSCL(PB8) before Wire.begin()

I haven’t used the Arduino SPI library so you’ll have to look up how to configure it, but the pins are
SS PA4
SCK PA5
MISO PB4
MOSI PB5

I believe I printed the open loop code on the back silk screen of the 4-layer lepton, if it’s of any help.

I need a single .ino file or cut and pastable code to upload to the Lepton that lets me do a basic test, closed loop torque mode is fine, skips the complications with the PID tuning etc. in velocity mode. Similar to the stuff in the mosquito guide. There, there is an actual piece of code that contains all the details, all wrapped up and ready to use.

Similar to the examples available for the uno and shield combo.

I think if I try to piece things together myself something is bound to slip through the cracks and I’ll be going around in circles. As you note, nothing is very clear.

I am willing to do the work to roll things myself, but sooner or later we have to have this stuff sorted, I think.

Valentine, surely you used some code to test the lepton in your testing? Can you plonk that in a google drive folder or something?

Sorry if it seems like I am repeating myself, but this seems to be common in open source projects. The people on the inside seem to be under the impression things are easy to use, but someone who isn’t a software dev and steeped in this particular project finds that the info they need to go ahead and use it as part of a foundation to stand upon is very, very scattered and diluted. It takes a long time to come up to speed, and there is a lot else to do. I believe it’s important to condense things every once in a while, make it highly applicable to exact manifestations of hardware etc, accessible and put it all in one place.

As I said, surely you have some code you used last time?

I’m very busy now will try to get you the code later today.

no rush! I’m planning ahead myself, the leptons have not arrived yet :). Gotta do my part to try to plan ahead. I greatly appreciate the help. If this works out it will be really helpful, my alternative was to try the allegro chip. I can return the texas instruments eval board and donate the money to the simplefoc project, and in the future if I make some money off this stuff send a royalty per unit made perhaps. Whatever I saved as compared with going with some other driver, probably a couple bucks.

#include <SimpleFOC.h>
BLDCMotor motor = BLDCMotor(1);
BLDCDriver6PWM driver = 
BLDCDriver6PWM(PA8, PA7, PB3, 
               PB0, PB6, PB1);
float target_velocity = 1.0;
float target_voltage = 2.0;
void setup() {
  driver.voltage_power_supply = 12;
  driver.pwm_frequency = 15000;
  driver.init();
  motor.linkDriver(&driver);
  motor.voltage_limit = 12;   // [V]
  motor.velocity_limit = 100; // [rad/s]
  motor.controller = 
  MotionControlType::velocity_openloop;
  motor.init();
  _delay(1000); }
void loop() {
  motor.voltage_limit = target_voltage;
  motor.move(target_velocity); }

You can start from whichever of the standard SimpleFOC examples best fits your setup. Paste the clock code somewhere in the file, and pin configurations in setup(), and you’ll be closer to complete than if I cleaned up my cluttered test code (which was started from the hall sensor example). The remaining details will depend on your particular hardware (power supply voltage, angle sensor, and PID tuning).

ok I realized in the nick of time this is likely to fry my motor. The power supply is 24 volts, which doesn’t seem to have been input anywhere, and this is open loop at 12 volts. I don’t think the motor will be able to handle that at least not for long, and it’s inside the fan so I cannot feel it.

An indicator LED on the board would be a good idea so that functionality and basic testing of the ability to program it and get it to run a program can be done.

The st-link does not have a ttl to USB converter. Only certain st-link modules have that. I am trying to use an arduino mega 2560 as a serial pass through instead.

Thanks Deku for the info on the serial pin config, I will try it now. I had been trying to get info out of the serial port but didn’t know that part wasn’t handled by arduino.

I have to go to bed soon, I haven’t been able to get anything working, except that when I click upload in arduino it does say it uploaded the file to the stm32 successfully. However there is no way I have figured out yet to ascertain if it is actually executing the code or not.

A good first start would be to get serial communication with the stm32 working. It’s not safe to do any kind of thing with the motor until I know it’s executing code properly and can do some tests. Again, an indicator led would be good. Right now there could be some kind of problem with my efforts to monitor the serial port or something I can’t know. There could be a problem with the connector or something, the clock may not be set right, which could explain why serial communication isn’t working, as I suppose the baud rate would be wrong. I can’t know, there is no diagnostic information or anything. I can try to figure out some way to toggle a pin or something tomorrow perhaps. or maybe I will take a risk and run some kind of code, maybe lower the voltage on that open loop example, or try to run a closed loop torque mode example later.

However, I need to ascertain the clock rate has been set properly, for which I need serial communication, maybe I should buy a TTL to usb converter. I think I will if I can’t get it going tomorrow, I expected to need one but I thought the stlink had one.

Another problem that arose is that it’s not clear what the minumum and maximum voltages of the lepton are. I see it has a 12 volt step down regulator, it’s not clear what that is for, but I assumed there could be a problem if the input voltage is less than 12 volts because it won’t be able to give it’s 12 volts output. Or if the input is too close to 12 volts. There is passing mention of 30 volts in the documentation, but it’s not clear if that is talking about some subcomponent or the actual input of the board.

This is the code I’m trying to get working:

#include <SimpleFOC.h>
BLDCMotor motor = BLDCMotor(1);
BLDCDriver6PWM driver =
BLDCDriver6PWM(PA8, PA7, PB3,
PB0, PB6, PB1);
float target_velocity = 1.0;
float target_voltage = 2.0;

void setup() {
Serial.setRx(PA15);
Serial.setTx(PA2);
Serial.begin(9600);
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

/** Initializes the RCC Oscillators according to the specified parameters

  • in the RCC_OscInitTypeDef structure.
    */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
    RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
    RCC_OscInitStruct.PLL.PLLN = 8;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
    RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
    Error_Handler();
    }

/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}

}

void loop() {
Serial.println(F_CPU);
delay(1);
}

BTW, I noticed in the mosquito documentation that it says not to connect the 3.3 volts line from the microcontroller to the 3.3volt line on the stlink’s SWD port, any ideas why that is? The way they do it with the blue pill seems to be that they connect those two pins together, so the 3.3 volts can supply the microcontroller with power. I did not have the board you used with the mosquito, so I can’t do it that way. I tried the bog standard approach, and it says it programmed the stm32. Maybe it didn’t actually program shit.

12v to 28v, it’s written on the silk screen between the input power leads

You can go down to 10V, but it’s not recommended.

The aux power already has 3v and if you connect to the debugger 3v you get a problem. If you only program the board without powering it up then you must connect the 3v power to the debugger to power the MCU. However double-powering is not allowed unless you want to see smoke.

Cheers,
Valentine

I actually did double power it accidentally and the stlink started blinking but it still seems to work ok.

Ok, double powering is a good explanation, thought.

I checked with the oscilloscope, the microcontroller is not printing anything out of the uart. So it’s not my arduino serial pass through that’s the problem. Any ideas on why my code doesn’t work/how to get it working? I definitely need to be able to communicate with the chip over serial to do anything.

I can’t see between the power leads after putting the 1000 uf capacitor on, but good that it’s on there.

I increased the delay to 1000, I don’t know why you use _delay most of the time. I forgot that delay is in milliseconds in arduino. In micropython it’s sleep() and it’s in seconds (but you can have floating point numbers in there)

also I don’t know why I didn’t just use the mosquito, something about 3 pin pwm instead of 6 maybe.

_delay doesn’t work, btw, it says it’s not defined and gives a compilation error

nope, even this doesn’t work:

void setup() {

Serial.setRx(PA15);

Serial.setTx(PA2);

Serial.begin(38400);

}

void loop() {

Serial.println(“test”);

delay(1000);

}

I think maybe the pins Deku mentioned are wrong?hm no from the schematic looks right. Probably no problem with the board. Says it was programmed.

reading stuff like this: https://github.com/stm32duino/Arduino_Core_STM32/issues/1637 Are you sure I don’t have to do anything to get the system to execute the code or anything? It says something about start command completed successfully and sounds like it may have started executing the program after being programmed. Not clear. Not clear if it does so automatically upon reboot either. I was assuming it works like an arduino, after being programmed with the arduino ide, maybe not. Maybe there is a bootloader built into the arduino ide I can use. Maybe that’s not useful or not applicable or not needed… much uncertainty. This is the sort of thing I thought would happen, this is why I started well ahead of time and asked for exact details, which I appreciate the details thus far, but it appears that something is missing yet.

That should work. The first 4 lines of my setup() are

  Serial.setRx(UART2_RX);
  Serial.setTx(UART2_TX);
  Serial.begin(115200);
  Serial.println(F_CPU);

And it does print 64000000, so that should work as the entire program. Make sure you have the same baud rate selected in arduino serial monitor as you use in the program.

The clock code does not go in setup. Copy/paste the whole function SystemClock_Config from my earlier post. The function only has to exist, and it will be called by the arduino/stm32 library sometime earlier in the bootup process.

To check if it’s running at all, you can use any of the connector pins as an indicator. For example toggle PB7 off and on every second or whatever, and touch a voltmeter to GND and the SDA pin on the I2C connector to watch it change (obviously don’t call Wire.begin when doing this test)

I agree with you Valentine.

The SWD interface 3.3V is an output, not an input.
The STLink expects to receive the MCU’s voltage on its 3.3V pin. that’s why it’s called Vtarget… it does not supply the MCU with power on this line. It’s only dubious clone STlinks that supply power on this pin.

I recommend to get a proper STLink V3 Mini, they aren’t expensive. This will also support Serial TTL 2 USB conversion.