Sometimes you need to manage the same amount of LEDs and buttons and maybe you run out of pins. You might consider Charlieplexing, but this makes wiring and software a bit complicated. This is a way to use only the same number of pins as you have buttons/LEDs plus two extra pins.
So you can reduce the pin-count from N x 2 to N + 2. It can be done installing an ISR that switches continuously between the LEDs and the buttons.
How to connect this breadboard containing seven buttons and seven LEDs?
Take a look at the colored circles in the picture above The holes marked in yellow go to pins to control each channel, in my case (see sketch below) to pin-3 up to pin-9. The hole marked in red next to the 47-ohms resistor goes to pin-10, which will temporarily be set to Vcc. The hole marked in blue goes to pin-2, which will temporarily be set to GND. The trick is setting the pinMode of the plusPin and the minusPin to INPUT or OUTPUT before using those pins. The code shown below shows an example of a game using an Arduino UNO where 7 buttons control 7 LEDs and the goal is to set all LEDs to the ON state. When you were using all the 20 pins of an Arduino UNO you could control 18 buttons and 18 LEDs.
const byte minusPin = 2;
const byte thePins[] = {3, 4, 5, 6, 7, 8, 9};
const byte plusPin = 10;
const byte sop = sizeof thePins;
boolean ledState[sop];
int cnt = 0;
int btn = -1;
void setup() {
Serial.begin(9600);
digitalWrite(minusPin, LOW);
TCCR2A = 0;
TCCR2B = 4;
TIMSK2 = 1;
rnd16();
newGame();
}
void loop() {
if (btn < 0) return;
Serial.println(btn);
toggle(btn);
toggle(btn - 1);
toggle(btn + 1);
btn = -1;
delay(100);
for (int i = 0; i < sop; i++)
if (!ledState[i]) return;
Serial.println("geschafft! - Neues Spiel");
newGame();
}
void newGame() {
delay(2000);
int j = 0;
int t = 100;
for (int i = 0; i < 200; i++) {
ledState[j] = false;
j++;
if (j >= sop) j = 0;
ledState[j] = true;
delay(t);
if (t > 10) t--;
}
for (int i = 0; i < sop; i++)
ledState[i] = random(2);
}
void toggle(int i) {
if (i >= sop) i = 0;
if (i < 0) i = sop - 1;
ledState[i] = !ledState[i] ;
}
ISR(TIMER2_OVF_vect) {
static boolean button;
static byte pinNr = 0; /* 0 - 6 */
static byte prev = thePins[0];
static boolean buttonState[sop];
pinNr++;
if (pinNr >= sop) {
pinNr = 0;
button = !button;
}
pinMode(plusPin, !button);
pinMode(minusPin, button);
byte pin = thePins[pinNr];
if (button) {
pinMode(prev, INPUT);
pinMode(pin, INPUT_PULLUP);
/* negative Flanke erkennen: */
byte neu = digitalRead(pin);
if (neu < buttonState[pinNr]) btn = pinNr;
buttonState[pinNr] = neu;
}
else {
/* LEDs: */
digitalWrite(plusPin, HIGH);
pinMode(pin, OUTPUT);
digitalWrite(pin, !ledState[pinNr]);
prev = pin;
}
}
void rnd16() {
word w = 0;
for (int i = 0; i < 16; i++) {
ADMUX = 0xC0 + 8; /* read internal temperature */
ADCSRA |= (1 << ADEN); /* enable the ADC */
delay(10); /* get stable */
ADCSRA |= (1 << ADSC); /* start the ADC */
/* detect end of conversion */
while (ADCSRA & (1 << ADSC));
w = (w << 1) + ADCW;
}
randomSeed(w);
WDTCSR = 0;
}
Take
care: if you want to run this skeatch using the new Arduino UNO R4, you have to modify at least these three things:
- replace the the ISR by a Timer routine (easy)
- find another way to initalize randomseed (no idea)
- increase the resistor driving the LEDs (470 ohms instead of 47 ohms).
Have fun!
Comments
Please log in or sign up to comment.