Go Down

Topic: Mux Madness Coding Query (Read 879 times) previous topic - next topic

sirkristofer

Jul 03, 2016, 12:15 pm Last Edit: Jul 03, 2016, 12:27 pm by sirkristofer
I want to use this code in a MIDI controller I'm working on. But I want it to only print a value if a value has changed rather than cycling through the values.

Much like...(in psuedo code)

if(value != lastValue) {
Serial.println( new value );
}

Any help would be grately appreciated. I just can't figure out how to do it. I'm such a noobie.

Code: [Select]
//Mux control pins
int s0 = 2;
int s1 = 3;
int s2 = 4;
int s3 = 5;

//Mux in "SIG" pin
int SIG_pin = 0;
int valLast = 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);

 Serial.begin(9600);
}


void loop(){

 //Loop through and read all 16 values
 //Reports back Value at channel 6 is: 346
 for(int i = 0; i <= 1; i ++){
   Serial.print("Value at channel ");
   Serial.print(i);
   Serial.print("is : ");
   Serial.println(readMux(i));
   delay(1000);
  }
}


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]);
 }

 //read the value at the SIG pin
 int val = analogRead(SIG_pin);


 return val;
}



OldSteve

#1
Jul 03, 2016, 12:18 pm Last Edit: Jul 03, 2016, 12:32 pm by OldSteve
These are not code tags:- <code></code>
These are code tags:-

If you change your post you'll make potential helpers much happier. :)
(It gets rid of those annoying italics and makes it much easier to read.)

It also helps to hit Ctrl-T in the IDE to auto-format the code before posting.

Thanks for doing that. :)

I'm too tired to go right over your code right now, it's getting late here, but someone will come along who will help.

N.B. Good to see you fixed this line. I was about to suggest it. :) :-
Code: [Select]
digitalWrite(controlPin[i], muxChannel[channel][i]);
Please do not PM me for help. I am not a personal consultant.
And others will benefit as well if you post your question publicly on the forums.

OldSteve

Just looking quickly, perhaps you could have your function return -1 if the value hasn't changed, then only print if the return value isn't -1.

You need to look over your code for other problems, too.

Code: [Select]
//Loop through and read all 16 values
 //Reports back Value at channel 6 is: 346
 for(int i = 0; i <= 1; i ++){

The above will only loop through two values, 0 and 1, not 16.
Please do not PM me for help. I am not a personal consultant.
And others will benefit as well if you post your question publicly on the forums.

Whandall

The generation of the address can be much simpler.
I think good naming can make comments superfluous.

Code: [Select]
const byte muxControlPins[] = {2, 3, 4, 5};
const byte muxInputPin = A0;

int lastValues[16];

void setup() {
  for (byte mcp = 0; mcp < sizeof(muxControlPins); mcp++) {
    pinMode(muxControlPins[mcp], OUTPUT);
  }
  Serial.begin(115200);
}

void loop() {
  static unsigned long lastCheck;
  unsigned long topLoop = millis();
  if (topLoop - lastCheck >= 1000) {
    lastCheck = topLoop;
    for (byte channel = 0; channel < 16; channel++) {
      int currVal = readMux(channel);
      if (currVal != lastValues[channel]) {
        Serial.print(F("Value at channel "));
        if (channel < 10) {
          Serial.write(' ');
        }
        Serial.print(channel);
        Serial.print(F(" changed from "));
        Serial.print(lastValues[channel]);
        Serial.print(F(" to "));
        Serial.println(currVal);
        lastValues[channel] = currVal;
      }
    }
  }
}

int readMux(byte channel) {
  digitalWrite(muxControlPins[0], channel & 0x01);
  digitalWrite(muxControlPins[1], channel & 0x02);
  digitalWrite(muxControlPins[2], channel & 0x04);
  digitalWrite(muxControlPins[3], channel & 0x08);
  return analogRead(muxInputPin);
}
Code: [Select]
Value at channel  0 changed from 0 to 703
Value at channel  1 changed from 0 to 703
Value at channel  2 changed from 0 to 703
Value at channel  3 changed from 0 to 703
Value at channel  4 changed from 0 to 703
Value at channel  5 changed from 0 to 703
Value at channel  6 changed from 0 to 703
Value at channel  7 changed from 0 to 703
Value at channel  8 changed from 0 to 703
Value at channel  9 changed from 0 to 703
Value at channel 10 changed from 0 to 703
Value at channel 11 changed from 0 to 703
Value at channel 12 changed from 0 to 703
Value at channel 13 changed from 0 to 703
Value at channel 14 changed from 0 to 703
Value at channel 15 changed from 0 to 703
Value at channel  0 changed from 703 to 704
Value at channel  1 changed from 703 to 704
Value at channel  2 changed from 703 to 704
Value at channel  3 changed from 703 to 704
Value at channel  4 changed from 703 to 704
Value at channel  5 changed from 703 to 704
Value at channel  6 changed from 703 to 704
Value at channel  7 changed from 703 to 704
Value at channel  8 changed from 703 to 704
Value at channel  9 changed from 703 to 704
Value at channel 10 changed from 703 to 704
Value at channel 11 changed from 703 to 704
Value at channel 12 changed from 703 to 704
Value at channel 13 changed from 703 to 704
Value at channel 14 changed from 703 to 704
Value at channel 15 changed from 703 to 704
Value at channel 14 changed from 704 to 705
Value at channel 15 changed from 704 to 705
Value at channel  0 changed from 704 to 705
Value at channel  1 changed from 704 to 705
Value at channel  2 changed from 704 to 706
Value at channel  3 changed from 704 to 706
Value at channel  4 changed from 704 to 705
Value at channel  5 changed from 704 to 705
Value at channel  6 changed from 704 to 705
Value at channel  7 changed from 704 to 705
Value at channel  8 changed from 704 to 705
Value at channel  9 changed from 704 to 705
Value at channel 10 changed from 704 to 705
Value at channel 11 changed from 704 to 706
Value at channel 12 changed from 704 to 706
Value at channel 13 changed from 704 to 706
Value at channel  0 changed from 705 to 708
Value at channel  1 changed from 705 to 708
Value at channel  2 changed from 706 to 708
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

aarg

Actually, the way you have connected the pins, you could write the 4 bits directly to portD using bit manipulation. Just a shift and mask to get them into the right position. Pins 2-5 are bits 2-5 on portD of the Uno, at least.
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

sirkristofer

Thank you so much!!! Works a like charm. I'm slowley picking up this coding arduino but that totally stumped me. Picking it apart really helps me learn a lot. Cheers.






The generation of the address can be much simpler.
I think good naming can make comments superfluous.

Code: [Select]
const byte muxControlPins[] = {2, 3, 4, 5};
const byte muxInputPin = A0;

int lastValues[16];

void setup() {
  for (byte mcp = 0; mcp < sizeof(muxControlPins); mcp++) {
    pinMode(muxControlPins[mcp], OUTPUT);
  }
  Serial.begin(115200);
}

void loop() {
  static unsigned long lastCheck;
  unsigned long topLoop = millis();
  if (topLoop - lastCheck >= 1000) {
    lastCheck = topLoop;
    for (byte channel = 0; channel < 16; channel++) {
      int currVal = readMux(channel);
      if (currVal != lastValues[channel]) {
        Serial.print(F("Value at channel "));
        if (channel < 10) {
          Serial.write(' ');
        }
        Serial.print(channel);
        Serial.print(F(" changed from "));
        Serial.print(lastValues[channel]);
        Serial.print(F(" to "));
        Serial.println(currVal);
        lastValues[channel] = currVal;
      }
    }
  }
}

int readMux(byte channel) {
  digitalWrite(muxControlPins[0], channel & 0x01);
  digitalWrite(muxControlPins[1], channel & 0x02);
  digitalWrite(muxControlPins[2], channel & 0x04);
  digitalWrite(muxControlPins[3], channel & 0x08);
  return analogRead(muxInputPin);
}
Code: [Select]
Value at channel  0 changed from 0 to 703
Value at channel  1 changed from 0 to 703
Value at channel  2 changed from 0 to 703
Value at channel  3 changed from 0 to 703
Value at channel  4 changed from 0 to 703
Value at channel  5 changed from 0 to 703
Value at channel  6 changed from 0 to 703
Value at channel  7 changed from 0 to 703
Value at channel  8 changed from 0 to 703
Value at channel  9 changed from 0 to 703
Value at channel 10 changed from 0 to 703
Value at channel 11 changed from 0 to 703
Value at channel 12 changed from 0 to 703
Value at channel 13 changed from 0 to 703
Value at channel 14 changed from 0 to 703
Value at channel 15 changed from 0 to 703
Value at channel  0 changed from 703 to 704
Value at channel  1 changed from 703 to 704
Value at channel  2 changed from 703 to 704
Value at channel  3 changed from 703 to 704
Value at channel  4 changed from 703 to 704
Value at channel  5 changed from 703 to 704
Value at channel  6 changed from 703 to 704
Value at channel  7 changed from 703 to 704
Value at channel  8 changed from 703 to 704
Value at channel  9 changed from 703 to 704
Value at channel 10 changed from 703 to 704
Value at channel 11 changed from 703 to 704
Value at channel 12 changed from 703 to 704
Value at channel 13 changed from 703 to 704
Value at channel 14 changed from 703 to 704
Value at channel 15 changed from 703 to 704
Value at channel 14 changed from 704 to 705
Value at channel 15 changed from 704 to 705
Value at channel  0 changed from 704 to 705
Value at channel  1 changed from 704 to 705
Value at channel  2 changed from 704 to 706
Value at channel  3 changed from 704 to 706
Value at channel  4 changed from 704 to 705
Value at channel  5 changed from 704 to 705
Value at channel  6 changed from 704 to 705
Value at channel  7 changed from 704 to 705
Value at channel  8 changed from 704 to 705
Value at channel  9 changed from 704 to 705
Value at channel 10 changed from 704 to 705
Value at channel 11 changed from 704 to 706
Value at channel 12 changed from 704 to 706
Value at channel 13 changed from 704 to 706
Value at channel  0 changed from 705 to 708
Value at channel  1 changed from 705 to 708
Value at channel  2 changed from 706 to 708


Whandall

You're welcome!

Like aarg hinted, the address change could be made directly from one selection to the next, without sending the mux through some unused selections (which happens if you change the selection bits one by one) and faster, but that would make the code and the wiring less portable.

Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

sirkristofer

I'm testing it on an Arduino Leonardo but it will end up on an Arduino Mega once it arrives. Port registers is something I'm yet to play around with. The leonardo is different to the Uno or Megas and can't find much documentation or tutorials for the leo. When I get my mega I'll look into it. I know it will be much faster done that way. But this will do for now as a sort of prrof of concept. With that code I've now got 16 pots controlling 16 parameters in Reaper (DAW) which was the end goal really.


You're welcome!

Like aarg hinted, the address change could be made directly from one selection to the next, without sending the mux through some unused selections (which happens if you change the selection bits one by one) and faster, but that would make the code and the wiring less portable.



PaulMurrayCbr

Code: [Select]

//Mux control pins

byte controlPin[] = { 2, 3, 4, 5 }; // s0, s1, s2, s3

//Mux in "SIG" pin
int SIG_pin = A0; // A0 is not the same as 0

int valLast[16];

void setup(){
  for(int i = 0; i< 4; i++) {
    pinMode(controlPin[i], OUTPUT);
    digitalWrite(controlPin[i], LOW);
  }

 Serial.begin(9600);
}


void loop(){
 for(int i = 0; i <16; i ++){
   int v = valLast[i];
   valLast[i] = readMux(i);
   if(v != valLast[i]) {
     Serial.print("Value at channel ");
     Serial.print(i);
     Serial.print("is : ");
     Serial.println(valLast[i]);
    }
  }
  delay(1000);
}


int readMux(int channel){
  for(int i = 0; i<4; i++) {
    // there are many, many ways to do this. Some are faster.
    digitalWrite(controlPin[i], channel & (1<<i) ? HIGH: LOW);
  }

  return analogRead(SIG_pin);
}
[code]
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

sirkristofer

Is there any way to do a bit smoothing on the pot value in the for loop like.....


Code: [Select]

#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

const byte muxControlPins[] = {2, 3, 4, 5};
const byte muxInputPin = A0;
//int smoothedVal     = 0;
//int samples         = 5;

int lastValues[16];

void setup() {
  for (byte mcp = 0; mcp < sizeof(muxControlPins); mcp++) {
    pinMode(muxControlPins[mcp], OUTPUT);
  }
  MIDI.begin();
  Serial.begin(115200);
}

void loop() {




  static unsigned long lastCheck;
  unsigned long topLoop = millis();
  if (topLoop - lastCheck >= 50) {
    lastCheck = topLoop;
    for (byte channel = 1; channel < 16; channel++) {
      int currVal = readMux(channel);

  //smoothedVal = smoothedVal + ((currVal - smoothedVal) / samples);// Smoothing...?!
     
      if (currVal != lastValues[channel]) {
        Serial.println(channel);
        Serial.println(currVal / 8); // trouble shooting noisey pots
        MIDI.sendControlChange(channel, currVal / 8 , 1);
        lastValues[channel] = currVal;
      }
    }
  }
}


int readMux(byte channel) {
  digitalWrite(muxControlPins[0], channel & 0x01);
  digitalWrite(muxControlPins[1], channel & 0x02);
  digitalWrite(muxControlPins[2], channel & 0x04);
  digitalWrite(muxControlPins[3], channel & 0x08);
  return analogRead(muxInputPin);
}




When I try it gives some weird results.


You're welcome!

Like aarg hinted, the address change could be made directly from one selection to the next, without sending the mux through some unused selections (which happens if you change the selection bits one by one) and faster, but that would make the code and the wiring less portable.



Whandall

To average currVal over 5 samples you could use (untested)
Code: [Select]
      int currVal = readMux(channel);
      for (byte samples = 1; samples<5; samples++) {
        currVal += analogRead(muxInputPin);
      }
      currVal /= samples;
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

Go Up