Wiznet makers

TheoIm

Published November 29, 2023 ©

32 UCC

20 WCC

5 VAR

0 Contests

0 Followers

0 Following

WIZnet Smart Farm(AI Server + W5100S-EVB-PICO)

This project implements a simple smart farm using W5100S-EVB-PICO, where an AI server receiving data measures and manages real-time status, optimal temperature.

COMPONENTS Hardware components

WIZnet - W5100S-EVB-Pico

x 1

Software Apps and online services

OpenAI - ChatGPT

x 1


PROJECT DESCRIPTION

 

Introduction


Hello, everyone! In this project, I implemented a small smart farm with WIZnet's Benjamin. We all sometimes want to grow plants, but it can be a hassle to water them, and our plants often end up dying. However, with this project as your reference, that won't be the case. This project will help your plants thrive and grow well.

 

Project Objectives


Our first task is to receive optimal environmental data (temperature, humidity, brightness, watering time) from the AI and send it to PICO. Once data arrives at my PICO server from Benjamin's AI server, I have implemented internal logic to undergo a comparison process with the sensors. Through this comparison process, the lights, fan, and water pump will be activated accordingly.

 

Development Preparation and Process


Project Materials: W5100S-EVB-PICO, GPIO LED (Light), DC Motor (FAN), Water pump, CDS Sensor (ADC), DHT22, SG-90(servo Motor)

Development Environment: VS Code 

Programming Languages: C, Python 

Development Steps: W5100S-EVB-PICO Logic Testing - Creating AI Server - Circuit Configuration and Assembly - Testing Operations

(Please refer to Benjamin's Smart Farm WCC post for detailed information on the AI server.)

 

 

Project Hardware Photos


 

 

Project Hardware Port Configuration


DC MOTOR DRIVER 1 (FAN) : GPIO 0

SERVO MOTOR (WINDOW) : GPIO 1

LED (LIGHT) : GPIO 2

DC MOTOR DRIVER 2 (WATER PUMP) : GPIO 3

DHT 22 : GPIO 15

ADC SENSOR : GPIO 26(ADC 0)

POWER(HIGH SIGNAL) : 3.3V

 

 

C Code(W5100S-EVB-PICO)


  • tcp.c(Eth part)
 #include <stdio.h>
#include "loopback.h"
#include "socket.h"
#include "wizchip_conf.h"
#include <string.h>
#include <stdlib.h>

#if LOOPBACK_MODE == LOOPBACK_MAIN_NOBLCOK


void parseAiBuf(const uint8_t *ai_buf, uint16_t *temp, uint16_t *humi, uint16_t *bright, uint16_t* wf) {
    char bufCopy[2049];  // copy of ai_buf (길이가 2048인 문자열 + NULL 종료 문자)
    strncpy(bufCopy, (const char *)ai_buf, sizeof(bufCopy) - 1);
    bufCopy[sizeof(bufCopy) - 1] = '\0';  // 문자열 마지막에 NULL 종료 문자 추가

    char *token = strtok(bufCopy, ".");
    if (token != NULL) {
        *temp = atoi(token);
    }

    token = strtok(NULL, ".");
    if (token != NULL) {
        *humi = atoi(token);
    }

    token = strtok(NULL, ".");
    if (token != NULL) {
        *bright = atoi(token);
    }
   token = strtok(NULL, ".");
    if (token != NULL) {
        *wf = atoi(token);
    }
}



int32_t tcps(uint8_t sn, uint8_t* buf, uint16_t port, uint16_t* out_temp, uint16_t* out_humid, uint16_t* out_brightness, uint16_t* water_flag)
{
   int32_t ret;
    uint16_t size = 0, sentsize=0;

#ifdef _LOOPBACK_DEBUG_
   uint8_t destip[4];
   uint16_t destport;
#endif

   switch(getSn_SR(sn))
   {
      case SOCK_ESTABLISHED :
         if(getSn_IR(sn) & Sn_IR_CON)
         {
#ifdef _LOOPBACK_DEBUG_
            getSn_DIPR(sn, destip);
            destport = getSn_DPORT(sn);

            printf("%d:Connected - %d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
#endif
            setSn_IR(sn, Sn_IR_CON);
         }
         if(send_cnt >= 6){

             ret = send(sn, buf, strlen((char*)buf));
           
         if(send_cnt >= 6 && ret < 0)
         {
            close(sn);
            return ret;
         }
            send_cnt = 0;
         }
         else{
            send_cnt++;
         } 

         

   if ((size = getSn_RX_RSR(sn)) > 0)
    {
   if (size > sizeof(ai_buf))
       size = sizeof(ai_buf);

    ret = recv(sn, ai_buf, 2048);

   parseAiBuf(ai_buf, out_temp, out_humid, out_brightness, water_flag);

   printf("loopback.c Temperature: %d\n", *out_temp);
   //  printf("loopback.c Humidity: %d\n", ai_humid);
   //  printf("loopback.c Brightness: %d\n", ai_brightness);
        if (ret <= 0)
            return ret;
    }
         break;

      case SOCK_CLOSE_WAIT :
#ifdef _LOOPBACK_DEBUG_
         //printf("%d:CloseWait\r\n",sn);
#endif
         if((ret = disconnect(sn)) != SOCK_OK) return ret;
#ifdef _LOOPBACK_DEBUG_
         printf("%d:Socket Closed\r\n", sn);
#endif
         break;

      case SOCK_INIT :
#ifdef _LOOPBACK_DEBUG_
         printf("%d:Listen, TCP server loopback, port [%d]\r\n", sn, port);
#endif
         if( (ret = listen(sn)) != SOCK_OK) return ret;
         break;

      case SOCK_CLOSED:
#ifdef _LOOPBACK_DEBUG_
         //printf("%d:TCP server loopback start\r\n",sn);
#endif
         if((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret;
#ifdef _LOOPBACK_DEBUG_
         //printf("%d:Socket opened\r\n",sn);
#endif
         break;

      default:
         break;
   }
   return 1;
}
  • tcp.h(Eth part)
#ifndef _LOOPBACK_H_
#define _LOOPBACK_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

/* Loopback test debug message printout enable */
#define	_LOOPBACK_DEBUG_

/* DATA_BUF_SIZE define for Loopback example */
#ifndef DATA_BUF_SIZE
	#define DATA_BUF_SIZE			2048
#endif

/************************/
/* Select LOOPBACK_MODE */
/************************/
#define LOOPBACK_MAIN_NOBLOCK    0
#define LOOPBACK_MODE   LOOPBACK_MAIN_NOBLOCK


static uint8_t ai_buf[2048];
static int send_cnt = 0;


int32_t tcps(uint8_t sn, uint8_t* buf, uint16_t port, uint16_t* out_temp, uint16_t* out_humid, uint16_t* out_brightness, uint16_t* water_flag);

void parseAiBuf(const uint8_t *ai_buf, uint16_t *temp, uint16_t *humi, uint16_t *bright, uint16_t* wf);

#ifdef __cplusplus
}
#endif

#endif
  • main.c
 /**
 * Copyright (c) 2021 WIZnet Co.,Ltd
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

/**
 * ----------------------------------------------------------------------------------------------------
 * Includes
 * ----------------------------------------------------------------------------------------------------
 */
#include <stdio.h>
#include "pico/stdlib.h"
#include "port_common.h"
#include "hardware/adc.h"
#include <dht.h>
#include "wizchip_conf.h"
#include "w5x00_spi.h"
#include "socket.h"
#include "loopback.h"
#include "hardware/pwm.h"

// extern uint16_t ai_temp;
// extern uint16_t ai_humid;
// extern uint16_t ai_brightness;

uint16_t ai_temp_main;
uint16_t ai_humid_main;
uint16_t ai_brightness_main;
uint16_t ai_water_flag_main;
void set_servo_angle(float angle, int servo_pin);
/**
 * ----------------------------------------------------------------------------------------------------
 * Macros
 * ----------------------------------------------------------------------------------------------------
 */
/* Clock */
#define PLL_SYS_KHZ (133 * 1000)
 
/* Buffer */
#define ETHERNET_BUF_MAX_SIZE (1024 * 2)

/* Socket */
#define SOCKET_LOOPBACK 0

/* Port */
#define PORT_LOOPBACK 5000

/**
 * ----------------------------------------------------------------------------------------------------
 * Variables
 * ----------------------------------------------------------------------------------------------------
 */
/* Network */
static wiz_NetInfo g_net_info =
    {
        .mac = {0x00, 0x08, 0xDC, 0x1D, 0x6B, 0x52}, // MAC address
        .ip = {192, 168, 0, 11},                     // IP address
        .sn = {255, 255, 255, 0},                    // Subnet Mask
        .gw = {192, 168, 0, 1},                     // Gateway
        .dns = {8, 8, 8, 8},                         // DNS server
        .dhcp = NETINFO_STATIC                       // DHCP enable/disable
};

/* Loopback */
static uint8_t g_loopback_buf[ETHERNET_BUF_MAX_SIZE] = {
    0,
};
extern uint8_t ai_buf[2048];



static const dht_model_t DHT_MODEL = DHT22;
static const uint DATA_PIN = 15;
static float celsius_to_fahrenheit(float temperature) {
    return temperature * (9.0f / 5) + 32;
}

/**
 * ----------------------------------------------------------------------------------------------------
 * Functions
 * ----------------------------------------------------------------------------------------------------
 */
/* Clock */
static void set_clock_khz(void);
void set_gpio();
/**
 * ----------------------------------------------------------------------------------------------------
 * Main
 * ----------------------------------------------------------------------------------------------------
 */



int main()
{
    /* Initialize */
    int retval = 0;
    int buf_len = 0;
    set_clock_khz();
    
    stdio_init_all();
    set_gpio();
    adc_init();
    adc_gpio_init(26);
    // Select ADC input 0 (GPIO26)
    adc_select_input(0);


    dht_t dht;
    dht_init(&dht, DHT_MODEL, pio0, DATA_PIN, true /* pull_up */);
    printf(" DHT TEST SIGNAL\n");



    wizchip_spi_initialize();
    wizchip_cris_initialize();

    wizchip_reset();
    wizchip_initialize();
    wizchip_check();

    network_initialize(g_net_info);

    /* Get network information */
    print_network_information(g_net_info);

    /* Infinite loop */
    while(1){
  
       dht_start_measurement(&dht);

        float humidity;
        float temperature_c;
        uint16_t adc_result = adc_read();
        dht_result_t result = dht_finish_measurement_blocking(&dht, &humidity, &temperature_c); 
        if (result == DHT_RESULT_OK) {
            // printf("%.1f C (%.1f F), %.1f%% humidity\n", temperature_c, celsius_to_fahrenheit(temperature_c), humidity);
          //  printf("adc value = %d\n Temp = %.1f \n humi = %.1f\n", adc_result, temperature_c, humidity);
        } 
        
        else if (result == DHT_RESULT_TIMEOUT) {
            
        } 
        else {
            assert(result == DHT_RESULT_BAD_CHECKSUM);
         //   puts("Bad checksum");
        }
        sleep_ms(500);
        
                /* TCP server loopback test */
        sprintf(g_loopback_buf, "temp : %.1f, humi : %.1f, adc_result : %d\n", temperature_c, humidity, adc_result);
        
    // printf("Main Temperature: %d\n", ai_temp);
    // printf("Main Humidity: %d\n", ai_humid);
    // printf("Main Brightness: %d\n", ai_brightness);
        if ((retval = tcps(SOCKET_LOOPBACK, g_loopback_buf, PORT_LOOPBACK, &ai_temp_main, &ai_humid_main, &ai_brightness_main, &ai_water_flag_main)) < 0)
        {
            printf(" Loopback error : %d\n", retval);

            while (1)
                ;
        }


        // 출력
        printf("Main Temperature: %d\n", ai_temp_main);
        printf("Main Humidity: %d\n", ai_humid_main);
        printf("Main Brightness: %d\n", ai_brightness_main);
        printf("Main water flag: %d\n", ai_water_flag_main);
    


        if(ai_temp_main <= temperature_c)// Temp high? , FAN(GPIO 0) ON 
        {
                gpio_put(0, 1);
        }
        else                                    // else FAN(GPIO 0) Off
        {
                gpio_put(0, 0);
        }

        if(ai_humid_main <= humidity)      //Humi high? Window(GPIO 1) OPEN
        {
                set_servo_angle(90, 1);
        }
        else                                    //else? Window(GPIO 1) Close
        {
                set_servo_angle(0, 1);
        }


        if(ai_brightness_main >= adc_result)      //Brightness? Light(GPIO 2) ON
        {
                gpio_put(2, 1);
        }
        else                                    //else? Light(GPIO 2) OFF
        {
                gpio_put(2, 0);
        }

        if(ai_water_flag_main == 0)      //Water flag off?      Pump (GPIO 3) OFF 
        {
                gpio_put(3, 0);
        }
        else                             //else? pump (GPIO 3) ON for 2 sec
        {
                gpio_put(3, 1);
                sleep_ms(2000);
                gpio_put(3, 0);
        }


    }
}
/**
 * ----------------------------------------------------------------------------------------------------
 * Functions
 * ----------------------------------------------------------------------------------------------------
 */
/* Clock */
static void set_clock_khz(void)
{
    // set a system clock frequency in khz
    set_sys_clock_khz(PLL_SYS_KHZ, true);

    // configure the specified clock
    clock_configure(
        clk_peri,
        0,                                                // No glitchless mux
        CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, // System PLL on AUX mux
        PLL_SYS_KHZ * 1000,                               // Input frequency
        PLL_SYS_KHZ * 1000                                // Output (must be same as no divider)
    );
}

void set_gpio(){
        
         gpio_init(0);
         gpio_init(1);
        gpio_init(2);
        gpio_init(3);      
        gpio_init(4);

        gpio_set_dir(0, GPIO_OUT);
        gpio_set_dir(1, GPIO_OUT);

        gpio_set_dir(2, GPIO_OUT);
        gpio_set_dir(3, GPIO_OUT);
        gpio_set_dir(4, GPIO_OUT);
}

void set_servo_angle(float angle, int servo_pin) {
    if (angle < 0.0) {
        angle = 0.0;
    } else if (angle > 90.0) {
        angle = 90.0;
    }

    //convert deg into pulse (0 deg: 0.5ms, 90deg: 2.5ms)
    float pulse_width = 0.5 + (angle / 90.0) * 2.0;

    // GPIO set up
    gpio_set_function(servo_pin, GPIO_FUNC_PWM);
    uint slice_num = pwm_gpio_to_slice_num(servo_pin);

    // PWM set up
    pwm_set_wrap(slice_num, 1000000);  // freq set up (1e6 = 1MHz)
    pwm_set_chan_level(slice_num, PWM_CHAN_A, (uint16_t)(pulse_width * 50000));  // 펄스 폭 설정 (20ms 주기)

    // wating
    sleep_ms(20);  // wating for 20ms

    // PWM end
    pwm_set_chan_level(slice_num, PWM_CHAN_A, 0);
    sleep_ms(20);  // wating for 20ms
}

Git Link


[Git Link]  :  smartfarm_rp2040

 

AI Server


When you press the 'Start Cultivation' button on the AI server, it will establish a connection with the W5100S-EVB-PICO assigned to the same router. After the connection is established, the AI server will send optimal environmental data values for plant growth. Subsequently, in step 3, you can confirm through Tera Term (UART) how PICO receives the optimal environmental data values.

 

PICO processes data through sensors and sends real-time data from the smart farm to the AI server. The AI server presents real-time data on a webpage and uses a trained model to assess the plant's status based on real-time time and images. Additionally, when it's time to water the plants, the AI server automatically sends data to PICO, causing PICO to use the water pump to provide water.

 

Documents
  • smartfarm_rp2040

Comments Write