a few questions regarding multiplexing and interrupts

Ok first of all, I'm a complete newbie to c++ and the whole arduino scene, I've read a lot and am now trying to realize a project.

The project will be a pretty self sufficient plant watering system for my house plants.

What I did already is to solder together some capacitive soil moisture sensors (schematics like here: german page) which work multiplexed via an 74ac151 IC. I've got five of them so far, eventually there will be eight sensors in total, so one 74ac151 is enough.

I've managed to get them working (pretty basic copy paste job with a few changes here and there from here). The sketch basically uses an interrupt in order to count a wave that is generated by the sensor.

Now my problem is: If i do it like this, I get moisture0 which constantly changes as soon as another sensor is read.

Is there any way to get 5 different values for moisture0 moisture1 moisture2....

This would be great because if one plant dries out, the other one would not be watered as well.

any help is much apprieciated! THX in advance

here is my sketch so far:

volatile unsigned int moisture0; // Interrupt 0 Pin 2
int strobe=7;   //digital outputs to control mux D7  
int c=6;        //control from IC pin S2
int b=5;        //control from IC pin S1
int a=4;        //control from IC pin S0


//aux

int entrada=0;
int a_val=0;
int b_val=0;
int c_val=0;
// to store the values from mux
int val[] = {
  0,0,0,0,0,0,0,0};
  
// digital values to control 8 inputs
int c_bin[]={LOW,LOW,LOW,LOW,HIGH,HIGH,HIGH,HIGH};
int b_bin[]={LOW,LOW,HIGH,HIGH,LOW,LOW,HIGH,HIGH};
int a_bin[]={LOW,HIGH,LOW,HIGH,LOW,HIGH,LOW,HIGH};
  

void setup() 
{                
  Serial.begin(9600);
  pinMode(strobe, OUTPUT);
  pinMode(c, OUTPUT);
  pinMode(b, OUTPUT);
  pinMode(a, OUTPUT);
}

void loop() 
{
  for(entrada=0;entrada<=4;entrada++) {

    //select mux input
    a_val=a_bin[entrada];
    b_val=b_bin[entrada];
    c_val=c_bin[entrada];

    digitalWrite(a,a_val);
    digitalWrite(b,b_val);
    digitalWrite(c,c_val);

    //strobe LOW to read
    digitalWrite(strobe,LOW);
  
  Serial.println("Starting measurement Sensor1...");
  // set moisture0 to 0
  moisture0 = 0;
  // set interrupt active rising
  attachInterrupt(0, count0, RISING);
  // wait 10 ms
  delay(10);
  // deactivate interrupt
  detachInterrupt(0);
  Serial.print("moisture0: ");
  Serial.println(moisture0);
  
  digitalWrite(strobe,HIGH);
  // wait 1 sec
  delay(1000);
  } 
}

void count0()
{
  moisture0++;
}

There are many ways to do it, here is one:

Make the moisture variable an array:

volatile unsigned int moisture[5];

In your interrupt routine you would need to know which one is the active sensor:

int active = 0;

void count()
{
  moisture[active]++; // active is a global variable
}

Then your measurement code would be something like:

  // set active sensor
  active = entrada;
  // set moisture to 0
  moisture[active] = 0;
  // set interrupt active rising
  attachInterrupt(0, count, RISING);
  // wait 10 ms
  delay(10);
  // deactivate interrupt
  detachInterrupt(0);

After you have looped this 5 times, the moisture array would hold the measurements for the five sensors.

But you maybe don't need to do it like this. It depends what you want to do with the values.

For example, if you just want to react to a sensor value you can do it in your original example just after the detachInterrupt call. Remember, your moisture0 variable contains the value of the most recent measurement. Maybe something like this:

if(moisture0 < 10) {
  // .. do whatever you need to water the plants…
}

Hope this helps!

  attachInterrupt(0, count0, RISING);
  // wait 10 ms
  delay(10);
  // deactivate interrupt
  detachInterrupt(0);

Why ?

I hadn't realized soil moisture changes so quickly that it needs interrupts to detect it.

...R

A very sudden rain shower perhaps ?

Robin2:
I hadn't realized soil moisture changes so quickly that it needs interrupts to detect it.

...R

Using the interrupt is just the way these sensors work, basically what i am doing is measuring a frequency. The interrupt simply acts as a counter, which - correct me if I'm wrong - is the only way to do this when the sensors themselves do not have an IC which does output the frequency via analog.

PetriH:
There are many ways to do it, here is one:

Make the moisture variable an array:

volatile unsigned int moisture[5];

In your interrupt routine you would need to know which one is the active sensor:

int active = 0;

void count()
{
  moisture[active]++; // active is a global variable
}



Then your measurement code would be something like:


// set active sensor
  active = entrada;
  // set moisture to 0
  moisture[active] = 0;
  // set interrupt active rising
  attachInterrupt(0, count, RISING);
  // wait 10 ms
  delay(10);
  // deactivate interrupt
  detachInterrupt(0);




After you have looped this 5 times, the moisture array would hold the measurements for the five sensors.

But you maybe don't need to do it like this. It depends what you want to do with the values.

For example, if you just want to react to a sensor value you can do it in your original example just after the detachInterrupt call. Remember, your moisture0 variable contains the value of the most recent measurement. Maybe something like this:



if(moisture0 < 10) {
  // .. do whatever you need to water the plants…
}




Hope this helps!

THX!
this actually helped ALOT, creating arrays is something I haven't come across during my brief time with C++ :smiley:

The simple solution you mentioned is pretty good too, but not feasible for my setup, I hadn't mentioned that there will be a 4digit 7-segment led display eventually that will show the values for each sensor once a button is pressed. This - to my understanding - will require the values being stored and read from somewhere.

But anyways, BIG THX!