Kapacitní čidlo vlhkosti nám může posloužit k měření vlhkosti půdy a lze pomocí něho a Pica například vytvořit automatický zavlažovací systém pro květiny. Čidlo převádí kapacitu na napětí v rozsahu 0 až 3V. Základem jeho zapojení je použit populární obvod TCL555I (NE555). Stačí nám ho zapojit k analogově digitálnímu převodníku ADC Pica a můžeme měřit vlhkost. Existují i odporová čidla vlhkosti, která však jsou téměř nepoužitelná, protože silně trpí rozpadem elektrod díky elektrolýze, která probíhá ve vlhkém prostředí vždy.

Vnitřní schéma zapojení čidla

schema zapojeni cidla vlhkosti2

Problémem však je nekvalita výroby řady výrobců (a neserióznost řady prodejců), kdy např. napěťová reference chybí a je nahrazena odporem (potom čidlo měří v závislosti na napájecím napětí, tedy nesmysly) a špatné zapojení rezistoru R1. Detailně je o tom pojednáno ve videu Capacitive Soil Moisture Sensors don’t work correctly + Fix for v2.0 v1.2 Arduino ESP32 Raspberry Pi. Je třeba dobře vybírat. Mě se snad podařilo koupit čidlo dobré.

Obrázek čidla

IMG 20240226 005440

Černý drát je zem, červený drát je napájecí napětí 3.3V až 5V a žlutý drát je měřené napětí v rozsahu 0 až 3V.

Detail

IMG 20240226 005400

Předběžné výsledky

Vlhká sonda

IMG 20240226 025337

Suchá sonda

IMG 20240226 025248

Poznámka: Suché čidlo měří 1V, ponořené 0.5V, budeme ho muset ještě detailně proměřit,
protože to nějak neodpovídá specifikaci a možná jde o další zmetek.

Základ programu je převzat z předchozího měření teploty, takže program měří i teplotu pomocí čidla UMW DS8B20 a vlhkost a zobrazuje ji na displeji OLED SH1106.

ds18b20_test.cpp
#include <stdio.h>

const int ROMSize = 8;

#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "hardware/adc.h"
#include "modules/pico-onewire/api/one_wire.h"
#include "ss_oled.hpp"

// RPI Pico I2c
#define SDA_PIN 4
#define SCL_PIN 5
#define PICO_I2C i2c0
#define I2C_SPEED 100 * 1000


int main()
{
static uint8_t ucBuffer[1024];
char buf[128];
uint8_t uc[8];
int i, j, rc;
char szTemp[32];
uint16_t araw; // z adc
const float conversion_factor = 3.3f / (1<<12);
float napeti;

    // displej pripojen na Pin 4 SDA a Pin 5 SCL
    picoSSOLED myOled(OLED_128x64, 0x3c, 0, 0, PICO_I2C, SDA_PIN, SCL_PIN, I2C_SPEED);

    rc = myOled.init() ;
    myOled.set_back_buffer(ucBuffer);
    stdio_init_all();
    One_wire one_wire(15); // cislo teploty cteme na GP15 - Pin 20 on Pi Pico
    one_wire.init();
    rom_address_t address{};
    // inicializace ADC
    adc_init();
    adc_select_input(0); // merime na pinu 31 (ADC0)
    while (true) {
        one_wire.single_device_read_rom(address);
        printf("Device Address: %02x%02x%02x%02x%02x%02x%02x%02x\n", address.rom[0], address.rom[1], address.rom[2], address.rom[3], address.rom[4], address.rom[5], address.rom[6], address.rom[7]);
	    sprintf(buf,"%02x%02x%02x%02x%02x%02x%02x%02x",address.rom[0], address.rom[1], address.rom[2], address.rom[3], address.rom[4], address.rom[5], address.rom[6], address.rom[7]);
	    one_wire.convert_temperature(address, true, false);
        myOled.fill(0,1);
	    myOled.set_contrast(127);
	    myOled.write_string(0,0,0,buf, FONT_8x8, 0, 1);
        printf("Temperature: %3.1foC\n", one_wire.temperature(address));
	    sprintf(buf,"%3.1f C",one_wire.temperature(address));
	    myOled.write_string(0,0,3,buf, FONT_12x16, 0, 1);
	    // cteni ADC
	    araw = adc_read();
	    napeti = araw*conversion_factor;
	    printf("araw = %d: napeti %f\n", araw,napeti );     // na debug
	    sprintf(buf,"%5.3f V",napeti);                      // na displej
	    myOled.write_string(0,0,5,buf, FONT_12x16, 0, 1);

        sleep_ms(1000);
    }
    return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.13)

# initialize the SDK based on PICO_SDK_PATH
# note: this must happen before project()
include(pico_sdk_import.cmake)

project(vlhkost1)

# set(CMAKE_C_STANDARD 11)

# initialize the Raspberry Pi Pico SDK
pico_sdk_init()

# rest of your project

add_executable(vlhkost1
	ds18b20_test.cpp
)

add_subdirectory(modules/pico-onewire)
add_subdirectory(modules/pico-ss-oled)

target_link_libraries(vlhkost1
pico_stdlib
pico_one_wire
pico_ss_oled
hardware_adc
)

pico_enable_stdio_usb(vlhkost1 1)
pico_enable_stdio_uart(vlhkost1 0)

# create map/bin/hex/uf2 file in addition to ELF.
pico_add_extra_outputs(vlhkost1)

Zabalený projekt verze 0.1: teplota_vlhkost-0.1.tar.gz

Měření

Čidlo se ukazuje jako zmetek, neodpovídá specifikaci. Při napájecím napětí 5.0V 3 Voltový stabilizátor stabilizuje referenční napětí na hodnotě 3.33V a při napájecím napětí 3.3V stabilizuje na referenční napětí na hodnotě 3.23V. Značení součástek neodpovídá schématu. Jeho výstupní měřené napětí je od 0.5V (plně ve vodě) do 1.0V (na suchu), specifikace říká 0 V až 3V.

UNI-T UT61E+ měří referenční napětí Pica, Mustool MDS8207 měří napětí sondy

IMG 20240226 231536

Měření ponořené sondy

Drobná úprava kódu

Referenční napětí Pica jsem změril pomocí UTI-T UT61E+ (přesnost měření napětí na daném rozsahu +/- 0.05% +5dig) a podle skutečné hodnoty jsem upravil konverzní faktor. Protože měření napětí pomocí ADC na Picu hodně skáče, změřím 10 hodnot rychle za sebou a budu zobrazovat jejich průměr. Přesnost měření je teď 1% z naměřené hodnoty.

Úprava měření
const float conversion_factor = 3.22f / (1<<12);

	    araw = adc_read();
	    for( uint8_t i=0; i<9; i++ ) {
	        araw += adc_read();
	        sleep_ms(5);
	        }
	    napeti = araw*conversion_factor*0.1;

Zabalený projekt verze 0.2: teplota_vlhkost-0.2.tar.gz

Závěr

Pro jednoduché hlídání zalitých květin se čidlo dá snad použít. V každém případě je nutné každý kus aspoň přibližně ocejchovat a až potom používat. Za cenu 38 Kč to docela jde. Lepší čidla budou o hodně dražší.

Zdroje a odkazy