I want to make a VFD (this code is without knobs for now) and I am running into a problem where the ESP32C6 is far too slow for this. How can I optimize this further? Here is the code.
The Serial.parseFloat() will cause a major delay while waiting for the entire number to arrive. It would be better to read the Serial data into a buffer, then parse the numbers after a complete line has been received.
for (int i = 0; i < 361; i = i + 1) {
int z = i * 1;
double radiany = (((double)z * 71.0) / 4068.0);
sinval[i] = 2047 * (abs(sin(radiany)));
Serial.println(sinval[i]);
}
double radiany = z * (71.0 / 4068.0); // compiler can now optimize compile time.
but that is executed only once in setup()
More performance gain is by removing the % and fmod as those are expensive.
You could use 3 variables for the 3 different phases, better use arrays.
something like
You’re saying the ESP32C6 is too slow for your VFD code, yeah this can happen if timing isn’t optimized properly. I think the main issue is using float values and sin calculations in real-time, which makes it slower. It’s better to use a precomputed lookup table with integers and avoid float math inside the loop. Also try using hardware timers or PWM (like LEDC) instead of updating manually, it reduces CPU load. If it’s still slow, maybe lower the resolution a bit or tweak the loop timing, small changes can help alot.
Since memory really is not a scarce resource, anything that can be pre-calculated and stored will be fine.
Also avoid float computations, many times you know where how many decimals you will be using. 32-bit integer computations should easily suffice if you decide on the accuracy up front (a float is anyway only 23-bit accurate but has a floating decimal point, so you should get plenty of accuracy)
You appear to be calculating the degrees within the waveform from the value of micros(). Unless the rollover period of micros() is an even number of cycles there will be a disruption in the output waveform when rollover occurs. The use of a timer to give a consistent timing would seem to be a better idea.
If true, then unwrap any loops that use an index into some stringy code with numeric values for indexes. Only useful when the programmed loop only loops a few times. Yeah, doesn’t look so nice, but runs fast!
On top of the other remarks, why don’t you use LEDC? It will give you hardware-driven PWM with far less overhead and much more stable timing than analogWrite on the ESP32-C6.
Have you also considered using a hardware timer instead of rebuilding the phase from micros() on every loop iteration? Driving the waveform from a fixed-rate timer interrupt with a phase accumulator is a common approach. It removes the need for fmod, divisions, and repeated time reads, and it gives deterministic timing without jitter.
I don’t know enough about the C6 to be certain, but have you looked at MCPWM as well? It should be preferred if you need true three-phase complementary outputs with proper dead time - as long as it’s in the feature set on ESP32-C6 .