
☛ 功能說明
利用 Arduino UNO 開發板、 FreeRTOS 函式庫及 semphr 函式庫,使用互斥旗標的機制控制兩個溫度感測器 ( DHT11、DS18B20 ) ,並將偵測的溫度、濕度顯示於 LCD 上,當 DHT11 取得互斥旗標顯示於偵測值於 LCD 時,點亮 LED1,釋放互斥旗標時,熄滅 LED1。當 DS18B20 取得互斥旗標顯示於偵測值於 LCD 時,點亮 LED2,釋放互斥旗標時,熄滅 LED2。
☛ 使用材料
Arduino UNO R3 開發板 × 1、DHT11 溫度感測器模組 × 1、DS18B20 溫度感測器模組 × 1、LCD 1602A 顯示器模組 × 1、可變電阻 20KΩ × 1、電阻 220Ω × 1、LED × 2。
☛ 電路圖及麵包板接線圖


☛ 程式碼
#include <Arduino_FreeRTOS.h> //引用 FreeRTOS 函式庫
#include <semphr.h> //引用 semphr.h 互斥旗標函式庫
#include <DHT.h> //引用 DHT11 函式庫
#include <OneWire.h> //引用 OneWire 函式庫
#include <DallasTemperature.h> //引用 DallasTemperature 函式庫
#include<LiquidCrystal.h> //引用 LiquidCrystal.h 函式庫
SemaphoreHandle_t mutex_v; //宣告一個 SemaphoreHandle_t 類型的變數來存儲互斥旗標的值
LiquidCrystal lcd(12,11,5,4,3,2); //宣告 LCD 變數並定義使用接腳
void setup()
{
lcd.begin(16,2); //使用 16 行 × 2 列 LCD
lcd.setCursor(0,0); //設定游標位置於第 0 列第 0 行
lcd.print("DHT:"); //顯示 "DHT:"
lcd.setCursor(0,1); //設定游標位置於第 1 列第 0 行
lcd.print("DS18:"); //顯示 "DS18:"
mutex_v = xSemaphoreCreateMutex(); //創建一個互斥旗標 mutex_v
if (mutex_v == NULL)
{
lcd.setCursor(0,0);
lcd.print("Mutex can not");
lcd.setCursor(1,0);
lcd.print("be created");
}
xTaskCreate(Sens1, "Task 1", 128, NULL, 1, NULL); //建立 DHT11 任務
xTaskCreate(Sens2, "Task 2", 128, NULL, 1, NULL); //建立 DS18B20任務
}
void loop()
{
}
void displayLCD(int col,int row, float num) //LCD 顯示溫濕度副程式
{
char c[10]; //宣告字元陣列 c
dtostrf(num,2,2,c); //將浮點數轉換成字串,整數 2 位,小數 2 位
lcd.setCursor(col,row); //設定 LCD 顯示字串的位置
lcd.print(c); //在 LCD 上顯示轉換的溫度、濕度值
}
void Sens1(void *pvParameters) //DHT11 任務
{
int led=8; //LED 連接數位接腳 8
DHT dht;
pinMode(led,OUTPUT); //設定數位接腳 8 為輸出模式
dht.setup(7); //DHT11 資料接腳連接數位接腳 7
while(1)
{
// 根據溫濕度感測器型號來選取取樣時間
vTaskDelay(dht.getMinimumSamplingPeriod()/portTICK_PERIOD_MS);
float humidity = dht.getHumidity(); //讀取感測器的濕度值
float temperature = dht.getTemperature(); //讀取感測器的溫度值
xSemaphoreTake(mutex_v, portMAX_DELAY); //獲取互斥旗標 Mutex_v
digitalWrite(led,HIGH); //點亮 LED1
displayLCD(5,0,temperature); //在 LCD 上顯示 DHT 的溫度
displayLCD(11,0,humidity); //在 LCD 上顯示 DHT 的濕度
digitalWrite(led,LOW); //熄滅 LDE1
xSemaphoreGive(mutex_v); //返回互斥旗標 Mutex_v
vTaskDelay(pdMS_TO_TICKS(1000)); //延遲1秒
}
}
void Sens2(void *pvParameters) //DS18B20 任務
{
int led=9;
OneWire oneWire(10); //連接至數位接腳 10,設置一個單線實例以與任何單線設備進行通信
DallasTemperature sensors(&oneWire); //參考 Dallas 溫度。
sensors.begin(); //啟動 DS18B20 感測器
pinMode(led,OUTPUT); //設定數位接腳 9 為輸出模式
while(1)
{
sensors.requestTemperatures(); //發送命令以獲得溫度
xSemaphoreTake(mutex_v, portMAX_DELAY); //獲取互斥旗標 Mutex_v
digitalWrite(led,HIGH); //點亮 LED2
displayLCD(5,1,sensors.getTempCByIndex(0)); //在 LCD 上顯示 DS18B20 的溫度
digitalWrite(led,LOW); //熄滅 LED2
xSemaphoreGive(mutex_v); //返回互斥旗標 Mutex_v
vTaskDelay(pdMS_TO_TICKS(1000)); //延遲1秒
}
}




