More Colours
We can also leave the PWM-based control of the LEDs directly to the microcontroller.
For sat.cfg
:
board chocolate 0.2 rascal +allpwmled !device has_custom_hooks y build_files custom.cpp
This time we leave out the components
option. The code running on the microcontroller in custom.cpp
to produce the cycling rainbow pattern is:
#include <sat/satx.hpp> #include <math.h> using namespace sat; using namespace sat::resource; namespace { // Number of RGB LEDs. constexpr const uint NUM_LEDS = 5; // Maximum brightness. constexpr const float MAX_BRIGHTNESS = 0.02f; // Duty resolution. constexpr const uint DUTY_RESOLUTION = 32768; // How far each adjacent LED is in the colour cycle ahead of the previous // one. constexpr const float COLOUR_LEAD = 0.04f; // Full cycle time in milliseconds. constexpr const float FULL_CYCLE_TIME = 8192.0f; struct LED { LED() {} LED(PWM* _r, PWM* _g, PWM* _b) : r(_r), g(_g), b(_b) {} PWM* r = nullptr; PWM* g = nullptr; PWM* b = nullptr; }; LED leds[NUM_LEDS]; } void Init() { leds[0] = LED{led0r, led0g, led0b}; leds[1] = LED{led1r, led1g, led1b}; leds[2] = LED{led3r, led3g, led3b}; leds[3] = LED{led4r, led4g, led4b}; leds[4] = LED{led2r, led2g, led2b}; for (uint i=0; i<NUM_LEDS; i++) { LED& led(leds[i]); led.r->setDutyResolution(DUTY_RESOLUTION); led.g->setDutyResolution(DUTY_RESOLUTION); led.b->setDutyResolution(DUTY_RESOLUTION); } } void Update() { uint ticks = sys->ticks(); for (uint i=0; i<NUM_LEDS; i++) { LED& led(leds[i]); float r = fmodf((float)ticks / FULL_CYCLE_TIME + COLOUR_LEAD*(float)i, 1.0f) * 6.0f; float cr = 0.0f; float cg = 0.0f; float cb = 0.0f; if (r < 1.0f) { cr = 1.0f; cg = r; cb = 0.0f; } else if (r < 2.0f) { cr = 1.0f - (r - 1.0f); cg = 1.0f; cb = 0.0f; } else if (r < 3.0f) { cr = 0.0f; cg = 1.0f; cb = r - 2.0f; } else if (r < 4.0f) { cr = 0.0f; cg = 1.0f - (r - 3.0f); cb = 1.0f; } else if (r < 5.0f) { cr = r - 4.0f; cg = 0.0f; cb = 1.0f; } else { cr = 1.0f; cg = 0.0f; cb = 1.0f - (r - 5.0f); } led.r->setDuty((int)(cr * (float)DUTY_RESOLUTION * MAX_BRIGHTNESS + 0.5f)); led.g->setDuty((int)(cg * (float)DUTY_RESOLUTION * MAX_BRIGHTNESS + 0.5f)); led.b->setDuty((int)(cb * (float)DUTY_RESOLUTION * MAX_BRIGHTNESS + 0.5f)); } }