☛ 功能說明
利用 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秒 } }