Idea for leveraging a Blheli_32 ESC like the Wraith with Simplefoc - just send it the electrical angle and voltage

Ok. I have an idea to help solve my problem that would also dovetail well with many of the rest of the SimpleFOC project and the things that most people seem to want to do with it.

For me, it’s become clear that it is very time consuming and possibly impossible to do all the input, output and processing and waveform generation on a single board with a single core processor.

So I have decided I need a separate component that produces the waveform. For me, it will accept rotational speed and voltage, then hand back data about the electrical angle when requested. The second MCU in the system can take it’s sweet time to do all the other stuff, and yet I still get smooth, low noise motion.

That’s the hope. I think this can work for me because I am using a fan, which has a load-speed curve and smoothness, doesn’t change direction fast etc.

However, I realized that you could also make a very small program on a Blheli_32 board, which others have posted about reprogramming, apparently with success in running a basic program. (for example, BLHELI32 ESC feasible?)

Ok. My idea, then, to make this generally more useful and fit in with the stuff other people tend to want to do, is to simply use openloopAngle mode on the Blheli_32 board. Using half duplex communication over the input pin of the (formerly) blheli board (I’m not to clear on how to do this, you want a high data rate to reduce delays) , you can simply command it to take on the right electrical angle and set the voltage when you want.

This inserts into the SimpleFOC system in place of the setElectricalAngle or whatever it’s called function.

If this system is responsive enough, we finally get a solution for the power stage and also glitchyness at the same time, at a bargain price. There are a great many Blheli_32 based boards readily available which could be used probably each of them just as well. The current capacities are massive. I do not know if they integrate current sensing. It’s possible they use an ADC and could export useful current information.

People don’t have to worry about dead time with the PWM, pwm frequency and all kinds of other stuff. It’s been a real nightmare for me on a tight schedule trying to roll my own everything, especially when this really is not my domain. Not everyone can know everything, and I think technological progress may sensibly proceed in the direction of reducing training requirements and making things more elegant…

The other code doesn’t appear to be terribly timing critical, at least if it takes a while the delays can be compensated for, usually, and still get good performance.

These things cannot reverse direction with their default firmware, and have many other downsides. To make them into a useful general purpose building block would be laudable and broadly useful.

With this approach, many of the limitations of using a single MCU to do everything evaporate. The issues with slow read speeds over I2C, for instance. Commutation speed can be good probably even for higher rpm applications.

I am having quite a variety and quanitity of problems trying to use one MCU for everything, although it may be possible, the amount of knowledge and time and capital it takes is a legit serious problem. This could really help I think, to get this sorted.

I have ordered some Wraith boards to experiment with.

edit: this is the board I ordered 35A Wraith32 – 32bit BLHELI ESC – Quads RTF

I don’t really know what to say, except that I don’t think this will be a fruitful direction…

BLHeli does trapezoidal commutation, based on BEMF sensing. It actually also has a “Sine mode” but this is still not FOC.

As input it accepts speed (throttle) and at least by default is designed to drive motors in one direction only… so kind of uni-directional velocity control… It can neither report back the electrical angle (it doesn’t work with sensors) nor can it set an electrical angle as output - it controls rotational velocity…

So unless you’re planning to replace its firmware with a completely modified version, I don’t see how this would really work in conjunction with SimpleFOC.

I think it’s also a misconception that it would make things simpler to “split the algorithm” across multiple MCUs. I think this would greatly increase the complexity, if the latencies introduced by it even permit it to work at all.

In theory, you can of course implement any part of the control algorithm as its own piece of hardware, communicating with the other pieces via some kind of protocol… in practice, code running on the same MCU and sharing memory (using the same variables) is of course a very easy integration pattern compared to any kind of communication via protocol.
It’s only once programs reach a certain complexity, and only at very well defined “interface points” that separating out functionality into their own modules begins to make sense.

All that said, why not just try the BLHeli ESCs as they are? Perhaps they will work just fine for you out of the box?

Yes, I am talking about reprogramming it, definitely.

So you take the setElectricalAngle code, basically, chop that out, put that in the Wraith module or whatever.

The rest of the simpleFOC firmware runs on another mcu.

Then you make a communication interface between them, ideally over the one wire in/out that is already provided. Boom. Should work?

We cannot access the power stage of the ESC directly, but we can do this. Secondly, this is even better than jacking straight into the power stage of the ESC, I think. Smoother glitch free waveform, you can do whatever fancy time consuming stuff on the main MCU you want, etc.

It might work, but it will probably just be another debugging nightmare. Splitting time-critical tasks between CPUs is usually very difficult, and it won’t solve anything anyway if the sensor update rate remains unchanged. Plus it would add a lot of cost to each unit. If you’re going to spend money on anything, make it a fast sensor. That will probably “just work” without any tricks.

But you could try using the Blheli_32 ESC as-is. Spinning a fan is what it was made for :slight_smile: I was not aware that it had a sine wave commutation mode. That may give the silent operation you’re after. Problem solved, no sensor needed.

Yeah, I am actually hoping I could just use the escs as they are mostly. But I’m not optimistic. I’ve tried 7 other devices at this point, including some that are advertised as quiet, and they are not as good as the smooth open loop waveform from the lepton or G431 boards. They are not reversible, but I could use an hbridge on the output to swap two of the connections and reverse rotation.

What I do to get a peek into the future is start at low speed with open loop, accelerate it up to about 250 rads per second, and then reduce the voltage until I get to the minimal current value before it stalls. I can leave it there in a steady state and ascertain what the ideal situation would be if I could get the commutation perfect.

Even the texas instruments chip makes a substantial ringing noise that doesn’t arise when I do this.

Interestingly, I discovered that some motors actually benefit from trapezoidal drive, the SM type motors, in contrast to the IP type. This basically equates to the ring type, some motors have a ceramic ring that is magnetized differently in different areas, these are the SM type motors, basically (an SM motor could have gaps, but these don’t, it’s the curvature of the magnet’s surface that makes it qualify as an SM type as far as I can tell).

I tried the trapezoidal 120 drive in open loop, and it’s just as quiet and low vibration as sine wave drive. So my problem is not sine wave vs other approaches, it’s the other stuff that is happening during waveform generation. I think fundamentally it’s just easier and cheaper to put everything on one mcu and then tolerate some glitching that leads to noise, thus everybody does that.

I’m not sure my idea is coming across here. This is a general purpose building block, that solves the problem of a power stage and also frees the main MCU from the demanding task of waveform generation, with one widely available and very economical component.

For instance, should you wish to control multiple motors, you can now do that with only one MCU, and several of these driver modules. Based on my investigations, there is basically no way you will get things smooth if you try to use one MCU, even the fastest STM32, to produce the waveform for more than one motor, especially at higher rpm.

The limit of SimpleFOC in torque mode is in the range of 60 rads per second right now, with the B-G431b-ESC1, which has a pretty fast processor. That’s not so hot. And it vibrates like crazy and gets poor efficiency, I tried it with PWM sensor that was well tuned, so no read time issues. And fundamentally, there is no need to have such a rapid response to the angular variation during torque mode, because the motor has inertia anyway, so there is no point in changing the angle faster than it can keep up, really.

SPI is also blocking apparently. It’s faster, but how much faster? The I2C communication delay from the AS5600, just when you retrieve the data (that is, excluding the time it takes to prepare it) is 300 microseconds on the G431 based board. I don’t know exactly what the delay is caused by, but even 50 microseconds is too much, that will cause noise.

I guess smooth waveforms just aren’t a priority for most people, however again I think this is a good general purpose method. It’s a logical system division. Have one really cheap easy to get module that does what you need with the truly timing critical stuff, and one general purpose programmable module for $4 or whatever that does the rest.

You say it’s not a good idea to divide timing critical stuff between processors, but that’s my point, you aren’t doing that. The only thing that really has to happen on a scale of a few microseconds is updating the waveform. Everything else involved with FOC can take a lot longer, because the motor has inertia, and thus there is time to deal with things.

Also there is actually way less debugging to do, precisely because all the complicated code is not timing critical. All the signal filtering, reading the sensor, accepting commands, replying, pid, everything else happens on the second MCU.

When you try to do everything on one MCU, everything interacts. I’m getting beat frequencies in the sensor reading, for instance. Near top dead center there is always a small region where the angle readings are a little bit borked. At certain rpms, the readings occur many times in a row at that region. This kicks the pid controller and messes up the motor timing (difference between shaft angle and electrical angle). I can add extra padding to the timing, but that reduces efficiency.

If I can use a digital sensor this problem is mostly solved because I can have a faster update rate or make the update rate random. Can’t do that with PWM. But any kind of digital communication with the sensor is a problem because it takes too long, so can’t do that either.

I agree you canprobably put everything on microcontroller and get good results. But no one is doing or has done that, because it’s a ton of work to get everything working just so, and especially for a wide range of applications with a wide range of hardware. This approach, in contrast, makes things much more flexible.

It’s not more expensive because you get a deal on the power stage, nothing is cheaper than buying these things, and again if you want to control more than one motor you can do that cheaper. But the main thing is it really reduces the time to remix things and make something that works well for a given application, with a given combo of hardware. It’s more general purpose.

Again, there is no cheaper power stage, but previously it was assumed that because you can’t hijack the pwm stage of these devices, they can’t practically be used. This not only solves that problem, you actually benefit from the computational capability of the MCU that you got for free. Partly this is by recognizing that the electrical angle actually never needs to be updated with very high frequency, because the motor cannot change direction or speed that rapidly. The occasional adjustment to the position and and frequency of the waveform is adequate. With a megabit baud rate it should work fine, you send it what 12 bytes or something per update. That’s lots of speed and time. The slightly increased propagation delays are not going to be noticeable, I think, again because of inertia overwhelming that impact.

Ideally you should use the hardware encoder functionality of the G431 timers. As @runger keeps saying I2C is to slow. I will order magnets tomorrow, when they arrive we can try to time the encoder response.

1 Like

But updating the waveform can only happen at the rate that the sensor provides angle information. That’s the nature of closed loop control. To get smoother than that, you have to use extrapolation like the SmoothingSensor class I wrote. And in the case of the multi-CPU system, the Blheli won’t know exactly when the sensor reading was taken, so even though the waveform is smooth it won’t be perfectly in phase with what the motor needs.

Reading about the PWM output of AS5600, I think it can work with a little modification. Give MagneticSensorPWM an empty update() function so it doesn’t touch angle_prev_ts, and replace line 56 of handlePWM() with this:

    if (!digitalRead(pinPWM)) {
      pulse_length_us = now_us - last_call_us;
      Sensor::update();
      angle_prev_ts = last_call_us;
    }

That way SmoothingSensor will perform its predictions relative to the time that the sensor actually took its measurement. The PWM pulse takes time after that before the angle is communicated, but the SmoothingSensor will continue performing good predictions based on the previous measurement during that time. (Note: The downsample variable of SmoothingSensor will be irrelevant in this case, since the updating is done in the PWM interrupt)

I like Juan-Antonio’s encoder suggestion too.

I was not able to figure out how to use your smoothing sensor thing, I posted in the thread saying an example might help, I haven’t checked for a reply yet, I had to hustle so what I did was export the timestam from the measurement when the pwm interrupt gets fired with a variable I could access in the main program (slight modification to the library), took the angle after the calibration correction, and that did help a lot.

When I do that I am able to get a good result, but only up to about 120 rads/s. After that it stops accelerating and flakes out and stalls. I was not able to figure out why. I started looking back up the chain, under the hood, but whatever is happening is happening too fast to catch with printing to serial.

With that batch of code there were numerous other deviations from the idea I wasn’t able to figure out, notably very low efficiency. Probably related, it was thinking the phase angle was ok when it wasn’t. It had something to do with code timing as when I chopped out some sections of code I got higher rpm, but still nowhere near the 250 rads/s at least that I need.

In other words, even doing as you propose, the fundamental problem arises: the MCU is not fast enough to do things with basic code. If I was a wizard with C and embedded systems maybe with enough work I could get it rolling. If I learned to use the STM32 debugging tools I might be able to figure out this problem. However there are sure to be many more, and that process of learning to do everything and get it done would probably take at least 2 weeks. Also I would have to design my own board with the G431 chip because if it’s such a tight squeeze it would be even harder or impossible to do it all with the lepton.
That means I have to get custom boards made. There are likely to be errors, which means I need to do it at least twice to get to the next stage.

You see how complexity and costs explode… I have to backup and look at the bigger picture. I agree it’s probably possible to do what I need with the G431 board. However I don’t have the capital to get it done. Human capital, financial capital. I need a cheaper approach, even if it implies higher parts cost (which it may not).

This system division appears promising, I may use the Lepton as the waveform generator instead of trying to use an ESC, the price and performance etc is similar anyway. However if the Lepton works there is no good reason the Wraith can’t do it, if it can be reprogrammed. That would be a lot easier for other people in the future, that’s why I like the idea. I don’t need the Wraith. One of the reasons I ordered some is as you said it might work out of the box (with an h bridge to reverse direction).

BTW I did an experiment where I sent the information back, through a global variable, after the extrapolation process based on mechanical sensor data extrapolation (using separately calculated velocity data to avoid a feedback loop, can’t use the library’s shaft velocity data to extrapolate the sensor reading and then send it back as the velocity measurement would access that same data point and there would be a feedback loop as that was then used to extrapolate the sensor reading on the next loop) and then that got returned after calibration, and used in torque mode FOC. It does smooth it out a great deal, but at higher RPM again it flakes for some reason which isn’t clear. So both sensor calibration and also sensor extrapolation, in aid of trying to get smooth motion at higher RPM. There are always problems, and it has become clear the road is very long and not that promising, when using a single MCU.

Was the timestamp taken from the interrupt at the rising edge or falling edge of the PWM pulse? It needs to be rising edge, as in my previous post. That’s when the sensor has taken the measurement. Falling edge is what completes communication of the angle, but that could be several ms later depending on the PWM frequency setting in the CONF register. At 120rad/s with 7 pole pairs, 1ms is 48 electrical degrees, so that could definitely start to fail.

Have you tested how fast open loop can go before it flakes out? That should give some idea of how close you are to CPU speed being the problem. Closed loop does have more calculations, but the fact that it works in open loop at your target speed proves that the CPU is at least pretty close to being fast enough. My little 9N12P hall sensor motor runs happily at 500rad/s closed loop on Lepton. I haven’t tried any faster yet.

whoops, yeah I was taking it falling edge. I took a minute and corrected it and tried it again just now. It’s less prone to flaking out and stalling (from which it recovers, but still), but the rpm limit is still there.

The thing is that I keep having to add features, smoothing, calculations of whatever kind. Sensor compensation. All that stuff takes time and things get so complicated. I must say I am still partial to my waveform generator idea.

Btw I was just noticing, the lepton only runs the waveform update at 5khz. The g431 board at 37kHz. So you can’t possibly update it faster than that. That’s not a very high update rate for a unidirectional SPI connection. You don’t have to wait for a reply or anything. Any delays in timing can be compensated for easily because they are always the same. I don’t get why the resistance to the waveform generator module idea. Again, it plugs in where the setelectrical angle goes, basically. Well anyway, perhaps I can give it a try and we will see.

Hmm, now that’s interesting. Why would the speed limit remain the same with such a large change in timing?

If you’re worried about adding features and complexity, then do not add communication between CPUs. Very difficult! Even if they are running on the same master clock and have access to shared RAM… speaking from experience on Nintendo DS.

Nintendo didn’t even allow professional developers to write CPU communication code. They just supplied a pre-compiled ARM7 binary, which the ARM9 library had functions to communicate with. We could read through the ARM9 source and see that side of the communication, but you can’t really understand it without seeing both sides, and you couldn’t modify anything since all the action was on the ARM7 side. It wasn’t until the homebrew guys cracked the anti-piracy features that I got to try programming with full control of the hardware. Great fun, but I can certainly see why they wanted to simplify it :slight_smile: I never did get my ARM9 sound mixer to synchronize 100% of the time, and that should have been dead simple. But failures were so rare that it was impossible to figure out why they happened.

Fond memories.

Because an I2C sensor is being used… or because the motor’s KV limit is reached.

No, this was testing with the PWM output. It’s super slow, but non-blocking, and presumably the rising edge of the pulse happens immediately after measuring the angle so it gives us a precise timestamp to extrapolate from. The updates may just be too infrequent, so any variation in speed causes feedback effects that destabilize it. But I would have expected that to happen at a much lower RPM when extrapolating from the falling edge, since it’s not only offset from the time of the measurement, but the offset varies depending on the value of the angle. I don’t think kv limit is being reached either if open loop can go twice as fast.

Yeah, it’s with PWM, using interrupts indeed. It’s also not the KV rating of the motor, this motor goes more than 4000 rpm no load, and I can get it up to 3000 with the fan blades attached, so approx 300 rads/sec.

I don’t know what it is, but I know if I chop out all the complicated stuff it goes faster, and the more stuff I chop out the better. I also noticed that the current consumption is quite high.

In my code, I can adjust the motor timing i.e. the difference between sensor and electrical angle. So I can use that to compensate for any repeating, regular bias in either the electrical angle or the sensor angle, due to time to execute code or whatever.

And yet no matter what I do, it always flakes and stalls at around 115 to 130 rads per second. I really don’t know, but I do know that even if I solve this there are other problems right around the corner, with arduino and C to do this kind of thing you actually have to know C. I don’t. Trying to get in there and modify the library in various hacky ways is very difficult and time consuming and stressful.

What I know will probably work in a finite, defined time, is the waveform generation approach, and I can probably do it even with micropython and a pico. That’s what I intend to use in the future for other stuff so I don’t mind spending time overcoming my lack of knowledge there. The pico is a relatively good design that’s open source, low cost, generally pretty good, with a sizeable community that’s growing rapidly. Micropython is also way less stressful to deal with. Every tiny thing I do in arduino always has a question mark hanging over it re if it will work. Compiling also takes forever even on my desktop…

I am sure I will have plenty of problems in micropython, but at least over there I’m not always going in circles.

My plan is to get a good waveform generator going and never touch arduino again unless I have to. It’s one strength was supposed to be that it’s fast, but now I see that debugging things that move fast is not practical in arduino anyway. I’m glad other people are on the case, but I’m tired of it for now.

Here is the code I’m trying to use on the b-G431B-ESC1 board for a waveform generator. It’s far from perfect, I gave it an angle setting mode that may be used for sensor calibration etc. at low speeds. However I would not use that, I would just set the open loop to 0.1 rads per second or something and gather data that way. That was probably a waste of time and I think I will get rid of it, but it can wait. I was going to try to make it plug into the rest of simpleFOC so I could use the sensor calibration and stuff, maybe even try torque mode with my new setup, but I just don’t have time for any detours and I immediately ran into problems getting SimpleFOC to compile on the mega2560. It wont’ even print to serial, get stuck on something before even starting the setup code. I don’t know, I am just going to abandon arduino and redo things in Micropython. It still helps a lot to have the C code to look at as a framework to show the logic and stuff, that’s important for sure and I appreciate that. And the waveform generation stuff is worked out, so there’s that.

Thanks Deku for the serial communicator thing, I have used it a lot.

#include <SimpleFOC.h>

// NUMBER OF POLE PAIRS, NOT POLES
BLDCMotor motor = BLDCMotor(7); 
// MUST USE 6PWM FOR B-G431 DRIVER
BLDCDriver6PWM driver = BLDCDriver6PWM(A_PHASE_UH, A_PHASE_UL, A_PHASE_VH, A_PHASE_VL, A_PHASE_WH, A_PHASE_WL);
float goal_speed =0;
float v=1;
int mode = 0;
float angle_for_angle_mode = 0;
void SerialComm()
{
  switch(Serial.read())
  {
  case 'T': goal_speed = Serial.parseFloat(); Serial.print("T");break;
  case 't': Serial.print("T "); Serial.println(goal_speed); break;

  case 'V': v = Serial.parseFloat(); Serial.print("V");break;
  case 'v': Serial.print("V"); Serial.println(v); break;
  
//  case 'S': p_gain = Serial.parseFloat(); Serial.print("P");break;
  case 'e': Serial.print("e"); Serial.println(motor.shaft_angle); break;
  case 'A': angle_for_angle_mode = Serial.parseFloat(); break;
  case 'M': Serial.print("mode changed"); mode = int(Serial.parseFloat()); break;

 // case 'I': diff_filter.Tf = Serial.parseFloat(); Serial.print("I");break;
//  case 'i': Serial.print("f:"); Serial.println(diff_filter.Tf); break;
 // case 'D': d_gain = Serial.parseFloat(); Serial.print("d_gain set");
 // case 'd': Serial.print("d_gain is:"); Serial.println(d_gain); break;
//  case 'O': i_windup_limit = Serial.parseFloat(); Serial.print("i_windup_limit set");
  //case 'o': Serial.print("windup limit is:"); Serial.println(i_windup_limit); break;
//  case 'U': setpoint = Serial.parseFloat(); Serial.print("S"); break;
//  case 'u': Serial.print("s:"); Serial.println(setpoint); break;
  
  }
}


void e_val_req(){
  Serial.println(motor.shaft_angle);
}



void setup() {
  Serial.begin(115200);
  Serial.println("test serial");
  // driver config
  // power supply voltage [V]
  
  driver.voltage_power_supply = 24;
  driver.init();

  // link the motor and the driver
  motor.linkDriver(&driver);
FOCModulationType::SinePWM;
  // limiting motor movements
  motor.voltage_limit = 3;   // [V]
  motor.velocity_limit = 520; // [rad/s]
 
  // open loop control config
  motor.controller = MotionControlType::velocity_openloop;

  // init motor hardware
  motor.init();
  //accelerate
  motor.voltage_limit = 2;
  goal_speed = 2;
  pinMode(PB6, INPUT_PULLUP);//might want to change that to INPUT_PULLUP at some point, wasn't sure if that would work
  attachInterrupt(digitalPinToInterrupt(PB6), e_val_req, RISING);
//  for (int j = 0; j<(maxradianspersec*accel_step_divisions); j++){
///     for (int i = 0; i<accel_loops; i++){
 //    motor.move(j/accel_step_divisions);
 //       } 
 // motor.voltage_limit = 2.4+(3.6*(float(j)/(maxradianspersec*accel_step_divisions))); 
  // Serial.println(motor.voltage_limit);
 // }
}
  
void loop() {

  
  switch(mode)
  {
  case 0: 
  motor.controller = MotionControlType::velocity_openloop;
  for (int q = 0; q<10;q++){
   for(int j=0;j<10;j++){
  

     if (motor.target < goal_speed-0.3){
      motor.target = motor.target+0.075;
     }

     if (motor.target > goal_speed){
      motor.target = motor.target-0.075;
     }
     for (int i=0;i<20;i++){ // Motor.move goes at about 37khz with a for loop, probably a bit faster this way, with multiple one after the other. actually no because a for loop comparison is extremely fast compared to the code in motor.move but whatever.
     motor.move();
     motor.move();
     motor.move();
     motor.move();
     motor.move();
     }
    motor.voltage_limit = v;
}
 //Serial.println("t");  
     SerialComm();
  }
  break;
  case 1: 
    motor.controller = MotionControlType::angle_openloop;
  for (int w = 0 ; w < 10; w++){
      SerialComm();
      motor.move(angle_for_angle_mode);
      motor.voltage_limit = v;
  }
  
  break;
  }

    
}

Oh and I solved the open loop clicking, again, this time I’m pretty sure for real. I changed several suspected things at once, I think it’s something to do with what happens when the data types are coerced when the difference between the microsecond counters are close to zero, but maybe that has as much merit as my last hypothesis. I just know this code works, when I sub it in in place of the velocityopenloop stuff.

// Function (iterative) generating open loop movement for target velocity
// - target_velocity - rad/s
// it uses voltage_limit variable
float BLDCMotor::velocityOpenloop(float target_velocity){
  // get current timestamp
  static float other_shaft_angle = 0;// there is a mysterious flake out that occurs once per rotation, using  a local variable helps a bit.
  unsigned long now_us = _micros();
  float delta_angle = 0;
  // calculate the sample time from last call
  //float Ts = (now_us - open_loop_timestamp) * 1e-6f;
   unsigned long micros_int_dt = now_us-open_loop_timestamp;
    // quick fix for strange cases (micros overflow + timestamp not defined)
  if(micros_int_dt <= 0 || micros_int_dt > 1000) {
    micros_int_dt = 1000;
  }

 delta_angle = (target_velocity*float(now_us-open_loop_timestamp))/1000000;
  // calculate the necessary angle to achieve target velocity
  other_shaft_angle = fmod((other_shaft_angle + delta_angle), _2PI);
  shaft_angle = other_shaft_angle;
  // for display purposes
  shaft_velocity = target_velocity;

  // use voltage limit or current limit
  float Uq = voltage_limit;
  if(_isset(phase_resistance)){
    Uq = _constrain(current_limit*phase_resistance + fabs(voltage_bemf),-voltage_limit, voltage_limit);
    // recalculate the current  
    current.q = (Uq - fabs(voltage_bemf))/phase_resistance;
  }

  // set the maximal allowed voltage (voltage_limit) with the necessary angle
  setPhaseVoltage(Uq,  0, _electricalAngle(other_shaft_angle, pole_pairs));

  // save timestamp for next call
  open_loop_timestamp = now_us;

  return Uq;
}

BTW looks like someone already created the arduino board files and stuff for the Wraith32:STM32 Arduino based Electronic Speed Controller - RC Groups

I can confirm, there it is in the arduino ide under stm32 boards, electronic speed controllers, wraith32, v1. However the boards aren’t as common as I had though. Still, good board. It has an UART, too, which is handy, the pins are exposed as pads on the board.

The lepton is still better, if I just get a few more pins broken out and some better connectors, but still a cool idea to use a commodity board, I’m pretty sure if it’s supported under arduino it would work pretty well. Remember the motor.move command takes 200 microseconds to run on the Lepton anyway, so the electrical angle isn’t getting updated that fast not matter what you do. To smooth out the signal a bit and use a peripheral instead of doing everything in one mcu does make sense. It occurred to me today that the angle could be set and then the generator peripheral could ramp smoothly to the new position. It’s basically like a trinamic2208 stepper motor driver but with three phase output instead of two, which is exactly what I have thought many times I needed.

I assume the main reason no one has done this is that most people don’t care that much about vibration etc. which is fair enough. However it does free the CPU and have many advantages. Well, looks like it’s promising for my purposes anyway so cheers.

Again, it’s basically a peripheral to the CPU. Suppose the data transfer rate is a megabit. That’s not going to introduce much latency, in fact I bet you could get it down to a lot less than 200 microseconds between outputting the value and having your program flow back. And when you are doing high speed motion it’s imposible to get such smoothness. No one criticises the idea of using a PWM peripheral for generating a waveform of good quality, after all. Or a stepper motor driver.

edit:
ok, I got the wraith32 boards today. As mentioned above, someone made a board file for arduino so that’s good. I inspected them and they look promising. They have the pins for the uart and the SWD port broken out to pads. The MCU says stm32f051k66 on it, which would be the version with only 32 kb of flash. The lepton has 64 kb and still the open loop code only just sneaks in under the wire. I would also have to figure out the pins that go to the fortior driver to use in the arduino code, which wouldn’t take that long but still.

It has one 50milliohm sense resistor before the half h-bridge circuits. So you can measure total current apparently, somehow. I don’t see any op amps on there but there is a little thing that might be one. It’s possible it just goes straight to an ADC pin and is only good for relatively crude current measurments, but if that is so I don’t know how they do sensorless commutation with a sine wave.

I think probably the commutation is done by measuring the current and optimizing it to the lowest point.

I was not able to get it working without modification with my gimbal motor. As with most other sensorless driver chips, it appears to be confused by the motor characteristics, unable to start the motor. Therefore I could not use it as it is, in any case BlHeli cannot reverse direction, so I would need even more stuff to do that.

Ultimately this may have promise, however given that these boards are not open source, not widely available, and the flash is small, there are no other pins broken out so you don’t get any other options for ports etc, it is quite hard to access the pins, I decided not to pursue this any more. A next generation lepton is a wiser strategy for the long term, something that can acutally be used for a wider range of applications, and therefore be supported better. It would probably be a challenge to get interrupts and all other peripherals working on this board, for instance. There is the board file but it’s probably not thoroughly done, the guy seems to have done a quick job and was surprised serial worked…

A next generation lepton based around the G431 as mentioned in my previous approach appears to be the wisest course of action. I’m a bit hesitant because I don’t need that much CPU power for my own application, but using open source widely used components is important so it’s important for me to use the better CPU, with higher clock rate and op amps for current sense and floating point, as that will be more useful to others and be more broadly supported.

The current plan is basically to make a board that is like the G431 board but with all the expensive stuff chopped out, and pins broken out better etc. A cross between the lepton and the G431 board basically, with the best features of both, minus the kind of less useful ones from the G431 board.