RGB Mixer with keyboard

After having major issues due to knowing nothing about coding, I eventually got round to reading the reference files and working out how to do it.

The project was to light up a red green and blue LED using a keyboard and typing in RGB values. I created two versions of the code, one to use serial through the pc and one just to work on its own.

Photos:
http://www.flickr.com/photos/mowcius/sets/72157620583653204/

No serial version:

/* RGB Keyboard no serial v3

 *

 * Board may need resetting after turning on, not sure why but all 3 LEDs occasionally light up full when a key is pressed after turn on.

 *

 * Robin Whitfield

 * 25th June 2009

 *

 * Approx 2150 bytes

 */

 

#include "binary.h"

typedef uint8_t boolean;

typedef uint8_t byte;

#include <PS2Keyboard.h>



#define DATA_PIN 4 // Define keyboard data pin

PS2Keyboard keyboard;

int LEDR = 11; // Assign Red LED pin

int LEDG = 10; // Assign Green LED pin

int LEDB = 9; // Assign Blue LED pin

int r = 0; // Zero Red value

int g = 0; // Zero Green value

int b = 0; // Zero Blue value



void setup() {

  pinMode(LEDR, OUTPUT);  // Set Red LED pin as output

  pinMode(LEDG, OUTPUT);  // Set Green LED pin as output

  pinMode(LEDB, OUTPUT);  // Set Blue LED pin as output

  

  keyboard.begin(DATA_PIN); // Set up keyboard

}



int keyIn(){

  int key1 = 0; // Zero value for key1

  int key2 = 0; // Zero value for key2

  int key3 = 0; // Zero value for key3

  

  while(!keyboard.available()) {} // When keyboard is available:

  key1 = keyboard.read() -'0'; // Read data and assign to key1

  while(!keyboard.available()) {} // When keyboard is available

  key2 = keyboard.read() -'0'; // Read data and assign to key2

  while(!keyboard.available()) {} // When keyboard is available

  key3 = keyboard.read() -'0'; // Read data and assign to key3

  

  return ((key1*100)+(key2*10)+key3); // Turn key1, key2 and key3 into intended 3 digit number

  

}



void loop() {



  r = keyIn(); // run 'keyIn' to get Red value

  g = keyIn(); // run 'keyIn' to get Green value

  b = keyIn(); // run 'keyIn' to get Blue value

 

  r=min(r, 255); // Assign value to 255 if greater

  g=min(g, 255); // Assign value to 255 if greater

  b=min(b, 255); // Assign value to 255 if greater

  

  analogWrite(LEDR, r); // Write value to Red LED

  analogWrite(LEDG, g); // Write value to Blue LED

  analogWrite(LEDB, b); // Write value to Green LED

}

Serial version:

/* RGB Keyboard Serial v2

 * 

 * Robin Whitfield

 * 25th June 2009

 *

 * Approx 3276 bytes

 */





#include "binary.h"

typedef uint8_t boolean;

typedef uint8_t byte;

#include <PS2Keyboard.h>



#define DATA_PIN 4

PS2Keyboard keyboard;

int LEDR = 11;

int LEDG = 10;

int LEDB = 9;

int r = 0;

int g = 0;

int b = 0;



void setup() {

  pinMode(LEDR, OUTPUT);

  pinMode(LEDG, OUTPUT);

  pinMode(LEDB, OUTPUT);

  

  Serial.begin(9600);

  

  Serial.println("RGB Colour Mixer");



  keyboard.begin(DATA_PIN);

}



int keyIn(){

  int key1 = 0;

  int key2 = 0;

  int key3 = 0;

  

  while(!keyboard.available()) {}

  key1 = keyboard.read() -'0';

  Serial.print("*");

  while(!keyboard.available()) {}

  key2 = keyboard.read() -'0';

  Serial.print("*");

  while(!keyboard.available()) {}

  key3 = keyboard.read() -'0';

  Serial.println("*");

  

  return ((key1*100)+(key2*10)+key3);

  

}



void loop() {

  Serial.println("Type 'R' value now:");

  r = keyIn();

  Serial.println("Type 'G' value now:");

  g = keyIn();

  Serial.println("Type 'B' value now:");

  b = keyIn();

 

  r=min(r, 255);

  g=min(g, 255);

  b=min(b, 255);

  

  Serial.println();

  Serial.print("R =");

  Serial.println(r);

  analogWrite(LEDR, r);

  Serial.print("G =");

  Serial.println(g);

  analogWrite(LEDG, g);

  Serial.print("B =");

  Serial.println(b);

  analogWrite(LEDB, b);

  Serial.println();

  Serial.println("----------------------------");

  Serial.println();



}

I think that this code is the smallest it can get but if anyone can suggest improvements then I’ll change it…

I am going to connect it to a BlinkM Maxm once my Sparkfun order arrives…

Mowcius

A little smaller, and easier to extend:
(uncompiled, untested)

#include "binary.h"

typedef uint8_t boolean;

typedef uint8_t byte;

#include <PS2Keyboard.h>

#define DATA_PIN 4 // Define keyboard data pin

PS2Keyboard keyboard;

#define N_LEDS 3

const byte LEDpins [N_LEDS] = {11, 10, 9};

byte levels [N_LEDS];

void setup() {

  for (i = 0; i < N_LEDS; ++i) {

     pinMode(LEDpins [i], OUTPUT);
  }

  keyboard.begin(DATA_PIN); // Set up keyboard
}

int keyIn(){

  byte key [3];

  for (i = 0; i < 3; ++i) {

    while(!keyboard.available()) {} // When keyboard is not available:

    key[i] = keyboard.read() -'0'; // Read data and assign to key1
  }

  return (((int)key[0]*100L)+((int)key[1]*10L)+(int)key[2]); // Turn key1, key2 and key3 into intended 3 digit number
}



void loop() {

  for (i = 0 ; i < N_LEDS; ++i)[
      level [i] = keyIn();
    
    level [i] = min(level [i], 255); // Assign value to 255 if greater

    analogWrite(LEDpin [i], level [i]);
  }
}

Thanks!

I am not currently very familiar with using 'i' so that's why I didn't try anything with that for fear of it not working, I will test it in a mo...

Anything to make the serial one smaller because that's the one that is taking up the most space or should I just use that code as the base and add the serial commands in...

I was expecting a package with my BlinkM MaxM in today and I got a package but it was from libelium with my microSD module instead (and it came from Spain and it was still first!). I haven't been that impressed with Sparkfun so far as I ordered the stuff a few days before the board from libelium and haven't had any news (but it has been dispatched so I suppose it is the delivery rather than sparkfun themselves...

Anyway I just felt like a rant...

Thanks for the help on the code! :)

Mowcius

I am not currently very familiar with using 'i'

Oops! Well spotted - I forgot to declare it!

Of course, it doesn't have to be "i" - that's just harking back to FORTRAN (old habits die hard).

void loop() {

for (i = 0 ; i < N_LEDS; ++i)[ {
level = keyIn();[/quote]
You also managed to put in a [ when it should have been {
Once I had defined ‘i’ and changed the bracket it then told me that level had not been defined…
As I said, I don’t really know enough about coding to sort that in the best way, I had a fiddle but didn’t get to finish it…
Thanks anyway,
Mowcius

here is AWOL’s code where it compiles.

#include "binary.h"
#include <PS2Keyboard.h>

typedef uint8_t boolean;
typedef uint8_t byte;

#define DATA_PIN 4 // Define keyboard data pin
#define N_LEDS 3

const byte LEDpins[N_LEDS] = {11, 10, 9};
byte levels[N_LEDS];

PS2Keyboard keyboard;

void setup() {
  for (int i = 0; i < N_LEDS; ++i) {
     pinMode(LEDpins[i], OUTPUT);
  }
  keyboard.begin(DATA_PIN); // Set up keyboard
}

int keyIn(){
  byte key[3];
  for (int i = 0; i < N_LEDS; ++i) {
    while(!keyboard.available()) {} // When keyboard is not available:
    key[i] = keyboard.read() -'0'; // Read data and assign to key1
  }
  return (((int)key[0]*100L)+((int)key[1]*10L)+(int)key[2]); // Turn key1, key2 and key3 into intended 3 digit number
}

void loop() {
  for (int i = 0 ; i < N_LEDS; ++i){
    levels[i] = keyIn();
    levels[i] = min(levels[i], 255); // Assign value to 255 if greater
    analogWrite(LEDpins[i], levels[i]);
  }
}

Ok, thanks, I modified it slightly…

I got it slightly smaller by doing int pins and int levels rather than byte pins and byte levels and a few other things…

That also solved issues with when I put in values larger than 255… It would set it as random lower values before…

Here is the updated code:

/* Keyboard RGB Mixer
 *
 * Approx 1770 bytes
 * 
 * Created 26th June 2009
 * Modified 27th June
 *          28th June 
 */
 
#include "binary.h"
typedef uint8_t boolean;
typedef uint8_t byte;
#include <PS2Keyboard.h>

#define DATA_PIN 4 // Define keyboard data pin
#define N_LEDS 3 // Define 3 LEDs

const int LEDpins[N_LEDS] = {11, 10, 9}; // LEDs on pins 9, 10 and 11
int levels[N_LEDS];

PS2Keyboard keyboard;

void setup() {
  for (int i = 0; i < N_LEDS; ++i) {
     pinMode(LEDpins[i], OUTPUT); // Set LED pins as output
  }
  keyboard.begin(DATA_PIN); // Set up keyboard
}

int keyIn(){
  byte key[3];
  for (int i = 0; i < N_LEDS; ++i) {
    while(!keyboard.available()) {} // When keyboard is not available {} do nothing... When it is available:
    key[i] = keyboard.read() -'0'; // Read data and assign to key[i]
  }
  return ((key[0]*100)+(key[1]*10)+key[2]); // Turn key0, key1 and key2 into intended 3 digit number
}

void loop() {
  for (int i = 0 ; i < N_LEDS; ++i){
    levels[i] = keyIn();
    levels[i] = min(levels[i], 255); // Assign value to 255 if greater
    analogWrite(LEDpins[i], levels[i]); // Write the value to LED
  }
}

And here is my serial version:

/* Keyboard RGB Mixer Serial
 *
 * Approx 3274 bytes
 * 
 * Created 28th June
 * Modified 
 */
 
#include "binary.h"
typedef uint8_t boolean;
typedef uint8_t byte;
#include <PS2Keyboard.h>

#define DATA_PIN 4 // Define keyboard data pin
#define N_LEDS 3 // Define 3 LEDs

const int LEDpins[N_LEDS] = {11, 10, 9}; // LEDs on pins 9, 10 and 11
int levels[N_LEDS];

PS2Keyboard keyboard;

void setup() {
  for (int i = 0; i < N_LEDS; ++i) {
     pinMode(LEDpins[i], OUTPUT); // Set LED pins as output
  }
  
  Serial.begin(115200);
  Serial.println("Keyboard RGB Mixer");
  
  keyboard.begin(DATA_PIN); // Set up keyboard
}

int keyIn(){
  byte key[3];
  for (int i = 0; i < N_LEDS; ++i) {
    while(!keyboard.available()) {} // When keyboard is not available {} do nothing... When it is available:
    key[i] = keyboard.read() -'0'; // Read data and assign to key[i]
  }
  return ((key[0]*100)+(key[1]*10)+key[2]); // Turn key0, key1 and key2 into intended 3 digit number
}

void loop(){
  for (int i = 0 ; i < N_LEDS; ++i){
    if (i == 0)
    {
    Serial.println();
    Serial.println("---------------------");
    Serial.println("Type 'R' value now:");
    }
    else if (i == 1)
    {
    Serial.println("Type 'G' value now:");
    }
    else
    {
    Serial.println("Type 'B' value now:");
    }
    levels[i] = keyIn();
    levels[i] = min(levels[i], 255); // Assign value to 255 if greater
    analogWrite(LEDpins[i], levels[i]); // Write the value to LED
    Serial.println(levels[i], DEC);
  }

}

Thanks for the code :wink:

Mowcius

I got it slightly smaller by doing int pins and int levels rather than byte pins and byte levels and a few other things...

That also solved issues with when I put in values larger than 255... It would set it as random lower values before...

ints are two bytes, a byte is just a byte.

But, as you've experienced, the byte overflows at 255 (because 2^8 == 256), so it is insufficient if you want to store values larger than 255 [or below zero]. :)

Ok, I was not aware of what an int is classed as...

Thanks for clearing that up. I have now received my order containing a BlinkM MaxM (after paying a £13.50 surcharge of UK VAT when it entered the UK) so I will hopefully post up any changes/ some photos/videos in a few days...

Mowcius

OK, I have received my BlinkM from Sparkfun but I am not quite sure how I should try and implement it... Anyone help with the best way?

Mowcius