Go Down

Topic: Reading multiplexed data in Pd (Read 1 time) previous topic - next topic

alexandros301

Hi,
I've been trying to use two multiplexers, one for potentiometers and the other for push buttons and read that in Pure Data. My initial problem was that I couldn't set the beginning of the data stream, every time I opened the serial port the data array would start in another position.
Tweaking it a bit and copying a bit of code from the repatcher (http://www.openmusiclabs.com/projects/repatcher/) I managed to make it more stable, but now I'm getting some values that won't change even if I turn the knobs or push the buttons.
This is the code I've come up with so far

Code: [Select]

#define CONTROL0 5
#define CONTROL1 4
#define CONTROL2 3
#define CONTROL3 2

byte muxarray0[33];
byte muxarray1[16];

void setup() {
  Serial.begin(9600);
  pinMode(CONTROL0, OUTPUT);
  pinMode(CONTROL1, OUTPUT);
  pinMode(CONTROL2, OUTPUT);
  pinMode(CONTROL3, OUTPUT);
}

void loop() {
  muxarray0[0] = 0xc0; // denote beginning of data
  byte k = 1;
  for (int i = 1; i < 17; i++) {
    digitalWrite(CONTROL0, (i&15)>>3);
    digitalWrite(CONTROL1, (i&7)>>2);
    digitalWrite(CONTROL2, (i&3)>>1);
    digitalWrite(CONTROL3, (i&1));
    unsigned int mod = analogRead(i);
    muxarray0[k++] = mod & 0x007f;
    muxarray0[k++] = (mod >> 7) & 0x0007; // in order to get 0 - 1023
  }
  for (int j = 0; j < 16; j++) {
    digitalWrite(CONTROL0, (j&15)>>3);
    digitalWrite(CONTROL1, (j&7)>>2);
    digitalWrite(CONTROL2, (j&3)>>1);
    digitalWrite(CONTROL3, (j&1));
    muxarray1[j] = digitalRead(A1);
  }
    Serial.write(muxarray0, 33);
    Serial.write(muxarray1, 16);
}


Can someone tell me what I'm doing wrong?

Thanks

g_u_e_s_t

why is it analogRead(i) below?  there are only 6 analog ins, and this will make it count up to 16.

Code: [Select]

   digitalWrite(CONTROL3, (i&1));
    unsigned int mod = analogRead(i);
    muxarray0[k++] = mod & 0x007f;

alexandros301

This section is LEDs and Multiplexing, right? Well, I'm using a multiplexer...with four digital pins you can turn one analog pin into sixteen...
BTW, I'm trying all this on a Nano, which has eight analog pins, but that won't really matter in this case..

g_u_e_s_t

i must be confused about how analogRead() works.  i thought you put in a number, and that was the pin it read.  so analogRead(1) reads the first pin, analogRead(2) reads the second pin, and analogRead(16) reads the 16th pin.  i dont know exactly what your circuit looks like, but i am assuming you have a mux which funnels all your inputs into a single analog input pin (if you had 16 analog input pins, you wouldnt need the mux).

your for() loop increments i from 1 to 16.  therefore you are reading in analog from pins 1 to 16, but there are no pins above 8 on the chip you are using.

Code: [Select]

 for (int i = 1; i < 17; i++) {
   digitalWrite(CONTROL0, (i&15)>>3);
   digitalWrite(CONTROL1, (i&7)>>2);
   digitalWrite(CONTROL2, (i&3)>>1);
   digitalWrite(CONTROL3, (i&1));
   unsigned int mod = analogRead(i);
   muxarray0[k++] = mod & 0x007f;
   muxarray0[k++] = (mod >> 7) & 0x0007; // in order to get 0 - 1023
 }

alexandros301

Hm, I mixed things up a bit I guess, It should write analogRead(0) I guess.And the for loop should go from 0 to 15 not 1 to 16. I don't have my arduino available right now, so I'll have to check tomorrow. Thanks for pointing this out.

Grumpy_Mike

Your loop should output the loop index to the four multiplex pins. Do you know how to do that?

alexandros301

This is how I do it

Code: [Select]

for (int i = 0; i < 16; i++) {
    digitalWrite(CONTROL0, (i&15)>>3);
    digitalWrite(CONTROL1, (i&7)>>2);
    digitalWrite(CONTROL2, (i&3)>>1);
    digitalWrite(CONTROL3, (i&1));


Which I actually copied from an older thread about multiplexing and reading data in Max/MSP.
This uses the four digital pins for the multiplexing and outputs a four bit binary number that goes from 0-15 decimal which are the multiplexer channels AFAIK. Am I getting something wrong here?

Grumpy_Mike

#7
Mar 25, 2013, 09:52 am Last Edit: Mar 25, 2013, 09:56 am by Grumpy_Mike Reason: 1
Well it is backwards. That is control 3 is normally the most significant bit not the least.
Then the and masks are a bit wrong. You need to isolate a single bit not several.
Finally there is no need to do all that shifting.
Code: [Select]

for (int i = 0; i < 16; i++) {
   digitalWrite(CONTROL0, i & 1);
   digitalWrite(CONTROL1, i & 2);
   digitalWrite(CONTROL2, i & 4);
   digitalWrite(CONTROL3, i & 8);

alexandros301

I'm using the digital pins in a sequence I used to in earlier attempts where my problem was the header of the array. Trying out your suggestion what I get (in a Pd patch) is the following:
0 0 0 0
0 0 0 1
0 0 2 0
0 0 2 1
0 4 0 0
0 4 0 1
0 4 2 0
0 4 2 1
8 0 0 0

etc. which looks correct as far as the switching between zero and non-zero numbers in each bit occur, but those should be ones and zeros only, right? Why get twos, fours and eights? The anding and shifting I'm doing gives sequences of zeros and ones in the range of 0-15 (0000, 0001, 0010, 0011, 0100 etc.)..

Grumpy_Mike

Quote
Why get twos, fours and eights?

I don't know you have posted nothing of your PD sketch and you said that the code you had was only for switching the multiplexer so it is nothing to do with what PD displays.
So give me something to go on please. Howe about the full code from the arduino as a start.

alexandros301

I put the code in the very first post of this thread, but changed it slightly after the suggestion of g_u_e_s_t. So here's what I have so far

Code: [Select]

#define CONTROL0 5
#define CONTROL1 4
#define CONTROL2 3
#define CONTROL3 2

byte muxarray0[33];
byte muxarray1[16];

void setup() {
  Serial.begin(9600);
  pinMode(CONTROL0, OUTPUT);
  pinMode(CONTROL1, OUTPUT);
  pinMode(CONTROL2, OUTPUT);
  pinMode(CONTROL3, OUTPUT);
}

void loop() {
  muxarray0[0] = 0xc0; // denote beginning of data
  byte k = 1;
  for (int i = 0; i < 16; i++) {
    digitalWrite(CONTROL0, (i&15)>>3);
    digitalWrite(CONTROL1, (i&7)>>2);
    digitalWrite(CONTROL2, (i&3)>>1);
    digitalWrite(CONTROL3, (i&1));
    unsigned int mod = analogRead(0);
    muxarray0[k++] = mod & 0x007f;
    muxarray0[k++] = (mod >> 7) & 0x0007; /* I got this from some other sketch. I multiply this by 128 in Pd and then add it to the result of the line of code above this, this way I'm supposed to get a range of 0-1023, cause byte will take only 8bit...
*/
  }
  for (int j = 0; j < 16; j++) {
    digitalWrite(CONTROL0, (j&15)>>3);
    digitalWrite(CONTROL1, (j&7)>>2);
    digitalWrite(CONTROL2, (j&3)>>1);
    digitalWrite(CONTROL3, (j&1));
    muxarray1[j] = digitalRead(A1);
  }
    Serial.write(muxarray0, 33);
    Serial.write(muxarray1, 16);
}


This is for two multiplexers in pin 0 and 1, the first one with 16 potentiometers and the second with 16 push buttons. I have also attached the Pd patch where I'm trying to read all the data, in case you're using Pd you could give it a glimpse...I've also attached the patch where I'm testing the bitwise operations, the one I've included in the code above and the one you suggested.

Thanks

alexandros301

Ok got some point further. First of all, this is really embarrassing, but I forgot to power up the breadboard with the potentiometers and the buttons. Guys I'm really sorry for this.
What happens now is that the potentiometers work fine (or almost fine, they reach 1023, but they go down to 6 or 7, not 0), but the push buttons show some strange behavior. When I press any of them all the potentiometer values change. For example if a potentiometer is at 1023 it will go to around 1000, if it's 432 it won't change, if it's 530 it will go to 527. These value changes seem stable for all potentiometers. Plus, the built in blue LED on the arduino dims slightly when I push a button. I don't get any 1 or 0 where I'm expecting to get in the Pd patch from the buttons.
I've been using 220 Ohm resistors for the buttons after this wiki page (https://ccrma.stanford.edu/wiki/Sensor_Arduino_Lab), since all this is supposed to end up in a box with a beagleboard (this wiki is about the beagleboard and Pd), but I'm connecting the resistor to ground and the multiplexer pin, instead of 5 volts as indicated in the wiki page.

Any help greatly appreciated,
Thanks

Grumpy_Mike

If the pots don't go down to zero then they are either wired wrong or they have some end stop resistors. Have you wired it up like the flex sensor in that link? If so that is not the way to wire a pot. Each end to supply and ground and the wiper to the analogue input.
If pushing a button effects the analogue readinfpg then again you have wired it wrong to used the wrong value of resistor. You only need a 10K pull down resistor not a 220R, even that will not affect the reading but if it is 22R then you could be dragging too much power out of the supply and causing the output voltage to sag.

alexandros301

No the pots are wired as you say, not as the flex sensor in that link. It's a bit funny, cause I've used the same buttons with 220Ohm resistors with the standard firmata and they worked fine. I'll give it a try with 10K resistors tomorrow.
Just to be sure, I'm wiring one leg of the button to ground through the resistor, the same leg goes to the digital input (in the multiplexer) and the other leg goes to 5 volts, right?

Thanks

Grumpy_Mike

No that is not the way to wire a button.
From input to button, other end to ground and then enable the internally pull up resistors.
This gives a LOW on press
To invert this
10K from input to ground, button from input to +5V

Go Up