Friday, December 9, 2011

Arduino classes

Underneath the Arduino programming environment is C++, but I didn't think I'd be trying to find my copy of Leendert Ammeraal's C++ for Programmers this Friday afternoon (I have Stroustrup, of course, but it's not a book to find a quick and easy solution in).  I hooked up four of the RGB LED units to the Arduino Mega's 12 PWM pins, and wanted to implement a little algorithm I had run with one unit earlier in the week - set a random "target" value for the RGB values, gradually increase (or decrease) the intensity to reach the target, and then set a new random target.  The effect is to gradually change the colour and intensity of each unit, but in a pleasant drifting manner rather than jumping around all over the place.  Once I had written the code, I looked for ways to make it simpler - first using a struct, but there are difficulties writing functions for the Arduino which take a struct as a parameter (as I understand it, the pre-processor shuffles the code around so that your function ends up before the struct declaration, which means the compiler doesn't recognise the struct when it comes to compile the function).  The answer was to go straight to writing a C++ class, which turned out to be fairly simple (though I did try writing a proper constructor function, and was reminded what a complete bloody nightmare that can be especially on a Friday afternoon in a very warm office when you haven't written any O-O C++ code for about a decade - once you start dabbling in constructors, you need to think hard about copy constructors, destructors, deep and shallow copies, all that stuff).




Here's the code:
#include "rgb.h"

rgb_led led_array[4];

void setup()
{
    randomSeed(analogRead(0));
    led_array[0].initialise(3, 2, 4);    
    led_array[1].initialise(6, 5, 7);
    led_array[2].initialise(9, 8, 10);
    led_array[3].initialise(12, 11, 13);
}

void loop()
{
    for (int i = 0; i < 4; i++)
    {
        led_array[i].update();
        led_array[i].output();
    }
    delay(10);
}
This lot goes into a new tab in the Arduino project called rgb.h:
#ifndef RGB_LED
#define RGB_LED
#include <Arduino.h>

class rgb_led
{
    byte pin[3];
    byte value[3];
    byte target[3];

    public:
        void update(void);
        void output(void);
        void initialise(byte, byte, byte);
};


#endif
And this lot goes into another tab called rgb.cpp:
#include "rgb.h"

void rgb_led::initialise(byte r, byte g, byte b)
{
    pin[0] = r;
    pin[1] = g;
    pin[2] = b;
    for (int i=0; i<3; i++)
    {
        pinMode(pin[i], OUTPUT);
        value[i] = 0;
        target[i] = random(256);
    }
}

void rgb_led::update(void)
{
    for (int i=0; i<3; i++)
    {
        if (value[i] < target[i])
        {
            value[i]++;
        }
        else if (value[i] > target[i])
        {
            value[i]--;
        }
        else
        {
            target[i] = random(256);
        }
    }
}

void rgb_led::output(void)
{
    for (int i=0; i<3; i++)
    {
        analogWrite(pin[i], value[i]);
    }
}

No comments:

Post a Comment