PDA

View Full Version : Using a 4051 to read buttonstates



davidteensy
04-15-2013, 07:51 PM
I have researched widely on the 4051 multiplex chip on the internet, and found some useful info. But I have not been able to deduce a code that fit's my needs.


I am trying to use the 4051 to read eight buttons (momentary switches), and then write to led's depending on the buttons latest state. I know how to write the code for this using the teensy alone (in a few different ways), but I require more pins then come on the teensy. maybe I need a different chip then the 4051? but from what I have read I should be able to use it...

from the teensy site -

// select 74HC4051 channel 5 (of 0 to 7)
digitalWrite(1, HIGH);
digitalWrite(2, LOW);
digitalWrite(3, HIGH);

// allow 50 us for signals to stablize
delayMicroseconds(50);

// read the signals routed to pins 10, 19, 20
// through channel 5 of each 74HC4051 chip
buttonPin10channel5.update();

-
ok, that, and other sources, show me how to select one of the pins on the 4051, and initiate a delay to allow the chip to be read/written.

but my question is regarding the debounce for the button... my attempts to turn on an led with the above example have not worked.

I will provide my attempted code later today, and verify my schematic with y'all, but in the meantime any clear ideas to aid me in my project would be great.

thank you

PaulStoffregen
04-16-2013, 12:52 AM
Usually you would not use a 4051 chip for LEDs. The 74HC4051 is really only useful for connecting lots of switches and analog signals to the analog inputs.

Normally, shift registers or latches are used for LEDs. You write data to them and they remember the state for each LED, so the output signal is maintained constant. With a mux like the '4051, the LED is only on briefly.

It is possible to mux LEDs, but normally that is done by driving them with much higher current since they're on for only a fraction of the time. Normally other circuitry than a '4051 is used, because the current requirements are so high.

davidteensy
04-16-2013, 04:41 PM
Hey PAul, thanks for the reply. I was aware of the limitations regarding the 4051 driving outputs, and so perhaps I wasn't clear in the first post. I won't have any leds on the 4051 pins, but rather the switches solely, driving the leds on teensy pins.

It's a tight fit but I think i will be using all 25 teensy pins, so the switches on the mux would be necessary.

how does that code look?

Nantonos
04-16-2013, 07:51 PM
Rather than depend on software debouncing, have you considered hardware RC or RC-schmitt trigger debouncing (before the multiplexer)?

PaulStoffregen
04-17-2013, 11:04 AM
I have never tried the Bounce library with muxed switches. It seems like this should work, more or less the way you described. I would use a 4.7K pullup resistor at the Teensy pin, to minimize the need for delay between switching the mux and calling the Bounce update() function.

Since you're posting this question, does that mean it is not actually working?

davidteensy
04-22-2013, 05:48 PM
I have tried a few different methods (bounce update, and boolean) to digitalwrite to a specific pin on the 4051, and then read the in/out pin to see when the button has been pressed. but it has not worked...

I found this helpful tutorial -
http://www.gammon.com.au/forum/?id=11976

but I cannot for the life of me figure out how to write the loop part to read a set of buttons... i dunno, shouldn't this be easier?

truncated and altered from the link -


int readSensor (const byte which)
{
// select correct MUX channel
digitalWrite (addressA, (which & 1) ? HIGH : LOW);
digitalWrite (addressB, (which & 2) ? HIGH : LOW);
digitalWrite (addressC, (which & 4) ? HIGH : LOW);
// now read the sensor
return digitalRead(sensor);
} // end of readSensor

void loop ()
{
// show all 8 sensor readings
for (byte i = 0; i < 7; i++)
{
\\what do I write here?
digitalWrite (ledPIN,
(readSensor (i));
}
delay (300);
} // end of loop

aedile
04-23-2013, 03:53 AM
Here is basic code that will write out which input is being activated to the Serial monitor. I ripped this out of a sketch that used a 4051 and modified with your function. It's untested, so take with a grain of salt.


void loop (){
// show all 8 sensor readings
for (byte i = 0; i < 7; i++){
if (readSensor(i) == HIGH) {
//Button is not pressed...
} else {
//Button is pressed
Serial.print(i);
Serial.println(" Button is pressed!!!");
}
}
delay(300);
}

PaulStoffregen
04-23-2013, 01:56 PM
You probably need a brief delay.





int readSensor (const byte which)
{
// select correct MUX channel
digitalWrite (addressA, (which & 1) ? HIGH : LOW);
digitalWrite (addressB, (which & 2) ? HIGH : LOW);
digitalWrite (addressC, (which & 4) ? HIGH : LOW);


// A BRIEF DELAY IS PROBABLY NEEDED HERE


// now read the sensor
return digitalRead(sensor);
} // end of readSensor



When things like this do not work, first verify the hardware. Remove all code which rapidly changes the output. Just set it to route one of the 8 signals and measure the 3 control signals, 8 inputs and 1 output with a voltmeter. Change the input and make sure the output changes. Then repeat 7 more times, to verify all 8 paths work.

While you do this, you'll gain a much better "feel" for the hardware. Later, when you work on the software, not only will you know the hardware works, but if you initially had any misunderstandings, you will have cleared up your understanding of the hardware which allows you to write the software well.

phoenixperry
01-29-2017, 08:45 AM
[QUOTE=PaulStoffregen;30961]You probably need a brief delay.


I can confirm this to be true.Even 1ms fixes this. Code w/no delay works fine on an Uno but not on a teensy. Is this possibly because the teensy is so much faster?

The delay isn't even visible or tactile (for the motors I am using) it is so fast.