DIY smart home from scratch - intelligent water turbidity sensor based on ESP32

Keywords: IoT arduino

preface

There is a fish tank at home with several fish to play, but the problem of changing the water is really a headache. If you don't pay attention, you often forget to change the water, and the fish will disappear. o(╥﹏╥)o

After obtaining Spirit 1 Edge computer After that, it is equivalent to having a personal intelligent device server, which can develop intelligent devices at home, so I am ready to make an intelligent water turbidity sensor to solve my problem of difficult water exchange.

The current idea is to see when the water is changed. Remind me that the equipment for manual water change and automatic water change filtration is too expensive. I can only see how to DIY a set.

Hardware selection

We still use anxinko this time ESP32S , don't ask, asking is cheap. As for the IOT PI? It has been made by me Intelligent formaldehyde detector It's in the cupboard. Interested friends can go and have a look! The cost of replacing IOT PI with ESP32S is 60 yuan.
DFrboot for sensor Water turbidity sensor.
Wing Hui for server Spirit 1 .

Should I let Anxin give me the advertising fee? Use his board every day ~ ω Let's see the specific reasons why I chose anxinko arduino Development Guide and arduino development: the first application based on ESP32S - infrared temperature measuring gun (with pin diagram) There is also a very detailed introduction to arduino.

Sensor wiring: A0 control (SVP/IO36) is used, and the power supply is connected to 5V.

Code parsing

Get code

In order to facilitate the explanation of logic, I will disrupt the order of the code and may cut it. If you want to run directly with the code, you can go directly The secret treasure house of inspiration desktop Get the code, or directly clone:

https://gitee.com/inspiration-desktop/DEV-lib-arduino.git

If you don't even know what git is, you can refer to it Simple and brainless, ready to use - hand to hand teaches you to use the code of intelligent infrared temperature sensor and the gitee library you rely on!
After downloading or clone code, the three folders are used this time:


Cjson: the cjson library I transplanted is the standard cjson library. Put it in the libraries folder under the arduino installation directory and Baidu can use the cjson functions.

libsddc: I transplanted it from the official SDDC library and the SDK I wrote, and just put it in the libraries folder. Inside is the processing function of SDDC protocol. We don't care.

In the demo folder are the demo codes of our various sensors:


Turboditya in red circle_ sddc_ The demo folder contains our code. Click in to see turboditya_ sddc_ sdk_ Demo.ino file. Double clicking the file will automatically start Arduino ide to open the code. Select the corresponding COM port in tools - > port and click upload to burn the code into the board:

For the specific arduino tutorial, see my previous articles arduino Development Guide and arduino development: the first application based on ESP32S - infrared temperature measuring gun (with pin diagram)

Equipment control command:

Via Spirit 1's application or Sniffer Commands sent to sensor devices:

{
  "method": "get",          // This command allows the sensor to actively send a current water turbidity
  "obj": ["turbidity"]
}
{
  "method": "set",         // This command can adjust the time interval actively reported by the sensor. The change of water turbidity should not be fast. It can be set slower
  "periodic_time": 1000
}

Device and protocol initialization process:

It is written based on the official demo and does not need to be modified. It is mainly about device initialization, pin configuration, and protocol initialization.

/*
 * Initialize sensor
 */
void sensor_init()
{
    // Create a sensor task, periodically obtain the data of water turbidity sensor and send it to EdgerOS
    xTaskCreate(periodic_sensor_task, "periodic_sensor_task", ESP_TASK_STACK_SIZE, NULL, ESP_TASK_PRIO, NULL);
}

void setup() {
    byte mac[6];
    Serial.begin(115200);
    Serial.setDebugOutput(true);
    Serial.println();

    // Initialize sensor
    sensor_init();

    // Clear the state of the key state machine
    button.reset();
  
    // Create a key scanning thread, long press the IO0 key, and the ESP32 will enter the SmartConfig mode after releasing it
    sddc_printf("Press and hold the key to enter Smartconfig...\n");
    button.attachLongPressStop(esp_io0_key_task);
    xTaskCreate(esp_tick_task, "button_tick", ESP_TASK_STACK_SIZE, NULL, ESP_TASK_PRIO, NULL);
    
    // Start WiFi and connect to the network
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) 
    {
        delay(500);
        Serial.print(".");
    }
  
    // Get and print IP address
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.print("'ip :");
    Serial.print(WiFi.localIP());
    Serial.println("' to connect"); 
  
    // sddc protocol initialization
    sddc_lib_main(&sys_cfg);

    // Obtain and print the mac address of the network card
    WiFi.macAddress(mac);
    sddc_printf("MAC addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
              mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]);
    // Use the network card mac address to set the device unique ID UID
    sddc_set_uid(G_sddc, mac);
}

void loop() {
    // Run SDDC protocol cycle
    while (1) 
    {
        sddc_printf("SDDC running...\n");
        sddc_run(G_sddc);
        sddc_printf("SDDC quit!\n");
    }

    // Destroy SDDC protocol
    sddc_destroy(G_sddc);
}

Configure device information

This part of the code can configure the WiFi name and WiFi password, the pin to be used, and configure the information displayed by the device on Spirit 1:

#include "Arduino.h"    
#include <OneButton.h>       
#include <WiFi.h>
#include <SDDC_SDK_lib.h>
#include <cJSON.h>
#include <Wire.h>


#define SDDC_ CFG_ Port 680u / / port number used by SDDC protocol
#define PIN_INPUT 0 / / select IO0 to control
#define ESP_TASK_STACK_SIZE   4096
#define ESP_TASK_PRIO         25

static const int sensor_in = 34;                   // Data input pin

static const char* ssid = "EOS-000045";        // WiFi name
static const char* password = "1234567890";        // WiFi password


static  int xTicksToDelay = 100;                   // Cycle delay time
  
OneButton button(PIN_INPUT, true);

/*
 *  Information definition of the current device
 */
DEV_INFO    dev_info = {
            .name     = "Water turbidity sensor",
            .type     = "sensor",
            .excl     = SDDC_FALSE,
            .desc     = "ESP-32S",
            .model    = "1",
            .vendor   = "Inspiration desktop",
};

/*
 *   System registration object aggregation
 */
SDDC_CONFIG_INFO sys_cfg = {
        .token             = "1234567890",            // Device password
        .devinfo           = &dev_info,               
        .io_dev_reg        = io_dev,
        .io_dev_reg_num    = ARRAY_SIZE(io_dev),
        .num_dev_reg       = num_dev,
        .num_dev_reg_num   = ARRAY_SIZE(num_dev),
        .state_get_reg     = dev_state_get_reg,
        .state_get_reg_num = ARRAY_SIZE(dev_state_get_reg),
        .dis_dev_reg       = dis_dev,
        .dis_dev_num       = ARRAY_SIZE(dis_dev),
};

Callback function registration

This is the location where the callback function is registered after receiving the command. Only the functions registered here can be called correctly by the SDK and perform correct actions.

For specific SDK analysis, please refer to The official series of coerced death! SDK framework based on sddc protocol_ sdk_ Lib parsing and The official series of coerced death! From DDC sniffer to SDDC_ sdk_ Data analysis of Lib

/* 
 *  Registration of object function and processing method of digital quantity equipment
 */
NUM_DEV_REGINFO num_dev[] = {
        {"periodic_time",periodic_time_set},        // When there is periodic in the received command_ Time, period is executed_ time_ Set function
};

/*
 *  Display device object function and processing method registration
 */
DIS_DEV_REGINFO dis_dev[] = {

};

/*
 * IO Device object setting function and processing method registration
 */
IO_DEV_REGINFO io_dev[] = {

};

/*
 *  System object status get registration
 */
DEV_STATE_GET  dev_state_get_reg[] = {
        {"turbidity",   DEV_NUM_TYPE,  single_get_sensor},

};

Data acquisition and sending process

Here is the processing flow written by ourselves, which can be changed according to your needs. After receiving set or get, enter the corresponding processing function according to the previously registered function.
The device will detect the sensor output, and then regularly report the water turbidity data according to the set reporting interval. It can also actively send the get command to actively query the current data of the sensor:

/* 
 *  Periodic reporting function
 */
static void periodic_sensor_task(void *arg)
{
    while(1)
    {
        // After the task is created, set the delay period
        printf("Delay time:%d",xTicksToDelay);
        delay(xTicksToDelay);
        get_sensor();
        delay(100);
    }  
   // Sending data stopped
   Serial.printf("Soil humidity data OFF\n");
}

/* 
 *  Active data reporting function
 */
static void report_sensor()
{  
    int sensorValue = 0;
    cJSON *value;
    cJSON *root;
    char  *msg;
     
    value =  cJSON_CreateArray();
    root = cJSON_CreateObject();
    sddc_return_if_fail(value);
    sddc_return_if_fail(root);
      
    sddc_return_if_fail(value);
      
    // Assembly report message
    cJSON_AddItemToArray(value, cJSON_CreateString("turbidity"));
    cJSON_AddItemToObject(root, "obj", value);
      
    // Send the assembled message to the reporting function
    msg = cJSON_Print(root);
    printf("Regular reporting: %s\n",msg);
    object_report(root);
      
    cJSON_Delete(value);
    cJSON_free(msg);
}


/* 
 *  Set cycle wait time
 */
sddc_bool_t periodic_time_set(const uint64_t value)
{
    printf("Modify timing time!\n");
    xTicksToDelay = value;
    return SDDC_TRUE;
}
/* 
 *  Single acquisition of data
 */
sddc_bool_t single_get_sensor(char *objvalue, int value_len)
{
    int sensorValue = analogRead(A0);  //put Sensor insert into soil
    int value = sensorValue * (5.0 / 1024.0); // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
    snprintf(objvalue, value_len, "%d", value);
    return SDDC_TRUE;
}
 

After the code is written, it will be finished by burning it. It is exactly the same as before. Click Save, and then upload OK. You can see the details Previous documents , I'm too lazy to write it again (/ ω\)

summary

The sensor has been completed, but emmmm what is the turbidity range of fish culture and water change? I can only react to it after it is completed. Then I have time to record the turbidity when I change the water, and then make a judgment at the front end

This article is only for personal learning and use. If there are errors, please correct them ˙ ᗜ ˙ ) Thank you, boss!

Posted by tieded on Thu, 30 Sep 2021 16:53:22 -0700