code not working for 16-channel multiplexer

I have been pulling my hair out for hours trying to get the below code to work. It compiles and uploads and works in Max, but the values are just noise.... Any ideas how to get the multiplexer to work properly?

// Code for multiplexing Analog inputs and getting all the others into MaxMSP
//based on Andrew Benson's sketch
// 16 channels
int r0 = 0;
int r1 = 0;
int r2 = 0;
int r3 = 0;
int row = 0;
int ID = 0;
char analogValue[96];//array of analog values
char current=0;//current position of analog value in array
int digVal;//digital pins bits are packed into a single variable
char imask = 128;//index bytes start with 1
char theEnd = 255;//byte to signal message end to Max patch

//set multiplexer control pins
#define mpinA 5
#define mpinB 6
#define mpinC 7
#define mpinD 8

//bit-packed truth tables per pin for multiplexer
int bin [] = {0, 1, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111};


//select analog channels to multiplex
char is_muxPIN[6] = {1,0,0,0,0,0};//currently just uses A0. change to multiplex other inputs
char muxcount;//variable to store the number of multiplexed inputs

void setup(void) {
  Serial.begin(9600);
  digVal=0;
  muxcount=0;
  for (int i = 0;i<6;i++){
    muxcount+=is_muxPIN[i];
  }
  for (int i = 2;i<14;i++){
    digitalWrite(i,HIGH);//enable pullups
  }
  if(muxcount>0){
    pinMode(mpinA,OUTPUT);
    pinMode(mpinB,OUTPUT);
    pinMode(mpinC,OUTPUT);
     pinMode(mpinD,OUTPUT);
  }  
  while (establishContact()==0){delay(100);}  //wait for 99 byte
}
  
//uses serial.write() to avoid needless symbol creation in MaxMSP  
void loop() {
  
  //read analog pins
  for (int g = 0;g<6;g++){ 
    packValue(g);
  }
  char total = current+1;
  sendOFF(total);//send everything to Max
  current=0;//reset analog value counter
  delay(10);//wait 10 milliseconds
  //see if someone tried to turn us off:
  if(establishContact()==1) {
    while(establishContact()==0) {delay(100);}//go into idle mode
  }
}

void sendOFF(char total){
  //Send analog values in the format 0x81 a1 a2.....0xFF
  Serial.write(imask|1);
  for (int i = 0;i<total;i++){
      Serial.write(analogValue[i]);   
  }
  Serial.write(theEnd);//ends analog stream
}

//read an analog pin and then pack into low/high bytes
void packValue(int index) {
    if(is_muxPIN[index]==1) muxAnalog(index);
    else regAnalog(index);
}


char establishContact(void){
    if (Serial.available() > 0) {
      char checkup = Serial.read();
      if (checkup==99) return 1;
      else return 0;
    }
    else return 0;
}

//function for handling multiplexed analog reading
void muxAnalog(char index){
  if (Serial.available()) {
    ID = Serial.read();
    Serial.print(ID);
  }
  row = bin[ID];
  r0 = row & 0x01;
  r1 = (row>>1) & 0x01;
  r2 = (row>>2) & 0x01;
  r3 = (ID>7)? 1:0;
  digitalWrite(5, r0);
  digitalWrite(6, r1);
  digitalWrite(7, r2);
  digitalWrite(8, r3);
  delayMicroseconds(50);//allow analog signal to settle
  regAnalog(index);
    }

//read an analog pin
void regAnalog(char index) {
      int tempA = analogRead(index);
      analogValue[current]=tempA & 127;
      current++;
      analogValue[current] = (tempA>>7);
      current++;
}

int bin [] = {0, 1, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111};

Binary?

You could just as well have used ID.

row = bin[ID];
  r0 = row & 0x01;
  r1 = (row>>1) & 0x01;
  r2 = (row>>2) & 0x01;
  r3 = (ID>7)? 1:0;

As AWOL inferred that "bin" array values are not binary as such, they are 16 decimal numbers half of which are greater than 1 thousand.

Hint, 1001 != B00001001

Also as this is just a straight 1:1 mapping of the ID, use that directly.


Rob

The thing is I have tried to combine 2 examples of multiplexer code....one that used the old 405 multiplexer that only needs 3 digital control pins (this is the one that comes into Max in a usable format) and an example for the 406 multiplexer, that you have to set 4 pins in the code. Plus I am a total beginner with the language..

But if I just replace the messed up binary bit with ID, i get errors....

//bit-packed truth tables per pin for multiplexer
int bin [ID];

//select analog channels to multiplex
char is_muxPIN[6] = {1,0,0,0,0,0};//currently just uses A0. change to multiplex other inputs
char muxcount;//variable to store the number of multiplexed inputs

Given the time differences AWOL's probably tuck up in bed now, so I'll have a stab.

int bin [ID];

Wrong, you don't need this array at all, just use the ID value directly

row = bin[ID];

use

row = ID;


Rob

Similar problem. I've been trying yo make this thing work with no success. When I attach anything to the inputs of the multiplexer, nothing happens (the serial keeps printing zero as value for each pin). Where did I go wrong?

int count;
int pinval;

int s0=6; // control pins
int s1=7;
int s2=8;
int s3=9;

void setup(){
Serial.begin(9600);
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(){
for(count=0; count<=15; count++){
s0 = count & 0x01;
s1 = (count>>1) & 0x01;
s2 = (count>>2) & 0x01;
s3 = (count>>3) & 0x01;
int pinval=analogRead(0);
Serial.print(count);
Serial.print("-");
Serial.println(pinval);
//Serial.println(count,DEC);
delay(300);}

}

Does the below actually make the digital output pin high when needed?

s0 = count & 0x01;
s1 = (count>>1) & 0x01;
s2 = (count>>2) & 0x01;
s3 = (count>>3) & 0x01;

Clue:

const int s0=6; // control pins
const int s1=7;
const int s2=8;
const int s3=9;

I replaced

int s0=6; // control pins
int s1=7;
int s2=8;
int s3=9;

with

const int s0=6; // control pins
const int s1=7;
const int s2=8;
const int s3=9;

and got the following error message:

_16_ch_multiplexer.cpp: In function 'void loop()':
_16_ch_multiplexer:22: error: assignment of read-only variable 's0'
_16_ch_multiplexer:23: error: assignment of read-only variable 's1'
_16_ch_multiplexer:24: error: assignment of read-only variable 's2'
_16_ch_multiplexer:25: error: assignment of read-only variable 's3'

Why doesn't it work? Is it the binary counter?

No, the clue is that you're not writing to the multiplexer, just to the variables s0, s1, s2 and s3.

Thanks very much! Will follow that lead!

You were right! The solution:

int count;
int pinval;

int cpin1=6;
int cpin2=7;
int cpin3=8;
int cpin4=9;

int a;
int b;
int c;
int d;

void setup(){
Serial.begin(9600);
pinMode(cpin1, OUTPUT);
pinMode(cpin2, OUTPUT);
pinMode(cpin3, OUTPUT);
pinMode(cpin4, OUTPUT);
}
void loop(){
for(count=0; count<=15; count++){
a = count & 0x01;
b = (count>>1) & 0x01;
c = (count>>2) & 0x01;
d = (count>>3) & 0x01;
digitalWrite(cpin1, a);
digitalWrite(cpin2, b);
digitalWrite(cpin3, c);
digitalWrite(cpin4, d);
int pinval=analogRead(0);
Serial.print(count);
Serial.print("-");
Serial.println(pinval);
delay(300);
}
}

Things like pin numbers are generally constant (or arrays of constants), so it is best to make them such.
It helps to avoid problems like yours earlier.