Come isolare più sonde di umidità del terreno collegate tramite CD4051 per evitare crosstalk e derive di tensione?
Ciao a tutti, premetto che sono un biologo che si diletta di elettronica molto basic e che sta usando ogni guida disponibile, ma a volte alcune cose che faccio non mi sono al 100% chiare proprio per la mancanza della base necessaria, comunque ho una necessità sperimentale a cui nessuno riesce a rispondere ![]()
sto lavorando a un progetto con Arduino Nano per mappare l’umidità del terreno in verticale, usando più sonde inserite nel suolo a distanza di ~2 mm. L’idea è ottenere una sorta di profilo della distribuzione dell’acqua quando irrigo dal basso. Mi serve in realtà sapere l'istante in cui l'acqua propaga fino a quel punto e magari avere una lettura abbastanza riproducibile da poter identificare un valore di umidità stabile.
Configurazione attuale
6 sonde puntiformi nel terreno.
Un CD4051BE come multiplexer per selezionare una sonda alla volta che verrà letta separatamente dalla stessa entrata analogica di Arduino (su entrate direttamente separate il crosstalk era terribile, usandone una aperta esclusivamente per una sonda alla volta sembra essere migliorato ma non perfetto).
Ogni sonda viene alimentata da un uscita digitale separata di Arduino tramite una resistenza da 1kΩ per la lettura su un PIN analogico tramite il cd4051.
Ogni sonda è collegata poi alla porta del CD4051 per la lettura tramite la porta in uscita, collegata tramite una resistenza di 1 kΩ ad A0 di Arduino. Ogni sonda è anche collegata tramite una resistenza da 100kΩ a terra per scaricare ogni residuo prima di passare alla lettura successiva.
La modifica della lettura avviene tramite la scarica verso un elettrodo di ritorno (GND) inserito nel terreno, uno per sonda a circa 2mm lateralmente alla sonda stessa per evitare che il segnale abbia un lag dovuto alla distanza sonda-gnd
Schema semplificato del wiring (una sonda rappresentativa, replicate le altre sul CD4051):
Sonda i (es. canale 0):
D8 --[1k]--o-----> X0 (CD4051)----->[1k]----->A0
|
[elettrodo attivo]
|
(terriccio)
|
[elettrodo di ritorno a gnd]
Teoricamente con letture separate da una lettura dummy e un pochino di delay (non troppo, mi servono letture veloci sul mezzo secondo in totale) dovrei riuscire a percepire l'arrivo dell'acqua tramite la diminuzione di resistenza del terreno come una diminuzione del readout ad a0.
Codice: (ho usato chatGPT per aiutarmi nella pulizia del codice e per avere una media di letture consecutive, cosa che non riuscivo in alcun modo a fare)
const int pinS0 = 2;
const int pinS1 = 3;
const int pinS2 = 4;
const int analogPin = A0; // Z -> (10k) -> A0
const int probePins[6] = {8,9,10,11,12,13};
const int NPROBES = 6;
const unsigned int POWER_SETTLE_US = 500; // microsecondi, regola 300-800
const unsigned int BETWEEN_SAMPLES_US = 200;
const int SAMPLES = 2;
void setup() {
Serial.begin(115200);
pinMode(pinS0, OUTPUT);
pinMode(pinS1, OUTPUT);
pinMode(pinS2, OUTPUT);
// inizializza probe pins come INPUT (scollegati)
for (int i=0;i<NPROBES;i++) pinMode(probePins[i], INPUT);
analogRead(analogPin); // lettura di scarto iniziale
delay(50);
Serial.println("time_ms,p0,p1,p2,p3,p4,p5");
}
void selectMuxChannel(int ch) {
digitalWrite(pinS0, ch & 1);
digitalWrite(pinS1, (ch >> 1) & 1);
digitalWrite(pinS2, (ch >> 2) & 1);
}
int readProbe(int idx) {
// Assicuriamo che tutte le sonde siano spente
for (int i=0;i<NPROBES;i++) pinMode(probePins[i], INPUT);
// Seleziona canale
selectMuxChannel(idx);
// Accendi la sonda (OUTPUT HIGH via 1k)
pinMode(probePins[idx], OUTPUT);
digitalWrite(probePins[idx], HIGH);
// Attendi il settling (microsecondi)
delayMicroseconds(POWER_SETTLE_US);
// Lettura di scarto
analogRead(analogPin);
long sum = 0;
for (int s=0;s<SAMPLES;s++) {
sum += analogRead(analogPin);
if (s < SAMPLES-1) delayMicroseconds(BETWEEN_SAMPLES_US);
}
int value = sum / SAMPLES;
// Spegni sonda e scollega return
pinMode(probePins[idx], INPUT);
return value;
}
void loop() {
unsigned long t = millis();
int values[NPROBES];
for (int i=0;i<NPROBES;i++){
values[i] = readProbe(i);
delayMicroseconds(200); // piccolo gap tra canali
}
// stampa CSV
Serial.print(t);
for (int i=0;i<NPROBES;i++){
Serial.print(',');
Serial.print(values[i]);
}
Serial.println();
delay(1000);
}
Problemi osservati:
Crosstalk: quando irrigo dal basso, anche le sonde più lontane rispondono parzialmente come se fossero influenzate dall’acqua, mentre dovrebbero rispondere in ritardo anche perché io vedo dal lato il progredire dell'acqua e non arriva così in fretta all'ultima sonda. Alcune delle sonde (la seconda e le ultime due dal basso in particolare) cambiano molto anche quando fuori dal terreno collego direttamente gnd alla sonda per mandare la lettura a 0 come test di prova, cosa che non dovrebbe essere possibile assolutamente dato che senza il terreno non dovrebbe esserci nessun crosstalk.
Deriva a riposo: anche senza irrigazione, vedo un trend discendente lento dei valori (es. da 495 ADC a ~450 in 10 minuti). Questa cosa non capita sempre, su breadboard ogni tanto capitava, poi ho saldato tutto su una millefori e capita ancora, quindi non penso sia dovuto alla stabilità del collegamento.
Domanda:
Qual è il modo migliore per:
isolare le letture delle sonde (per ridurre il crosstalk tra ingressi del CD4051 e tra le sonde stesse),
stabilizzare le oscillazioni/derive del voltaggio, considerando che non posso usare buffer esterni al momento?
Ha senso usare un'alimentazione esterna, magari con un condensatore in Vin per stabilizzarla quando magari la lettura la fa oscillare? O magari mandare le sonde a un PIN digitale in LOW separato per ogni sonda invece che all'elettrodo di ritorno a gnd comune?
Accetto consigli sia sul circuito (resistenze di pull-down, modifiche al wiring, disposizione dell’elettrodo di ritorno, ecc.) sia a livello software (tempi di lettura, medie, ecc.).
Grazie in anticipo per ogni spunto!