Saturday, 29 November 2008

Nano Arduino and Classes

I bought a Nano Arduino because I love the form factor of the whole package. It's small, has the built in USB interface which means you don't even have to worry about a seperate power supply and the breadboard means you can do simple prototyping with the minimum of hassle.
I have had a bit of hassle with the Arduino build environment. It's set up to compile C++ but to keep things simple the developers have put in automatic function prototyping. This is very good except when you find that simple things that should work don't. I had trouble passing structs in as parameters to a function so I switched to using classes. In this case a colour class that had a method to set the LED to a particular colour or to 'fadeTo' a specified colour.
I wanted to make a simple program that used PWM on 3 seperate pins to change the colour of an RGB LED. Very simply to get working but a bit harder to get working neatly. Here's my working solutions where I configure an array of colour objects and then call methods of those objects to set the colour or to fade from one colour to another.


// Cycling colours
// by Adam http://hackinghardware.blogspot.com/

int ledpin_green = 6;
int ledpin_blue = 11;
int ledpin_red = 3;

// Class declared inline to allow for simple prototyping
class Colour
{
public:
int red;
int blue;
int green;
void SetColour();
void FadeTo(Colour,int);
void Do(int,int,int);
Colour (void);
Colour(int,int,int);
};

// Constructor
Colour::Colour(void)
{}

// Constructor with parameters
Colour::Colour(int r, int g, int b)
{
red = r;
green = g;
blue = b;
}

void Colour::SetColour()
{
// Note all the values are 255 minus the value as my output is active low
analogWrite(ledpin_red, 255-red);
analogWrite(ledpin_green, 255-green);
analogWrite(ledpin_blue, 255-blue);
}

void Colour::FadeTo(Colour col, int fadeDelay)
{
int c_red;
int c_green;
int c_blue;
int value;
for(value = 0; value < 255; value++)
{
c_red = ((red * 255) + (col.red * value) - (red * value)) / 255;
c_green = ((green * 255) + (col.green * value) - (green * value)) / 255;
c_blue = ((blue * 255) + (col.blue * value) - (blue * value)) / 255;

analogWrite(ledpin_red, 255-c_red);
analogWrite(ledpin_green, 255-c_green);
analogWrite(ledpin_blue, 255-c_blue);

delay(fadeDelay);
}
}

void Colour::Do(int red, int green, int blue)
{
}

Colour Colours[12] = {
Colour(255,0,255), // Magenta
Colour(127,0,255), // Violet
Colour(0,0,255), // Blue
Colour(0,127,255), // Azure
Colour(0,255,255), // Cyan
Colour(0,255,127), // Aquamarine
Colour(0,255,0), // Green
Colour(127,255,0), // Charteuse
Colour(255,255,0), // Yellow
Colour(255,127,0), // Orange
Colour(255,0,0), // Red
Colour(255,0,127) // Rose
};

int MaxCols = 12;
int CurrentCol;
void setup()
{
CurrentCol = 0;
}

void loop()
{
int newColour = (CurrentCol + 1) % MaxCols;
Colours[CurrentCol].FadeTo(Colours[newColour], 10);
CurrentCol = newColour;
if (random(20) == 1)
{
delay(random(1000,5000));
}
}

The pre-defined colour wheel is pulled from here:http://en.wikipedia.org/wiki/Tertiary_color

I'm happy with this because it allows me to call very simple functions from the main loop. Not 100% happy with the RGB output pins being hardwired in. But I don't want to add extra complexity into my colour class to avoid that. Probably I should have an output class that I pass into the .FadeTo method which contains that configuration information.