Question on teensy analog inputs

Status
Not open for further replies.

Glouton

Member
Hi!
I'm quite new on teensy programming, just made an arcade midi controller but that's not the point here.
I want to make a controller which has 20 potentiometers and 2 faders. But my question is: is it possible with teensy ? Cause at my knownledge teensy only have 12 Analog inputs and it seems I need 22. How can I do that ?
Thanks for your answers !
 
You're right. I also want to use the Teensy for its 12 analog inputs. I first considered using a 4067 (16-input analog multiplexer) and maybe it would work for you (4digital out, and you can connect 16 pots to one analog in). In my case, I dropped the idea because I wanted lots of precision and the internal resistor would have had an impact.

But at the cost of the teensy, and given its "flexibility/cost" factor, I'd recommend you simply to use 2 teensy instead of one, one master and one slave. Probably all other alternative will be more complex and in the end more costly... even if they look easier and/or cheaper at first.
 
Thanks for your reply !
The idea of two teensy seems the best for me. Do I google it or can you explain to me how to use a teensy as slave / master ?
 
Another option is the use of a analog multiplexing chip like the 4067 series. Keep in mind, the chip adds about 120-160Ohm to the total resistance, but in return, you get 16 inputs into one analog port, though you will have to use 4 digital lines to control them all. Use two 4067 chips with one Teensy (and two analog channels) and you can send the same input channel select signals to both 4067's, allowing you 32 inputs with 4 digital and two analog lines.

Whether external multiplexing makes sense is largely a function of speed - but the Teensy ADC is so fast that I doubt your project would not be able to read each channels hundreds of times per second.
 
Thanks for your reply !
The idea of two teensy seems the best for me. Do I google it or can you explain to me how to use a teensy as slave / master ?

If you can get CD4067 (they can run from 3.3 V) it will be easier to use than inventing a scheme to connect two Teensys. It sounds like your application won't need extreme precision, so it should suit. If you can't get the CD4067, perhaps a CD4051 is more available (but only 8 channnels).
 
Wow ! Thanks for your very complete replys!
I'll look for that CD4067, but the thing is that I'm more Bob the builder than an Electronic genius. I tough about something that seems a lot more simple to me. You'll probably say that it's awful but if I juste take two teensy, program them individually (like teensy one: button 1/2/3/4 and teensy two: button 5/6/7/8) and then just link the two "individual" controllers that I have with a USB HUB ? (It's just to send midi signals, not to make something very advanced).
Thanks again for all your tips ;)
 
The 4067 is very easy to use. The four Select pins can be driven directly from the teensy - 2^4 = 16. So if all pins are off, channel 0 is selected, etc. - look for the 'truth' table in the chip datasheet. Mr. Tigoe of Arduino fame even has an example on his website re: how to use one. The only difference being that he's using it as an output to drive LEDs vs. using it as an input into the ADC. To me, this is a lot simpler than making a master/slave teensy combination. But to each his/her own.
 
Analog switches like the 4067 are a pretty good solution. I personally prefer to use the 74HC4051, because it's very easily available and less expensive. It's only 8 switches instead of 16, but you can expand to 16, 24 or 32 by using multiple chips. Each chip has an enable pin that can shut off all 8 switches, so it's easy to connect the outputs of 2 or more chips together and use more digital pins to enable only 1 chip at a time.

The MIDI page has a section called "Connecting Many Buttons & Knobs/Sliders". Scroll down, since it's near the end.

The 2 Teensy approach is also a good one. The easiest way to communicate between them is I2C using the Wire library. You only need to connect 2 pins, plus ground. Pullup resistors are a good idea (and required if using Teensy 3.0). On the main "slave" chip, use Write.begin(address) and set up an onRequest function to give the other board whatever data you want. On the "master" board, use the normal Wire requestFrom(address, quantity) to read the data. You can connect as many slave devices as needed, each with a different address. Well, at least up to 127 of them, since the address is 7 bits and has to be non-zero. Probably the easiest and fastest design would have the slave always reading the inputs in loop() to an array, and then just transmit the array contents within the onRequest function. You could also do the analogRead() inside the onRequest function, but that would cause the master to wait while the slave makes the measurements, so reading them in loop() to an array is probably best.
 
Thanks everyone !
I read about that 4067 and it's seems really a good thing for me, so i'll try to use it and come back if it doesn't work as I want or if I have another question.
 
Hi again

I ordered three 74HC4051 to connect my 20 pots and wired all the stuff as explained at the bottom of this tutorial : http://http://www.pjrc.com/teensy/td_midi.html.

I now have my first problem (but not the last, i'm sure). When I connect the usb cable my mac says “As an USB peripheral consumed too much energy one or more USB peripherals were disabled“ (not the right traduction, i had it in french). I tried cutting the VCC wire and the message didn't appear anymore. It's seems logic. But my pots won't work ;) so anybody can help me with that ? Do a need a resistor ? Are my pots too strong ? a cable is wrong wired ?

Thanks for your reply
 
It's quite likely your wiring has a mistake that is connecting +5V and GND together.

If you have a multimeter, set it to ohms. Disconnect any cables from your board, and measure between GND (black lead) and +5V (red lead). It will probably read 0 ohms (or very close to 0), which is bad. The normal reading is a slowly increasing number, because the small test current from your multimeter slowly charges the capacitors on the board.
 
Hello! Hadn't much time to finish my project but I'm back on it with new questions. I read this nice tutorial http://bildr.org/2011/02/cd74hc4067-arduino/ and decided to use one of the sparkfun's multiplexers. As I need 20 pots I wired 16 of them on the mux as the schematics on blidr and thougt wiring the 4 lasting to the tennsy's analog ins. The wiring seems to be pretty well I don't have any error message when plugin-in teensy and can transport code to it. At this point it's a step forward but now my ignorance in coding stops me from finishing my midi controller. Can I modify the code from bildr to get my midi signals ? I searched and tried quite a lot but it never worked. Ableton detected the teensy midi but not any midi signals.
Thank you for your helpful answers
 
Sorry for the re-up but I really need your help. I know it seems a bit lazy but I spent this whole afternoon trying and searching for solutions cause I really haven't patience to learn all the arduino code by myself. Wit the exemple code from Bildr I get the values from all my potentiometers in the serial monitor so my only problem is how to get these values and transform them to midi signals. I saw a lot of midi libraries but I don't know of to integrate them. Sorry for disturbing again.. Hope someone can help me find my way out
 
First, make sure you have the latest 1.18-rc1 Teensyduino installed.

Then look at the examples in File > Examples > Teensy > USB_MIDI

AnalogControlChange might be a good starting point.
 
Thanks again for your help
I tried to build my code with the usb midi example you show me and this helps me going on. But I made a (or more) mistake in the code and when I tried to compile it I got “invalid operands of types 'void' and 'int' to binary 'operator/' “.
Here's the entire code (be kind it's probably awful :rolleyes: )
Code:
#include <Bounce.h>

const int channel = 1;


int s0 = 10;
int s1 =11;
int s2 = 14;
int s3 = 13; //Mux control pins

int controlpin = A0;

int previouspot0 = 0;
int previouspot1 = 0;
int previouspot2 = 0;
int previouspot3 = 0;
int previouspot4 = 0;
int previouspot5 = 0;
int previouspot6 = 0;
int previouspot7 = 0;
int previouspot8 = 0;
int previouspot9 = 0;
int previouspot10 = 0;
int previouspot11 = 0;
int previouspot12 = 0;
int previouspot13 = 0;
int previouspot14 = 0;
int previouspot15 = 0; // store previous values


int MUX_read = 0;

elapsedMillis msec = 0;


void setup(){

  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT); 
  
  digitalWrite(s0, LOW);
  digitalWrite(s1, LOW);
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);
  
}

void loop(){
  
  if (msec >= 20) {
    msec = 0;
    int pot0 = readMux(0) / 8;
    int pot1 = readMux(1) / 8;
    int pot2 = readMux(2) / 8;
    int pot3 = readMux(3) / 8;
    int pot4 = readMux(4) / 8;
    int pot5 = readMux(5) / 8;
    int pot6 = readMux(6) / 8;
    int pot7 = readMux(7) / 8;
    int pot8 = readMux(8) / 8;
    int pot9 = readMux(9) / 8;
    int pot10 = readMux(10) / 8;
    int pot11 = readMux(11) / 8;
    int pot12 = readMux(12) / 8;
    int pot13 = readMux(13) / 8;
    int pot14 = readMux(14) / 8;
    int pot15 = readMux(15) / 8; //read values and write them in variables
    
    // transmit only if control change
   if (pot0 != previouspot0) {
      usbMIDI.sendControlChange(controlpin, pot0, channel);
      previouspot0 = pot0;
    }
    if (pot1 != previouspot1) {
      usbMIDI.sendControlChange(controlpin, pot1, channel);
      previouspot1 = pot1;
    }
    if (pot2 != previouspot2) {
      usbMIDI.sendControlChange(controlpin, pot2, channel);
      previouspot2 = pot2;
    }
    if (pot3 != previouspot3) {
      usbMIDI.sendControlChange(controlpin, pot3, channel);
      previouspot3 = pot3;
    }
    if (pot4 != previouspot4) {
      usbMIDI.sendControlChange(controlpin, pot4, channel);
      previouspot4 = pot4;
    }
    if (pot5 != previouspot5) {
      usbMIDI.sendControlChange(controlpin, pot5, channel);
      previouspot5 = pot5;
    }
    if (pot6 != previouspot6) {
      usbMIDI.sendControlChange(controlpin, pot6, channel);
      previouspot6 = pot6;
    }
    if (pot7 != previouspot7) {
      usbMIDI.sendControlChange(controlpin, pot7, channel);
      previouspot7 = pot7;
    }
    if (pot8 != previouspot8) {
      usbMIDI.sendControlChange(controlpin, pot8, channel);
      previouspot8 = pot8;
    }
    if (pot9 != previouspot9) {
      usbMIDI.sendControlChange(controlpin, pot9, channel);
      previouspot9 = pot9;
    }
    if (pot10 != previouspot10) {
      usbMIDI.sendControlChange(controlpin, pot10, channel);
      previouspot10 = pot10;
    }
    if (pot11 != previouspot11) {
      usbMIDI.sendControlChange(controlpin, pot11, channel);
      previouspot11 = pot11;
    }
    if (pot12 != previouspot12) {
      usbMIDI.sendControlChange(controlpin, pot12, channel);
      previouspot12 = pot12;
    }
    if (pot13 != previouspot13) {
      usbMIDI.sendControlChange(controlpin, pot13, channel);
      previouspot13 = pot13;
    }
    if (pot14 != previouspot14) {
      usbMIDI.sendControlChange(controlpin, pot14, channel);
      previouspot14 = pot14;
    }
     if (pot15 != previouspot15) {
      usbMIDI.sendControlChange(controlpin, pot15, channel);
      previouspot15 = pot15;
    }
    
  }
   
  // MIDI Controllers should discard incoming MIDI messages.
   while (usbMIDI.read()) {
    // ignore incoming messages
  }
}

void readMux(int channel){
  int controlPin[] = {s0, s1, s2, s3};

  int muxChannel[16][4]={
    {0,0,0,0}, //channel 0
    {1,0,0,0}, //channel 1
    {0,1,0,0}, //channel 2
    {1,1,0,0}, //channel 3
    {0,0,1,0}, //channel 4
    {1,0,1,0}, //channel 5
    {0,1,1,0}, //channel 6
    {1,1,1,0}, //channel 7
    {0,0,0,1}, //channel 8
    {1,0,0,1}, //channel 9
    {0,1,0,1}, //channel 10
    {1,1,0,1}, //channel 11
    {0,0,1,1}, //channel 12
    {1,0,1,1}, //channel 13
    {0,1,1,1}, //channel 14
    {1,1,1,1}  //channel 15
  };

  //loop through the 4 sig
  for(int i = 0; i < 4; i ++){
    digitalWrite(controlPin[i], muxChannel[channel][i]);
  }
}
 
The problem is with your readMux() function. It doesn't output any number, but in loop() you're using it as if it output a number.

First, you need to change readMux() from "void" to "int", like this:

Code:
int readMux(int channel) {

When you use "void", that means your function doesn't return any output. When you use "int", that means your function will output an integer.

Of course, this is only half of the problem. The other half is your readMux function needs to actually use "return" to send some integer back to loop().

Perhaps you meant for it to do something like this:

Code:
    {0,1,1,1}, //channel 14
    {1,1,1,1}  //channel 15
  };

  //loop through the 4 sig
  for(int i = 0; i < 4; i ++){
    digitalWrite(controlPin[i], muxChannel[channel][i]);
  }

  // allow a brief delay for the voltage to stabilize after changing the mux pins
  delayMicroseconds(25);

  int n;
  n = analogRead(A9);
  return n;   // this sends the variable "n" as output, so loop() can receive it
}

I just took a random guess on "A9" (you didn't post a diagram or other solid info about what you've wired up to the pins, but it seems you have a 4067 mux which feeds 16 pots to a pin?)

Actually, it's just a guess that you intended to use analogRead, but that seems to fit the conversation above. I must confess, I only skimmed briefly before writing this message, but hopefully this helps get you past this compiler error, even if it's exactly the right thing?
 
Thanks again

It's true I didn't give you much info about my project. It's was clear for me but yes it can't be as clear for you so let's make it clearer.

My project is to make a simple MIDI controller with 16 pots to use it to control effects and stuff in my DAW.
I tried to adapt a scheme to show my wiring: here it is Wiring.png

I think this can make helping easier. Tell me if I missed something.

I tried the changes you suggested me for the code and yes it it compiles well now, my DAW seems to receive continue midi signal so my code isn't that good..

I really appreciate your help and hope can make this little program to the end and have my Midi controller working soon :)

EDIT: I repost my code so you can check it
Code:
#include <Bounce.h>

const int channel = 1;


int s0 = 10;
int s1 =11;
int s2 = 14;
int s3 = 13; //Mux control pins

int controlpin = A0;

int previouspot0 = 0;
int previouspot1 = 0;
int previouspot2 = 0;
int previouspot3 = 0;
int previouspot4 = 0;
int previouspot5 = 0;
int previouspot6 = 0;
int previouspot7 = 0;
int previouspot8 = 0;
int previouspot9 = 0;
int previouspot10 = 0;
int previouspot11 = 0;
int previouspot12 = 0;
int previouspot13 = 0;
int previouspot14 = 0;
int previouspot15 = 0; // store previous values


int MUX_read = 0;

elapsedMillis msec = 0;


void setup(){

  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT); 
  
  digitalWrite(s0, LOW);
  digitalWrite(s1, LOW);
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);
  
}

void loop(){
  
  if (msec >= 20) {
    msec = 0;
    int pot0 = readMux(0) / 8;
    int pot1 = readMux(1) / 8;
    int pot2 = readMux(2) / 8;
    int pot3 = readMux(3) / 8;
    int pot4 = readMux(4) / 8;
    int pot5 = readMux(5) / 8;
    int pot6 = readMux(6) / 8;
    int pot7 = readMux(7) / 8;
    int pot8 = readMux(8) / 8;
    int pot9 = readMux(9) / 8;
    int pot10 = readMux(10) / 8;
    int pot11 = readMux(11) / 8;
    int pot12 = readMux(12) / 8;
    int pot13 = readMux(13) / 8;
    int pot14 = readMux(14) / 8;
    int pot15 = readMux(15) / 8; //read values and write them in variables
    
    // transmit only if control change
   if (pot0 != previouspot0) {
      usbMIDI.sendControlChange(controlpin, pot0, channel);
      previouspot0 = pot0;
    }
    if (pot1 != previouspot1) {
      usbMIDI.sendControlChange(controlpin, pot1, channel);
      previouspot1 = pot1;
    }
    if (pot2 != previouspot2) {
      usbMIDI.sendControlChange(controlpin, pot2, channel);
      previouspot2 = pot2;
    }
    if (pot3 != previouspot3) {
      usbMIDI.sendControlChange(controlpin, pot3, channel);
      previouspot3 = pot3;
    }
    if (pot4 != previouspot4) {
      usbMIDI.sendControlChange(controlpin, pot4, channel);
      previouspot4 = pot4;
    }
    if (pot5 != previouspot5) {
      usbMIDI.sendControlChange(controlpin, pot5, channel);
      previouspot5 = pot5;
    }
    if (pot6 != previouspot6) {
      usbMIDI.sendControlChange(controlpin, pot6, channel);
      previouspot6 = pot6;
    }
    if (pot7 != previouspot7) {
      usbMIDI.sendControlChange(controlpin, pot7, channel);
      previouspot7 = pot7;
    }
    if (pot8 != previouspot8) {
      usbMIDI.sendControlChange(controlpin, pot8, channel);
      previouspot8 = pot8;
    }
    if (pot9 != previouspot9) {
      usbMIDI.sendControlChange(controlpin, pot9, channel);
      previouspot9 = pot9;
    }
    if (pot10 != previouspot10) {
      usbMIDI.sendControlChange(controlpin, pot10, channel);
      previouspot10 = pot10;
    }
    if (pot11 != previouspot11) {
      usbMIDI.sendControlChange(controlpin, pot11, channel);
      previouspot11 = pot11;
    }
    if (pot12 != previouspot12) {
      usbMIDI.sendControlChange(controlpin, pot12, channel);
      previouspot12 = pot12;
    }
    if (pot13 != previouspot13) {
      usbMIDI.sendControlChange(controlpin, pot13, channel);
      previouspot13 = pot13;
    }
    if (pot14 != previouspot14) {
      usbMIDI.sendControlChange(controlpin, pot14, channel);
      previouspot14 = pot14;
    }
     if (pot15 != previouspot15) {
      usbMIDI.sendControlChange(controlpin, pot15, channel);
      previouspot15 = pot15;
    }
    
  }
   
  // MIDI Controllers should discard incoming MIDI messages.
   while (usbMIDI.read()) {
    // ignore incoming messages
  }
}

int readMux(int channel){
  int controlPin[] = {s0, s1, s2, s3};

  int muxChannel[16][4]={
    {0,0,0,0}, //channel 0
    {1,0,0,0}, //channel 1
    {0,1,0,0}, //channel 2
    {1,1,0,0}, //channel 3
    {0,0,1,0}, //channel 4
    {1,0,1,0}, //channel 5
    {0,1,1,0}, //channel 6
    {1,1,1,0}, //channel 7
    {0,0,0,1}, //channel 8
    {1,0,0,1}, //channel 9
    {0,1,0,1}, //channel 10
    {1,1,0,1}, //channel 11
    {0,0,1,1}, //channel 12
    {1,0,1,1}, //channel 13
    {0,1,1,1}, //channel 14
    {1,1,1,1}  //channel 15
  };

  //loop through the 4 sig
  for(int i = 0; i < 4; i ++){
    digitalWrite(controlPin[i], muxChannel[channel][i]);
  }
  delayMicroseconds(25);
  
  int n;
  n = analogRead (A0);
  return n;
}

If you have a simpler solution fell free not using this code I really don't know if I'm in the right way w
 
Last edited:
Status
Not open for further replies.
Back
Top