Programming the Lepton from start to finish

I sent you a DM! Don’t feel you have to do this, but if it would help you I am more than happy to spend some time on it. I think others may also benefit, as the Lepton is a very nice little driver…

I would be happy to, the progress may come too late for me, it’s not clear, but I am a believer and it’s my way of paying it forward

edit: even this doesnt work. using hte build flag appears to be counter to the way one is supposed to use arduino, as Runger said they don’t make it easy. Do I need to do that?

#include <HardwareSerial.h>

HardwareSerial mySerial1(PA15,PA2);
void setup() {

mySerial1.begin(38400);
pinMode(PB7, OUTPUT);
}

void loop() {
// put your main code here, to run repeatedly:
mySerial1.println(“test”);
delay(1000);
digitalWrite(PB7, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(PB7, LOW);
}

Yes, there are some environmental issues lurking here, as building the code is literally only a few clicks. I feel bad but this is nearly impossible for me to debug. There was another person, he ordered the Lepton and had absolutely no problem running Serial, sensors, etc. I cannot quote/disclose the name, due to privacy reasons, but he did manage everything on his own, so I’m quite certain it’s very straightforward. In addition, I’m using the exact same MCU for the mosquito board, and it works there, too.

@runger, that’s really awesome. I’m buried with multiple other projects, and now only type a few lines here, no time to even design cool new stuff. I always subscribed to the idea that I only design the hardware and others figure it out, I guess, later when I get the time, I have to change my approach and make it a lot more user-end friendly. At the end, it’s just about programming a generic g031 mcu. I guess the learning curve may be steeper than I estimated for new people coming into the field and I took too many things for granted.

Cheers,
Valentine

PS here is another full-stack design (the whole servo mechanics are also my design) I did for a dual-motor ultra-high torque robotic servo based on the Lepton (only re-arranged the components to fit the servo inside) and it works, so there are so many things you could do with that design. I’m quite certain it works, so @Anthony_Douglas don’t give up, it will eventually come together.

1 Like

I deleted the library and reinstalled… same deal. Well the SPI port works ok, just not the UART. Perhaps I can debug and get things approximately working using software serial and then take that out later. I could use pulsin() and the pwm peripheral on the pico to control the board perhaps. I can only access like 4 pins, it’s so tiny I have to use whatever is broken out to the picoblade connectors.

Valentine: how did you get the serial port working, exactly? The build_opt thing doesn’t work in arduino, so it must have been some other way? Were you using STMcubeIDE? As you say it worked for you, an advisable approach is to use exactly the same approach as you and then diversify or build upon that. That’s why I asked for an exact .ino file a couple days ago, the exact stuff that is known to work. Although agreed it’s not exactly the same stuff i.e. the voltage was not suitable for my motor. But we need a standard test file. The commander thing that is available for the uno is good.

c:/users/anthony/appdata/local/arduino15/packages/stmicroelectronics/tools/xpack-arm-none-eabi-gcc/10.3.1-2.3/bin/…/lib/gcc/arm-none-eabi/10.3.1/…/…/…/…/arm-none-eabi/bin/ld.exe: C:\Users\anthony\AppData\Local\Temp\arduino-sketch-E6525D67E19444744D397AC9C0CF5638/sketch_feb14combiningoldarduinowith new stm32stuff.ino.elf section .text' will not fit in region FLASH’
c:/users/anthony/appdata/local/arduino15/packages/stmicroelectronics/tools/xpack-arm-none-eabi-gcc/10.3.1-2.3/bin/…/lib/gcc/arm-none-eabi/10.3.1/…/…/…/…/arm-none-eabi/bin/ld.exe: region `FLASH’ overflowed by 13180 bytes
collect2.exe: error: ld returned 1 exit status

exit status 1

Compilation error: exit status 1

Sounds like there isn’t enough flash on this microcontroller??

Code I was trying to compile:>

#include “SoftwareSerial.h”
#include <SimpleFOCDrivers.h>
#include “encoders/sc60228/MagneticSensorSC60228.h”
#include <SimpleFOC.h>
// SENSOR SPI SC60228
// SPI2 PINS
#define CSN2 PA4
#define CLK2 PA5
#define MISO2 PB4
#define MOSI2 PB5

#define SS_USB_RX PA15
#define SS_USB_TX PA2
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();
}
}
// BAUD RATE MUST BE BETWEEN 9600…38400
// ANY OTHER BAUD RATE WILL CHOKE

SoftwareSerial SoftSerialUSB(SS_USB_RX, SS_USB_TX);
MagneticSensorSC60228 sensor(CSN2);
BLDCMotor motor = BLDCMotor(7);
BLDCDriver6PWM driver = BLDCDriver6PWM(PA8, PA7, PB3, PB0, PB6, PB1);
SPIClass SPISensor(MOSI2, MISO2, CLK2);
Commander command = Commander(SoftSerialUSB);
void onMotor(char* cmd){ command.motor(&motor, cmd); }

void setup()
{
//set pins for Software Serial communication
SoftSerialUSB.begin(38400);
pinMode(SS_USB_RX, INPUT);
pinMode(SS_USB_TX, OUTPUT);
SoftSerialUSB.println(“got this far, testing serial port”);
SoftSerialUSB.println(F_CPU);
sensor.init(&SPISensor);
delay(1000);
motor.linkSensor(&sensor);
driver.voltage_power_supply = 24;
driver.init();
motor.linkDriver(&driver);
motor.controller = MotionControlType::torque;
motor.voltage_limit = 12;
motor.useMonitoring(SoftSerialUSB);
// initialise motor
motor.init();
// align encoder and start FOC
motor.initFOC();
// set the inital target value
motor.target = 2;
// define the motor id
command.add(‘A’, onMotor, “motor”);
SoftSerialUSB.println(F(“Motor commands sketch | Initial motion control > torque/voltage : target 2V.”));
delay(1000);

}

void loop()
{
motor.loopFOC();

// iterative function setting the outter loop target
// velocity, position or voltage
// if tatget not set in parameter uses motor.target variable
motor.move();

// user communication
command.run();
//SoftSerialUSB.println(sensor.getAngle());
//sensorSC60228.update();
}

It’s a combo of what worked on the arduino uno with the adaptations for the STM32 of concern and this exact encoder.

update: beware when cutting and pasting code, sometimes quotes get replaced with characters that cause problems with the compiler. There should be a thing to enclose code. I don’t know how Deku did it, there is nothing on the toolbar when editing/making a post.

Update: was not able to get the build option stuff working, despite finding some instructions on how to modify the boards.txt file in order to add build options to the compiler. I tried adding the one Runger mentioned but it didn’t seem to make any differnce, tried a couple more things, didn’t work, put it back.

this code does something, it starts the motor initialization and runs the pole pair check ,but the results are borked. At least it doesn’t run out of flash memory.

recalling what was said about Valentine encountering problemw with this encoder driver not working yet with other modules of the system, I plan to try switching to an as5600 encoder and seeing if I can get that to do something useful . That’s what worked with the arduino uno.

#include "SoftwareSerial.h"
#include <SimpleFOCDrivers.h>
#include "encoders/sc60228/MagneticSensorSC60228.h"
#include <SimpleFOC.h>
// SENSOR SPI SC60228
// SPI2 PINS
#define CSN2 PA4
#define CLK2 PA5
#define MISO2 PB4
#define MOSI2 PB5

#define SS_USB_RX  PA15
#define SS_USB_TX  PA2
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();
  }
}
// BAUD RATE MUST BE BETWEEN 9600..38400
// ANY OTHER BAUD RATE WILL CHOKE

SoftwareSerial SoftSerialUSB(SS_USB_RX, SS_USB_TX);
MagneticSensorSC60228 sensor(CSN2);
BLDCMotor motor = BLDCMotor(7);
BLDCDriver6PWM driver = BLDCDriver6PWM(PA8, PA7, PB3, PB0, PB6, PB1);
SPIClass SPISensor(MOSI2, MISO2, CLK2);

void setup()
{
  //set pins for Software Serial communication
  SoftSerialUSB.begin(38400);
  pinMode(SS_USB_RX, INPUT);
  pinMode(SS_USB_TX, OUTPUT);
  SoftSerialUSB.println("got this far, testing serial port");
  SoftSerialUSB.println(F_CPU);
sensor.init(&SPISensor);
  delay(1000);
motor.linkSensor(&sensor);
 driver.voltage_power_supply = 24;
  driver.init();  
   motor.linkDriver(&driver);
    motor.controller = MotionControlType::torque;
     motor.voltage_limit = 12;
  motor.useMonitoring(SoftSerialUSB);
    // initialise motor
  motor.init();
  // align encoder and start FOC
  motor.initFOC();
    // set the inital target value
  motor.target = 2;
   // define the motor id


 delay(1000);

}

void loop()
{
  motor.loopFOC();

  // iterative function setting the outter loop target
  // velocity, position or voltage
  // if tatget not set in parameter uses motor.target variable
  motor.move();
  SoftSerialUSB.println("still running");
delay(100);
  //SoftSerialUSB.println(sensor.getAngle());
  //sensorSC60228.update();
}

serial output from the code above was:
64000000

MOT: Monitor enabled!

MOT: Init

MOT: Enable driver.

MOT: Align sensor.

MOT: sensor_direction==CW

MOT: PP check: fail - estimated pp: 4095.99

MOT: Zero elec. angle: 2.33

MOT: No current sense.

MOT: Ready.

still running

If I get the time I can try, but it may take a day or two or more. I’m away on a trip and will be back Friday.

It’s the 6th icon from the left above the text area. Looks like </> and the tooltip says “Preformatted text (Ctrl+E)”.

Lepton does not have enough flash for Commander. I wrote a quick and dirty serial communication interface via the Arduino IDE serial monitor, where you type single letter commands to read and write variables for tuning and debugging. Lowercase to output the current value, uppercase followed by a number to set the value and then print it for confirmation. Feel free to change the letters to whatever you prefer, or just use it as inspiration to make something better.

void SerialComm()
{
  switch(Serial.read())
  {
  case '?':
    Serial.print("sensor_direction ");
    Serial.print(motor.sensor_direction);
    Serial.print(", zero_electric_angle ");
    Serial.println(motor.zero_electric_angle);
    break;
  case 's': Serial.print("shaft_velocity "); Serial.println(motor.shaft_velocity); break;
  case 'a':
    Serial.print("shaft_angle ");
    Serial.print(motor.shaft_angle);
    Serial.print(", electric_rotations ");
    Serial.print(sensor.electric_rotations);
    Serial.print(", electric_sector ");
    Serial.println(sensor.electric_sector);
    break;
  case 'K': motor.KV_rating = Serial.parseFloat(); Serial.print("Set ");
  case 'k': Serial.print("kv "); Serial.println(motor.KV_rating); break;
  case 'R': motor.phase_resistance = Serial.parseFloat(); Serial.print("Set ");
  case 'r': Serial.print("phase_resistance "); Serial.println(motor.phase_resistance); break;
  case 'T': target_range = Serial.parseFloat(); Serial.print("Set ");
  case 't': Serial.print("target_range "); Serial.println(target_range); break;

  case 'V': motor.voltage_limit = Serial.parseFloat(); Serial.print("Set ");
  case 'v': Serial.print("motor.voltage_limit "); Serial.println(motor.voltage_limit); break;
  case 'C': motor.current_limit = motor.PID_velocity.limit = Serial.parseFloat(); Serial.print("Set ");
  case 'c': Serial.print("motor.current_limit "); Serial.println(motor.current_limit); break;

  case 'O': motor.PID_velocity.output_ramp = Serial.parseFloat(); Serial.print("Set ");
  case 'o': Serial.print("motor.PID_velocity.output_ramp "); Serial.println(motor.PID_velocity.output_ramp); break;
  case 'F': motor.LPF_velocity.Tf = Serial.parseFloat(); Serial.print("Set ");
  case 'f': Serial.print("motor.LPF_velocity.Tf "); Serial.println(motor.LPF_velocity.Tf); break;
  case 'P': motor.PID_velocity.P = Serial.parseFloat(); Serial.print("Set ");
  case 'p': Serial.print("motor.PID_velocity.P "); Serial.println(motor.PID_velocity.P); break;
  case 'I': motor.PID_velocity.I = Serial.parseFloat(); Serial.print("Set ");
  case 'i': Serial.print("motor.PID_velocity.I "); Serial.println(motor.PID_velocity.I); break;
  case 'D': motor.PID_velocity.D = Serial.parseFloat(); Serial.print("Set ");
  case 'd': Serial.print("motor.PID_velocity.D "); Serial.println(motor.PID_velocity.D); break;

  case 'W': motor.P_angle.P = Serial.parseFloat(); Serial.print("Set ");
  case 'w': Serial.print("motor.P_angle.P "); Serial.println(motor.P_angle.P); break;
  }
}
1 Like

Thanks man, I will check it out. Even when I remove the commander entirely, it still often runs out of flash. It’s clear this MCU is way too small, even the most elementary sketches are too big. This for instance is 688 bytes too big according to the compiler:

#include <SimpleFOC.h>
#include "SoftwareSerial.h"
#include <Wire.h>
#define SS_USB_RX  PA15
#define SS_USB_TX  PA2
// magnetic sensor instance
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();
  }
}

MagneticSensorI2C sensor = MagneticSensorI2C(0x36, 12, 0X0C, 4);
// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(7);
BLDCDriver6PWM driver = BLDCDriver6PWM(PA8, PA7, PB3, PB0, PB6, PB1);
SoftwareSerial SoftSerialUSB(SS_USB_RX, SS_USB_TX);
// commander interface
void setup() {
Wire.setSDA(PB7); 
Wire.setSCL(PB8);
Wire.begin();
  
  SoftSerialUSB.begin(38400);
  SoftSerialUSB.println("serial test");
  // initialise magnetic sensor hardware
  sensor.init();
  // link the motor to the sensor
  motor.linkSensor(&sensor);

  // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 24;
  driver.init();
  // link driver
  motor.linkDriver(&driver);

  // set control loop type to be used
  motor.controller = MotionControlType::torque;

  // contoller configuration based on the control type 
  motor.PID_velocity.P = 0.2;
  motor.PID_velocity.I = 20;
  motor.PID_velocity.D = 0;
  // default voltage_power_supply
  motor.voltage_limit = 12;

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

  // angle loop controller
  motor.P_angle.P = 20;
  // angle loop velocity limit
  motor.velocity_limit = 50;


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

  // initialise motor
  motor.init();
  // align encoder and start FOC
  motor.initFOC();

  // set the inital target value
  motor.target = 3;

  // Run user commands to configure and the motor (find the full command list in docs.simplefoc.com)
 SoftSerialUSB.println("got this far");
  
  _delay(1000);
}


void loop() {

  motor.loopFOC();

  // iterative function setting the outter loop target
  // velocity, position or voltage
  // if tatget not set in parameter uses motor.target variable
  motor.move();

}

I’m going to have to remove the softwareserial stuff, which means I’m totally flying blind. I’m using the I2C now so I don’t even have that pin, maybe I can use the old pins from the SPI port.

It does not need the pid loop tuning stuff but I left it in as I wanted to change the bare minimum to adapt it from the uno, which it worked on, to the stm32

Make sure you have optimization set to “Smallest (-Os) with LTO”. That should give you around 10kb to work in.

How do I set the optimization in arduino?

It’s in the Tools menu.

1 Like

lol, I assumed I would have to modify some buried file, which is different in the latest arduino IDE and no one knows where it is…

Ok, with Deku’s advice it compiles and uploads, but it says

MOT: Monitor enabled!

MOT: Init

MOT: Enable driver.

MOT: Align sensor.

MOT: Failed to notice movement

MOT: Init FOC failed.

got this far

It doesn’t actually do any attempt to move the motor properly. I think it might be trying to move it extremely slowly as the current changes slowly and sometimes it moves by one pole. I will keep trying for a bit, I think there was one more sample of code that might have worked.

update:
ok one of the motor wire connectors was subtly borked, I only just managed to figure it out. However it still gives the same output.

the motor now moves, but only very very slowly in very small maybe 1/50th of a rotation jumps after it says align sensor. It takes several minutes to move a fraction of a rotation, and then back again. I don’t remember it being that slow with the arduino. It’s not clear if the encoder is working, but I think it’s reading the angle ok, I have to go to bed now but can check that directly tomorrow.

And so ends another 10 hour work day…

First try open loop velocity mode to make sure all the motor business is working. Then voltage-torque mode to make sure the encoder is working and tune the voltage-based current limiting. Then velocity mode to tune velocity PID. And finally angle mode, which in my case required a few more tweaks to velocity PID in addition to tuning angle P.

fortunately I only need torque mode, I don’t need velocity or angle mode Will try open loop now, then.

ok open loop works, for anyone else has the same problem:
‘’’

// Open loop motor control example
#include <SimpleFOC.h>
#include "SoftwareSerial.h"
#define SS_USB_RX  PA15
#define SS_USB_TX  PA2
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();
  }
}
// BLDC motor & driver instance
// BLDCMotor motor = BLDCMotor(pole pair number);
BLDCMotor motor = BLDCMotor(7);
// BLDCDriver3PWM driver = BLDCDriver3PWM(pwmA, pwmB, pwmC, Enable(optional));
BLDCDriver6PWM driver = BLDCDriver6PWM(PA8, PA7, PB3, PB0, PB6, PB1);
SoftwareSerial SoftSerialUSB(SS_USB_RX, SS_USB_TX);
// Stepper motor & driver instance
//StepperMotor motor = StepperMotor(50);
//StepperDriver4PWM driver = StepperDriver4PWM(9, 5, 10, 6,  8);


//target variable
float target_velocity = 0;


void setup() {

  // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 24;
  // limit the maximal dc voltage the driver can set
  // as a protection measure for the low-resistance motors
  // this value is fixed on startup
  driver.voltage_limit = 6;
  driver.init();
  // link the motor and the driver
  motor.linkDriver(&driver);

  // limiting motor movements
  // limit the voltage to be set to the motor
  // start very low for high resistance motors
  // currnet = resistance*voltage, so try to be well under 1Amp
  motor.voltage_limit = 3;   // [V]
 
  // open loop control config
  motor.controller = MotionControlType::velocity_openloop;

  // init motor hardware
  motor.init();


  SoftSerialUSB.begin(38400);
  SoftSerialUSB.println("Motor ready!");
  SoftSerialUSB.println("Setting target velocity [rad/s]");
  target_velocity = 2;
  _delay(1000);
}

void loop() {

  // open loop velocity movement
  // using motor.voltage_limit and motor.velocity_limit
  motor.move(target_velocity);
}

‘’’

compiling is still extremely slow, and given the commander doesn’t work and serial hardly works, that means frequently recompiling… I disabled the antivirus and tried to read up on it, it appears to be a flaw with the arduino ide somehow according to other people

update: ok same behaviour as the torque control mode last night. It moves extremely slowly for about 5 minutes, one way and then back the other. Then it says it failed to notice movement.

/**
 * 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 hte current. 
 * 
 * This makes the BLDC motor effectively a DC motor, and you can use it in a same way.
 */
#include <SimpleFOC.h>
#include "SoftwareSerial.h"
#define SS_USB_RX  PA15
#define SS_USB_TX  PA2
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();
  }
}
// magnetic sensor instance - I2C
 MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);

// BLDC motor & driver instance
// BLDCMotor motor = BLDCMotor(pole pair number);
BLDCMotor motor = BLDCMotor(7);
// BLDCDriver3PWM driver = BLDCDriver3PWM(pwmA, pwmB, pwmC, Enable(optional));
BLDCDriver6PWM driver = BLDCDriver6PWM(PA8, PA7, PB3, PB0, PB6, PB1);
SoftwareSerial SoftSerialUSB(SS_USB_RX, SS_USB_TX);

// voltage set point variable
float target_voltage = 2;

void setup() {

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

  // power supply voltage
  driver.voltage_power_supply = 24;
  driver.init();
  motor.linkDriver(&driver);

  // aligning voltage 
  motor.voltage_sensor_align = 5;
  // choose FOC modulation (optional)
  motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
  // set motion control loop to be used
  motor.controller = MotionControlType::torque;

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

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


  Serial.println(F("Motor ready."));
  Serial.println(F("Setting the target voltage"));
  target_voltage = 4;
  _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);

}

hm, searching the forum for this error state, I found this guy PlatformIO B-G431-ESC1 Code not working - #12 by Kacko
but he makes no mention of the align being extremely slow. It seems like that might be an important clue.

I hypothesized maybe the motor was going the wrong way and the system wasn’t advanced enough to notice and compensate, but I reversed motor rotation direction by swapping two of the wires and behavior is the same, except that it turns the opposite direction now.

I’m pretty baffled. Will keep reading the forum and the docs.

update: tried removing all the software serial stuff in the off chance the interrupts might be interfering or something. Same behaviour.

Update: ok so trying to get the sensor working, should this code work to tell me the angle of the sensor?

#include "SoftwareSerial.h"
#include <SimpleFOC.h>


#define SS_USB_RX  PA15
#define SS_USB_TX  PA2
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();
  }
}
// BAUD RATE MUST BE BETWEEN 9600..38400
// ANY OTHER BAUD RATE WILL CHOKE

SoftwareSerial SoftSerialUSB(SS_USB_RX, SS_USB_TX);
 MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);


void setup()
{
  //set pins for Software Serial communication
  SoftSerialUSB.begin(38400);
  pinMode(SS_USB_RX, INPUT);
  pinMode(SS_USB_TX, OUTPUT);

sensor.init();
  delay(1000);
}

void loop()
{
  SoftSerialUSB.println("TEST SSERIAL_USB");
  SoftSerialUSB.println(F_CPU);
  SoftSerialUSB.println(sensor.getAngle());
  
  sensor.update();
  delay(100);
}

The output on the serial monitor is:


TEST SSERIAL_USB
64000000
12.56

But it just keeps saying 12.56 no matter what angle the motor is at. I tried holding a magnet close to the sensor and rotating it. This sensor worked with the arduino. Should the above code work or is it borked?

The connections for theI2C interface appear to be sound.

ok, I had not set up the I2C interface right as Deku had told me, I thought maybe it was not needed, however it seems to work if I do this:

#include <SimpleFOC.h>
#include <Wire.h>
#include "SoftwareSerial.h"
#define SS_USB_RX  PA15
#define SS_USB_TX  PA2
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();
  }
}
// MagneticSensorI2C(uint8_t _chip_address, float _cpr, uint8_t _angle_register_msb)
//  chip_address  I2C chip address
//  bit_resolution  resolution of the sensor
//  angle_register_msb  angle read register msb
//  bits_used_msb  number of used bits in msb register
// 
// make sure to read the chip address and the chip angle register msb value from the datasheet
// also in most cases you will need external pull-ups on SDA and SCL lines!!!!!
//
// For AS5058B
// MagneticSensorI2C sensor = MagneticSensorI2C(0x40, 14, 0xFE, 8);

// Example of AS5600 configuration 
MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);
SoftwareSerial SoftSerialUSB(SS_USB_RX, SS_USB_TX);

void setup() {
Wire.setSDA(PB7); 
Wire.setSCL(PB8);
Wire.begin();
  pinMode(SS_USB_RX, INPUT);
  pinMode(SS_USB_TX, OUTPUT);
  // monitoring port
  SoftSerialUSB.begin(38400);

  // configure i2C
  Wire.setClock(400000);
  // initialise magnetic sensor hardware
  sensor.init();

  SoftSerialUSB.println("Sensor ready");
  _delay(1000);
}

void loop() {
  // iterative function updating the sensor internal variables
  // it is usually called in motor.loopFOC()
  // this function reads the sensor hardware and 
  // has to be called before getAngle nad getVelocity
  sensor.update();
    SoftSerialUSB.println("TEST SSERIAL_USB");
  SoftSerialUSB.println(F_CPU);
  // display the angle and the angular velocity to the terminal
  SoftSerialUSB.print(sensor.getAngle());
 SoftSerialUSB.print("\t");
  SoftSerialUSB.println(sensor.getVelocity());
}

I spliced the two peices of code together, the working encoder code and the voltage torque control example that sets the clock, prints to serial, and very slowly turns the motor to initialize. Doesn’t work… I had high hopes for this one, but it’s the same behaviour and output as before. I’m goig to the post office and to get something to eat, when I get back I will try printing the ecoder values in a loop after the initialization to see if the encoder stuff still works after being spliced into it’s new home.

This is what I tried:

 * 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 hte current. 
 * 
 * This makes the BLDC motor effectively a DC motor, and you can use it in a same way.
 */
#include <SimpleFOC.h>
#include "SoftwareSerial.h"
#include <Wire.h>
#define SS_USB_RX  PA15
#define SS_USB_TX  PA2
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();
  }
}
// magnetic sensor instance - I2C
 MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);

// BLDC motor & driver instance
// BLDCMotor motor = BLDCMotor(pole pair number);
BLDCMotor motor = BLDCMotor(7);
// BLDCDriver3PWM driver = BLDCDriver3PWM(pwmA, pwmB, pwmC, Enable(optional));
BLDCDriver6PWM driver = BLDCDriver6PWM(PA8, PA7, PB3, PB0, PB6, PB1);
SoftwareSerial SoftSerialUSB(SS_USB_RX, SS_USB_TX);

// voltage set point variable
float target_voltage = 2;

void setup() {
Wire.setSDA(PB7); 
Wire.setSCL(PB8);
Wire.begin();
 Wire.setClock(400000);
  pinMode(SS_USB_RX, INPUT);
  pinMode(SS_USB_TX, OUTPUT);
  // initialise magnetic sensor hardware
  sensor.init();
  // link the motor to the sensor
  motor.linkSensor(&sensor);

  // power supply voltage
  driver.voltage_power_supply = 24;
  driver.init();
  motor.linkDriver(&driver);

  // aligning voltage 
  motor.voltage_sensor_align = 5;
  // choose FOC modulation (optional)
  motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
  // set motion control loop to be used
  motor.controller = MotionControlType::torque;

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

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


  SoftSerialUSB.println(F("Motor ready."));
 SoftSerialUSB.println(F("Setting the target voltage"));
  target_voltage = 4;
  _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);

}

update: yeah, when I add SoftSerialUSB.println(sensor.getAngle()); to the loop, it prints the angles fine. The angle seems to be in radians.

So the encoder works fine, the motor turns in open loop, but even using the most elementary example code simplefoc isn’t able to put two and two together.

It seems like there is an issue in the code deeper than I can deal with :frowning:

You can increase motor.velocity_index_search to make it turn faster for calibration. It’s in radians per second and defaults to 1. I can’t see any actual problems though. If you’re getting good angle readings now, it should spin. What exactly is the motor behavior? Holding strongly in one position, vibrating, no force at all, or something else?

The motor behavior is that it goes very very slowly one way, then reverses direction and goes about the same distance, then it gives the error and goes unpowered. It takes like 4 minutes to complete. Definitely way slower than 1 radians per second. Open loop went at about the right speed, I think. I set it to 3, so if in radians per second that would be roughly one rotation every two seconds, which it did.

I’m thinking about swapping the uno back in and trying to see if I can get that working, then swapping back and forth to see if I can zero in on whatever is different. But I sort of already did that, the code that worked with the uno I adapted with minimal change, I had to get rid of the commander but that shouldn’t matter to initialization. I noticed that with the uno and the commander on it checked the direction of rotation with the angle sensor, but without the commander it gives a different output. Maybe the sensor didn’t initialize properly, the angle can be read and printed but the connection between the two software modules or something… maybe I haz no clue

Oh, that is messed up then. I would suggest setting your sights on BLDCMotor::alignSensor. It doesn’t look like absoluteZeroSearch on line 166 will be called when using MagneticSensorI2C, so the slow movement must be during the for loops on lines 175-190. That leaves the _delay(2); calls or the I2C communication during the sensor->update as the primary suspects. Comment out one or the other and see which results in fast spinning. It is technically possible to mess up the delay tick rate with the clock config, but the function you’re using was generated by STM32CubeIDE and works on mine so that shouldn’t be it.

Side note, looking at the code there, velocity_index_search won’t affect the calibration speed after all. It’s only used in BLDCMotor::absoluteZeroSearch.

Ok, will investigate tomorrow, thanks for the advice. As you can tell I am quite out of my depth messing with C. I’m anxious to ascertain if this can give the rpm and what kind of noise it results in. I’ve been very foolish to pour so much time into my erv project and have too many chips in this basket of being able to roll my own quiet fan.

update:
I got inspired and tried uncommenting those two lines. When I uncomment the the sensor update line only and not the delay, it does go at a more reasonable speed for about 1/7th of a rotation, but then starts turning super slow again, I didn’t let it finish.

Sounds like it’s the i2c communication, then, but when I did the sensor.update() and printed the sensor readings it seemed as though it worked fine. Something to do with the connections… or maybe it actually updates extremely slowly and I don’t notice when I just have a loop that checks it and prints to serial… the motor initialization takes different amounts of time depending on if I am powered off the 24 volt supply or allow things to work off of the stlink adapter, and sometimes when running on the stlink adapter it says pole pair check fail etc but doesn’t say no movement detected. If I turn the motor by hand while running off the stlink adapter, it says

OT: Init

MOT: Enable driver.

MOT: Align sensor.

MOT: sensor_direction==CW

MOT: PP check: fail - estimated pp: 5.36

MOT: Zero elec. angle: 4.80

MOT: No current sense.

MOT: Ready.

Motor ready.

Setting the target voltage

Obviously it’s confused but it finishes the proceedure quickly and moves on.

Something that makes the updates extremely slow only when running off the external power… or when the motor is turning only in small increments. No, because when it’s not turning at all it still gives up and concludes there is no motion in a couple of seconds. This super slow updating only happens when externally powered, I think. And yet I can print the angles to serial no problem. Maybe I just don’t notice the slow updating when printing to serial. But no, because it does update, and yet motor init fails to notice any motion. The update seems to not only be very slow but also to not actually give a legit return value in that context, and that context specifically.

Wait, I don’t know if I ever actually tried reading the sensor and printin got serial when externally powered. But it’s 10:30 now and I haven’t showered, I have to try again tomorrow. If the external power borks the i2c connection maybe I can use the SPI encoder, perhaps a second visit to that would get results.

ok, now I commented out the second of the two updates, when it moves the motor back again, and instead of moving slowly it stutters gives a bit of a grinding sound for a fraction of a second and then remains powered but in a fixed position.

I checked the wires for the i2c connection are a centimeter or more from the motor wires and any other suspected source of interference, like the buck regulator’s inductance. Moved some stuff, same deal.

ok, now it appears to be related to the difference between being powered off of the st-link vs the bench supply/from the vmot terminal. Sometimes, it continues working to print the angle to serial after I transition power from the stlink to the bench supply (turn on the bench supply without turning the sti-link off). Sometimes it doesn’t. When it doesn’t, it usually says 6.28 is the angle, sometime 0.48 I think. Sometimes it prints one for a long time and switches. obviously something pretty borked.

Good call checking for electromagnetic interference.

Try putting some calls to micros() in MagneticSensorI2C::read and print the differences between them to see where all the time is being spent.

Since those loops in BLDCMotor::alignSensor do 500 iterations each, then if the whole process takes 4 minutes then it should be around 240ms per iteration. That would be pretty unnoticeable when taking a single reading, but is ridiculously slow for such a short transmission.

I suppose you could try a lower I2C clock rate and see if it makes any difference. And try removing the CPU clock config to leave it at 16MHz and see if that makes any difference. Something weird is going on, but I don’t know what. But don’t lose faith, we just need to keep prodding it a bit longer and it will surely give up its secret :slight_smile:

ok, experimentation continues. just want to post quickly that there is some kind of problem with the sensor driver for the SC8022 encoder, it reads only 1pi radians per full revolution, it should be 2 pi correct? 2 pi radians per circle.

update, ok so I switched back to the sc8022 encoder to see if I could circumvent the problem with the I2C communication.

It gets further than it did but still doesn’t work.

output is:
got this far, testing serial port

64000000

MOT: Monitor enabled!

MOT: Init

MOT: Enable driver.

MOT: Align sensor.

MOT: sensor_direction==CW

MOT: PP check: fail - estimated pp: 15.11

MOT: Zero elec. angle: 5.59

MOT: No current sense.

MOT: Ready.

Motor commands sketch | Initial motion control > torque/voltage : target 2V.

1.89

1.89

motor behaviour: it turns back and forth a bit to do the sensor align, then it twitches briefly, and then stays locked with about 50 milliamps draw, but the current is more than enough to turn the fan, I can tell it’s got a fair bit of force if I turn the fan by hand.

This is the code I used:

#include "SoftwareSerial.h"
#include <SimpleFOCDrivers.h>
#include "encoders/sc60228/MagneticSensorSC60228.h"
#include <SimpleFOC.h>
// SENSOR SPI SC60228
// SPI2 PINS
#define CSN2 PA4
#define CLK2 PA5
#define MISO2 PB4
#define MOSI2 PB5

#define SS_USB_RX  PA15
#define SS_USB_TX  PA2
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();
  }
}
// BAUD RATE MUST BE BETWEEN 9600..38400
// ANY OTHER BAUD RATE WILL CHOKE

SoftwareSerial SoftSerialUSB(SS_USB_RX, SS_USB_TX);
MagneticSensorSC60228 sensor(CSN2);
BLDCMotor motor = BLDCMotor(7);
BLDCDriver6PWM driver = BLDCDriver6PWM(PA8, PA7, PB3, PB0, PB6, PB1);
SPIClass SPISensor(MOSI2, MISO2, CLK2);

void setup()
{
  //set pins for Software Serial communication
  SoftSerialUSB.begin(38400);
  pinMode(SS_USB_RX, INPUT);
  pinMode(SS_USB_TX, OUTPUT);
  SoftSerialUSB.println("got this far, testing serial port");
  SoftSerialUSB.println(F_CPU);
sensor.init(&SPISensor);
  delay(1000);
motor.linkSensor(&sensor);
 driver.voltage_power_supply = 24;
  driver.init();  
   motor.linkDriver(&driver);
    motor.controller = MotionControlType::torque;
     motor.voltage_limit = 12;
  motor.useMonitoring(SoftSerialUSB);
    // initialise motor
  motor.init();
  // align encoder and start FOC
  motor.initFOC();
    // set the inital target value
  motor.target = 2;
   // define the motor id
 
    SoftSerialUSB.println(F("Motor commands sketch | Initial motion control > torque/voltage : target 2V."));
 delay(1000);

}

void loop()
{
  for (int i=0; i<10000; i++) {
  motor.loopFOC();

  // iterative function setting the outter loop target
  // velocity, position or voltage
  // if tatget not set in parameter uses motor.target variable
  motor.move();
   }
     for (int i=0; i<100; i++) {
  motor.loopFOC();

  // iterative function setting the outter loop target
  // velocity, position or voltage
  // if tatget not set in parameter uses motor.target variable
  motor.move();
  
  SoftSerialUSB.println(sensor.getAngle());
  sensor.update();
   }
delay(10000);
}

I noticed the value of the encoder keeps going up and up, 2pi radians per circle. But it doesn’t wrap around at 2pi, it just keeps going up. Is that how it’s suppose dto be?

update: I wnt back to the as5600 on i2c and thought it might be some kind of noise on the power supply messing up the sensor, so I added a 10uf ceramic cap to the supply lines near the chip. The first time I powered it up it didn’t work, then I tried disconnecting the motor, and it did get past motor initialization (failed pp check etc of course as the motor wasn’t connected, but it read the sensor ok) And it showed some values of the encoder for ilke a second Then it started showing the usual 6.28 radians. it’s always the same. 2 pi radians. Spooky. IT never worked again after that first time I powered it up without the motor connected. Indicates some kind of noise issue, due to the randomness, to me

The magnet is super close to the sensor, I don’t think it could be some kind of magnetic field issue, and in any case that wouldn’t explain the extremely slow (probably a timeout error, so takes a long time and never returns anything good in the end) I2c communication, which only occurs when the board is powered through the Vmot terminal, and not when the logic is powered with the 3.3 volts of the stlink.

My best guess for now, which is not a great guess, is that I2C doesn’t work because of interference on the signal line caused by some of the power stag stuff, causing the I2C peripheral to get messed up or something.

Valentine, did you use an I2C sensor or an SPI sensor? The SPI seems to work fine.

But then the problem is that some other aspect of the system does not work with the SC8022 sensor. There is likely more than one problem with the driver code. One is the directory structure. The other is that the reading wraps around at 1 pi radians. I don’t know if it’s supposed to wrap around or keep going. The sensors act differently, the I2C sensor doesn’t wrap around, at least for a long time, whereas the SPI wraps around every revolution.

Serial interface still doesn’t work. I don’t need it to, for the application, but… There are a lot of things here that don’t work. I’m definitely at the end of the line regarding my own limited ability to get stuff working. I’m going to put it down until I get a promising idea, from here or elsewhere, or thing to try, and work on other aspects of the energy recovery ventilator.

updats: while reviewing the above, I noticed the suggestion to change the clock rate of the I2C port. Sorry Deku I did not respect your suggestion more before, there was a lot of stuff going on. I changed it to 100000 from 400000 and now the sensor will read when the motor in unconnected, but not when it is.

tried changing it further to 30000, still doesn’t work. It did move during align at a reasoable speed for a fraction of a second one time when I had the motor connected. Might indicate that it is some issue that persists over reboots. Could be some kind of high voltage injecting charge somewhere that takes a while to clear out.

I used only SPI, never tried i2c.