Collegare Arduino MKR 1010 a multiplexer 74HC4067 per sensori umidità

Salve a tutti popolo della community.
Vi scrivo per chiedervi aiuto in merito ad un progettino che starei cercando di realizzare.
Partendo dal codice che seguirà (preso da internet), il mio obiettivo è realizzare un dispositivo che mi permetta di leggere l'umidità del terreno che è stato già realizzato con il codice che segue.

// configurazione Blynk
#define BLYNK_TEMPLATE_ID "xxxxx"
#define BLYNK_TEMPLATE_NAME "Sensori"

#define BLYNK_FIRMWARE_VERSION        "0.1.0"
 
#define BLYNK_PRINT Serial
//#define BLYNK_DEBUG
 
#define APP_DEBUG
 
#include "BlynkEdgent.h"
 
// configurazione sensori di temperatura
#include "DHT.h"
 
#define DHTPIN_A 2
#define DHTTYPE_A DHT11
DHT dhtA(DHTPIN_A, DHTTYPE_A);
 
#define DHTPIN_B 1
#define DHTTYPE_B DHT11
DHT dhtB(DHTPIN_B, DHTTYPE_B);
 
// configurazione Blynk
BlynkTimer timer;
 
// variabili
 

 
int alimentazione;
 

 
int sensoreUmidita1;
int sensoreUmidita2;
int sensoreUmidita3;
int sensoreUmidita4;
int sensoreUmidita5;
 
float temperatura1;
float umidita1;
 
float temperatura2;
float umidita2;
 
float velocitaVento;
 
void setup()
{
  Serial.begin(115200);
  delay(2000);
 
  BlynkEdgent.begin();
  
  //pin alimentazione
  pinMode(8, INPUT); //feedback
  
  //sens. temperatura
  dhtA.begin();
  dhtB.begin();
 
  //timer
  timer.setInterval(2000L, trasmissioneDati);
}
 
void trasmissioneDati(){
  // lettura sensori
  sensoreUmidita1 = analogRead(A1);
  sensoreUmidita2 = analogRead(A2);
  sensoreUmidita3 = analogRead(A3);
  sensoreUmidita4 = analogRead(A4);
  sensoreUmidita5 = analogRead(A5);
  
  // lettura temperatura
  temperatura1 = dhtA.readTemperature();
  umidita1 = dhtA.readHumidity();
 
  temperatura2 = dhtB.readTemperature();
  umidita2 = dhtB.readHumidity();
 
  // trasmissione dati sensori
  Blynk.virtualWrite(V1, 100 - (sensoreUmidita1/10));
  Blynk.virtualWrite(V2, 100 - (sensoreUmidita2/10));
  Blynk.virtualWrite(V3, 100 - (sensoreUmidita3/10));
  Blynk.virtualWrite(V4, 100 - (sensoreUmidita4/10));
  Blynk.virtualWrite(V5, 100 - (sensoreUmidita5/10));
  
  Blynk.virtualWrite(V6, temperatura1);
  Blynk.virtualWrite(V8, umidita1);
  Blynk.virtualWrite(V7, temperatura2);
  Blynk.virtualWrite(V9, umidita2);
 

}
 
BLYNK_CONNECTED() {
  Blynk.syncAll();
}
 
BLYNK_WRITE(V10)
{
 
}
 
void loop() {
  BlynkEdgent.run();
  timer.run();
}

Ora fin qua tutto ok, il codice funziona e anche in ottimo modo. Sorge però una problematica ovvero che sull'MKR 1010 posso sfruttare al massimo 5 input analogici.
Per ovviare al problema ho deciso di acquistare un multiplexer che come ben sappiamo tutti sfrutta 1 input analogico e 4 digitali ( più nello specifico Modulo multiplexer analogico 16 74HC4067 CD74HC4067). Il mio problema sta in sostanza nel mettere in collegamento l'MKR e il multiplexer e fargli capire che da un certo sensore in poi deve ricevere dati dal multiplexer e poi mandarmi il tutto su un cloud ( nel mio caso utilizzo blynk).
Di seguito il codice:

// configurazione Blynk
#define BLYNK_TEMPLATE_ID "xxxxx"
#define BLYNK_TEMPLATE_NAME "Sensori"

#define BLYNK_FIRMWARE_VERSION        "0.1.0"
 
#define BLYNK_PRINT Serial
//#define BLYNK_DEBUG
 
#define APP_DEBUG
 
#include "BlynkEdgent.h"

 
// configurazione sensori di temperatura
#include "DHT.h"
 
#define DHTPIN_A 2
#define DHTTYPE_A DHT11
DHT dhtA(DHTPIN_A, DHTTYPE_A);
 
#define DHTPIN_B 1
#define DHTTYPE_B DHT11
DHT dhtB(DHTPIN_B, DHTTYPE_B);
 
// configurazione Blynk
BlynkTimer timer;
 
// variabili
 
 
int alimentazione;

int canale;

int sensoreUmidita1;
int sensoreUmidita2;
int sensoreUmidita3;
int sensoreUmidita4;
int sensoreUmidita5;

int sensoreUmidita6;
int sensoreUmidita7;
int sensoreUmidita8;
int sensoreUmidita9;
int sensoreUmidita10;

int sensoreUmidita11;
int sensoreUmidita12;
int sensoreUmidita13;
int sensoreUmidita14;
int sensoreUmidita15;

int sensoreUmidita16;
int sensoreUmidita17;
int sensoreUmidita18;
int sensoreUmidita19;
int sensoreUmidita20;
int sensoreUmidita21;
int sensoreUmidita22;

 
float temperatura1;
float umidita1;
 
float temperatura2;
float umidita2;
 
float velocitaVento;
int s0 = 8;
int s1 = 9;
int s2 = 10;
int s3 = 11;
int sig = 0;
 
int multiplexer[16][4] = { {0,0,0,0}, //canale 0
                           {0,0,0,1}, //canale 1
                           {0,0,1,0}, //canale 2
                           {0,0,1,1}, //canale 3
                           {0,1,0,0}, //canale 4
                           {0,1,0,1}, //canale 5
                           {0,1,1,0}, //canale 6
                           {0,1,1,1}, //canale 7
                           {1,0,0,0}, //canale 8
                           {1,0,0,1}, //canale 9
                           {1,0,1,0}, //canale 10
                           {1,0,1,1}, //canale 11
                           {1,1,0,0}, //canale 12
                           {1,1,0,1}, //canale 13
                           {1,1,1,0}, //canale 14
                           {1,1,1,1}  //canale 15
                         };
 
 void multi() {
  canale(0);
  Serial.read();
  canale(1);
  Serial.read();
  canale(2);
  Serial.read();
  canale(3);
  Serial.read();
  canale(4);
  Serial.read();
  canale(5);
  Serial.read();
  canale(6);
  Serial.read();
  canale(7);
  Serial.read();
  canale(8);
  Serial.read();
  canale(9);
  Serial.read();
  canale(10);
  Serial.read();
  canale(11);
  Serial.read();
  canale(12);
  Serial.read();
  canale(13);
  Serial.read();
  canale(14);
  Serial.read();
  canale(15);
 Serial.read();

}
void setup() {
  // put your setup code here, to run once:
  pinMode(s0,OUTPUT);
  pinMode(s1,OUTPUT);
  pinMode(s2,OUTPUT);
  pinMode(s3,OUTPUT);
  Serial.begin(9600);
Serial.begin(115200);
  delay(2000);
 
  BlynkEdgent.begin();
  
  //pin alimentazione
  pinMode(8, INPUT); //feedback
  
  //sens. temperatura
  dhtA.begin();
  dhtB.begin();
 
  //timer
  timer.setInterval(2000L, trasmissioneDati);
}
 
void trasmissioneDati(){
  // lettura sensori
  sensoreUmidita1  = analogRead(A1);
  sensoreUmidita2  = analogRead(A2);
  sensoreUmidita3  = analogRead(A3);
  sensoreUmidita4  = analogRead(A4);
  sensoreUmidita5  = analogRead(A5);
  sensoreUmidita6  = analogRead(A6);
  
    
  sensoreUmidita7  = analogRead(canale(0),Serial.read());
  sensoreUmidita8  = analogRead(canale(1),Serial.read());
  sensoreUmidita9  = analogRead(canale(2),Serial.read());
  sensoreUmidita10 = analogRead(canale(3),Serial.read());
  sensoreUmidita11 = analogRead(canale(4),Serial.read());

  sensoreUmidita12 = analogRead(canale(5),Serial.read());
  sensoreUmidita13 = analogRead(canale(6),Serial.read());
  sensoreUmidita14 = analogRead(canale(7),Serial.read());
  sensoreUmidita15 = analogRead(canale(8),Serial.read());
  sensoreUmidita16 = analogRead(canale(9),Serial.read());

  sensoreUmidita17 = analogRead(canale(10),Serial.read());
  sensoreUmidita18 = analogRead(canale(11),Serial.read());
  sensoreUmidita19 = analogRead(canale(12),Serial.read());
  sensoreUmidita20 = analogRead(canale(13),Serial.read());
  sensoreUmidita21 = analogRead(canale(14),Serial.read());
  sensoreUmidita22 = analogRead(canale(15),Serial.read());


  
  // lettura temperatura
  temperatura1 = dhtA.readTemperature();
  umidita1 = dhtA.readHumidity();
 
  temperatura2 = dhtB.readTemperature();
  umidita2 = dhtB.readHumidity();
 
  // trasmissione dati sensori
  Blynk.virtualWrite(V1, 100 - (sensoreUmidita1/10));
  Blynk.virtualWrite(V2, 100 - (sensoreUmidita2/10));
  Blynk.virtualWrite(V3, 100 - (sensoreUmidita3/10));
  Blynk.virtualWrite(V4, 100 - (sensoreUmidita4/10));
  Blynk.virtualWrite(V5, 100 - (sensoreUmidita5/10));

  Blynk.virtualWrite(V6, 100 - (sensoreUmidita6/10));
  Blynk.virtualWrite(V7, 100 - (sensoreUmidita7/10));
  Blynk.virtualWrite(V8, 100 - (sensoreUmidita8/10));
  Blynk.virtualWrite(V9, 100 - (sensoreUmidita9/10));
  Blynk.virtualWrite(V10, 100 - (sensoreUmidita10/10));

  Blynk.virtualWrite(V11, 100 - (sensoreUmidita11/10));
  Blynk.virtualWrite(V12, 100 - (sensoreUmidita12/10));
  Blynk.virtualWrite(V13, 100 - (sensoreUmidita13/10));
  Blynk.virtualWrite(V14, 100 - (sensoreUmidita14/10));
  Blynk.virtualWrite(V15, 100 - (sensoreUmidita15/10));

  Blynk.virtualWrite(V16, 100 - (sensoreUmidita16/10));
  Blynk.virtualWrite(V17, 100 - (sensoreUmidita17/10));
  Blynk.virtualWrite(V18, 100 - (sensoreUmidita18/10));
  Blynk.virtualWrite(V19, 100 - (sensoreUmidita19/10));
  Blynk.virtualWrite(V20, 100 - (sensoreUmidita20/10));
  Blynk.virtualWrite(V21, 100 - (sensoreUmidita21/10));
  Blynk.virtualWrite(V22, 100 - (sensoreUmidita22/10));
  
  Blynk.virtualWrite(V23, temperatura1);
  Blynk.virtualWrite(V24, umidita1);
  Blynk.virtualWrite(V25, temperatura2);
  Blynk.virtualWrite(V26, umidita2);
 
  
}
 BLYNK_CONNECTED() {
  Blynk.syncAll();
}
void loop() {
  // put your main code here, to run repeatedly:
  
  BlynkEdgent.run();
  timer.run();
}

Dopo aver scritto il tutto, l'IDE mi restituisce come errore il seguente:

In function 'void multi()':
Edgent_MKR1010:95:11: error: 'canale' cannot be used as a function
   canale(0);

questo errore me lo riporta per tutti i canali definiti nel void multi.

Grazie a chiunque possa aiutarmi e/o darmi qualche dritta.

Buonasera e benvenuto nella sezione Italiana del forum,

cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto. :wink:

1 Like

Benvenuto, cas3se!

Giustamente ti dice che hai dichiarato una variabile int canale e poi cerchi più volte di chiamare una funzione canale, che non esiste, passandole anche un argomento!

Fosse solo quello.
@cas3se ti consiglio di provare prima il multiplexer in un progetto più semplice perché dal codice che hai scritto si capisce che non hai idea di come usarlo.
Ad esempio sensoreUmidita7 = analogRead(canale(0),Serial.read()); non ha nessun senso.

Butta quella multi(), devi creare un comando/funzione settaCanale e poi leggi dal digitale A0 (presumo hai collegato quello al multi)
Qualcosa del genere:

void SettaCanale(byte s0, byte s1, byte s2, byte s3, byte canale)
{ switch(canale)
  { case  0: digitalWrite(s0,0); digitalWrite(s1,0);digitalWrite(s2,0);digitalWrite(s3,0); break;
    case  1: digitalWrite(s0,1); digitalWrite(s1,0);digitalWrite(s2,0);digitalWrite(s3,0); break;
...
    case 10: digitalWrite(s0,0); digitalWrite(s1,1);digitalWrite(s2,0);digitalWrite(s3,1); break;
...   devi scriverti tutti i casi da 0 a 15 !!
  }
}

Quindi lo usi così:

SettaCanale(s0,s1,s2,s3, 0) ;
sensoreUmidita7  = analogRead(A0);
SettaCanale(s0,s1,s2,s3, 1);
sensoreUmidita8  = analogRead(A0);

P.S. questi int s0 = 8; meglio scritti come const uint8_t s0 = 8;

1 Like

Potrebbe invece avere senso una sintassi come la seguente:

sensoreUmidita7 = analogRead((canale(0), A0));

...se e solo se: A0 è l'ingresso di Arduino a cui è collegata l'uscita del mux E se 'canale' è una funzione che imposta gli ingressi di selezione del mux, cioè le corrispondenti uscite di Arduino collegate agli ingressi di selezione del mux.

Infatti la chiamata passa un solo argomento (nota la doppia parentesi) :wink:

@nid69ita: ... evitiamo di cancellare domande DOPO che qualcuno ha risposto alle nostre affermazioni ... rende illegibile il thread. Ho ripristinato il tuo post #6 a cui Claudio_FF ha risposto nel post #7.

Grazie.

Guglielmo

@Claudio_FF: l'uso del "Comma operator" rende, specie per i meno esperti, solo più illegibile il codice a fronte di nessuno/scarsissimo vantaggio per l'eseguibile rispetto ad una serie esplicita di istruzioni. Dato che NON siamo qui per fare ottimizzazioni spinte, ma per aiutare dei neofiti (o quasi) ... evitiamo.

Grazie :slight_smile:

Guglielmo

Si, ci hai preso giusto sostanzialmente :sweat_smile: :rofl:

Per selezionare il canale, basta fare così:

void sel_canale(uint8_t n)
  {
  digitalWrite(BIT0_MPX, n%2);
  n/=2;
  digitalWrite(BIT1_MPX, n%2);
  n/=2;
  digitalWrite(BIT2_MPX, n%2);
  n/=2;
  digitalWrite(BIT3_MPX, n%2);
  }

Meglio ancora. Io però aggiungerei una if con controllo n sia <=15

1 Like

Mah... Mi sembrano byte sprecati! Basta fare un minimo (proprio un minimo...) di attenzione nella scrittura del programma! :slight_smile:

Giusto, quando devi fare un minino di attenzione su 2/3 cose e non presti attenzione sei sbadato. Ma quando devi prestare un minimo di attenzione a 1000 cose e una ti sfugge allora sei sbadato 0.1%.

Per me fa la differenza.

Ciao.

void sel_canale(uint8_t n)
{
  digitalWrite(BIT0_MPX, bitRead(n, 0));
  digitalWrite(BIT1_MPX, bitRead(n, 1));
  digitalWrite(BIT2_MPX, bitRead(n, 2));
  digitalWrite(BIT3_MPX, bitRead(n, 3));
}

o

void sel_canale(uint8_t n)
{
  digitalWrite(BIT0_MPX, (bool)(n & 1));
  digitalWrite(BIT1_MPX, (bool)(n & 2));
  digitalWrite(BIT2_MPX, (bool)(n & 4));
  digitalWrite(BIT3_MPX, (bool)(n & 8));
}
2 Likes

Mi piace!

In alternativa avrei scritto i 4 bit di n su PORT, ma non avevo pensato a fare così... :slightly_smiling_face:

In realtà funziona anche senza il cast a bool, perché la digitalWrite comunque scrive 1 se il secondo parametro non è zero. Ma così l'operazione è esplicita.

Sospettavo che distinguesse solo tra 0 e !0...

Quindi diventerebbe:

void sel_canale(uint8_t n)
{
  digitalWrite(BIT0_MPX, n&1);
  digitalWrite(BIT1_MPX, n&2);
  digitalWrite(BIT2_MPX, n&4);
  digitalWrite(BIT3_MPX, n&8);
}

Salve a tutti.
@nid69ita ho seguito il tuo consiglio e mi sono visto un paio di tutorial su come usare un multiplexer, ecc. dunque ho cercato di mettere insieme i pezzi con un po' di logica e sono arrivato a scrivere (quello che sembra) qualcosa di sensato:


// configurazione Blynk
BlynkTimer timer;

// variabili
int alimentazione;

int sensoreUmidita1;
int sensoreUmidita2;
int sensoreUmidita3;
int sensoreUmidita4;
int sensoreUmidita5;
int sensoreUmidita6;


float temperatura1;
float umidita1;

float temperatura2;
float umidita2;

float velocitaVento;

//variabili multiplexer
const int muxSIG = A0;
const int muxS0 = 3;
const int muxS1 = 4;
const int muxS2 = 5;
const int muxS3 = 6;

//canali multiplexer
int SetMuxChannel(byte channel)
{
  digitalWrite(muxS0,bitRead(channel,0));
  digitalWrite(muxS1,bitRead(channel,1));
  digitalWrite(muxS2,bitRead(channel,2));
  digitalWrite(muxS3,bitRead(channel,3));

void setup() {
  //pin multiplexer
  pinMode(muxSIG, INPUT);
  pinMode(muxS0, OUTPUT);
  pinMode(muxS1, OUTPUT);
  pinMode(muxS2, OUTPUT);
  pinMode(muxS3, OUTPUT);
  Serial.begin(9600);
  //inizio blynk
  Serial.begin(115200);
  delay(2000);

  BlynkEdgent.begin();

  //pin alimentazione
  pinMode(8, INPUT); //feedback

  //sens. temperatura
  dhtA.begin();
  dhtB.begin();

  //timer
  timer.setInterval(2000L, trasmissioneDati);
}

void trasmissioneDati() {
  // lettura sensori
  sensoreUmidita1 = analogRead(A1);
  sensoreUmidita2 = analogRead(A2);
  sensoreUmidita3 = analogRead(A3);
  sensoreUmidita4 = analogRead(A4);
  sensoreUmidita5 = analogRead(A5);

  sensoreUmidita6= 

.............

void loop() {
  BlynkEdgent.run();
  timer.run();
}

Tuttavia mi riesce ancora difficile andare a selezionare per ogni singolo sensoreUmidità che vado ad aggiungere la chiamata allo specifico canale. Penso che la soluzione sia davanti ai miei occhi ma ancora non essendo io uno che mangia pane e Arduino tutti i giorni, non la riesco a vedere.

Non capisco dove ti incarti, avevi già fatto tutto, solo che dovevi cambiare la lettura su A0 dove hai il multiplex.

A questa manca la graffa finale e puoi mettere void invece di int davanti (ovvero non ritorna nulla)
Poi per selezionare devi usarla a ripetizione.

SetMuxChannel(0);
sensoreUmidita7 = analogRead(A0);      // al posto di  sensoreUmidita7=analogRead(canale(0),Serial.read());
SetMuxChannel(1);
sensoreUmidita8 = analogRead(A0);      // al posto di  sensoreUmidita8=analogRead(canale(1),Serial.read());   
SetMuxChannel(2);
sensoreUmidita9 = analogRead(A0);
etc