SparkFun Forums 

Where electronics enthusiasts find answers.

For the discussion of Arduino related topics.
By warcher1
I'm having an issue with the Mayhew Labs MUX shied... the old version. Not the MUX II shield.

My project is a ping pong ball arcade and I'm using the MUX shield to read Piezo sensors on 24 different targets. The targets are split between two separate guns so I am running the positive side of 12 piezo sensors into 12 ports on the same mux chip. In other words 12 piezos are in the ports on MUX chip 1, and 12 more are on MUX chip 2.

The problem I'm seeing is that the analogRead on the chip is returning a value no matter which target gets hit. Here is a basic code fragment from my sketch:

//Give convenient names to the control pins
#define CONTROL0 5
#define CONTROL1 4
#define CONTROL2 3
#define CONTROL3 2

void setup()
//Set MUX control pins to output

void loop()
digitalWrite(CONTROL0, (0&15)>>3);
digitalWrite(CONTROL1, (0&7)>>2);
digitalWrite(CONTROL2, (0&3)>>1);
digitalWrite(CONTROL3, (0&1));
targtevalue = analogRead(2);

So, even though this should read port 0 (the first port) on the 3rd mux chip, it returns a value even though the input was on target 3 (port 2).

The ground side of the piezo is tied to a common ground. I don't think that should be a problem since it seems that the mux grounds are all tied together to the arduino ground.

At first I thought vibrations might be being transferred through the target frames... however it does the same thing if I simply squeeze the piezo.

I should also mention that I am conditioning the piezo signal using a diode inline on the positive side, and a capacitor across the positive and negative terminals. This is in addition to the usual 1m resistor across the piezo terminals. The additional components work to keep the piezo signal active and readable for about 300ms instead of the normal 20-30ms the raw signal would give.

I'll upload a schematic and photos tonight if it will help. Any input would be appreciated!
By Mee_n_Mac
warcher1 wrote:So, even though this should read port 0 (the first port) on the 3rd mux chip, it returns a value even though the input was on target 3 (port 2).
While I await the schematic, if I've understood your description, there's nothing attached on that input and so you'd expect a nothing to be read. Moreover you read something on every channel, no matter which was hit.

My initial guess is that you're seeing the effect of feeding the ADC with a high impedance source. The ATMega has a mux prior to the ADC and both have some inherent capacitance. That gets charged up, either from the piezo that was hit or stray leakage. Disconnect your shield and read open the analog pins and you'll see a similar effect. If you want to, do this test ... tie the unused ports (or port of your choosing) to ground via a 10k to 100k resistor. Then read that port. You should see it now reads near 0. Alas this isn't much of a solution as what you'll want to do in the real code is cycle among just the ports that have piezo sensors tied to them. And if you do that you'll be shuffling from high impedance to high impedance. One suggestion is that you discharge the internal capacitances by doing a dummy read between each real port. That is read a port that's terminated as suggested above between each real reading.

And even then you may face a problem. If you read the ATMega 328 datasheet you'll see it's intended to work with sources that have output impedances of 10k or less. The result of a higher source impedance is a longer time to charge up those internal capacitances. The timing of the code behind an analogRead() probably won't wait long enough btw switching the mux to read the analog pin and the actual triggering of the ADC. What I've heard is that people do a read, toss that value away, wait and then do another read to get the real ADC value. Whether that will work for you is TBD. Afterall you need to cycle among all 24 sensors in the 300 msec (or less) leaving, at best, 12.5 msec to do a dummy read, a toss-away read, a wait of XX and the real read with all the commands that have to go out to accomplish those functions. Still, if I'm correct, that (or some portion of that, perhaps no dummy read) is a potential solution.

FWIW when posting code you may want to use the code buttons so your code appears nicely formatted.
(click on to open and enlarge)
You do not have the required permissions to view the files attached to this post.
By warcher1
Sorry if I wasn't clear about this... I am only reading ports that have Piezo sensors attached to them. My project calls for 24 targets total with a single piezo attached in the corner. Right now I am only testing with three targets... attached to ports 0-2 on the third mux chip. The problem is that I'm getting a reading on one port when the input is on another. Both ports have the piezo sensors on them.

I'll upload the diagram when I get home tonight. I did draw the diagram but it's on my home computer and the topic didn't get approved until this morning.

That is an interesting idea about reading a terminated port in between real reads. I'll give that a try. There will be plenty of free ports to spare to have one terminated this way.

I also like the idea of using a double-read. Also, easy to try. Right now my code is reading the active target port every 180ms. (I have a lot more code to add but I'll try to keep the loop cycle time as low as possible.)

Ow... forgot about the code button! I'll keep that in mind in the future.

In the meantime Mark Mayhew responded to a question posted on his site and I performed some tests last night. First I tested the MUX board by disconnecting my circuit and shunting the ports to either GND or 5v. In all cases the MUX returned correct values based on way the port was jumpered. So it doesn't appear to be a problem with the shield.

Next I removed the MUX board and attached my circuit for the first 3 targets directly to the Arduino analog ports (0-2). This also worked with no problem, even when using the same target sketch that I use with the MUX (but with the analogRead function tweaked to refer to the Arduino ports.)

Tonight I'm going to try replacing the piezos with momentary switches to see if I can recreate the problem that way. I will also try your suggestions as well! Thanks for the tips!
By warcher1
One thing I forgot to mention... and I may be way off-base here. The wires I'm using to connect the piezo circuit to the MUX with are in a ribbon cable. That is to say the piezo outputs travel in parallel very close together for about 8 inches before they get to the MUX. Do you think I might be getting some inductance between the lines? I've been avoiding splitting the cable because it makes the circuit look neater... but if it's a possible issue I'll pull it apart.
By warcher1
Here is the diagram for the piezo circuit:
Of course, this shows the piezo directly attached to the arduino, but in reality we are talking about it being attached to the MUX port.
You do not have the required permissions to view the files attached to this post.
By Mee_n_Mac
Another issue ... and along the same lines ... how does the cap in the circuit above discharge once charged up via the piezo ? I'd say only by the leakage resistances of the cap and "off" state MUX. If you have enough sensitivity and SNR you might want to think about adding a resistor to more quickly bleed off that cap if it doesn't bleed off quickly enough to distinguish between two successive hits.

As for the ribbon cable ... I don't see that as a big issue. What you have is a low frequency pulse that occurs intermittently (when hit). That's not going to couple very much onto the adjacent wires.
By warcher1
I think you're right that the leakage resistance and the state of the MUX are what drain the cap. I chose one of the smallest caps I could find (a 47pf ceramic) just to keep the drain to a minimum timeframe. I tried some larger caps and they kept the signal high for as long as a minute and a half. But these 47pf caps only keep a readable signal for around 300ms, which should be about perfect for my purposes.

It was suggested that I could set an arduino port to output after reading it and that would make the port a current sink and would drain the cap quickly. That would reset it for the next read. I wasn't sure if this MUX would operate the same way... although I guess it probably would. And I also wasn't sure how long switching modes would take. So I just went with a small cap instead.
By warcher1
Ow... so... I know just enough about electronics to be confused by that. Just enough to be dangerous as they say.

I get the part about the signal needing to overcome the pin capacitance. But what does the switch in that diagram represent? Is that the selection of the port as input or output? I don't think that can be the case since it would leave the pin capcitor out of the picture. I would guess the switch gets engaged as the port gets read?

I would think that the diode/capacitor pair that I have would even the signal out for a longer period of time and that would be good for the input pin. The diode will also remove any negative voltage spikes that might be generated.

But I also understand that it will create a higher impedance on the signal and that would work against getting a reliable signal. Unfortunately I don't have a scope so I can't see exactly what is being generated. I would expect the cap is producing some kind of a sine wave.

I'm not exactly sure how to size the diode/cap pair to optimize the charge time of the pin capacitor.

I suppose we should also keep in mind that the ADC here isn't the ATMEL one, but it's the ADC in the TI CD74HC4067 chip. But I would be suprised to see it work much differently.
By Mee_n_Mac
warcher1 wrote:I suppose we should also keep in mind that the ADC here isn't the ATMEL one, but it's the ADC in the TI CD74HC4067 chip. But I would be suprised to see it work much differently.
Actually the CD74HC4067 is just a multiplexer, aka MUX, IC. It has no ADC, it's just a bunch of switches. What the code does when setting the control lines is turn off the switches to the inputs you don't want, and turn on the switch to the channel you do want. In fact I believe you get 3 channels turned on, 1 from each MUX IC. The outputs from the 3 ICs are routed to 3 analog inputs, A0 - A2, on the Arduino. The code then performs an A/D conversion on one of those channels using the Arduino ADC. I guess you could then do the other 2 channels if you wanted to, w/o having to change the controls to the MUX shield.

So the signal chain is the piezo, which will produce an AC "ringing" waveform when hit. It can't provide much current but the voltage can be very high (>100 V !!). The 1 Mohm resistor knocks that down a bit and the diode and cap act to pick and hold the biggest positive voltage. It's basically the envelope detector shown in the wiki below but with a large value resistor (as shown) in parallel with the cap.

Now I think it most likely that when the code gets around to switching the MUX to the channel that has been hit, and so has a hit induced voltage on it, that the piezo is all done it's ringing thing and what's left is your charged up 47 pF cap (which is slowly discharging due to leakage). When the MUX IC and the MUX internal to the 328 gets switched so as to connect that cap to the amp part of the ADC, charge will be transferred from your 47 pF cap to all the other caps not switched to be in parallel. The will charge up (if initially discharged) and so the voltage presented to the ADC will be reduced.

Then as you switch from one channel to the next, some of those internal caps will retain the voltage on them (again slowly discharging due to leakage) and that will charge up the MUX caps in the signal-less channel path that you switched to. That's why I think doing a dummy read will help, it will provide a (relatively) low resistance path to discharge those caps downstream of the MUX IC's output.

Because I'm working a somewhat similar thing (for an airsoft target array) when I get a chance tonight I'll see if I can make up a fair simulation to show the waveforms and what happens when switched. I think your 47 pF may be a bit on the smallish size but there's definitely a balance to be found to get the voltage in range for the ADC and have it go away fast enough so as to be able to see 2 hits, back-to-back, when fired as quickly as can be expected. I'm interested to see what range of voltages you measure for soft vs hard hits when you get this all working.
By warcher1
You know... I HAVE read the CD74HC4067 data sheet but the description at the top didn't really register until now. Yes, it makes sense that the MUX is just a switch!

Initially I'm just trying to make the game simple. So the sketch is simply activating one of the targets by turning on a set of LEDs. Then it reads that one target until it detects a hit. So I guess I could do a dummy read of a target when I activate the LEDS, and then do reads on that target until I detect a hit.

I'm still not understanding how these hits are being registered on the piezo I'm reading from when the input is on a neighboring target. Even though I'm not doing the dummy reads now I certainly would have done several reads on the activated target (with reads below the threshold) prior to vibrating the neighbor target.

That's cool to know you're working on an Airsoft target array. If you'd like to see the project I'm working on here is a video: The guns are powered by vacuum cleaner motors and the ping pong balls are filled with contruction foam. (They hit the back wall at 20' with a satisfying smack.) Fire rate is controlled by arduino with a servo motor. At this event we only had one gun complete and we were using knock-down targets. Our goal is to complete this for the Detroit Maker Faire (with two guns, automated targets, and an automated ball return and loader) in late July this year.
By Mee_n_Mac
warcher1 wrote:I'm still not understanding how these hits are being registered on the piezo I'm reading from when the input is on a neighboring target. Even though I'm not doing the dummy reads now I certainly would have done several reads on the activated target (with reads below the threshold) prior to vibrating the neighbor target.
Well .... I may be beginning to understand that. I slapped together a start on a model of the circuitry. I've yet to finalize the values and some of them are quite arbitrary (like how big a voltage you get out of the piezo itself and how long it "rings for") but I'm already seeing a result that I hadn't expected and, I think, matches what you're seeing.

I'll post both the model I'm using and the very preliminary analysis results a bit later after I've had a chance to double check that I've not made an obvious FU. And had a chance to try to understand what I'm seeing. But very briefly what I've done is simulate a piezo making an pulsed AC waveform as if it's been hit. I've sim'ed 2 such piezos (1 "hit", 1 not hit) followed by two of your envelope detectors and connected them to an Arduino ADC via a 2 channel MUX (that should match the 48 channel MUX in it's electrical characteristics). What I'm seeing is detector #1's "hit" waveform voltage at "un-hit" detector #2's output, even though that channels MUX is off and only channel #1 is on. It's as if the MUX isn't there and everything is just connected together.

My 1'st thought is that is true, everything is connected together but the MUX's off resistance isn't making any difference. Perhaps that makes sense because the piezo output resistance is so high ??? I have to think about it some more. If that turns out the be the truth, there is a solution ... to put an op-amp in as part of the envelope detector circuitry. So I do think a solution can be found, I just hate to make things more "complicated" than they need to be ... unless it really needs to be. :mrgreen:
By Mee_n_Mac
I'm beginning to understand but I need to ask a question. When you say you see a hit when reading a non-hit channel, what levels are you reading from the ADC ? What levels do you see when reading the that channel that is hit ? When you said the pulsewidth was 300 msec, how did you determine that ? What levels did you measure ?

I guess that's more than 1 question but what I'm trying to get at is how large a voltage is really coming from the piezo and then the envelope detector. If it's really many many volts > 5v, you'll still read 5v from the ADC. From the sim there seems to be 3 dominate factors pertaining to what you're seeing; the true magnitude of the signal, the output resistance of the piezo+envelope detector and the off resistance of the MUX channel. High signal levels, high output resistance (1M) and "low" off resistance (<10M) can make the hit channel appear in an un-hit channel.
By warcher1
Awesome! So, I can stop doubting my sanity. :-)

That does sound exactly like what I'm experiencing. The readings I'm getting from the ports on hits are between 870 and 1023. I determined the pulse width by writing a sketch with as little in the main loop as possible from which I printed the value read from the port and the millis() time. From that I was able to measure how long it took for the raw piezo signal, and how long it took to decay with various capacitor combinations.

I tried something else tonight. I breadboarded 3 normally open switches and jumpered them into the first 3 ports. So basically I replaced the piezo and envelope circuit with a switch with 5v on one side and the I/O port on the other (plus a 10k pull-down resistor to GND.) The reads are working fine when I hit the switches. I'm not getting reads from alternate ports.

So I tried wiring the envelope detector circuit around the switches. First I tried it without the pull-down resistor reasoning that it defeated the purpose of the capacitor. I guess I was thinking that the resistor would bleed off the capacitor too quickly. But that didn't work at all. All of the readings off of the switches were 900 or more even when they weren't closed. Once I added a pull-down resistor everything worked fine. Here is the diagram:
I know this isn't a perfect analog of the piezo sensors but the only things I can think of that are different are the use of the pull-down resistor and the kind of signal that the piezo puts out... it could be a lot higher voltage than the 5v supply I'm using.

Maybe the piezo circuit really needs that pull-down?
You do not have the required permissions to view the files attached to this post.
By Mee_n_Mac
warcher1 wrote:Maybe the piezo circuit really needs that pull-down?
Yes. Here's the circuit I started with today.
(click on to open and enlarge)
What it has is 2 envelope detectors, one 2 channel MUX and the Arduino. The Arduino also has a MUX, but I've modeled that as being "stuck" on just one channel. As it turns out the Arduino model isn't important to the analysis. In between the above items I've placed some resistors to model the wiring and traces connecting the items. Again their exact values turn out to be un-important. What I then did was vary the resistances of the MUX channels to see what happens when one channel is switched on (low resistance, = 70 ohms) and the other is switched off (high resistance, = 1 - 10 Mohms). I fiddled with the magnitude of the piezo output until it was just 5V at the detector output.

What I saw was with the off resistance = 1 Mohm, the detector #1 voltage (when "hit") was showing up at the detector #2 output at just about the same level. This was the case no matter what channel was selected (#1 or #2) to be on (the other channel would then be off). At first this surprised me but looking at the circuit some more, it made sense. A simple DC analysis with the Arduino having a very high input resistance gives me that same result. If you look back from the output of the MUX towards the input connected to the detector, you "see" a very very very high resistance. It's the leakage resistance of your 47 pF cap with a reversed biased diode in parallel. So even a 1 Mohm off MUX resistance is small in comparison and the voltage divider made by this resistance with the resistance of the active, "hit" channel gets you that same "hit" voltage on the inactive, "un-hit" channel. Increasing the MUX off resistance to 10 Mohm reduces the voltage divider but there's still some voltage that shows up on the inactive channel due to the hit.

What's the true off resistance of the MUX ? Hard to say but from the specs I'd say about 5 Mohm (which is why I picked 1 and 10 Mohm as my test cases). So depending on how large the piezo output is, you may be saturating the Arduino ADC when looking at the hit channel and still saturating (or nearly so) when looking at an un-hit channel. Dummy reads and waiting between reads won't help this problem. They only solve another problem, which you may (or may not) still have when this issue gets fixed.

So what's a simple fix ? It's to make the output resistance of the detector "small" compared to the off resistance of the MUX. Adding a resistor in parallel with the 47 pF cap does that. It also makes the voltage bleed off that cap sooner and reduces the sensed voltage at the ADC when the channel is chosen. This last part might be good if the voltage is really too high (>> 5v) at the Arduino. The reduced pulsewidth may, or may not be a problem, depending on the time it takes to poll the input. If your code is repeatedly sampling just that one channel, waiting for a hit, then the polling can be done very quickly (< 200 us btw samples) and so a short PW probably isn't an issue. A larger than 47 pF cap can also be used to "stretch" the pulse (as you've already seen).

Right now I'm playing with the sim to see what kind of resistance and cap values might be good. Something like a 100k resistor might be "small" enough to reduce the crosstalk btw channels and still retain a "long enough" PW so as to be caught by your code loop polling. But in reality a lot depends on the kind of voltage is coming out of the detector when smacked. I know the piezos can output > 100V. I was planning on placing some 5.1V Zeners on the inputs to my PIC (equivalent to your Arduino ADC pins) to make sure the voltage spikes don't smoke the input circuitry. If you're seeing 1023 counts when sampling the hit channel, you might want to think about doing that. Alternately making the resistor in parallel with the 47 pF cap smaller, your 10k or maybe even less, will also reduce the detectors output voltage. Of course this will also make the PW shorter and so you may then need to increase the 47 pF to something larger. This is where an o-scope measurement would come in very handy. Perhaps a series of measurements (using the Arduino) of the hit channel with varying resistances would be just as good as having a o-scope.
You do not have the required permissions to view the files attached to this post.
long long title how many chars? lets see 123 ok more? yes 60

We have created lots of YouTube videos just so you can achieve [...]

Another post test yes yes yes or no, maybe ni? :-/

The best flat phpBB theme around. Period. Fine craftmanship and [...]

Do you need a super MOD? Well here it is. chew on this

All you need is right here. Content tag, SEO, listing, Pizza and spaghetti [...]

Lasagna on me this time ok? I got plenty of cash

this should be fantastic. but what about links,images, bbcodes etc etc? [...]