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));
      }
    }
  
< USB Control
Sensors >
^ Overview ^

Garth is generally available for part-time, casual, and full-time appointments, ad-hoc, short-term or long-term. Click here for further information, or here for Garth's contact details.

Navigation