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.
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!
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.
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?).
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.
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.
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);
}
}
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.
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?
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)?