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):
// 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 ).