一、項(xiàng)目介紹
隨著現(xiàn)代農(nóng)業(yè)的發(fā)展,人們對(duì)于水資源的合理利用越來(lái)越重視。而傳統(tǒng)的灌溉方式往往存在著浪費(fèi)水資源、勞動(dòng)力投入大、效率低等問(wèn)題。因此,設(shè)計(jì)一款智能灌溉控制系統(tǒng),可以實(shí)現(xiàn)對(duì)灌溉水量的精準(zhǔn)控制,增加水資源利用率,提高農(nóng)業(yè)生產(chǎn)效率,具有廣泛的應(yīng)用前景。
當(dāng)前文章介紹一款高性能的智能灌溉控制系統(tǒng)的開(kāi)發(fā)過(guò)程,可自動(dòng)采集電壓、電流、累計(jì)用水量,并根據(jù)用戶需要實(shí)現(xiàn)自動(dòng)灌溉、定時(shí)灌溉、周期灌溉和手動(dòng)灌溉等多種模式,同時(shí)具備中控室控制、手機(jī)短信、現(xiàn)場(chǎng)遙控及現(xiàn)場(chǎng)手動(dòng)等多種方式控制功能。該系統(tǒng)可以對(duì)現(xiàn)場(chǎng)溫濕度限值進(jìn)行設(shè)置和修改,并通過(guò)控制器或后臺(tái)監(jiān)控系統(tǒng)完成灌溉起始時(shí)間、停止時(shí)間、噴灌時(shí)間等參數(shù)設(shè)置。系統(tǒng)顯示功能包括液晶屏以中文菜單方式顯示現(xiàn)場(chǎng)采集數(shù)據(jù)以及后臺(tái)監(jiān)控系統(tǒng)配大屏幕顯示器,圖形、表格等多種形式動(dòng)態(tài)顯示整個(gè)灌溉區(qū)運(yùn)行情況。同時(shí),在電壓、電流或者流量出現(xiàn)異常時(shí),系統(tǒng)可以及時(shí)報(bào)警。該系統(tǒng)供電為220VAC,流量計(jì)量誤差精度為2級(jí),使用二維碼或卡實(shí)現(xiàn)預(yù)付費(fèi)功能,通訊使用4G與云平臺(tái)連接。
二、設(shè)計(jì)功能
本系統(tǒng)采用STM32作為主控芯片,并通過(guò)AD模塊采集電壓、電流和流量等數(shù)據(jù)。同時(shí),通過(guò)繼電器控制灌溉設(shè)備的啟停,使用PWM控制閥門(mén)的開(kāi)合程度,從而實(shí)現(xiàn)精確控制灌溉水量。通信模塊則采用4G模塊與云平臺(tái)連接,實(shí)現(xiàn)遠(yuǎn)程監(jiān)控及控制功能。預(yù)付費(fèi)模塊則使用二維碼或卡實(shí)現(xiàn)預(yù)付費(fèi)功能,用戶需在充值后才能使用該系統(tǒng)進(jìn)行灌溉操作。
系統(tǒng)軟件設(shè)計(jì)包括采集程序、控制程序、前端程序和后臺(tái)程序。其中,采集程序主要負(fù)責(zé)采集電壓、電流、流量等數(shù)據(jù),并將采集到的數(shù)據(jù)上傳到云平臺(tái);控制程序主要負(fù)責(zé)控制灌溉設(shè)備的啟停和閥門(mén)的開(kāi)合程度,從而實(shí)現(xiàn)灌溉控制;前端程序主要負(fù)責(zé)實(shí)現(xiàn)中文菜單方式顯示現(xiàn)場(chǎng)采集數(shù)據(jù),并提供灌溉模式選擇、參數(shù)設(shè)置等功能;后臺(tái)程序主要負(fù)責(zé)實(shí)現(xiàn)大屏幕顯示器、圖形、表格等多種形式動(dòng)態(tài)顯示整個(gè)灌溉區(qū)運(yùn)行情況。
【1】硬件部分
- MCU:本系統(tǒng)采用STM32作為主控芯片,其具有高性能、低功耗等優(yōu)點(diǎn),可滿足該系統(tǒng)的高要求。
- 數(shù)據(jù)采集模塊:本系統(tǒng)通過(guò)AD模塊采集電壓、電流和流量等數(shù)據(jù),然后使用MCU進(jìn)行處理,并將采集到的數(shù)據(jù)存儲(chǔ)到Flash中。
- 控制模塊:本系統(tǒng)通過(guò)繼電器控制灌溉設(shè)備的啟停,同時(shí)使用PWM控制閥門(mén)的開(kāi)合程度,從而實(shí)現(xiàn)精確控制灌溉水量。
- 通信模塊:本系統(tǒng)采用4G模塊與云平臺(tái)連接,實(shí)現(xiàn)遠(yuǎn)程監(jiān)控及控制功能。
- 預(yù)付費(fèi)模塊:本系統(tǒng)使用二維碼或卡實(shí)現(xiàn)預(yù)付費(fèi)功能,用戶需在充值后才能使用該系統(tǒng)進(jìn)行灌溉操作。
【2】軟件部分
- 采集程序:本系統(tǒng)的采集程序主要負(fù)責(zé)采集電壓、電流、流量等數(shù)據(jù),并將采集到的數(shù)據(jù)上傳到云平臺(tái)。
- 控制程序:本系統(tǒng)的控制程序主要負(fù)責(zé)控制灌溉設(shè)備的啟停和閥門(mén)的開(kāi)合程度,從而實(shí)現(xiàn)灌溉控制。
- 前端程序:本系統(tǒng)的前端程序主要負(fù)責(zé)實(shí)現(xiàn)中文菜單方式顯示現(xiàn)場(chǎng)采集數(shù)據(jù),并提供灌溉模式選擇、參數(shù)設(shè)置等功能。
- 后臺(tái)程序:本系統(tǒng)的后臺(tái)程序主要負(fù)責(zé)實(shí)現(xiàn)大屏幕顯示器、圖形、表格等多種形式動(dòng)態(tài)顯示整個(gè)灌溉區(qū)運(yùn)行情況。
三、系統(tǒng)實(shí)現(xiàn)
具體實(shí)現(xiàn)過(guò)程如下:
(1)采集程序
采集程序主要由AD模塊和STM32芯片完成。AD模塊采集電壓、電流和流量等數(shù)據(jù),經(jīng)過(guò)濾波和放大處理后,傳輸?shù)絊TM32芯片上。STM32芯片通過(guò)串口將采集到的數(shù)據(jù)上傳到云平臺(tái),并存儲(chǔ)在Flash中。
(2)控制程序
控制程序主要由繼電器和PWM模塊完成。繼電器用于控制灌溉設(shè)備的啟停,PWM模塊則用于控制閥門(mén)的開(kāi)合程度,從而實(shí)現(xiàn)精確控制灌溉水量??刂瞥绦蛲ㄟ^(guò)讀取Flash中存儲(chǔ)的參數(shù),確定灌溉起始時(shí)間、停止時(shí)間、噴灌時(shí)間等操作流程,并根據(jù)實(shí)時(shí)采集到的數(shù)據(jù)進(jìn)行動(dòng)態(tài)調(diào)整,保證灌溉操作的準(zhǔn)確性和穩(wěn)定性。
(3)前端程序
前端程序主要是通過(guò)液晶屏以中文菜單方式顯示現(xiàn)場(chǎng)采集數(shù)據(jù),并提供灌溉模式選擇、參數(shù)設(shè)置等功能。用戶可以通過(guò)按鍵或觸摸屏來(lái)進(jìn)行操作,并實(shí)時(shí)查看灌溉操作的運(yùn)行情況。此外,用戶還可以通過(guò)手機(jī)短信、現(xiàn)場(chǎng)遙控或現(xiàn)場(chǎng)手動(dòng)等方式對(duì)灌溉操作進(jìn)行控制。
(4)后臺(tái)程序
后臺(tái)程序主要負(fù)責(zé)實(shí)現(xiàn)大屏幕顯示器、圖形、表格等多種形式動(dòng)態(tài)顯示整個(gè)灌溉區(qū)運(yùn)行情況,同時(shí)還能夠?qū)⒉杉降臄?shù)據(jù)進(jìn)行分析和統(tǒng)計(jì),為灌溉管理提供決策參考。
四、核心代碼
【1】電機(jī)控制代碼
以下是STM32F103ZET6通過(guò)PWM控制直流電機(jī)轉(zhuǎn)速的代碼,并封裝成子函數(shù)調(diào)用的示例:
首先,需要在STM32CubeMX中配置TIM定時(shí)器和GPIO引腳,以及將PWM模式設(shè)置為嵌套邊沿對(duì)齊模式,然后生成代碼,并在main.c文件中添加以下代碼:
#include "main.h"
#include "stm32f1xx_hal.h"
?
/* TIM handle structure */
TIM_HandleTypeDef htim;
?
/* Function prototypes */
void PWM_Init(TIM_HandleTypeDef *htim, uint32_t channel);
void Set_Motor_Speed(TIM_HandleTypeDef *htim, uint32_t channel, uint16_t speed);
?
int main(void)
{
/* Initialize the HAL Library */
HAL_Init();
?
/* Initialize TIM2 PWM with a frequency of 10 kHz */
PWM_Init(&htim2, TIM_CHANNEL_1);
?
/* Set the motor speed to 50% */
Set_Motor_Speed(&htim2, TIM_CHANNEL_1, 5000);
?
while (1)
{
/* Infinite loop */
}
}
?
/**
* @brief Initializes PWM output on specified TIM channel.
* @param htim: TIM handle structure.
* @param channel: TIM channel to be used for PWM output.
* @retval None
*/
void PWM_Init(TIM_HandleTypeDef *htim, uint32_t channel)
{
TIM_OC_InitTypeDef sConfigOC = {0};
?
/* Configure PWM output on specified TIM channel */
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(htim, &sConfigOC, channel);
?
/* Start PWM output */
HAL_TIM_PWM_Start(htim, channel);
}
?
/**
* @brief Sets the motor speed on specified TIM channel.
* @param htim: TIM handle structure.
* @param channel: TIM channel to be used for PWM output.
* @param speed: Motor speed in units of 1/10,000th of the maximum speed.
* For example, a speed of 5000 would set the motor speed to 50%.
* @retval None
*/
void Set_Motor_Speed(TIM_HandleTypeDef *htim, uint32_t channel, uint16_t speed)
{
uint16_t max_speed = htim->Init.Period;
?
/* Ensure that speed is within range */
if (speed > max_speed)
speed = max_speed;
?
/* Update PWM duty cycle */
__HAL_TIM_SET_COMPARE(htim, channel, speed);
}
在以上代碼中,定義了兩個(gè)函數(shù):PWM_Init和Set_Motor_Speed。PWM_Init用于初始化TIM定時(shí)器的PWM輸出,并設(shè)置指定通道的PWM模式和默認(rèn)占空比為0。Set_Motor_Speed用于設(shè)置電機(jī)的轉(zhuǎn)速,其接收三個(gè)參數(shù):TIM句柄結(jié)構(gòu)體,指定的通道,以及電機(jī)的轉(zhuǎn)速(單位為1/10,000最大速度)。該函數(shù)會(huì)將電機(jī)的轉(zhuǎn)速轉(zhuǎn)換為PWM占空比,并通過(guò)__HAL_TIM_SET_COMPARE函數(shù)更新PWM占空比。
最后,可以按照以下步驟將代碼封裝成子函數(shù)調(diào)用:
- 將以上代碼復(fù)制到單獨(dú)的.c文件中,并包含必要的頭文件。
- 在該文件中定義一個(gè)名為Motor_Control的函數(shù),該函數(shù)接收三個(gè)參數(shù):TIM句柄結(jié)構(gòu)體,指定的通道,以及電機(jī)的轉(zhuǎn)速。
- 在Motor_Control函數(shù)中調(diào)用PWM_Init和Set_Motor_Speed函數(shù),并傳遞相應(yīng)的參數(shù)。
- 在main函數(shù)中調(diào)用Motor_Control函數(shù),傳遞相應(yīng)的參數(shù)。
以下是Motor_Control函數(shù)的示例代碼:
#include "motor_control.h"
?
void Motor_Control(TIM_HandleTypeDef *htim, uint32_t channel, uint16_t speed)
{
/* Initialize PWM output on specified TIM channel */
PWM_Init(htim, channel);
?
/* Set the motor speed */
Set_Motor_Speed(htim, channel, speed);
}
在以上示例中,將PWM的初始化和設(shè)置電機(jī)轉(zhuǎn)速的函數(shù)封裝成了一個(gè)名為Motor_Control的函數(shù)??梢栽谛枰刂齐姍C(jī)轉(zhuǎn)速的其他地方調(diào)用Motor_Control函數(shù)即可。
注意,在調(diào)用Motor_Control函數(shù)之前,需要先定義并初始化TIM句柄結(jié)構(gòu)體,并確保GPIO引腳已經(jīng)正確配置為T(mén)IM模式。此外,如果需要控制多個(gè)電機(jī),可以在Motor_Control函數(shù)中增加參數(shù)以區(qū)分不同的電機(jī)通道。
以下是motor_control.h頭文件的示例代碼:
cCopy Code#ifndef __MOTOR_CONTROL_H__
#define __MOTOR_CONTROL_H__
?
#include "stm32f1xx_hal.h"
?
/* Function prototypes */
void PWM_Init(TIM_HandleTypeDef *htim, uint32_t channel);
void Set_Motor_Speed(TIM_HandleTypeDef *htim, uint32_t channel, uint16_t speed);
void Motor_Control(TIM_HandleTypeDef *htim, uint32_t channel, uint16_t speed);
?
#endif /* __MOTOR_CONTROL_H__ */
在以上頭文件中,聲明了三個(gè)函數(shù):PWM_Init,Set_Motor_Speed和Motor_Control,并包含必要的頭文件。
【2】電壓、電流采集
為了采集220V抽水電機(jī)的用電量和當(dāng)前電壓,當(dāng)前使用STM32F103ZET6的ADC(模數(shù)轉(zhuǎn)換器)來(lái)測(cè)量電壓和電流,并通過(guò)乘法器計(jì)算電功率和電能。
下面是實(shí)現(xiàn)方案和實(shí)現(xiàn)代碼:
- 選擇合適的傳感器: 為了測(cè)量電壓,可以使用AC-AC變壓器將220V交流電壓降至低電平,再使用電阻分壓器將電壓信號(hào)調(diào)整在ADC的輸入范圍內(nèi)。 為了測(cè)量電流,可以使用霍爾傳感器或者電阻式傳感器,將電流信號(hào)轉(zhuǎn)換成電壓信號(hào),然后通過(guò)電阻分壓器調(diào)整信號(hào)范圍。
- 配置ADC: 使用STM32CubeMX軟件選擇相應(yīng)的引腳和配置ADC模塊,設(shè)置采樣頻率、參考電壓等參數(shù)。需要注意的是,ADC模塊只能同時(shí)轉(zhuǎn)換一路模擬信號(hào),因此需要輪流采樣電壓和電流信號(hào)。
- 計(jì)算電流、電壓、功率和能量: 將電壓和電流信號(hào)轉(zhuǎn)換成數(shù)字值后,可以使用下面的公式計(jì)算電流、電壓、功率和能量:
Copy Code電流 = AD值 / 靈敏度
電壓 = AD值 / 分壓比
功率 = 電壓 * 電流
能量 = 功率 * 時(shí)間
其中,靈敏度是傳感器的轉(zhuǎn)換系數(shù),分壓比是電阻分壓器的比值,時(shí)間可以通過(guò)定時(shí)器計(jì)算。
- 輸出數(shù)據(jù): 將測(cè)量的電流、電壓、功率和能量輸出到串口或者LCD顯示屏上??梢栽O(shè)置一個(gè)定時(shí)器,在一定時(shí)間間隔內(nèi)輸出一次數(shù)據(jù)。
實(shí)現(xiàn)代碼:
#include "stm32f1xx_hal.h"
?
ADC_HandleTypeDef hadc1;
TIM_HandleTypeDef htim2;
?
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM2_Init(void);
?
uint16_t ad_val_ch1, ad_val_ch2;
float voltage, current, power, energy;
?
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM2_Init();
?
while (1)
{
// ADC采樣電壓信號(hào)
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
ad_val_ch1 = HAL_ADC_GetValue(&hadc1);
voltage = ad_val_ch1 * 3.3 / 4096 * 10; // 假設(shè)分壓比為10
?
// ADC采樣電流信號(hào)
HAL_TIM_Base_Start(&htim2);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
ad_val_ch2 = HAL_ADC_GetValue(&hadc1);
current = ad_val_ch2 * 3.3 / 4096 * 50; // 假設(shè)靈敏度為50mV/A
?
// 計(jì)算功率和能量
power = voltage * current;
energy += power * 0.1; // 假設(shè)定時(shí)器時(shí)間間隔為100ms
?
// 輸出測(cè)量結(jié)果
printf("Voltage: %.2f Vrn", voltage);
printf("Current: %.2f Arn", current);
printf("Power: %.2f Wrn", power);
printf("Energy: %.2f Jrn", energy);
?
HAL_Delay(1000); // 假設(shè)數(shù)據(jù)輸出間隔為1s
}
}
?
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
?
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
?
RCC_OscInitStruct.OscillatorType = RCCRCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
?
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
?
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
?
__HAL_RCC_ADC1_CLK_ENABLE();
?
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
?
sConfig.Channel = ADC_CHANNEL_0; // 假設(shè)測(cè)量電壓的ADC通道為0
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_13CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
?
sConfig.Channel = ADC_CHANNEL_1; // 假設(shè)測(cè)量電流的ADC通道為1
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
?
static void MX_TIM2_Init(void)
{
__HAL_RCC_TIM2_CLK_ENABLE();
?
htim2.Instance = TIM2;
htim2.Init.Prescaler = 7200 - 1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 10000 - 1; // 假設(shè)定時(shí)器時(shí)間間隔為100ms
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
}
?
void Error_Handler(void)
{
while (1)
{
}
}
?
#ifdef USE_FULL_ASSERT
?
void assert_failed(char *file, uint32_t line)
{
}
?
#endif
-
單片機(jī)
+關(guān)注
關(guān)注
6023文章
44376瀏覽量
628437 -
控制系統(tǒng)
+關(guān)注
關(guān)注
41文章
6419瀏覽量
110104 -
4G
+關(guān)注
關(guān)注
15文章
5454瀏覽量
118306 -
STM32
+關(guān)注
關(guān)注
2258文章
10828瀏覽量
352499
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論