Go Down

Topic: Full-colour RGB 4x4 button pad (monome-esque) (Read 7511 times) previous topic - next topic

A._Square

Over at my blog I've posted a write-up of my first Arduino project. It's a 4x4 button pad, inspired by the monome using the silicon rubber part from Sparkfun, which can display fully-blended RGB colours (not just R,G,B,C,M,Y) in each button independently.

The blog entry has plenty of description and a few videos of it in action, but no code, because I'm new to Blogger and haven't figured out how to get it to display code nicely yet. So, for those who are interested, here's the generic code framework, with some Serial debugging stuff in there too. (I'm always self-conscious about showing my code, because I'm sure it could be much better, but here it is anyways):

Code: [Select]

// This is generic code for the 4x4 button pad, with separate routines for every possible event

#define DATAOUT 11//MOSI (pin 7 of AD5206)
#define DATAIN 12//MISO - not used, but part of builtin SPI
#define SPICLOCK  13//sck (pin 8 of AD5206)
#define ROWS 4
#define COLS 4

#define slavesel(x) ((x<6) ? 0 : 1)
const byte rowpin[ROWS] = {
 14,15,16,17}; // Using the analog inputs as digital pins
const byte slaveselect[2] = {
 10, 18};

// The pot register numbers for each of the red, green, and blue channels
const byte red[4] = {
 8, 7, 2, 5};
const byte green[4] = {
 10, 6, 0 , 3};
const byte blue[4] = {
 11, 9, 4, 1};
 
// Main data for the drawing routine
byte rGrid[ROWS][COLS] = {
 0};
byte gGrid[ROWS][COLS] = {
 0};
byte bGrid[ROWS][COLS] = {
 0};

const byte buttonRead[4] = {
 5, 2, 3, 4}; //Pins for the Vin of the buttons
const byte buttonWrite[4] = {
 6, 7, 8, 9}; //Pins for reading the state of the buttons
boolean pressed[ROWS][COLS] = {
 0};
 
// END DEFINITIONS, BEGIN PROGRAM

char spi_transfer(volatile char data)
{
 SPDR = data;                    // Start the transmission
 while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
 {
 };
 return SPDR;                    // return the received byte
}

byte write_pot(byte address, byte value)
{
 digitalWrite(slaveselect[slavesel(address)], LOW);
 //2 byte opcode
 spi_transfer(address % 6);
 spi_transfer(constrain(255-value,0,255));
 digitalWrite(slaveselect[slavesel(address)], HIGH); //release chip, signal end transfer
}

void setup(){
 Serial.begin(19200);
 
 byte i;
 byte clr;
 pinMode(DATAOUT, OUTPUT);
 pinMode(DATAIN, INPUT);
 pinMode(SPICLOCK,OUTPUT);
 pinMode(slaveselect[0],OUTPUT);
 pinMode(slaveselect[1],OUTPUT);

 for(byte r = 0; r < ROWS; ++r){
   pinMode(rowpin[r], OUTPUT); // Initialize rows
   digitalWrite(rowpin[r], LOW); // Turn all rows off
 }

 digitalWrite(slaveselect[0],HIGH); //disable device
 digitalWrite(slaveselect[1],HIGH);
 // SPCR = 01010000
 //interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
 //sample on leading edge of clk,system clock/4 (fastest)
 SPCR = (1<<SPE)|(1<<MSTR);
 clr=SPSR;
 clr=SPDR;
 delay(10);
 // clear all of the pot registers
 for (i=0;i<12;i++)
 {
   write_pot(i,0);
 }

 //setup the button inputs and outputs
 for(int i = 0; i < ROWS; ++i){ // ???? Is ROWS the right quanitity here?
   pinMode(buttonWrite[i], OUTPUT);
   digitalWrite(buttonWrite[i],LOW);
   pinMode(buttonRead[i], INPUT);
 }

 grid_init();

 delay(10);
}

void loop(){
 always();
 
 for(byte r = 0; r < 4; ++r){

   digitalWrite(buttonWrite[r], HIGH);
   for(byte c = 0; c < COLS; ++c){
     if(pressed[r][c] != digitalRead(buttonRead[c])){
       pressed[r][c] = digitalRead(buttonRead[c]);
       if(pressed[r][c]){
         on_press(r, c);
       }
       else {
         on_release(r, c);
       }
     }
     else {
       if(pressed[r][c]){
         while_pressed(r, c);
       }
       else {
         while_released(r,c);
       }
     }

     write_pot(red[c],rGrid[c][r]);
     write_pot(green[c],gGrid[c][r]);
     write_pot(blue[c],bGrid[c][r]);

   }
   digitalWrite(buttonWrite[r], LOW);

   digitalWrite(rowpin[r], HIGH); //turn one row on
   delayMicroseconds(750); // display
   digitalWrite(rowpin[r], LOW); //turn the row back off  
 }
}

void grid_init(){
 //initialize the button grids with blank data
 for(byte x = 0; x < ROWS; ++x){
   for(byte y = 0; y < COLS; ++y){
     rGrid[x][y] = 0;
     gGrid[x][y] = 0;
     bGrid[x][y] = 0;
   }
 }
}

void always(){

}

void on_press(byte r, byte c){
 rgb(r, c, 0, 255, 0);
 Serial.print(r, DEC);
 Serial.print(", ");
 Serial.println(c, DEC);
}

void on_release(byte r, byte c){
 rgb(r, c, 0, 0, 0);
}

void while_pressed(byte r, byte c){

}

void while_released(byte r, byte c){

}

void rgb(byte x, byte y, byte r, byte g, byte b){
 rGrid[x][y] = r;
 gGrid[x][y] = g;
 bGrid[x][y] = b;
}


Feedback is appreciated, and for those of you who are into Processing, check out the "challenge" (which is really just me trying to get a free ride from a better Processing programmer  ;) ).

big93

the colors are very cool, they just amaze me how many colors can come from ONE rgb led!

hows the rubber buttons from spark by the way? i was thinking about gettin em and the breakout, but i wasent sure if it was quality, or just junk


A._Square

I think the buttons are very nice (although I have no basis for comparison). They're definitely not junk, though. Very good feel, and very sturdy.

big93


eustace


big93

well, it hurts me to say, i ordered all the parts to make this, and i cost me almost 100 bucks...

lol but i cant wait to get this working, it looks awsome-rific!

hopefully if i come up with problems, you can assist me in solving them...
nice project, and i cant wait to be able to make stuff!

A._Square

I've designed my own board for the second version of this. It has LED drivers on-board instead of the potentiometer, which allows the LEDs to be much brighter and have a wider range of colours. It'll still be driven by the Arduino, at least for now. I'm hoping to find a few like-minded tinkerers in order to split the costs of ordering boards. I've posted more details here. I'd confirm that the board works electrically first, and then send copies out to a group of people who can all play around with it, sharing Arduino code and interfacing software.

If you're interested, please send me a message (an email to the address on that page, or a PM on this board) and I'll be in touch.

big93

square, i am a little confused on how to get the first revision working.

ok, for the buttons, i connect the button grounds straight to the arduino, while connecting the power pins through pull down resistors? or the other way around? And laos, how do i check for button presses that way through the code?

and as for the led's;
why are they all the transistors connected to the analog pins? what is supposed to be sensed?

And finally;
how do i hook up the second digital potentiometer ic? it was VERY briefly explained, but it would be easier for me to receive a pin from the digital pot, to connect to the arduino. The other pins i got, just that one single pin that is different then the first digital pot.

thanks in advance!
good luck with the kit!

A._Square

Quote
ok, for the buttons, i connect the button grounds straight to the arduino, while connecting the power pins through pull down resistors? or the other way around? And laos, how do i check for button presses that way through the code?


The button grounds go straight to the Arduino (to input pins), with a pull-down resistor. The button power pins are connected to output pins, which you bring high one at a time in sequence. You check for button presses by reading the input pins. You know which row is being brought high, and you read input off of four columns, so you know all the button presses. The sequence is: set all rows low, bring row 1 high, read all four columns; set all rows low, bring row 2 high, read all four columns; etc.

Quote

and as for the led's;
why are they all the transistors connected to the analog pins? what is supposed to be sensed?


The analog pins are being used as digital pins here. You can address them like any other digital pin, numbers 14-19. The transistors are there so that the Arduino pins don't need to source too much current.

Quote

And finally;
how do i hook up the second digital potentiometer ic? it was VERY briefly explained, but it would be easier for me to receive a pin from the digital pot, to connect to the arduino. The other pins i got, just that one single pin that is different then the first digital pot.


I'm not sure I understand the question, but you connect all of the digital pot pins on the second pot to the exact same wires as the first one, except for the slave select pin. Then you send data to one pot by setting the slave select high on one and low on the other, and vice versa to send data to the other pot. If you get the AD5204 instead of the AD5206 there's a serial out and you can daisy chain the chips, but the 5204 is only a quad potentiometer, so you'd need 3 chips instead of 2.

I hope that helps!

big93

ok, this cleared alot up, but i have a few more questions;

resistor values seem to be different all over the board, what values did you use for the led's to light up, and what values did you use for the pull down resistors?

Now the digital potentiometers make more sense, but what pin did you connect the second slave pin?
and if i understand, your explination means that both digital pots cant be on at the same time?
So they are switch to and from very quickly im guessing.

And the code posted up top, Is it the code for the first video on the page? where the one color gets sent to all the other colors when pressed?
Also, how do i work with the code, meaning how do i make random colors appear? and how do i change individual buttons colors? The code is interesting, but very confusing, which means you did a good job shortening it! If i cant read the code, it means it's good, so don't worry, im just noobish at c... but i'm learning.

Thanks alot for the help already, and i cant wait to get this up and running hopefully tomorrow when my rgb led's get here. Stupid mail took almost 2 weeks to get them here...

Good luck with the future of this project!
-big93

big93

hmmm, i'm also having trouble hooking up the pull down resistors, can you tell me how you hooked them up?

i connected the brown black orange resistors together, and grounded them, and i connected the red red brown resistors to arduino pins, and i connected both of the other ends together, and connected the switch pins to with the resistors:

so it was like this

Wire to arduino -----> connected to red red brown resistor-----> connected to both button ground, and the brown black orange resistor -----> connected to ground.

with the sketch above, it seems only 1 row of buttons lights up, and the last 2 rows of buttons light up when i press the buttons, and the row in between them doesent do anything...

thanks in advance

Oracle

What does one do with this project besides blink the leds?  I've been reading about monomes and clones for ages but everything assumes you already know what to do with it.  Just to blink LEDs, wouldn't sparkfun's 8x8 RGB matrix be better?

Also, does the sparkfun bezel break into 2x2 units like the buttons and PCB do?

big93

well, to answer your first question, i believe monomes are just a huge pad of buttons, in this case only a 4x4 that when pressed producde sounds, from that, the sounds can be manipulated, like for instance you can set different sounds to different buttons and make your own types of songs, or remixes, or any other type of thing, try youtubing "monomes" and see why the buttons are important. Thats is why simple led's don't help, you need a buttons surrounding the led's to show an indication of a change. But then again, i'm just trying to repeat this dudes first experiment, and ill go from there.

and as for the bezel, i do not believe that it breaks up into 2x2, but with a saw im sure you could work something out... or just buy your own case, and drill holes, which is what ill probably do...

hope that helped u

Oracle

#14
Feb 28, 2008, 01:40 am Last Edit: Feb 28, 2008, 01:42 am by Oracle Reason: 1
Quote
well, to answer your first question, i believe monomes are just a huge pad of buttons, in this case only a 4x4 that when pressed producde sounds, from that, the sounds can be manipulated, like for instance you can set different sounds to different buttons and make your own types of songs, or remixes, or any other type of thing, try youtubing "monomes" and see why the buttons are important. Thats is why simple led's don't help, you need a buttons surrounding the led's to show an indication of a change. But then again, i'm just trying to repeat this dudes first experiment, and ill go from there.

and as for the bezel, i do not believe that it breaks up into 2x2, but with a saw im sure you could work something out... or just buy your own case, and drill holes, which is what ill probably do...

hope that helped u


From your description, I still don't really understand, maybe because I'm not into music.  You have samples on each button, but what do the lights do?  BTW, I do understand it's a generalized keyboard, it does nothing until programmed, but I mean in use how is it used.

I know I couldn't hack the bezel without it looking like crap, same for cutting the square holes out of an enclosure.  At least now I know not to order a bezel if I want 2x2 panels.

Go Up