Comparing 8 digital inputs to control multiplexer analog inputs

Hello!

This is my first time in the forum section and I am a beginner in Arduino. I am currently working on a logic in a electronic experiment that I could use some help with.

The hardware:
AVR Atmega328p
4051B DIP-16 Single 8-Channel Analog Multiplexer/Demultiplex

The goal:
To compare 8 digital inputs (square waves) and each 10ms decide wich input is the best (most pulses). The Atmega is also going to control the Multiplexer and choose the same input that has won the comparison.

Question:

  • Why each 10ms?
    The multiplexer is going to switch between 8 audio signals, when the current audio signal is getting week then another gets chosen. If I have more then 10ms then you will hear the switching between the different audio inputs, that I don't want.

Ideas:
The control of the multiplexer: Arduino Playground - HomePage
The reading of digital inputs: http://arduino.cc/en/Reference/PulseIn

Problem:
I have very little experience with programming and I have no idea of how to make all this code work together. I would be very happy if someone could help me out with this!

Best regards,
Swoshie

swoshie:
each 10ms decide wich input is the best (most pulses).

I don't understand your criteria for 'best', but assuming that pulse counting gives you what you want then doing that on eight inputs seems simple enough. I don't know what's involved in switching your multiplexer but it sounds as if you already know that part is possible. The only thing I'd change in your approach is to poll the inputs and count state transitions directly rather than try to use pulseIn to measure the pulse lengths.

Hello Peter and thank you for the quick response! :slight_smile:

Why I have chosen 10ms is because this has been done before and works really well (not by me), with a PIC processor that has slower speed.

I am sorry to say that I don't completely understand your explanation about "count state transitions directly". How should I do this? Does the wiki have any information about this? Maybe an example code?

The source for all the digital inputs is going to be a variable sine wave that goes thru an op-amp that converts it to a square wave, this seems to be the simplest way of measuring (and maybe the fastest?).

Feel free to add any thoughts and suggestions!

Best regards,
Swoshie

As I understand it, pulsein() measures pulsewidths, not #pulses in a time
period. If you know the inputs are squarewave, and running at a constant
frequency, however, then pulsein() should give you a good measure, ie
freq = 1/(2*pulsewidth).

Otherwise, whether or not you can do the job depends upon the pulse frequency
on your 8 channels. You didn't say what the 8 digital frequencies are.

Also, using 3 digital I/O pins to select the 4051 channel is the easy part.

Hello and thank you for your response!

I am sorry for the lack of information. The inputs gets a variable sine wave between 5-7KHz which is converted into a square wave.

The comparison can be done in anyway possible as long as it's doing it per 10ms.

Thank you again for your time and expertise!

Best regards,
Swoshie

5-7Khz should be easily doable. If original is sinewave, converted to squarewave,
then pulsein() should be usable. I think you're in business.

swoshie:
I am sorry to say that I don't completely understand your explanation about "count state transitions directly". How should I do this?

I assume the input frequency is much higher than 100 Hz.

In loop(), read the current state of each input. Compare it with the previous state of that input. If it's different, then the signal has just transitioned from high to low or low to high. Decide which of these you're going to use to denote a pulse, and increment a counter when it occurs.

Every 10 ms, compare the counters to see which input has the highest count and take that as your source, then zero the counters ready to start counting the next 10 ms.

Thank you for all the information!

I've started to write some code by using this pages and your suggestions, I am sure the code looks really weird but maybe this is a start?

The codes is taken from this pages:

http://arduino.cc/en/Reference/If

My code:

int rx1 = 5;                 // input pin for RX1
int rx2 = 6;                 // input pin for RX2
int rx3 = 7;                 // input pin for RX3
int rx4 = 8;                 // input pin for RX4
int rx5 = 9;                 // input pin for RX5
int rx6 = 10;                // input pin for RX6
int rx7 = 11;                // input pin for RX7
int rx8 = 12;                // input pin for RX8
int tx = 13;                 // output pin for TX

unsigned long duration1;
unsigned long duration2;
unsigned long duration3;
unsigned long duration4;
unsigned long duration5;
unsigned long duration6;
unsigned long duration7;
unsigned long duration8;

// Variables will change:
int duration1Counter = 0;     // counter for the number of pulses
int duration2Counter = 0;     // counter for the number of pulses
int duration3Counter = 0;     // counter for the number of pulses
int duration4Counter = 0;     // counter for the number of pulses
int duration5Counter = 0;     // counter for the number of pulses
int duration6Counter = 0;     // counter for the number of pulses
int duration7Counter = 0;     // counter for the number of pulses
int duration8Counter = 0;     // counter for the number of pulses

int duration1State = 0;       // current state of the input
int duration2State = 0;       // current state of the input
int duration3State = 0;       // current state of the input
int duration4State = 0;       // current state of the input
int duration5State = 0;       // current state of the input
int duration6State = 0;       // current state of the input
int duration7State = 0;       // current state of the input
int duration8State = 0;       // current state of the input

int lastDuration1State = 0;   // previous state of the input
int lastDuration2State = 0;   // previous state of the input
int lastDuration3State = 0;   // previous state of the input
int lastDuration4State = 0;   // previous state of the input
int lastDuration5State = 0;   // previous state of the input
int lastDuration6State = 0;   // previous state of the input
int lastDuration7State = 0;   // previous state of the input
int lastDuration8State = 0;   // previous state of the input

void setup()
{
  pinMode(rx1, INPUT);     // initialize the digital pin as a input
  pinMode(rx2, INPUT);     // initialize the digital pin as a input
  pinMode(rx3, INPUT);     // initialize the digital pin as a input
  pinMode(rx4, INPUT);     // initialize the digital pin as a input
  pinMode(rx5, INPUT);     // initialize the digital pin as a input
  pinMode(rx6, INPUT);     // initialize the digital pin as a input
  pinMode(rx7, INPUT);     // initialize the digital pin as a input
  pinMode(rx8, INPUT);     // initialize the digital pin as a input
}

void loop()
{
  duration1 = pulseIn(rx1, HIGH);
  duration2 = pulseIn(rx2, HIGH);
  duration3 = pulseIn(rx3, HIGH);
  duration4 = pulseIn(rx4, HIGH);
  duration5 = pulseIn(rx5, HIGH);
  duration6 = pulseIn(rx6, HIGH);
  duration7 = pulseIn(rx7, HIGH);
  duration8 = pulseIn(rx8, HIGH);
  
  // if input is detected, turn on output
 if (rxState >= 1)
 {
   digitalWrite(tx, HIGH);
 }
 else
 {
   digitalWrite(tx, LOW);
 }
}

Am I on the right track?

Best regards,
Swoshie

I think learning about arrays could make your task easier.
Certainly the code would be shorter.

swoshie:
Am I on the right track?

Well, it's a start. If you're trying to measure the frequency of those inputs you need to count pulses - pulseIn() is no help with that. Arrays will avoid you needing to copy your code eight times. To save head-scratching down the line, I recommend that you get used to thinking of your inputs as numbered 0 to 7 rather than 1 to 8. You'll understand why once you start using arrays.

Thank you for your advice!

I have now tried a different approach and made use of arrays (i understand now how much easier it gets) and came up with this:

int rxPins[] = {5, 6, 7, 8, 9, 10, 11, 12};    // input pins for rx 0 thru 7
int rxState = 0;                               // current rx selected
int count = 0;                                 // counters for rx 0 thru 7
int tx = 13;                                   // output pin for tx

// output pins for multiplexer
int r0 = 0;      //value of select pin at the 4051 (s0)
int r1 = 0;      //value of select pin at the 4051 (s1)
int r2 = 0;      //value of select pin at the 4051 (s2)
int countmux = 0;   //which y pin we are selecting

void setup()
{
  // initialize rx pins as input
  for (count=0;count<8;count++) {
    pinMode(rxPins[count], INPUT);
  }
  
  // initialize pins as output for multiplexer
  pinMode(2, OUTPUT);    // s0
  pinMode(3, OUTPUT);    // s1
  pinMode(4, OUTPUT);    // s2
}

void loop()
{
  // read inputs and count pulses
  for (count=0;count<8;count++) {
    rxState = digitalRead(rxPins[count], HIGH);
  }



 // if input is detected, turn on output
 if (rxState >= 1)
 {
   digitalWrite(tx, HIGH);
 }
 else
 {
   digitalWrite(tx, LOW);
 }
 
 
 
 // code for multiplexer
 for (countmux=0; countmux<=7; countmux++) {

    // select the bit  
    r0 = bitRead(countmux,0);    // use this with arduino 0013 (and newer versions)     
    r1 = bitRead(countmux,1);    // use this with arduino 0013 (and newer versions)     
    r2 = bitRead(countmux,2);    // use this with arduino 0013 (and newer versions)     

    //r0 = count & 0x01;      // old version of setting the bits
    //r1 = (count>>1) & 0x01;      // old version of setting the bits
    //r2 = (count>>2) & 0x01;      // old version of setting the bits

    digitalWrite(2, r0);
    digitalWrite(3, r1);
    digitalWrite(4, r2);

    //Either read or write the multiplexed pin here

  }  
}

I have no idea if this works but maybe it looks better? Any advice?

The problem now is how to compare the inputs and choose the one with most pulses each 10ms?

Best regards,
Swoshie

I have no idea if this works

It doesn't even compile.

    rxState = digitalRead(rxPins[count], HIGH);

The digitalRead() function takes ONE argument.

Why are you storing all 8 values in one variable? Only the last one would be there when the loop ended.

Hello Paul and thank you for your response!

As I said in the start of this post, I am a complete newbie at this and trying to put code from the "playground" site etc together to accomplish what I want to do. I appreciate all the help I can get to get one step closer to my goal!

Okey, so do I have to make a "rxState = digitalRead" for every input or is there a better way of doing it? Another thing I've been wondering about is if the "digitalRead" only reads the state of the input once or if I have to make a new function for that (to read it every 10ms)?

Best regards,
Swoshie