Friday, October 19, 2007

Reading 16 digital inputs

This post relates to the previous one and is an extension of trying to help Phil Savard on the Littlebird Electronics forum.

Circuit
The schematic that can be used is to be found in example number two ("Daisy Chaining") in the Arduino ShiftIn tutorial. However, the pin numbers have been changed in the Arduino code to match whatever pins are used as data, clock and latch.


Breadboard
Note that there are no switches or devices currently connected to the 4021s. This is so that the wiring is easier to see.



Max/MSP Patch

The Max/MSP patch can be downloaded here.





Arduino Code
The Arduino code is almost a duplicate of what can be found on the Arduino ShiftIn tutorial. Note that the pin numbers have been changed in the Arduino code to match whatever pins are used as data, clock and latch.
int latchPin = 2;

int dataPin = 4;
int clockPin = 3;

byte switchVar1 = 0;
byte switchVar2 = 0;

void setup() {
Serial.begin(57600);

pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, INPUT);

}

void loop() {
digitalWrite(latchPin,1);

delayMicroseconds(20);
digitalWrite(latchPin,0);
switchVar1 = shiftIn(dataPin, clockPin);

switchVar2 = shiftIn(dataPin, clockPin);
Serial.print(switchVar1);

Serial.print(switchVar2);
delay(10);
}

byte shiftIn(int myDataPin, int myClockPin) {
int i;

int temp = 0;
int pinState;
byte myDataIn = 0;

pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, INPUT);

for (i=7; i>=0; i--)

{
digitalWrite(myClockPin, 0);
delayMicroseconds(0.2);

temp = digitalRead(myDataPin);
if (temp) {

pinState = 1;
myDataIn = myDataIn | (1 << i);

}
else {
pinState = 0;
}

digitalWrite(myClockPin, 1);
}
return myDataIn;

}

10 comments:

xaft said...

thanks for the great example, it helped alot....

i was trying to find information about the other way around, i mean demultiplexing 16 outputs, in this case controlling 16 leds with 2 x 4051, and could not find any arduino related info about it... do you have any idea where should i look?

thanks so much for this great blog, it has been very helpful!

Sebastian Tomczak said...

Hi Xaft,
If you are wanting to control more than just 12 LEDs (ie. one per digital pin), then a good option is to use a 595 shift register.

I have made an example of achieving 24 digital (on / off) outputs suitable for driving LED's that only consumes three digital pins on the Arduino board and uses 3 595 shift registers.

http://little-scale.blogspot.com/2008/01/three-595-shift-registers.html

and be sure to check out the Arudino shiftOut example (this is for 16 LED's

http://www.arduino.cc/en/Tutorial/ShiftOut


Let me know if you need a hand with any of these tutorials. They are very handy to know and understand.

chiko said...

great! ill try it out tommorow... ill let u know!

thanks


xaft

xaft said...

btw, do you know whats resulting the delay in when shifting using this code? i have the feeling its allmost 100 ms delay or so....

Sebastian Tomczak said...

are you using a pc?

xaft said...

no, im on macbook (running 10.4.11)

luderec said...

Hi there, I tried this patch and it seems to work but I found that It's quite slow... am I probably doing something wrong? I'm using the 57600 serial port. But I takes something like half of a second from when I push the button to when I see the change in Max.. Do you have any suggestion?

Sebastian Tomczak said...

You might want to try changing the line:

delayMicroseconds(0.2);

to

delayMicroseconds(1);

Im not sure if this will help.

Cheers

luderec said...

Great! Now if works perfectly! Well, I still have to figure out why with this patch/code/circuit combination after a while my MacBookPro disables trackpad and keyboard and I have to reboot the computer but this is another problem... Thanks again! Booth for your help and your patch!

Sebastian Tomczak said...

Okay, this means that your USB serial buffer is overflowing.

You can try two things in tandem:

change the metro speed to 1, 2 or 3 milliseconds, and make the delay time in:

switchVar2 = shiftIn(dataPin, clockPin);
Serial.print(switchVar1);

Serial.print(switchVar2);
this line ---> delay(10);

higher, try 15 for example