- ข้อดีของโปรเซสเซอร์แบบมัลติคอร์
- ESP32 และ FreeRTOS
- ค้นหา ESP32 core ID
- การเขียนโปรแกรม ESP32 Dual Core
โมดูล ESP เป็นที่นิยมสำหรับฟังก์ชัน Wi-Fi เช่น ESP8266, ESP-12E เป็นต้นทั้งหมดนี้เป็นโมดูลไมโครคอนโทรลเลอร์ที่มีประสิทธิภาพพร้อมฟังก์ชัน Wi-Fi มีอยู่คนหนึ่งโมดูลเพิ่มเติม ESP ที่มีประสิทธิภาพมากขึ้นและหลากหลายกว่าก่อนหน้า ESP โมดูลชื่อของมันคือเป็นESP32มีการเชื่อมต่อ Bluetooth และ Wi-Fi และเราได้อธิบายความสามารถของ BLE ของ ESP32 แล้วและใช้ ESP32 ในโครงการ IoT หลายโครงการ แต่คนน้อยมากที่รู้ว่าESP32 เป็นไมโครคอนโทรลเลอร์แบบ
ESP32มีไมโครโปรเซสเซอร์ Tensilica Xtensa LX6 32 บิตสองตัวซึ่งทำให้เป็นไมโครคอนโทรลเลอร์แบบดูอัลคอร์ (core0 และ core1) ที่ทรงพลัง มีให้เลือกสองแบบ single-core และ dual-core แต่ตัวแปรดูอัลคอร์ได้รับความนิยมมากกว่าเนื่องจากไม่มีความแตกต่างด้านราคาอย่างมีนัยสำคัญ
ESP32 สามารถตั้งโปรแกรมได้โดยใช้ Arduino IDE, Espressif IDF, Lua RTOS ฯลฯ ในขณะที่เขียนโปรแกรมด้วย Arduino IDE โค้ดจะทำงานบน Core1 เท่านั้นเนื่องจาก Core0 ถูกตั้งโปรแกรมไว้สำหรับการสื่อสาร RF แต่นี่คือบทช่วยสอนนี้เราจะแสดงวิธีใช้ทั้งคอร์ของ ESP32เพื่อดำเนินการสองอย่างพร้อมกัน งานแรกคือการกะพริบ LED ออนบอร์ดและงานที่สองคือการดึงข้อมูลอุณหภูมิจากเซ็นเซอร์ DHT11
ก่อนอื่นเรามาดูข้อดีของโปรเซสเซอร์แบบมัลติคอร์บนคอร์เดียว
ข้อดีของโปรเซสเซอร์แบบมัลติคอร์
- โปรเซสเซอร์แบบมัลติคอร์มีประโยชน์เมื่อมีมากกว่า 2 กระบวนการในการทำงานพร้อมกัน
- เมื่องานกระจายไปตามคอร์ต่างๆความเร็วจะเพิ่มขึ้นและสามารถทำหลายกระบวนการพร้อมกันได้
- การใช้พลังงานสามารถลดลงได้เนื่องจากเมื่อคอร์ใด ๆ อยู่ในโหมดว่างเกินกว่าที่จะสามารถใช้ปิดอุปกรณ์ต่อพ่วงที่ไม่ได้ใช้งานในขณะนั้น
- โปรเซสเซอร์แบบดูอัลคอร์ต้องสลับไปมาระหว่างเธรดต่างๆน้อยกว่าโปรเซสเซอร์แบบ single-core เนื่องจากสามารถจัดการสองตัวพร้อมกันแทนที่จะเป็นทีละชุด
ESP32 และ FreeRTOS
บอร์ด ESP32 มีเฟิร์มแวร์ FreeRTOS ติดตั้งอยู่แล้ว FreeRTOS เป็นระบบปฏิบัติการเรียลไทม์แบบโอเพนซอร์สซึ่งมีประโยชน์มากในการทำงานหลายอย่างพร้อมกัน RTOS ช่วยในการจัดการทรัพยากรและเพิ่มประสิทธิภาพสูงสุดของระบบ FreeRTOS มีฟังก์ชัน API มากมายสำหรับวัตถุประสงค์ที่แตกต่างกันและเมื่อใช้ API เหล่านี้เราสามารถสร้างงานและทำให้มันทำงานบนคอร์ต่างๆได้
เอกสารฉบับสมบูรณ์ของ FreeRTOS API สามารถพบได้ที่นี่ เราจะพยายามใช้ API บางตัวในโค้ดของเราเพื่อสร้างแอปพลิเคชันมัลติทาสก์ที่จะทำงานบนคอร์ทั้งสอง
ค้นหา ESP32 core ID
ที่นี่เราจะใช้ Arduino IDE เพื่ออัปโหลดรหัสไปยัง ESP32 หากต้องการทราบ Core ID ที่โค้ดกำลังทำงานมีฟังก์ชัน API
xPortGetCoreID ()
ฟังก์ชันนี้สามารถเรียกใช้จากฟังก์ชัน void setup () และ void loop () เพื่อให้ทราบ ID หลักที่ฟังก์ชันเหล่านี้กำลังทำงานอยู่
คุณสามารถทดสอบ API นี้ได้โดยอัปโหลดแบบร่างด้านล่าง:
การตั้งค่าเป็นโมฆะ () { Serial.begin (115200); Serial.print ("setup () ฟังก์ชั่นทำงานบนแกน:"); Serial.println (xPortGetCoreID ()); } void loop () { Serial.print ("loop () ฟังก์ชั่นที่ทำงานบน core:"); Serial.println (xPortGetCoreID ()); }
หลังจากอัปโหลดภาพร่างด้านบนแล้วให้เปิด Serial monitor และคุณจะพบว่าทั้งสองฟังก์ชั่นทำงานบน core1 ดังที่แสดงด้านล่าง
จากข้อสังเกตข้างต้นสรุปได้ว่าร่าง Arduino เริ่มต้นจะทำงานบน core1เสมอ
การเขียนโปรแกรม ESP32 Dual Core
Arduino IDE รองรับ FreeRTOS สำหรับ ESP32 และ FreeRTOS API ช่วยให้เราสร้างงานที่สามารถทำงานได้อย่างอิสระบนคอร์ทั้งสอง งานคือส่วนของรหัสที่ดำเนินการบางอย่างบนกระดานเช่นไฟ LED กะพริบอุณหภูมิในการส่ง ฯลฯ
ฟังก์ชั่นด้านล่างนี้ใช้เพื่อสร้างงานที่สามารถทำงานได้ทั้งสองคอร์ ในฟังก์ชันนี้เราต้องให้อาร์กิวเมนต์เช่นลำดับความสำคัญรหัสหลักเป็นต้น
ตอนนี้ทำตามขั้นตอนด้านล่างเพื่อสร้างงานและฟังก์ชันงาน
1. ขั้นแรกให้สร้างงานในฟังก์ชัน การตั้งค่าโมฆะ ในที่นี้เราจะสร้างงานสองอย่างงานหนึ่งสำหรับ LED กะพริบทุกๆ 0.5 วินาทีและอีกงานหนึ่งคือการอ่านค่าอุณหภูมิทุกๆ 2 วินาที
ฟังก์ชัน xTaskCreatePinnedToCore () รับ 7 อาร์กิวเมนต์:
- ชื่อฟังก์ชันเพื่อใช้งาน (task1)
- ชื่อใด ๆ ที่กำหนดให้กับงาน (“ task1” ฯลฯ)
- ขนาดกองที่กำหนดให้กับงานเป็นคำ (1 word = 2bytes)
- พารามิเตอร์อินพุตงาน (สามารถเป็น NULL)
- ลำดับความสำคัญของงาน (0 คือลำดับความสำคัญต่ำสุด)
- ที่จับงาน (สามารถเป็น NULL)
- รหัสหลักที่งานจะทำงาน (0 หรือ 1)
ตอนนี้สร้าง Task1 สำหรับกะพริบ ledโดยให้อาร์กิวเมนต์ทั้งหมดในฟังก์ชัน xTaskCreatePinnedToCore ()
xTaskCreatePinnedToCore (Task1code, "Task1", 10000, NULL, 1, NULL, 0);
ในทำนองเดียวกันการสร้าง Task2สำหรับ Task2 และทำให้แกน ID 1 ใน 7 THโต้แย้ง
xTaskCreatePinnedToCore (Task2code, "Task2", 10000, NULL, 1, NULL, 1);
คุณสามารถเปลี่ยนลำดับความสำคัญและขนาดสแต็กได้ขึ้นอยู่กับความซับซ้อนของงาน
2. ตอนนี้เราจะดำเนินการ Task1code และ Task2code ฟังก์ชั่น ฟังก์ชันเหล่านี้มีรหัสสำหรับงานที่ต้องการ ในกรณีของเรางานแรกจะกะพริบไฟ led และงานอื่นจะดึงอุณหภูมิ ดังนั้นให้สร้างสองฟังก์ชันแยกกันสำหรับแต่ละงานนอกฟังก์ชันการตั้งค่าโมฆะ
ฟังก์ชั่น Task1code สำหรับไฟ LED บนบอร์ดกะพริบหลังจากใช้งาน 0.5 วินาทีดังที่แสดงด้านล่าง
โมฆะ Task1code (พารามิเตอร์โมฆะ *) { Serial.print ("Task1 ทำงานบนแกน"); Serial.println (xPortGetCoreID ()); สำหรับ (;;) {// digitalWrite วนไม่สิ้นสุด(led, HIGH); ล่าช้า (500); digitalWrite (นำต่ำ); ล่าช้า (500); } }
ในทำนองเดียวกันการดำเนินการ Task2code ฟังก์ชั่นสำหรับการเรียกอุณหภูมิ
โมฆะ Task2code (โมฆะ * pvParameters) { Serial.print ("Task2 ทำงานบนคอร์"); Serial.println (xPortGetCoreID ()); สำหรับ (;;) { ลอย t = dht.readTemperature (); Serial.print ("อุณหภูมิ:"); Serial.print (เสื้อ); ล่าช้า (2000); } }
3. ที่นี่ฟังก์ชัน void loop จะยังคงว่างเปล่า ดังที่เราทราบแล้วว่าฟังก์ชัน ลูป และ การตั้งค่า ทำงานบน core1ดังนั้นคุณสามารถใช้งาน core1 ในฟังก์ชัน void loop
ตอนนี้ส่วนการเข้ารหัสสิ้นสุดลงแล้วดังนั้นเพียงอัปโหลดโค้ดโดยใช้ Arduino IDE โดยเลือกบอร์ด ESP32 ในเมนู Tools ตรวจสอบให้แน่ใจว่าคุณได้เชื่อมต่อเซ็นเซอร์ DHT11 กับขา D13 ของ ESP32
ตอนนี้สามารถตรวจสอบผลลัพธ์ได้บน Serial Monitor หรือ Arduino IDE ดังที่แสดงด้านล่าง:
แอปพลิเคชันที่ซับซ้อนเช่นระบบเรียลไทม์สามารถสร้างขึ้นโดยการทำงานหลายอย่างพร้อมกันโดยใช้แกนคู่ของ ESP32
รหัสที่สมบูรณ์พร้อมกับวิดีโอสาธิตมีให้ด้านล่าง