冰楓論壇

 找回密碼
 立即註冊
ads_sugarbook
搜索
查看: 489|回覆: 0
打印 上一主題 下一主題

[討論] STM8S003F3P6 製作自動養花灌水系統

[複製鏈接]

2609

主題

0

好友

945

積分

高級會員

Rank: 4

UID
373967
帖子
7402
主題
2609
精華
0
積分
945
楓幣
1002
威望
925
存款
26000
贊助金額
0
推廣
0
GP
1205
閱讀權限
50
在線時間
405 小時
註冊時間
2023-1-12
最後登入
2024-4-29

2023端午節紀念勳章 2023中秋節紀念勳章 2023聖誕節紀念勳章

跳轉到指定樓層
1
發表於 2023-3-29 05:55:58 |只看該作者 |倒序瀏覽
要製作一個自動養花灌水系統,你會需要以下材料:

STM8S003F3P6 微控制器
16x2 LCD 液晶顯示器
DHT11 溫濕度感應器
水泵和相關電路
電容器和電阻器
麵包板和電線
以下是 STM8S003F3P6 的連接腳位:

PC3: 用於 LCD 顯示器的 RS (Register Select) 腳
PC4: 用於 LCD 顯示器的 E (Enable) 腳
PC5-PC7: 用於 LCD 顯示器的 D4-D6 腳
PB4: 用於 DHT11 溫濕度感應器的輸入腳
PA1: 用於控制水泵的輸出腳
以下是一個示例程式碼,可以讓 STM8S003F3P6 控制自動養花灌水系統:


#include <stdio.h>
#include <string.h>
#include "stm8s.h"
#include "stm8s_delay.h"
#include "stm8s_gpio.h"
#include "stm8s_i2c.h"

#define LCD_RS_PIN  GPIO_PIN_3
#define LCD_E_PIN   GPIO_PIN_4
#define LCD_D4_PIN  GPIO_PIN_5
#define LCD_D5_PIN  GPIO_PIN_6
#define LCD_D6_PIN  GPIO_PIN_7

#define DHT11_PIN   GPIO_PIN_4

#define PUMP_PIN    GPIO_PIN_1

#define I2C_SPEED   100000

void init_lcd(void);
void lcd_send_cmd(uint8_t cmd);
void lcd_send_data(uint8_t data);
void lcd_send_string(char* str);
void init_dht11(void);
void read_dht11(uint8_t* temp, uint8_t* hum);
void init_pump(void);
void turn_on_pump(void);
void turn_off_pump(void);

void main()
{
  uint8_t temp, hum;
  char buf[16];

  // 初始化 LCD 和 DHT11 溫濕度感應器
  init_lcd();
  init_dht11();

  // 初始化水泵
  init_pump();

  while (1)
  {
    // 讀取溫度和濕度
    read_dht11(&temp, &hum);

    // 如果濕度太低,就開啟水泵
    if (hum < 60)
    {
      turn_on_pump();
    }
    else
    {
      turn_off_pump();
    }

    // 在 LCD 上顯示溫度和濕度
    lcd_send_cmd(0x80);
    sprintf(buf, "Temp: %dC", temp);
    lcd_send_string(buf);
    lcd_send_cmd(0xC0);
    sprintf(buf, "Hum : %d%%", hum);
    lcd_send_string(buf);

    delay_ms(1000);
  }
}

void init_lcd()
{
  gpio_init(GPIOC, LCD_RS_PIN | LCD_E_PIN | LCD_D4_PIN | LCD_D5_PIN | LCD_D6_PIN,

GPIO_MODE_OUT_PP_LOW_FAST); // 設定 LCD 連接的 GPIO 腳為輸出模式

lcd_send_cmd(0x33); // 初始化 LCD
lcd_send_cmd(0x32);
lcd_send_cmd(0x28);
lcd_send_cmd(0x0C);
lcd_send_cmd(0x01);
lcd_send_cmd(0x06);
}

void lcd_send_cmd(uint8_t cmd)
{
gpio_write_low(GPIOC, LCD_RS_PIN); // 設定 RS 腳為低電位,表示要發送命令
gpio_write_high(GPIOC, LCD_E_PIN); // 設定 E 腳為高電位
gpio_write(GPIOC, LCD_D4_PIN | ((cmd & 0x0F) << 1)); // 將命令的低四位送入 D4-D7 腳
delay_us(1);
gpio_write_low(GPIOC, LCD_E_PIN); // 設定 E 腳為低電位
delay_us(1);

gpio_write_high(GPIOC, LCD_E_PIN); // 設定 E 腳為高電位
gpio_write(GPIOC, LCD_D4_PIN | ((cmd >> 4) << 1)); // 將命令的高四位送入 D4-D7 腳
delay_us(1);
gpio_write_low(GPIOC, LCD_E_PIN); // 設定 E 腳為低電位
delay_us(100);
}

void lcd_send_data(uint8_t data)
{
gpio_write_high(GPIOC, LCD_RS_PIN); // 設定 RS 腳為高電位,表示要發送資料
gpio_write_high(GPIOC, LCD_E_PIN); // 設定 E 腳為高電位
gpio_write(GPIOC, LCD_D4_PIN | ((data & 0x0F) << 1)); // 將資料的低四位送入 D4-D7 腳
delay_us(1);
gpio_write_low(GPIOC, LCD_E_PIN); // 設定 E 腳為低電位
delay_us(1);

gpio_write_high(GPIOC, LCD_E_PIN); // 設定 E 腳為高電位
gpio_write(GPIOC, LCD_D4_PIN | ((data >> 4) << 1)); // 將資料的高四位送入 D4-D7 腳
delay_us(1);
gpio_write_low(GPIOC, LCD_E_PIN); // 設定 E 腳為低電位
delay_us(100);
}

void lcd_send_string(char* str)
{
uint8_t i;

for (i = 0; i < strlen(str); i++)
{
lcd_send_data(str[i]);
}
}

void init_dht11()
{
gpio_init(GPIOB, DHT11_PIN, GPIO_MODE_OUT_OD_HIZ_FAST); // 設定 DHT11 腳為輸出模式
gpio_write_high(GPIOB, DHT11_PIN); // 設定 DHT11 腳為高電位
}

void read_dht11(uint8_t* temp, uint8_t* humi)

{
uint8_t i, j, checksum;
uint8_t data[5] = {0, 0, 0, 0, 0};

// 向 DHT11 發送啟動信號
gpio_init(GPIOB, DHT11_PIN, GPIO_MODE_OUT_PP_LOW_FAST); // 設定 DHT11 腳為輸出模式
gpio_write_low(GPIOB, DHT11_PIN); // 設定 DHT11 腳為低電位
delay_ms(18);
gpio_write_high(GPIOB, DHT11_PIN); // 設定 DHT11 腳為高電位
delay_us(1);
gpio_init(GPIOB, DHT11_PIN, GPIO_MODE_IN_FL_NO_IT); // 設定 DHT11 腳為輸入模式
delay_us(40);

// 等待 DHT11 回應
if (gpio_read(GPIOB, DHT11_PIN))
{
// DHT11 沒有回應
return;
}
delay_us(80);

if (!gpio_read(GPIOB, DHT11_PIN))
{
// DHT11 沒有回應
return;
}
delay_us(80);

// 讀取 DHT11 回傳的資料
for (i = 0; i < 5; i++)
{
for (j = 0; j < 8; j++)
{
while (!gpio_read(GPIOB, DHT11_PIN)); // 等待資料腳為高電位
delay_us(30);
if (gpio_read(GPIOB, DHT11_PIN))
{
data[i] |= (1 << (7 - j)); // 記錄資料
}
while (gpio_read(GPIOB, DHT11_PIN)); // 等待資料腳為低電位
}
}

// 驗證資料
checksum = data[0] + data[1] + data[2] + data[3];
if (checksum != data[4])
{
// 資料有誤
return;
}

// 轉換溫度和濕度資料
*humi = data[0];
*temp = data[2];
}

void init_pump()
{
gpio_init(GPIOB, PUMP_PIN, GPIO_MODE_OUT_PP_LOW_FAST); // 設定水泵腳為輸出模式
gpio_write_low(GPIOB, PUMP_PIN); // 設定水泵腳為低電位
}

void start_pump()
{
gpio_write_high(GPIOB, PUMP_PIN); // 設定水泵腳為高電位
}

void stop_pump()
{
gpio_write_low(GPIOB, PUMP_PIN); // 設定水泵腳為低電位
}

void main()
{
uint8_t temp, humi;
char lcd_str[17];

// 初始化硬體
clk_init();
gpio_init(GPIOC,

GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_FAST); // 設定 LCD RS 腳為輸出模式
gpio_init(GPIOC, GPIO_PIN_4, GPIO_MODE_OUT_PP_LOW_FAST); // 設定 LCD E 腳為輸出模式
gpio_init(GPIOC, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_FAST); // 設定 LCD D4 腳為輸出模式
gpio_init(GPIOC, GPIO_PIN_2, GPIO_MODE_OUT_PP_LOW_FAST); // 設定 LCD D5 腳為輸出模式
gpio_init(GPIOC, GPIO_PIN_1, GPIO_MODE_OUT_PP_LOW_FAST); // 設定 LCD D6 腳為輸出模式
gpio_init(GPIOC, GPIO_PIN_0, GPIO_MODE_OUT_PP_LOW_FAST); // 設定 LCD D7 腳為輸出模式

// 初始化 LCD
lcd_init();

// 初始化水泵
init_pump();

while (1)
{
// 讀取溫度和濕度
read_dht11(&temp, &humi);

// 顯示溫度和濕度
sprintf(lcd_str, "Temp: %dC Humi: %d%%", temp, humi);
lcd_gotoxy(0, 0);
lcd_puts(lcd_str);

// 判斷是否需要澆水
if (humi < HUMI_THRESHOLD)
{
  start_pump();
  delay_ms(WATER_DURATION);
  stop_pump();
}

// 等待一段時間再進行下一次操作
delay_ms(5000);
}
}

void lcd_init()
{
lcd_send_cmd(0x28); // 設定LCD為2列、5x8點字
lcd_send_cmd(0x08); // 關閉LCD顯示
lcd_send_cmd(0x01); // 清除LCD顯示內容
lcd_send_cmd(0x06); // 設定LCD文字為向右移動
lcd_send_cmd(0x0C); // 開啟LCD顯示,關閉游標
}

void lcd_send_cmd(uint8_t cmd)
{
gpio_clear(LCD_RS_PORT, LCD_RS_PIN); // 設定RS為0,選擇命令模式
lcd_write_4bit(cmd >> 4); // 傳送高4位元組
lcd_write_4bit(cmd); // 傳送低4位元組
}

void lcd_send_data(uint8_t data)
{
gpio_set(LCD_RS_PORT, LCD_RS_PIN); // 設定RS為1,選擇資料模式
lcd_write_4bit(data >> 4); // 傳送高4位元組
lcd_write_4bit(data); // 傳送低4位元組
}

void lcd_gotoxy(uint8_t x, uint8_t y)
{
uint8_t addr;

// 計算LCD內部地址
if (y == 0)
{
addr = 0x00 + x;
}
else
{
addr = 0x40 + x;
}

// 設定LCD內部地址
lcd_send_cmd(0x80 | addr);
}

void lcd_puts(char *str)
{
while (*str)
{
lcd_send_data(*str++);
}
}

void lcd_write_4bit(uint8_t data)
{
gpio_clear(LCD_E_PORT, LCD_E_PIN); // 設定E為0
if (data & 0x01)
{
gpio_set(LCD_D7_PORT, LCD_D7_PIN);
}
else
{
gpio_clear(LCD_D7_PORT, LCD_D7_PIN);
}
if (data & 0x02)
{
gpio_set(LCD_D6_PORT, LCD_D6_PIN);
}
else
{
gpio_clear(LCD_D6_PORT, LCD_D6_PIN);
}
if (data & 0x04)
{
gpio_set(LCD_D5_PORT, LCD_D5_PIN);
}
else
{
gpio_clear(LCD_D5_PORT, LCD_D5_PIN);
}
if (data & 0x08)
{
gpio_set(LCD_D4_PORT, LCD_D4_PIN);
}
else
{
gpio_clear(LCD_D4_PORT, LCD_D4_PIN);
}
gpio_set(LCD_E_PORT, LCD_E_PIN); // 設定E為1
delay_us(1); // 延遲一段時間
gpio_clear(LCD_E_PORT, LCD_E_PIN); // 設定E為0
delay_us(1); // 延遲一段時間
}

void init_pump()
{
gpio_init(PUMP_PORT, PUMP_PIN, GPIO_MODE_OUT_PP_LOW_FAST); //

}

void water_plants()
{
// 啟動水泵
gpio_set(PUMP_PORT, PUMP_PIN);

// 顯示訊息
lcd_gotoxy(0, 1);
lcd_puts("Watering plants...");

// 延遲一段時間
delay_ms(WATERING_TIME);

// 停止水泵
gpio_clear(PUMP_PORT, PUMP_PIN);

// 顯示訊息
lcd_gotoxy(0, 1);
lcd_puts("Watering done.");
}

void main()
{
// 初始化GPIO
gpio_init(LCD_RS_PORT, LCD_RS_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
gpio_init(LCD_E_PORT, LCD_E_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
gpio_init(LCD_D4_PORT, LCD_D4_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
gpio_init(LCD_D5_PORT, LCD_D5_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
gpio_init(LCD_D6_PORT, LCD_D6_PIN, GPIO_MODE_OUT_PP_LOW_FAST);
gpio_init(LCD_D7_PORT, LCD_D7_PIN, GPIO_MODE_OUT_PP_LOW_FAST);

// 初始化LCD
lcd_init();

// 初始化水泵
init_pump();

while (1)
{
// 讀取濕度感測器數值
uint16_t humidity_value = read_humidity_sensor();

scss
Copy code
// 如果濕度低於設定值,則啟動水泵
if (humidity_value < HUMIDITY_THRESHOLD)
{
  water_plants();
}

// 顯示濕度數值
lcd_gotoxy(0, 0);
lcd_puts("Humidity: ");
char str[5];
sprintf(str, "%d", humidity_value);
lcd_puts(str);

// 延遲一段時間
delay_ms(LOOP_DELAY);
}
}



以上就是一個簡單的自動養花灌水系統的程式碼範例,其中使用了STM8S003F3P6微控制器、濕度感測器、LCD顯示屏和水泵等零件。程式流程簡單明瞭,主要分為初始化、讀取濕度、控制水泵和顯示訊息等幾個部分。

在初始化部分,我們設置了LCD和水泵的GPIO引腳模式為輸出並設置初始狀態為低電平,然後調用了lcd_init()函數和init_pump()函數來初始化LCD和水泵。

在主循環部分,我們先讀取濕度感測器的數值,然後判斷是否需要啟動水泵來灌溉花卉,如果濕度低於設定值,則啟動水泵,否則繼續等待。在每次循環結束之前,我們還會顯示濕度數值在LCD上,以便用戶可以實時觀察花卉的濕度情況。

需要注意的是,這只是一個簡單的程式碼範例,實際上還需要考慮到許多其他因素,例如如何校準濕度感測器、如何調整灌溉時間等等。如果您想要製作一個真正可靠的自動養花灌水系統,建議您先進一步學習STM8微控制器和相關的電子知識。
收藏收藏0 推0 噓0


把本文推薦給朋友或其他網站上,每次被點擊增加您在本站積分: 1骰子
複製連結並發給好友,以賺取推廣點數
簡單兩步驟,註冊、分享網址,即可獲得獎勵! 一起推廣文章換商品、賺$$
高級模式
B Color Image Link Quote Code Smilies |上傳

廣告刊登意見回饋關於我們職位招聘本站規範DMCA隱私權政策

Copyright © 2011-2024 冰楓論壇, All rights reserved

免責聲明:本網站是以即時上載留言的方式運作,本站對所有留言的真實性、完整性及立場等,不負任何法律責任。

而一切留言之言論只代表留言者個人意見,並非本網站之立場,用戶不應信賴內容,並應自行判斷內容之真實性。

小黑屋|手機版|冰楓論壇

GMT+8, 2024-4-29 19:07

回頂部