Urgent - Controlling multiplexer outputs - Sensor Network

Hi there :D!

Okay so I'm using a CD4067B analogue multiplexer to control several sensor inputs. Now I want to control each channel which represents the different sensors. Below is an example of what I'm getting on the Serial Monitor. I have (0,1,2,3) 4 channels which represent different sensors. I want to be able to convert each of these channel from the voltage to the corresponding units eg.(temperature-degrees, gas -ppm, humidity % etc. ). How can I do that so i could convert those voltage values to the real value??

(Serial Monitor) - Example:

0 = 826 1 = 796 2 = 775 3 = 733
0 = 826 1 = 796 2 = 777 3 = 735
0 = 826 1 = 797 2 = 777 3 = 736
0 = 826 1 = 796 2 = 777 3 = 735
0 = 826 1 = 797 2 = 776 3 = 734
0 = 826 1 = 796 2 = 776 3 = 735
0 = 826 1 = 796 2 = 777 3 = 735
......

Help would be very much appreciated.
This is the code i used:

// This code reads the inputs using a CD 4067B multiplexer

/// the address pins will go in order from the first one:
const int A = 8; // First address pin corresponding to pin 8 on the microcontroller

void setup() {
Serial.begin(9600);
// set the output pins, from the first to the fourth:
for (int pinNumber = A; pinNumber < A + 4; pinNumber++) {
pinMode(pinNumber, OUTPUT);
// set Address pins A,B,C and D to low
//to connect input 0 to the output:
digitalWrite(pinNumber, LOW);
}
}

void loop() {

//loop over all the 4 input channels
for (int Channel = 0; Channel < 4; Channel++) {
setChannel(Channel);
//read the analog input and store it in the value array:
int analogReading = analogRead(0);
//print the result out:
Serial.print(Channel, DEC); // print the channel number
Serial.print(" = "); // insert = sign
Serial.print(analogReading, DEC ); // read the channels
Serial.print("\t"); // Insert tab between each channel

}

// linefeed after channels appear
Serial.println();
delay(500);
}

//Which channel connected to the output:

void setChannel(int whichChannel) {
// loop over all four bits in the channel number:
for (int bitPosition = 0; bitPosition < 4; bitPosition++) {
// read a bit in the channel number:
int bitValue = bitRead(whichChannel, bitPosition);
// pick the appropriate address pin:
int pinNumber = bitPosition + A;
// set the address pin
// with the bit value you read:
digitalWrite(pinNumber, bitValue);

}

You need to do the math in your code. To find out the equations for your particular sensors, you have to refer to their datasheet.

Yes definitely,

I do know all of these equations, the thing is I don't know if I can control these.
One of these channels represent the analogue value of a temperature sensor, but I want to convert it into Celsius and I know it's equation, yet where in the code and how can I control each channel separately?
Channel 0 - temperature values
Channel 1 - humidity values
Channel 2 - gas values
Channel 4 - pressure values

I hope you understand.

I want to print the real values of each sensor. I have the equations I just don't know if I could do that. If so how and where in the code exactly? Maybe someone give examples please ?

Thank you

You have a voltage from 0 to 5 that represents a value. The ADC is 10 bits, so 5/1023 represents 1 bit of data, about 0.00488V (4.88mV)

For temperature for example, 0 may represent 0 degrees C and 5V represents 200 degrees C.

So reading/500 = the percent of 200C that the reading represents. (Assumes your sensor for degrees C have a linear reading from 0 to 200. It may not).

Take a voltage reading, and now you have a digital number that represents that voltage.
Do some converting:
(digital #) * (5V/1023) = voltage that was read in.

(voltage read in)/5V * 200 = degrees read in.

Example: reading of 400
(400 * (5/1023)) / 5 * 200 = 78.2C.
(850 * (5/1023)) / 5 * 200 = 166.17C.

Your data sheets will tell you what the ADC readings between 0 and 1023 represent, you do a little math like above to convert that reading into your temperature, pressure, air density, whatever.

yet where in the code and how can I control each channel separately?

You don't control sensors you read them. They are inputs. You only control outputs.

Your code is in a for loop reading the channels. You have to insert a switch statement, switching on the loop's index variable to process each reading according to it's required formula. If that is too hard then just read the analogue inputs separately and apply the formula after the read.

Thanks for the reply guys.

Yes CrossRoad I understand what you mean and I know how to do the maths, I have the formulas ready. All I meant was that I've been trying to read each channel individually and having it printing out the real values of each parameter but there was no luck.

I think Grumpy_Mike is closer to what I meant. I need to read the sensors at pretty much the same rate that's why I used the multiplexer. If I'm going to use a switch statement to switch between the the different index variables could you post an example of how? Please? A quick simple example would be fine.

Thanks again for the replies.

Your loop() function needs to look like this:-

void loop() {
int analogReading;
    //loop over all the 4 input channels
    for (int Channel = 0; Channel < 4; Channel++) {
    setChannel(Channel);
     //read the analog input and store it in the value array:
     analogReading = analogRead(0); 
        switch (Channel) {
     case 0:
        // do calculations an print for sensor 0
     break;
      case 1:
        // do calculations an print for sensor 1
     break;
     case 2:
        // do calculations an print for sensor 2
     break;
     case 3:
        // do calculations an print for sensor 3
     break;    
        }
  }
   
   // linefeed after channels appear
  Serial.println();
delay(500);
}

Thank you so much! Worked perfectly fine!

/Okay now that I have the multiplexing bit working, how would I de-multiplex the signal? I want to demultiplex it so I can display each sensor through processing(graphical display). Do I need a de-multiplexer to do that? A friend of mine suggested a USB reader but I don't understand the logic behind that? So could anyone explain?

You just need to make sure that what you print (== send to Processing) has some unique identifier appended to it that will allow the Processing application to decide which set of readings the value belongs.

Knowing that I'm a newbie, is is difficult to code what you explained?

No, not difficult at all, in fact, it looks like you did something like that in your first post where you tabulated your results.
(I notice you're a low-count poster, but I have no idea whether you're a newbie or not)

Yes I am a newbie :slight_smile: ..
I hope not ! :slight_smile:

In the code you first posted each sensor had 0 = , 1= and so on in front of it. Just do the same for processing to latch onto so it knows what sensor the number is associated with.
Alternatively send all the numbers separated by a commer in one line, that is use print for all sensors and a println at the end. Processing the pickups a line and parses or splits the numbers up.

Thanks... I approached it the second way, by separating the values with comma. I managed to get the 4 graphs representing the four different sensors, but my graphs are turning out really small and unreadable. Another thing, because each sensor is represented in a different unit, so I can't scale them out. Some graphs are clear others are not. Any help?
Oh and .. is there a way I could grid in processing? And have a x and y axis? Sorry I'm totally new to processing, and I tried my best.

Thanks

This is the processing code I've used so far:

import processing.serial.*;

int maxNumberOfSensors = 4;       // Arduino has 4 sensors connected
boolean fontInitialized = false;  // whether the font's been initialized
Serial myPort;                    // The serial port

float[] previousValue = new float[maxNumberOfSensors];  // array of previous values
float xpos = 0;                     // x position of the graph
PFont myFont;                     // font for writing text to the window

void setup () {
  // set up the window to whatever size you want:
  size(1000, 500);        
  // List all the available serial ports:
  println(Serial.list());

  // is always my  Arduino or Wiring module, so I open Serial.list()[0].
  // Open whatever port is the one you're using.
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
  myPort.clear();

  myPort.bufferUntil('\n');
  // create a font with the fourth font available to the system:
  myFont = createFont("Times New Roman", 12);
  textFont(myFont);
  fontInitialized = true;
  // set inital background:
  background(255);
  // turn on antialiasing:
  smooth();
}

void draw () {
  // nothing happens in the draw loop, 
  
}

void serialEvent (Serial myPort) {
  // get the ASCII string:
  String inString = myPort.readStringUntil('\n');

  // if it's not empty:
  if (inString != null) {
    // trim off any whitespace:
    inString = trim(inString);

    // convert to an array of ints:
    int incomingValues[] = int(split(inString, ","));

    // print out the values
      //print("length: " + incomingValues.length + " values.\t");
    if (incomingValues.length <= maxNumberOfSensors && incomingValues.length > 0) {
      for (int i = 0; i < incomingValues.length; i++) {

        // map the incoming values (0 to  1023) to an appropriate
        // graphing range (0 to window height/number of values):
        float ypos = map(incomingValues[i], 0, 1023, 0, height/incomingValues.length);

        // figure out the y position for this particular graph:
        float graphBottom = i * height/incomingValues.length ;
        ypos = ypos + graphBottom;

        // make a black block to erase the previous text:
        noStroke();
        fill(170);
       //rect(10, graphBottom, 50, 15);

        // print the sensor numbers to the screen:
        fill(0);
        int textPos = int(graphBottom);
        // sometimes serialEvent() can happen before setup() is done.
        // so you need to make sure the font is initialized before
        // you text():
        if (fontInitialized) {
        //text("Sensor " + i , 10, textPos);
            }

        stroke(127,86,255);
        smooth();
        strokeWeight(1.3);
        // change colors to draw the graph line:
      
        stroke(127,56,255);
        line(xpos, height-previousValue[i], xpos+1, height-ypos);
        // save the current value to be the next time's previous value:
        previousValue[i] = ypos;
      }
    }
    // if you've drawn to the edge of the window, start at the beginning again:
    if (xpos >= width) {
      saveFrame();
      xpos = 0.5;
      background(255);
    } 
    else {
      xpos+=.80;
    }
  }
}

because each sensor is represented in a different unit, so I can't scale them out.

Yes you can, you apply a different scaling factor for each reading before you plot them.

You have to scale the values by different amounts. My guess is you would do it here somewhere

      for (int i = 0; i < incomingValues.length; i++) {

        // map the incoming values (0 to  1023) to an appropriate
        // graphing range (0 to window height/number of values):
        float ypos = map(incomingValues[i], 0, 1023, 0, height/incomingValues.length);

maybe

int scaleVals[maxNumberOfSensors ] = {1, 1, 2, 10};

      for (int i = 0; i < incomingValues.length; i++) {

        // map the incoming values (0 to  1023) to an appropriate
        // graphing range (0 to window height/number of values):
        float ypos = map(incomingValues[i], 0, 1023, 0, height/incomingValues.length * scaleVals[i]);

Although I have not looked to see what "height/incomingValues.length" is.


Rob

After including the part you suggested, i got this error message saying:

unexpected token: int

This is the code after adding your bit to it:

import processing.serial.*;

int maxNumberOfSensors = 4;       // Arduino has 6 analog inputs, so I chose 6
boolean fontInitialized = false;  // whether the font's been initialized
Serial myPort;                    // The serial port

float[] previousValue = new float[maxNumberOfSensors];  // array of previous values
float xpos = 0;                     // x position of the graph
PFont myFont;                     // font for writing text to the window

void setup () {
  // set up the window to whatever size you want:
  size(1000, 500);        
  // List all the available serial ports:
  println(Serial.list());
  // I know that the first port in the serial list on my mac
  // is always my  Arduino or Wiring module, so I open Serial.list()[0].
  // Open whatever port is the one you're using.
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
  myPort.clear();
  // don't generate a serialEvent() until you get a newline (\n) byte:
  myPort.bufferUntil('\n');
  // create a font with the fourth font available to the system:
  myFont = createFont("Times New Roman", 12);
  textFont(myFont);
  fontInitialized = true;
  // set inital background:
  background(255);
  // turn on antialiasing:
  smooth();
}

void draw () {
  // nothing happens in the draw loop, 
  
}

void serialEvent (Serial myPort) {
  // get the ASCII string:
  String inString = myPort.readStringUntil('\n');

  // if it's not empty:
  if (inString != null) {
    // trim off any whitespace:
    inString = trim(inString);

    // convert to an array of ints:
    int incomingValues[] = int(split(inString, ","));

    // print out the values
      //print("length: " + incomingValues.length + " values.\t");
      int scaleVals[maxNumberOfSensors] = {1, 1, 2, 10};
    //if (incomingValues.length <= maxNumberOfSensors && incomingValues.length > 0) {
      for (int i = 0; i < incomingValues.length; i++) {

        // map the incoming values (0 to  1023) to an appropriate
        // graphing range (0 to window height/number of values):
        //float ypos = map(incomingValues[i], 0, 1023, 0, height/incomingValues.length);
        float ypos = map(incomingValues[i], 0, 1023, 0, height/incomingValues.length * scaleVals[i]);
        // figure out the y position for this particular graph:
        float graphBottom = i * height/incomingValues.length ;
        ypos = ypos + graphBottom;

        // make a black block to erase the previous text:
        noStroke();
        fill(170);
       //rect(10, graphBottom, 50, 15);

        // print the sensor numbers to the screen:
        fill(0);
        int textPos = int(graphBottom);
        // sometimes serialEvent() can happen before setup() is done.
        // so you need to make sure the font is initialized before
        // you text():
        if (fontInitialized) {
        //text("Sensor " + i , 10, textPos);
            }

        stroke(127,86,255);
        smooth();
        strokeWeight(1.3);
        // change colors to draw the graph line:
      
        stroke(127,56,255);
        line(xpos, height-previousValue[i], xpos+1, height-ypos);
        // save the current value to be the next time's previous value:
        previousValue[i] = ypos;
      }
    }
    // if you've drawn to the edge of the window, start at the beginning again:
    if (xpos >= width) {
      saveFrame();
      xpos = 0.5;
      background(255);
    } 
    else {
      xpos+=.80;
    }
  }
}