In comp.arch.embedded Ivan Shmakov said:
But then, doesn't every other contemporary OS include some kind
of package management software? Thus making downloading and
installing GCC (whether AVR, ARM, "native," or some other
variety) essentially a "single-click" operation. (The same
applies to the Arduino IDE, though.)
It's not the installing that matters, it's writing your first program and
making it do something on your board. The Arduino environment targets
particular boards, and there's a repository of example programs supplied so
you run them and they just work. No hunting for the right header files or
the right compile options, or reading random blogs looking for examples.
My understanding is that the Arduino project relies heavily on
the community for the documentation, etc. It may thus be
beneficial to edit their Wiki pages as you go.
I'm not really confident enough about that - I've got things working, but
am not knowledgeable of the details to write a manual about them.
I've run into a few painful things too. For example, the IDE isn't really
designed to cope with more than one source file. Ditching the IDE turns out
to be nontrivial - I found a Makefile on the web, and eventually got it to
compile (library issues). But the binary I have is different from the one
output from the IDE, and my binary sits there doing nothing. Even for a
trivial LED blink program.
Well, the point of my question was: could someone please share
such "complex things in a few lines of Arduino code" examples?
OK, here's my fading LED mux example. Complicated by the fact that I'm
using HSV rather than RGB to set the colour so I have to convert between the
two. I have a string of 7 tri-colour LEDs with each LED with individual
colour control. There are three common cathodes for each colour and one
anode per LED, as I needed to minimise the wiring (10 pins). I'm using the
Arduino PWM to set the dimming of the cathodes, and then muxing the anodes
using a routine driven by an interrupt. I'm using a third-party timer
library to get timer interrupts on the Due (not sure the standard library
does this yet) and a third-party PWM library because the default PWM
frequency is 1KHz which beats with my interrupt rate and makes the LEDs
flicker. In the standard library you set the PWM duty cycle of a pin with
something like
analogWrite(pin, duty=0 to 255)
I've substantially refactored the code since and merged with a bigger
project, this is my previous version. The motivation is that the LED fading
now happens entirely under interrupts - the foreground task is oblivious
they're happening. This was about three more lines of code.
So you know where to start, setup() and loop() are the two entry points in
an Arduino sketch.
Theo
#include <ARMtimer.h> // third party timer library
#include "pwm01.h"
volatile void ledSwitch();
#define LEDS 7
// run system PWM at 20KHz
#define PWMFREQ1 20000
typedef struct {
int r;
int g;
int b;
} Colour;
Colour ledColour[LEDS];
// pin numbering
int anode[LEDS] = {12, 5, 4, 3, 2, 10, 11};
int blueCathode = 7;
int greenCathode = 9;
int redCathode = 8;
int currentLED=0;
// the setup routine runs once when you press reset:
void setup() {
// set up LEDs - all off
for (int i=0; i<LEDS; i++)
{
pinMode(anode
, OUTPUT);
digitalWrite(anode, LOW);
ledColour.r = 0;
ledColour.g = 0;
ledColour.b = 0;
}
pinMode(redCathode, OUTPUT);
pinMode(greenCathode, OUTPUT);
pinMode(blueCathode, OUTPUT);
digitalWrite(redCathode, LOW);
digitalWrite(greenCathode, LOW);
digitalWrite(blueCathode, LOW);
pwm_set_resolution(8); // 8 bits of PWM resolution
pwm_setup( 7, PWMFREQ1, 1); // Pin 7 freq set to "pwm_freq1" on clock B
pwm_setup( 8, PWMFREQ1, 1); // Pin 8 freq set to "pwm_freq1" on clock B
pwm_setup( 9, PWMFREQ1, 1); // Pin 9 freq set to "pwm_freq1" on clock B
// register for our timer interrupt
startTimer(TC1, 0, TC3_IRQn, 2000, selectLED); // run at 2KHz
}
//Convert a given HSV (Hue Saturation Value) to RGB(Red Green Blue) and set
//the led to the color
// h is hue value, integer between 0 and 360
// s is saturation value, double between 0 and 1
// v is value, double between 0 and 1
//http://splinter.com.au/blog/?p=29
void setLedColorHSV(int h, double s, double v, int led) {
//this is the algorithm to convert from RGB to HSV
double r=0;
double g=0;
double b=0;
double hf=h/60.0;
int i=(int)floor(h/60.0);
double f = h/60.0 - i;
double pv = v * (1 - s);
double qv = v * (1 - s*f);
double tv = v * (1 - s * (1 - f));
switch (i)
{
case 0: //rojo dominante
r = v;
g = tv;
b = pv;
break;
case 1: //verde
r = qv;
g = v;
b = pv;
break;
case 2:
r = pv;
g = v;
b = tv;
break;
case 3: //azul
r = pv;
g = qv;
b = v;
break;
case 4:
r = tv;
g = pv;
b = v;
break;
case 5: //rojo
r = v;
g = pv;
b = qv;
break;
}
//set each component to a integer value between 0 and 255
int red=constrain((int)255*r,0,255);
int green=constrain((int)255*g,0,255);
int blue=constrain((int)255*b,0,255);
setColour(red,green,blue,led);
}
/* multiplex LEDs as a background process run from a timer so
* the foreground process can get on with something else
*
* the LEDs themselves use PWM to set the intensity
* so care is required so it doesn't beat with the PWM frequency
*/
volatile void selectLED()
{
// deactivate the previous LED
digitalWrite(anode[currentLED],LOW);
currentLED++;// advance
if (currentLED>=LEDS) currentLED=0;// % LEDS;
// set the colours on the cathodes (low=on, so invert them)
pwm_write_duty(redCathode, 255-ledColour[currentLED].r);
pwm_write_duty(greenCathode, 255-ledColour[currentLED].g);
pwm_write_duty(blueCathode, 255-ledColour[currentLED].b);
// activate the current LED
digitalWrite(anode[currentLED],HIGH);
}
void setColour(int r, int g, int b, int led)
{
ledColour[led].r = r;
ledColour[led].g = g;
ledColour[led].b = b;
}
// the loop routine runs over and over again forever:
void loop() {
for(int hue=0;hue<360;hue++)
{
for (int led=0; led<LEDS; led++)
setLedColorHSV((hue+25*led)%360,1,1,led);
// each LED has a different hue, so we colour sweep
//We are using Saturation and Value constant at 1
delay(5); //each color will be shown for 5 milliseconds
}
}