Unstable analog values from multiplexing

Status
Not open for further replies.

Gripporillat

Well-known member
Hi everybody. I'm constructing a Midicontroller. It has three basic elements, potis, flash buttons and normal buttons. I wrote my own library and with a lot of help from this forum it works pretty well now. Thanks to responsiveanalogread library my potis work very smothly and stably. Since there will be a lot of inputs I'm now doing some testing with multiplexing. My first try was with 7 potis and 7 flash buttons and I got that many confusing values that I had to restart. My very simple circuit looks like this now:

circuit.jpg

This is the code:

Code:
#include "SkyController.h"

SkyPoti poti(A0, 1, 1);
int mpxpin1=0;
int mpxpin2=1;
int mpxpin3=2;

void setup() {
  pinMode(mpxpin1, OUTPUT);
  pinMode(mpxpin2, OUTPUT);
  pinMode(mpxpin3, OUTPUT);

}

void loop() {
digitalWrite(mpxpin1, LOW);
digitalWrite(mpxpin2, LOW);
digitalWrite(mpxpin3, LOW);
delayMicroseconds(200);
poti.send();
digitalWrite(mpxpin1, HIGH);
digitalWrite(mpxpin2, HIGH);
digitalWrite(mpxpin3, HIGH);
delayMicroseconds(200);

}

The result is not as catastrophic as with the 14 inputs I tried before, the fader works very smoothly. But I don't get any MIDI values above 110, which is very confusing to me. It's definitely not a conversion error. It seems that about 13% of the upper side of the poti deliver the same value.

What am I doing wrong?
 
These analog multiplexers are not ideal switches, they need time to settle and they have a nonlinear series resistance from 40 to 250 Ohms which can highly trouble these SAR ADCs with their switched capacitor inputs.
The settling problem can be solved by adding a 1ms delay after writing the mux pins before you start reading the ADCs. For the source impedance problem, you’d ideally put one voltage follower op-amp per channel between the multiplexer and the Teensy. A cheaper way might be to increase the read resolution to 8 or 9 bit and to apply a nonlinear function to restore the correct midi values.
 
The VEE pin must be connected, either to GND or a negative voltage.

The E pin also needs to connect to GND.

Your diagram shows 2 wires of the pot connected to GND, which can't possibly work. Maybe just a mistake in the diagram?
 
The VEE pin must be connected, either to GND or a negative voltage.

The E pin also needs to connect to GND.

Your diagram shows 2 wires of the pot connected to GND, which can't possibly work. Maybe just a mistake in the diagram?


yes, thats just on the diagram. It's connected to Y0 instead. As far as I know, on these breakout boards, E is connected to ground via a 10k resistor and Vee is connected to ground via a jumper. When I manually connect Vee to ground, everything gets worse. After that I only receive Midi Values between 83 and 115.

Edit: Nope. I accidently connected Vee to Vcc instead. When I connect it to Ground I receive proper Values. But it seems that it's not neccesary to connect E to ground as well.
 
Have you tried a longer delay?

I prefer to set the mux for the next read after the current one and let the other work of your loop be the delay.
 
Have you tried a longer delay?

I prefer to set the mux for the next read after the current one and let the other work of your loop be the delay.

I have even tried 50 milliseconds. But the strange thing is: Now everything works fine and I'm even down to 10 microseconds. But my original program still causes very weird errors. So my code is probably involved in this problem. At the moment I'm trying to figure out what it is.
 
As far as I know, on these breakout boards, E is connected to ground via a 10k resistor and Vee is connected to ground via a jumper.

Ok then. Without a direct link, I didn't go look this up on Sparkfun to check. I answered based only on the info you gave.

If you're sure those pins are covered, then fine.

For troubleshooting, I'd recommend increasing the delays in the code to many seconds, and printing in the serial monitor so you can see which state it's in. Then measure the actual voltages at the input and output on the chip.
 
I finally found the last cause for all my errors. Somehow my pins 0,1,2 don't get set to OUTPUT. I wrote a library to count through my multiplexer. this is the code:

Code:
#include "Arduino.h"
#include "MPX74HC4051.h"

//Constructor
MPX74HC4051::MPX74HC4051(int pin1, int pin2, int pin3, int Delay) {
	pinMode(pin1, OUTPUT);
	pinMode(pin2, OUTPUT);
	pinMode(pin3, OUTPUT);
	_pin1 = pin1;
	_pin2 = pin2;
	_pin3 = pin3;
	_delay = Delay;
	
}

//Switch
void MPX74HC4051::Switch(int number) {
	switch (number) {
	case 0:
		digitalWrite(_pin1, LOW);
		digitalWrite(_pin2, LOW);
		digitalWrite(_pin3, LOW);
		delayMicroseconds(_delay);
		break;
	case 1:
		digitalWrite(_pin1, HIGH);
		digitalWrite(_pin2, LOW);
		digitalWrite(_pin3, LOW);
		delayMicroseconds(_delay);
		break;
	case 2:
		digitalWrite(_pin1, LOW);
		digitalWrite(_pin2, HIGH);
		digitalWrite(_pin3, LOW);
		delayMicroseconds(_delay);
		break;
	case 3:
		digitalWrite(_pin1, HIGH);
		digitalWrite(_pin2, HIGH);
		digitalWrite(_pin3, LOW);
		delayMicroseconds(_delay);
		break;
	case 4:
		digitalWrite(_pin1, LOW);
		digitalWrite(_pin2, LOW);
		digitalWrite(_pin3, HIGH);
		delayMicroseconds(_delay);
		break;
	case 5:
		digitalWrite(_pin1, HIGH);
		digitalWrite(_pin2, LOW);
		digitalWrite(_pin3, HIGH);
		delayMicroseconds(_delay);
		break;
	case 6:
		digitalWrite(_pin1, LOW);
		digitalWrite(_pin2, HIGH);
		digitalWrite(_pin3, HIGH);
		delayMicroseconds(_delay);
		break;
	case 7:
		digitalWrite(_pin1, HIGH);
		digitalWrite(_pin2, HIGH);
		digitalWrite(_pin3, HIGH);
		delayMicroseconds(_delay);
		break;
	}
}

the constructor I'm setting pinMode() but this part of the code somehow doesn't get executed. In my .ino I construct the object by

Code:
MPX74HC4051 mpxCount(0, 1, 2, 50);

But my errors only disappear when I write

Code:
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);

in Setup()

So at least I know how to bypass my problem but I'd like to understand why it doesn't work the way I wanted. Can anybody please explain that to me? :)
 
Somehow my pins 0,1,2 don't get set to OUTPUT.

I ran your program from msg #1 (with 3 lines commented out, since it doesn't compile as-is) and indeed those 3 pins do get configured as outputs and work properly.

Here's the waveform from pin 1 when I use my scope.

file.png

This is the code I ran:

Code:
//#include "SkyController.h"

//SkyPoti poti(A0, 1, 1);
int mpxpin1 = 0;
int mpxpin2 = 1;
int mpxpin3 = 2;

void setup() {
  pinMode(mpxpin1, OUTPUT);
  pinMode(mpxpin2, OUTPUT);
  pinMode(mpxpin3, OUTPUT);

}

void loop() {
  digitalWrite(mpxpin1, LOW);
  digitalWrite(mpxpin2, LOW);
  digitalWrite(mpxpin3, LOW);
  delayMicroseconds(200);
  //poti.send();
  digitalWrite(mpxpin1, HIGH);
  digitalWrite(mpxpin2, HIGH);
  digitalWrite(mpxpin3, HIGH);
  delayMicroseconds(200);

}


So at least I know how to bypass my problem but I'd like to understand why it doesn't work the way I wanted.

How do you imagine anyone could have guessed this was the problem, much less explain it, when you provided a program which doesn't even compile, and doesn't show this extra C++ class you were using?

Look, we have the "Forum Rule" here for a reason. We can't help you, and you have no way to get any help, if you keep us in the dark by not showing the actual code which is having the problem. Please, if you ask more questions here, follow the forum rule. It lets us help you, and it avoids wasting everyone's valuable time (even yours) with pointless questions lacking necessary info. Send the extra few minute to ask proper questions with the CORRECT code so anyone can actually see & reproduce the same problem.
 
Also, as a general suggestion from seeing the several questions you have recently asked, perhaps you should not use these extra C++ classes? They are only adding extra complexity. If you are not an expert with C++, this extra complexity can really cause even simple programs to become quite difficult.

Sometimes special C++ classes can help. But often the best approach is to get the code working the simplest way first. Then later convert to a C++ class *after* the code is already tested and known to work.
 
How do you imagine anyone could have guessed this was the problem, much less explain it, when you provided a program which doesn't even compile, and doesn't show this extra C++ class you were using?

...

I totally understand this. Within the last days I tried several ways to describe my problems and provide the neccesary informations and I got criticized for every single on of it, even for the one time I provided my whole project in a .zip. Every time I understood the criticism so I tried it differently the next time. I totally understand that many people don't want to read complex programs but get simplified versions of the part with the problem. On the other hand I also understand that sometimes it's neccesary to provide the whole project and hope that there's someone out there willing to work through it. this time I wrote a simplified version of my programm (which you can see in the first post) and showed the circuit since I was pretty sure the problem was on the hardware side. Which it was indeed. You were absolutely right, I had to connect Vee to ground. Afterwards my simplified version worked but my actual programm still had weird errors and I found out that this was due to the fact that my class seems to be unable to set the pinmode. I'm sorry for all the confusion. I am very thankful for all your help, I learned a lot from it!

Regarding the classes: You're right, that's certainly not the most efficient way to realize my project but in my view it's a very good way to improve my understanding of c++ ;)
 
Regarding the classes: You're right, that's certainly not the most efficient way to realize my project but in my view it's a very good way to improve my understanding of c++ ;)

Help in these forums is provided by unpaid volunteers (even Paul does unpaid volunteering here) who are willing to sacrifice their free time to help everybody with Teensy platform specific issues. But C++ class programming is definitely not a Teensy specific issue, but a prerequisite which should be mastered before you start whatever micro controller project, like getting a driving licence before you buy a car. There are tons of C++ tutorials and references in hundreds of different languages on the www. Mrs Google is ready to help you with finding them.
 
This is the code I ran:

Again: Sorry for the confusion! This code should clarify my problem:

Code:
class MPX74HC4051 {
  public:
    MPX74HC4051(int pin1, int pin2, int pin3, int Delay);
    void Switch(int number);
  private:
    int _pin1;
    int _pin2;
    int _pin3;
    int _delay;
};

//Constructor
MPX74HC4051::MPX74HC4051(int pin1, int pin2, int pin3, int Delay) {
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  _pin1 = pin1;
  _pin2 = pin2;
  _pin3 = pin3;
  _delay = Delay;
  
}

//Switch
void MPX74HC4051::Switch(int number) {
  //deleted to improve readability
}


int mpxpin1 = 0;
int mpxpin2 = 1;
int mpxpin3 = 2;

MPX74HC4051 mpxCount(mpxpin1, mpxpin2, mpxpin3, 10); //I thought this should set the pins to OUTPUT because of the constructor but it doesn't

void setup() {

}

void loop() {
  digitalWrite(mpxpin1, LOW);
  digitalWrite(mpxpin2, LOW);
  digitalWrite(mpxpin3, LOW);
  delayMicroseconds(200);
  digitalWrite(mpxpin1, HIGH);
  digitalWrite(mpxpin2, HIGH);
  digitalWrite(mpxpin3, HIGH);
  delayMicroseconds(200);

}
 
Help in these forums is provided by unpaid volunteers (even Paul does unpaid volunteering here) who are willing to sacrifice their free time to help everybody with Teensy platform specific issues. But C++ class programming is definitely not a Teensy specific issue, but a prerequisite which should be mastered before you start whatever micro controller project, like getting a driving licence before you buy a car. There are tons of C++ tutorials and references in hundreds of different languages on the www. Mrs Google is ready to help you with finding them.

You're right. I will keep that in mind when posting here again.
 
Within the last days I tried several ways to describe my problems and provide the neccesary informations and I got criticized for every single on of it

Yes, we've been critical but also helpful. We really do try to help here. But we also expect you to do a better job of giving correct & complete info.

You have tried several ways, but almost all of those way have involved missing or inaccurate info. When you do this, it wastes the valuable time of everyone who is trying to help you, and the best help we can give is still not so good.

Please, help us to help you. Do better if you post again. Spend a few minutes to check the code you've posted is correct and really does reproduce the problem. Check any diagrams carefully (avoid the wrong wire to GND). When you mention any non-Teensy product, give a link to the technical info. These details matter. We really do help here, but we don't like time-wasting questions with wrong & incomplete info. You can do better, if you spend a little more effort.
 
Status
Not open for further replies.
Back
Top