FreeRTOS Ping Pong Game (ESP32)

 


ทดลองใช้งานและดูโค้ดได้จากลิงค์นี้ คลิก

เงื่อนไขของเกม

  • ใช้  Potentiometer ในการควบคุมตำแหน่งของผู้เล่น

  • ลูกบอลจะเริ่มเสิร์ฟจากฝ่ายใดฝ่ายหนึ่งโดยจะเกิดจากการสุ่ม

  • เมื่อได้ผู้ชนะได้คะแนนในแต่ละรอบ จะมีเสียงแจ้งเตือนจาก Buzzer และ กระดานคะแนนจะเพิ่มขึ้นในฝ่ายที่ชนะ

  • ผู้เล่นที่สามารถทำคะแนนได้ถึง 3 คะแนนก่อนฝ่ายตรงข้าม จะถูกตัดสินให้เป็นผู้ที่ชนะในไปในเกมรอบนั้นโดยทันที

  • เกมจะเริ่มรอบใหม่อัตโนมัติ

  • สามารถหยุดเกมได้ โดยการกดปุ่ม


Block Diagram (ภาพรวมของระบบ)
Block Diagram    
    ภาพรวมของระบบจากภาพ block diagram จะมีฝั่งรับข้อมูลเป็น สวิตซ์สถานะ และ ตัวต้านทานปรับค่าได้ทั้ง 2 ตัว อุปกรณ์พวกนี้จะทำการรับข้อมูลและส่งเข้าไปประมวลผลใน ESP32 จากนั้นทำการแสดงผลภาพทางจอ led matrix และ ส่งเสียงทาง buzzer
    ถ้ามองลงไปถึงหลักการทำงานของเกมคร่าวๆก็จะเป็นว่า รับข้อมูลตำแหน่งผู้เล่นจากตัวต้านทานปรับค่าได้และรับข้อมูลสถานะของเกม(หยุด/เล่นต่อ)จากทางปุ่มกดแล้วนำไปใช้งานในระบบเกม แล้วก็ทำการแสดงผลออกมาทางจอภาพ led matrix และส่งเสียงจาก buzzer

หมวดหมู่การเก็บค่าตัวแปรที่สำคัญ
ตัวแปรต่างๆ
    ในการรันเกมนั้นต้องมีการเก็บค่าต่างๆไว้ในตัวแปร ดังภาพด้านบน โดยมีการแยกเป็นหมวดหมู่ดังนี้
  • game settings : เก็บค่าความถี่ของการอัพเดดค่าต่างๆของเกมซึ่งมีส่วนทำให้เกมนั้นเร็วขึ้น/ช้าลง, เก็บสถานะของเกม(pause/continue) และความนานของการหน่วงเวลาก่อนเริ่มเกมใหม่เมื่อมีการชนะ/แพ้ของผู้เล่นเกิดขึ้น
  • player score : เก็บค่าคะแนนของผู้เล่น
  • player coordinate : เก็บค่าตำแหน่งของผู้เล่น
  • ball coordinate : เก็บค่าตำแหน่งของลูกบอล
  • ball direction : เก็บค่าสถานะการเคลื่อนที่ของลูกบอล ในแต่ละสถานะจะเคลื่อนที่ไปในทิศทางที่ต่างกัน
    ซึ่งจากตัวแปรต่างๆนี้มีความสำคัญในการทำงานของ tasks ต่างๆ ซึ่งในส่วนของ task จะอยู่ในหัวข้อถัดจากนี้ไป 

Tasks และการทำงาน
Tasks
    ในที่นี้เราจะใช้ freertos ในการทำงาน โดยจะมีการแบ่งการทำงานออกเป็น task ต่างๆ สามารถดูการแจกแจงในแต่ละ core และ priority ในการทำงาน ได้จากภาพด้านบน และสำหรับรายละเอียดหน้าที่ของแต่ละ tasks นั้นมีดังนี้
  • update_ball : อัพเดดตัวแปรตำแหน่งลูกบอล ซึ่งมันจะเคลื่อนไปเรื่อยๆ รวมทั้งตรวจเช็คเงื่อนไขที่การชนของลูกบอลและทำการทำงานตามเงื่อนไขที่ได้ตั้งไว้ เช่นเมื่อมีการชนฝั่งของผู้เล่นแล้วผู้เล่นรับไม่ได้ให้เข้าเงื่อนไขของเกมโอเวอร์ ซึ่งจะทำการนับคะแนนและเริ่มรอบต่อไปใหม่
  • p1_pos : รับค่า input จากตัวต้านทางปรับค่าได้ และนำมาเก็บเป็นตำแหน่งขอผู้เล่นที่ 1 ในขณะนั้น
  • p2_pos : รับค่า input จากตัวต้านทางปรับค่าได้ และนำมาเก็บเป็นตำแหน่งขอผู้เล่นที่ 2 ในขณะนั้น
  • render : อ่านค่าจากตัวแปรต่างๆ และทำการแสดงผลออกไปทางหน้าจอ led matrix 
  • game_state : รับค่า input จากปุ่มกดและทำการอัพเดดค่าตัวแปรสถานะของเกม
    สำหรับการทำงานประสานกันในแต่ละ tasks ก็จะใช้ event group ช่วยในการประสานงาน โดยจะมีการตั้งค่าตัวแปร event group เอาไว้เก็บค่าสถานะการทำงานของ task ทั้ง 3 ตัวตามภาพซึ่งประกอบไปด้วย update_ball, p1_pos และ p2_pos (ด้านซ้ายของภาพ) และเมื่อ tasks ทั้ง 3 นั้นทำงานเรียบร้อยแล้วก็จะเซ็ทบิตในตัวแปร event group ว่าสถานะพร้อมแล้ว และในขณะนั้นเองก็จะมี task render ซึ่งจะคอยอ่านค่าบิตจากตัวแปร event group เมื่อมีการเซ็ทบิตทั้งหมดครบแล้ว มันก็จะเคลียร์บิตของตัวแปร event group แล้วตัวมันเองก็จะทำการแสดงผลภาพออกมาทางจอ led matrix 

Task Core & Priority
Task Core & Priority
    ในการตั้งค่า priority และ core ของแต่ละ task จากการทำงานของ tasks ที่กล่าวมาจากข้างต้น เราจะยกให้ task render นั้น ทำงานอยู่ที่ core 0 และมี priority สูงที่สุดเพราะมันไม่ควรที่จะ ถูกขัดการทำงานและมันก็ไม่ได้ทำงานอยู่ตลอดเวลา มันจะทำงานก็ต่อเมื่อบิตทั้งหมดใน event group นั้นถูกเซ็ตแล้ว ต่อมาใน core 0 ก็จะมี update_ball ซึ่งเป็น task ที่สำคัญกับระบบเกมมากเป็นตัวดำเนินเกมและควบคุมความเร็วในการอัพเดดภาพของเกม ในเมื่อเรามีการใช้ event group และมีการแยก core การทำงานดังนั้นก็จะไม่มีปัญหาการทำงานผิดพลาดของ tasks ต่างๆ และสุดท้ายสำหรับ tasks ใน core 1 ก็จะเป็น task priority เดียวกันทั้งหมด ซึ่งมันมีหน้าที่เกี่ยวกับการรับค่า input จากภายนอกเข้ามา ซึ่งมันสามารถทำงานสลับกันได้ ก็เลยกำหนดให้ใช้ priority เดียวกันทั้งหมดได้โดยไม่มีปัญหา
ทดลองใช้งานและดูโค้ดได้จากลิงค์นี้ คลิก

ความคิดเห็น