Multiple analog input using multiplexer and NodeMCU

I am trying to read multiple analog sensors using multiplexer CD74HC4067 and NodeMCU.

I managed to read the sensors and print the analog value to the serial monitor, but can’t figure out how to send it to thinger.io.

Does anyone here have experience in reading multiple analog sensors with this MultiPlexer?

My code looks like this:

#include <CD74HC4067.h>
#include <ESP8266WiFi.h>
#include <ThingerESP8266.h>

#define USERNAME "username"
#define DEVICE_ID "deviceid"
#define DEVICE_CREDENTIAL "credential"

#define SSID "ssid"
#define SSID_PASSWORD "password"

ThingerESP8266 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);


/*
CD74HC4067 Analog / Digital Multiplexing

This sketch reads analog values from all 16 of the multiplexer pins.

created 17 Nov 2009
by Rory Nugent

The following pins must be connected:

Digital Pin 2 -> S0
Digital Pin 3 -> S1
Digital Pin 4 -> S3
Digital Pin 5 -> S4

Analog In Pin 0 -> SIG

*/

// Mux analog / digital signal pin
#define sig 0      // Analog In Pin 0

// Mux channel select pins
#define setPin0 5  //GPIO 5 (D1 on NodeMCU)
#define setPin1 4  //GPIO 4 (D2 on NodeMCU)
#define setPin2 0  //GPIO 0 (D3 on NodeMCU)
#define setPin3 2  //GPIO 2 (D4 on NodeMCU)


void setup()
{
Serial.begin(9600);

pinMode(setPin0, OUTPUT);
pinMode(setPin1, OUTPUT);
pinMode(setPin2, OUTPUT);
pinMode(setPin3, OUTPUT);

thing.add_wifi(SSID, SSID_PASSWORD);
}
void loop()
{
thing.handle();

// for loop to cycle through all mux channels, 0 - 15
for(int i = 0; i < 16; i++)
{
int sigValue = readSig(i);  // read from a mux channel

// print the analog / digital value to the serial monitor

Serial.print("Value at channel ");
Serial.print(i);
Serial.print(" is : ");
Serial.println(readSig(i));

}
Serial.println();      // NEW LINE
}

// NAME: readSig
// INPUT: mux channel as an integer, 0 - 15
// RETURN: analog value of the selected mux channel as an integer
int readSig(int channel)
{
// use the first four bits of the channel number to set the channel select pins
digitalWrite(setPin0, bitRead(channel, 0));
digitalWrite(setPin1, bitRead(channel, 1));
digitalWrite(setPin2, bitRead(channel, 2));
digitalWrite(setPin3, bitRead(channel, 3));

// read from the selected mux channel
int sigValue = analogRead(sig);

// return the received analog value
return sigValue;

thing["moisture"] >> [](pson & out) {
out["moist1"] =(unsigned int) analogRead(readSig(0)), 0, 1023, 0, 100;
out["moist2"] =(unsigned int) analogRead(readSig(1)), 0, 1023, 0, 100;
out["moist3"] =(unsigned int) analogRead(readSig(2)), 0, 1023, 0, 100;
out["moist4"] =(unsigned int) analogRead(readSig(3)), 0, 1023, 0, 100;
};
}

Please, do not define resources in the loop! It is not necessary

Did you tried this in your setup? If you just have the readSig function implemented… it is just like reading any other pin or analog value…

thing["moisture"] >> [](pson & out) {
    out["moist1"] = readSig(0);
    out["moist2"] = readSig(1);
    out["moist3"] = readSig(2);
    out["moist4"] = readSig(3);
};

Supposing that your readSig funcion works fine (remove the resource definition after the return):

int readSig(int channel)
{
   // use the first four bits of the channel number to set the channel select pins 
    digitalWrite(setPin0, bitRead(channel, 0));
    digitalWrite(setPin1, bitRead(channel, 1));
    digitalWrite(setPin2, bitRead(channel, 2));
    digitalWrite(setPin3, bitRead(channel, 3));

    // read from the selected mux channel
    return analogRead(sig);
}

You can store the read as a variable by any method, and this variable is what you are going to send to thinger.io platform

on setup, it can look like this:
setup()
{
thing[“First”] >> outputValue(first_variable);
thing[“Second”] >> outputValue(second_variable);

And in the loop, you must refresh the “first_variable” and “second_variable” by any method that you want, be aware avoid use the delay function because this interfieres with thinger communication

HI,

the solution proposed by @ega is also valid. However, take into account that this force reading the values in every loop, even if you do not want to use them. So, this is not quite efficient. If it is possible, it is better to define the reading also in the resource definition, like proposed in my above solution. In this way, the sensor read, analogr read, etc., it is only done when required (i.e. at a sampling interval established by a bucket, dashboard, etc.). As the resource code is only executed when “something” is extracting the information from it. This way, you can also assure that the information obtained from the resource is the current one, and not one that depends of the loop. Not sure if I explained it correctly, just let me know :wink:

Best.

Ok now I understood (I guess) the difference between the 2 methods, so I use my method because usually I code the control at the microcontroller loop, and after that I communicate to thinger (but always the microcontroller is reading and controlling the process), by the way you are proposing the microcontroller execute the read just when is it interrogated? please correct me if I understood wrong :slight_smile:

Hi @ega, this is correct. Suppose that you attach a DHT11 sensor to you micro, and you want to only to extract data every minute for a butcket. Does it worth to read the temperature and humidity in every loop (thousands of times in a minute) to use the reading once in a minute? Suppose now that you have 2, 3, or 4 devices… the loop is growing in readings that are not almost used, and the micro takes too much time doing things not necessary, or even delaying the thing.handle call, doing it less responsive to thinger communication.

This way, if the readings are not necessary for any other purpose (i.e. like calling and endpoint based on temp threshold), we can define them inside the resource. So, they are only read when the server request that (by default, the resources are not transmitted to the server unless necessary, like opening a dashboard for this resource, setting a bucket over theh resource, etc).

So, in the above example, the readings are defined just inside the resource definition. And the loop can contain just the thing.handle call.

thing["moisture"] >> [](pson & out) {
    out["moist1"] = readSig(0);
    out["moist2"] = readSig(1);
    out["moist3"] = readSig(2);
    out["moist4"] = readSig(3);
};