聚豐項目 > 基于AB32的自動澆水系統
平時因為出差不能給盆栽澆水,所以我做了一個自動澆水的系統,開發板采集土壤的濕度并且分析,當土壤濕度太高,開發板控制繼電器打開水泵澆水并且蜂鳴器會發出警報。OLED屏幕會顯示,室內的濕度以及溫度作為參考。
jf_1689824308.7499
分享jf_1689824308.7499
團隊成員
譚周強 主要編程
開發板使用的是中科藍訊的AB32,本系統分為3個部分。
OLED顯示部分,顯示溫濕度采集的值。
土壤濕度采集部分,采集土壤的濕度,對數據做出判斷,發出控制指令。
繼電器控制部分,開發板發出信號,控制繼電器打開水泵澆水,并且蜂鳴器會發出警告。
開發平臺使用的是RT_studio,它講很多模塊都集成,界面看著也很舒服。
運用了RT_Thre,事件發送,線程。
主函數程序部分:
#include
先初始化OLED屏幕,然后調用溫濕度傳感器線程初始化,oled屏幕線程初始化,adc線程初始化,蜂鳴器和繼電器線程初始化。
ADC程序部分:
static void adc_thread_entry(void *parameter) { (void)parameter; while(1) { rt_thread_mdelay(1000); if(adc_vol_sample()>800){ rt_event_send(adc_event, 1); rt_thread_mdelay(100); }else { rt_event_send(adc_event, 2); rt_thread_mdelay(100); } } } int adc_thread_init(void) { adc_event = rt_event_create("adc", // 事件名稱 RT_IPC_FLAG_FIFO); // 先進先出模式 if(adc_event == RT_NULL) return -1; adc_thread = rt_thread_create("adc", // 線程名稱 adc_thread_entry, // 線程入口函數 RT_NULL, // 入口函數入口參數 512, // 線程堆棧大小 8, // 線程優先級 20); // 時間片 if(adc_thread == RT_NULL) return -1; return rt_thread_startup(adc_thread); // 啟動線程 }
采集土壤濕度,當土壤濕度大于800的時候發送adc事件1,當小于800的時候發送事件2.
繼電器控制部分程序:
static void buzz_thread_entry() { rt_err_t result = RT_EOK; rt_uint32_t eventVal = 0; buzz_init(); // LED引腳初始化 while(1) { result = rt_event_recv(adc_event, 1|2,// 接收4個按鍵事件 RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,// 任意一個事件發生,完成后清除事件標志 500, // 等待時間 &eventVal); // 事件值 if(result == RT_EOK) { if(eventVal==1) { Buzz(1); } if(eventVal==2) { Buzz(0); } } } } int buzz_thread_init(void) { buzz_thread = rt_thread_create("buzz", // 線程名稱 buzz_thread_entry, // 線程入口函數 RT_NULL, // 入口函數傳入參數 256, // 線程堆棧大小 10, // 線程優先級 20); // 線程時間片 if(buzz_thread == RT_NULL) return -1; return rt_thread_startup(buzz_thread); }
接收adc發送來的事件進行判斷。
溫濕度傳感器部分程序:
int rt_hw_dht11_port(void) { struct rt_sensor_config cfg; cfg.intf.user_data = (void *)DHT11_DATA_PIN; rt_hw_dht11_init("dht11", &cfg); return RT_EOK; } static void read_temp_entry(void *parameter) { rt_device_t dev = RT_NULL; struct rt_sensor_data sensor_data; rt_size_t res; rt_uint8_t get_data_freq = 1; /* 1Hz */ dev = rt_device_find("temp_dht11"); if (dev == RT_NULL) { return; } if (rt_device_open(dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) { rt_kprintf("open device failed!\n"); return; } rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)(&get_data_freq)); while (1) { res = rt_device_read(dev, 0, &sensor_data, 1); if (res != 1) { rt_kprintf("read data failed! result is %d\n", res); rt_device_close(dev); return; } else { if (sensor_data.data.temp >= 0) { temp = (sensor_data.data.temp & 0xffff) >> 0; // get temp humi = (sensor_data.data.temp & 0xffff0000) >> 16; // get humi //rt_kprintf("temp:%d, humi:%d\n" ,temp, humi); } } rt_thread_delay(1000); } } void dht11_read_temp_sample(void) { rt_thread_t dht11_thread; dht11_thread = rt_thread_create("dht_tem", read_temp_entry, RT_NULL, 1024, RT_THREAD_PRIORITY_MAX / 2, 20); if (dht11_thread != RT_NULL) { rt_thread_startup(dht11_thread); } }
使用的是 DHT11的軟件包對溫濕度進行采集,將溫度以及濕度保存。
oled屏幕部分程序:
static void oled_display_entry(void *parameter) { char text[200]; while(1) { rt_memset(text, 0, sizeof(text)); rt_sprintf(text, "%d", temp); ssd1306_SetCursor(60, 6);//添加代碼,設置顯示光標位置 ssd1306_WriteString(text, Font_11x18, White);//添加代碼,設置顯示內容 // ssd1306_UpdateScreen();////添加代碼,更新顯示屏信息 rt_memset(text, 0, sizeof(text)); rt_sprintf(text, "%d", humi); ssd1306_SetCursor(60, 40);//添加代碼,設置顯示光標位置 ssd1306_WriteString(text, Font_11x18, White);//添加代碼,設置顯示內容 ssd1306_UpdateScreen();////添加代碼,更新顯示屏信息 rt_thread_mdelay(100); } } void oled_display_thread_create() { rt_thread_t oled_display_thread; oled_display_thread = rt_thread_create("oled_display", oled_display_entry, RT_NULL, 1024, 20, 40); if (oled_display_thread != RT_NULL) { rt_thread_startup(oled_display_thread); } }
將采集的溫濕度數據顯示在屏幕中,使用的是ssd1306 軟件包。