Pages: [1] 2   Go Down
Author Topic: Reading multiplexed data in Pd  (Read 1466 times)
0 Members and 1 Guest are viewing this topic.
Athens
Offline Offline
Full Member
***
Karma: 0
Posts: 105
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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
Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 99
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

Athens
Offline Offline
Full Member
***
Karma: 0
Posts: 105
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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..
Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 99
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
 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
  }
Logged

Athens
Offline Offline
Full Member
***
Karma: 0
Posts: 105
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34724
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Athens
Offline Offline
Full Member
***
Karma: 0
Posts: 105
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

This is how I do it

Code:
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?
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34724
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
for (int i = 0; i < 16; i++) {
    digitalWrite(CONTROL0, i & 1);
    digitalWrite(CONTROL1, i & 2);
    digitalWrite(CONTROL2, i & 4);
    digitalWrite(CONTROL3, i & 8);
« Last Edit: March 25, 2013, 03:56:54 am by Grumpy_Mike » Logged

Athens
Offline Offline
Full Member
***
Karma: 0
Posts: 105
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.)..
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34724
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Athens
Offline Offline
Full Member
***
Karma: 0
Posts: 105
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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

* muxuino.pd (5.09 KB - downloaded 5 times.)
* binary0-15.pd (1.32 KB - downloaded 5 times.)
Logged

Athens
Offline Offline
Full Member
***
Karma: 0
Posts: 105
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34724
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Athens
Offline Offline
Full Member
***
Karma: 0
Posts: 105
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34724
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Pages: [1] 2   Go Up
Jump to: