สารบัญ:
- ขั้นตอนที่ 1: ตั้งค่าบอร์ด
- ขั้นตอนที่ 2: เพิ่มปุ่มและตัวต้านทาน
- ขั้นตอนที่ 3: การเชื่อมต่อปุ่ม
- ขั้นตอนที่ 4: รหัส…
- ขั้นตอนที่ 5: การโต้เถียงเล็กน้อย
- ขั้นตอนที่ 6: การสร้างเมนู
- ขั้นตอนที่ 7: การแยกโค้ด - Global
- ขั้นตอนที่ 8: การแยกย่อยโค้ด - การตั้งค่าและฟังก์ชันที่กำหนดเอง
- ขั้นตอนที่ 9: วนรอบ…
- ขั้นตอนที่ 10: Final Code Block
วีดีโอ: เมนูใน Arduino และวิธีใช้ปุ่ม: 10 ขั้นตอน (พร้อมรูปภาพ)
2024 ผู้เขียน: John Day | [email protected]. แก้ไขล่าสุด: 2024-01-30 13:06
ในบทช่วยสอน Arduino 101 ของฉัน คุณจะได้รับการสอนวิธีตั้งค่าสภาพแวดล้อมของคุณใน Tinkercad ฉันใช้ Tinkercad เพราะเป็นแพลตฟอร์มออนไลน์ที่ทรงพลังมาก ซึ่งทำให้ฉันสามารถแสดงทักษะต่างๆ ให้กับนักเรียนในการสร้างวงจรได้ รู้สึกอิสระที่จะสร้างบทช่วยสอนทั้งหมดของฉันโดยใช้ Arduino IDE และ Arduino จริง!
ในบทช่วยสอนนี้ เราจะมาเรียนรู้เกี่ยวกับปุ่มต่างๆ กัน! เราจำเป็นต้องรู้:
- วิธีการวางสาย
- การอ่านค่า
- Debounce และเหตุใดจึงสำคัญ
- แอปพลิเคชั่นที่ใช้งานได้จริง (การสร้างเมนู)
คนส่วนใหญ่คิดว่าสิ่งที่เป็นประโยชน์ที่สุดในการทำปุ่มคือเปิดและปิดไฟ เราจะไม่ใช่ที่นี่! เราจะใช้เมนูของเราเพื่อสร้างเมนูและตั้งค่าตัวเลือกบางอย่างบน Arduino
พร้อม? มาเริ่มกันเลย!
ขั้นตอนที่ 1: ตั้งค่าบอร์ด
ขั้นตอนแรกคือการวาง Arduino และ Breadboard Small ลงบนพื้นที่สร้างต้นแบบ ตรวจสอบภาพด้านบนเพื่อดูวิธีการต่อสายไฟ
Breadboard Mini มีรางไฟฟ้าสองรางด้านบนและด้านล่าง เราเชื่อมต่อสิ่งเหล่านี้กับ Arduino เพื่อให้เราสามารถจ่ายพลังงานให้กับส่วนประกอบต่างๆ ได้มากขึ้น ต่อไปในบทช่วยสอนนี้ เราจะใช้ 3 ปุ่ม ดังนั้นเราจะต้องเพิ่มพลัง สิ่งที่ควรทราบคือบนเขียงหั่นขนมขนาดเล็ก รางไฟวิ่งข้ามกระดานในแนวนอน ซึ่งแตกต่างจากคอลัมน์ในพื้นที่สร้างต้นแบบหลักที่อยู่ตรงกลาง เหล่านี้ทำงานในแนวตั้ง คุณสามารถใช้พินเพาเวอร์ใดๆ เพื่อจ่ายไฟให้กับคอลัมน์ใดๆ ในพื้นที่หลักที่อยู่ตรงกลาง
เมื่อคุณเพิ่มกำลัง ให้ใช้สายสีดำและสีแดงกับขั้วลบและขั้วบวกตามลำดับ เพิ่มสายไฟที่ปลายสายไฟที่อีกด้านหนึ่งของบอร์ด เราจะไม่ใช้ด้านนั้น แต่เป็นการฝึกฝนที่ดี
ขั้นตอนที่ 2: เพิ่มปุ่มและตัวต้านทาน
เพิ่มปุ่มกดเล็กๆ จากถาดส่วนประกอบ ควรมีลักษณะเหมือนในภาพ ตรวจสอบให้แน่ใจว่าไม่ใช่สวิตช์! เพิ่มตัวต้านทานด้วย คลิกและตั้งค่าเป็น10kΩ นั่นก็เพียงพอแล้วที่จะดึงพินให้ต่ำเมื่อไม่ได้เชื่อมต่อ ซึ่งสำคัญมากในโค้ดในภายหลัง
วางส่วนประกอบไว้ตรงกลางของเขียงหั่นขนม วิธีการทำงานของปุ่มคือ:
- มุมต่อมุม ปุ่มไม่ได้เชื่อมต่อ การกดปุ่มจะปิดหน้าสัมผัสและเชื่อมต่อมุมต่างๆ
- ด้านข้างของปุ่มเชื่อมต่อกัน หากคุณต่อสายเข้ากับด้านซ้ายบนและด้านซ้ายล่าง วงจรจะถูกปิด
นี่คือเหตุผลที่เราวางองค์ประกอบข้ามช่องว่างตรงกลาง ทำให้แน่ใจว่ามุมต่างๆ ไม่ได้เชื่อมต่ออยู่ใต้หมุดในบอร์ด
ขั้นตอนต่อไปจะมีรูปภาพสองสามภาพที่แสดงให้เห็นประเด็นเหล่านี้
วางตัวต้านทานจากพินขวาล่างข้ามคอลัมน์ ให้วางในแนวนอน
ขั้นตอนที่ 3: การเชื่อมต่อปุ่ม
ภาพด้านบนทำให้เห็นได้ชัดเจนว่าปุ่มต่างๆ เชื่อมต่อกันอย่างไร เป็นเรื่องที่สับสนเสมอเมื่อคุณคิดว่ามีบางอย่างที่ดีและไม่ได้ผล!
ทีนี้มาเพิ่มสายไฟกัน
- วางตะกั่วสีแดงจากพินพลังงานบวกไปยังคอลัมน์เดียวกันกับพินขวาล่างของปุ่ม
- วางตะกั่วสีดำจากพินพลังงานลบไปยังคอลัมน์เดียวกันกับตัวต้านทาน
- วางลวดสี (ไม่ใช่สีแดง/ดำ) จากพินซ้ายบนไปยัง Digital Pin 2 บน Arduino
ตรวจสอบภาพด้านบนเพื่อให้แน่ใจว่าการเดินสายของคุณถูกต้อง
ขั้นตอนที่ 4: รหัส…
มาดูรหัสสำหรับปุ่มพื้นฐานกัน
เปิดตัวแก้ไขโค้ดและเปลี่ยนจาก Blocks เป็น Text ล้างคำเตือนที่ขึ้นมา เราพอใจกับข้อความ!
คุณทราบการตั้งค่าพื้นฐานแล้ว มากำหนดปุ่มและอ่านพื้นฐานกัน เราจะพิมพ์ผลลัพธ์ไปยัง Serial
ฉันใส่ความคิดเห็นพิเศษสองสามข้อลงในโค้ดด้านล่างเพื่อให้อ่านง่ายกว่ารูปภาพ
// กำหนดค่าคงที่
#define ปุ่ม 2 การตั้งค่าเป็นโมฆะ () { pinMode (ปุ่ม, INPUT); Serial.begin(9600); } วงเป็นโมฆะ () { // อ่านพินดิจิทัลเพื่อตรวจสอบสถานะของปุ่ม int ที่กด = digitalRead (ปุ่ม); // ปุ่มจะคืนค่า HIGH หากกด LOW ถ้าไม่เช่นนั้นหาก (กด == HIGH){ Serial.println("Pressed!"); } }
โอเค ได้ผล!
โดยพื้นฐานแล้ว สิ่งที่เราทำคือการตรวจสอบสถานะของพินดิจิทัลทุกครั้งที่โค้ดวนซ้ำ หากคุณคลิก เริ่มการจำลอง และกดปุ่ม คุณจะเห็น Serial Monitor (คลิกปุ่มด้านล่างโค้ด) แสดง "Pressed!" ซ้ำแล้วซ้ำเล่า
คุณลักษณะหนึ่งที่คุณจะเห็นในโค้ดด้านบนคือการประเมินเงื่อนไข if() ที่เกิดขึ้น โค้ดทั้งหมดที่ทำคือการถามคำถามและประเมินว่าจริงหรือไม่ ในกรณีนี้ เราใช้ is equal (เครื่องหมายเท่ากับสองเท่า เช่น ==) เพื่อตรวจสอบว่าค่าของตัวแปรเท่ากับค่าหนึ่งหรือไม่ digitalRead() ส่งกลับค่า HIGH หรือ LOW
การใช้ if() else if / else เราสามารถตรวจสอบเงื่อนไขได้หลายอย่างหรือทุกเงื่อนไข และหากคุณกลับไปที่ Arduino Basics คุณจะเห็นการเปรียบเทียบบางอย่างที่คุณสามารถทำได้
ตอนนี้… รหัสของเราอาจดูสมบูรณ์… แต่เรามีปัญหา
ดูสิ มันใช้งานได้ดีจริงๆ เมื่ออยู่ในเครื่องจำลอง แต่ไฟฟ้าจริงมีสัญญาณรบกวน โดยเฉพาะอุปกรณ์ไฟฟ้ากระแสตรง ดังนั้นปุ่มของเราอาจส่งคืนการอ่านที่ผิดพลาดในบางครั้ง และนั่นคือปัญหา เนื่องจากโครงการของคุณอาจไม่ตอบสนองในทางที่ถูกต้องสำหรับผู้ใช้
มาแก้ไขกันเถอะ!
ขั้นตอนที่ 5: การโต้เถียงเล็กน้อย
เราใช้ขั้นตอนที่เรียกว่า debounce เพื่อแก้ปัญหาปุ่มของเรา โดยพื้นฐานแล้วจะรอตามระยะเวลาที่กำหนดระหว่างเวลาที่กดปุ่มและตอบสนองต่อการกดจริง ผู้ใช้ยังคงรู้สึกเป็นธรรมชาติ (เว้นแต่คุณจะใช้เวลานานเกินไป) คุณยังสามารถใช้เพื่อตรวจสอบความยาวของการกด คุณจึงสามารถตอบสนองได้แตกต่างกันในแต่ละครั้ง ไม่ต้องเปลี่ยนสายไฟ!
ลองดูรหัส:
#define ปุ่ม 2#define debounceTimeout 100
การเปลี่ยนแปลงครั้งแรกอยู่ในขอบเขตทั่วโลก คุณจะจำได้ว่าเป็นที่ที่เรากำหนดตัวแปรที่ฟังก์ชันจำนวนมากของเราอาจใช้หรือตัวแปรที่ไม่สามารถรีเซ็ตได้ในแต่ละครั้งที่ลูปเริ่มทำงาน ดังนั้นเราจึงเพิ่ม debounceTimeout ให้กับค่าคงที่ที่กำหนดไว้ เราสร้าง 100 รายการนี้ (ซึ่งจะแปลเป็น 100 มิลลิวินาทีในภายหลัง) แต่อาจสั้นกว่านี้ อีกต่อไปและมันจะรู้สึกผิดธรรมชาติ
ยาว int lastDebounceTime;
ตัวแปรนี้ถูกประกาศไว้ด้านล่างค่าคงที่ นี่เป็นประเภท int แบบยาว ซึ่งช่วยให้เราสามารถเก็บตัวเลขที่ยาวไว้ในหน่วยความจำได้ เราเรียกมันว่า LastDebounceTime
เราไม่จำเป็นต้องเปลี่ยนแปลงอะไรในฟังก์ชัน void setup() ปล่อยอันนั้นไปเถอะ
วงเป็นโมฆะ () {// อ่านพินดิจิทัลเพื่อตรวจสอบสถานะของปุ่ม int ที่กด = digitalRead (ปุ่ม); ยาว int currentTime = millis(); // รหัสปุ่ม }
การเปลี่ยนแปลงครั้งแรกที่เราทำในฟังก์ชัน loop() อยู่ภายใต้การเรียกเพื่ออ่านปุ่ม เราจำเป็นต้องติดตามเวลาปัจจุบัน ฟังก์ชัน millis() จะคืนค่าเวลาปัจจุบันของนาฬิกาตั้งแต่ Arduino บูทขึ้นในหน่วยมิลลิวินาที เราจำเป็นต้องเก็บไว้ในตัวแปรชนิด int แบบยาว
ตอนนี้ เราต้องแน่ใจว่าเราทราบเวลาตั้งแต่กดปุ่ม ดังนั้นเราจึงรีเซ็ตตัวจับเวลาเมื่อไม่ได้กดปุ่ม ลองดูสิ:
วงเป็นโมฆะ () {// อ่านพินดิจิทัลเพื่อตรวจสอบสถานะของปุ่ม int ที่กด = digitalRead (ปุ่ม); ยาว int currentTime = millis(); ถ้า (กด == ต่ำ) {// รีเซ็ตเวลานับในขณะที่ไม่ได้กดปุ่ม lastDebounceTime = currentTime; } // รหัสปุ่ม }
อัลกอริทึม if(pressed == LOW) จะตรวจสอบว่าไม่ได้กดปุ่มหรือไม่ หากไม่เป็นเช่นนั้น รหัสจะจัดเก็บเวลาปัจจุบันตั้งแต่การดีบักครั้งล่าสุด ด้วยวิธีนี้ ทุกครั้งที่กดปุ่ม เราจะมีจุดที่เราสามารถตรวจสอบว่าปุ่มนั้นถูกกดเมื่อใด จากนั้นเราสามารถคำนวณทางคณิตศาสตร์อย่างรวดเร็วเพื่อดูว่ามีการกดปุ่มนานเท่าใดและตอบสนองอย่างถูกต้อง มาดูโค้ดที่เหลือกัน:
วงเป็นโมฆะ () {// อ่านพินดิจิทัลเพื่อตรวจสอบสถานะของปุ่ม int ที่กด = digitalRead (ปุ่ม); ยาว int currentTime = millis(); ถ้า (กด == ต่ำ) {// รีเซ็ตเวลานับในขณะที่ไม่ได้กดปุ่ม lastDebounceTime = currentTime; } // มีการกดปุ่มในช่วงเวลาที่กำหนด if(((currentTime - lastDebounceTime) > debounceTimeout)){ // หากหมดเวลาแล้ว ให้กดปุ่ม! Serial.println("กด!"); } }
บล็อกสุดท้ายของโค้ดใช้เวลาปัจจุบัน ลบเวลา debounce ล่าสุด และเปรียบเทียบกับระยะหมดเวลาที่เราตั้งไว้ หากมีค่ามากกว่า โค้ดจะถือว่ามีการกดปุ่มในช่วงเวลานั้นและตอบสนอง ประณีต!
เรียกใช้รหัสของคุณและตรวจสอบว่าใช้งานได้ หากคุณมีข้อผิดพลาด ตรวจสอบรหัสของคุณ!
ทีนี้มาดูตัวอย่างการใช้งานจริงกัน
ขั้นตอนที่ 6: การสร้างเมนู
ปุ่มนั้นน่าสนใจเพราะมีความเป็นไปได้มากมายกับมัน! ในตัวอย่างนี้ เราจะทำเมนู สมมติว่าคุณได้สร้างอุปกรณ์ที่ยอดเยี่ยมจริงๆ เครื่องนี้ และต้องการให้ผู้ใช้สามารถเปลี่ยนตัวเลือกเพื่อเปิดหรือปิดบางสิ่ง หรือตั้งค่าเฉพาะสำหรับการตั้งค่า การออกแบบปุ่มสามปุ่มนี้สามารถทำได้!
ดังนั้น สำหรับโครงการนี้ เราต้องการ:
- สามปุ่ม
- ตัวต้านทานสามตัวตั้งค่าเป็น10kΩ
เรามีหนึ่งในนี้แล้ว เราแค่ต้องการอีกสองตัว เพื่อเพิ่มสิ่งเหล่านั้นลงในกระดาน การเดินสายไฟนั้นซับซ้อนกว่าเล็กน้อย แต่เพียงเพราะฉันต้องการให้มันกะทัดรัดจริงๆ คุณสามารถทำตามรูปแบบเดียวกันสำหรับปุ่มแรกหรือทำตามภาพด้านบน
ปุ่มสามปุ่มคือตัวเลือกเปิด/ถัดไปของเมนู ตัวเลือกการเปลี่ยนแปลง (เช่น เปลี่ยนการตั้งค่า) และปุ่มบันทึก/ปิดเมนู
วางสาย มาดูโค้ดกันเลย!
ขั้นตอนที่ 7: การแยกโค้ด - Global
ตกลง นี่จะเป็นขั้นตอนที่ยาวนาน แต่ฉันจะอธิบายแต่ละส่วนของโค้ด
อันดับแรก มาดูตัวแปรส่วนกลางที่จำเป็นกันก่อน
// กำหนดค่าคงที่#define menuButton 2 #define menuSelect 3#define menuSave 4 #define debounceTimeout 50 // กำหนดตัวแปร int menuButtonPreviousState = LOW; int menuSelectPreviousState = ต่ำ; int menuSavePreviousState = ต่ำ; ยาว int lastDebounceTime; // ตัวเลือกเมนู char * menuOptions = {"Check Temp", "Check Light"}; bool featureSetting = {เท็จ เท็จ}; bool menuMode = เท็จ; เมนูบูลNeedsPrint = false; int optionSelected = 0;
สามช่วงตึกนี้ค่อนข้างคล้ายกับที่เราเคยเห็นมาก่อน ในตอนแรก ฉันได้กำหนดปุ่มสามปุ่มและระยะหมดเวลา สำหรับส่วนนี้ของโปรเจ็กต์ ฉันได้ตั้งค่าไว้ที่ 50 มิลลิวินาที ดังนั้นจึงต้องมีการกดอย่างรอบคอบเพื่อให้ใช้งานได้
บล็อกที่สองคือตัวแปรทั้งหมด เราจำเป็นต้องติดตาม buttonPreviousState และเราต้องติดตาม LastDebounceTime ตัวแปรเหล่านี้เป็นตัวแปรประเภท int ทั้งหมด แต่ตัวสุดท้ายเป็นตัวแปรแบบยาว เพราะฉันคิดว่าเราต้องการพื้นที่ในหน่วยความจำ
บล็อกตัวเลือกเมนูมีคุณสมบัติใหม่บางอย่าง อย่างแรก อักขระ * (ใช่ นั่นคือเครื่องหมายดอกจันโดยเจตนา) ซึ่งเป็นตัวแปรตามตัวอักษร/สตริงตามตัวอักษร เป็นตัวชี้ไปยังที่เก็บข้อมูลแบบคงที่ในหน่วยความจำ คุณไม่สามารถเปลี่ยนแปลงได้ (เช่น ใน Python เป็นต้น) char *menuOptions บรรทัดนี้สร้างอาร์เรย์ของตัวอักษรสตริง คุณสามารถเพิ่มรายการเมนูได้มากเท่าที่คุณต้องการ
ตัวแปร bool featureSetting เป็นเพียงอาร์เรย์ของค่าที่แสดงถึงแต่ละรายการในเมนู ได้ คุณสามารถเก็บอะไรก็ได้ที่คุณชอบ เพียงแค่เปลี่ยนประเภทตัวแปร (ตัวแปรทั้งหมดต้องเป็นประเภทเดียวกัน) ตอนนี้ อาจมีวิธีที่ดีกว่าในการจัดการสิ่งนี้ เช่น พจนานุกรมหรือ tuples แต่วิธีนี้ง่ายสำหรับแอปพลิเคชันนี้ ฉันอาจจะสร้างหนึ่งในแอปพลิเคชันที่ปรับใช้
ฉันได้ติดตามเมนูโหมด ดังนั้นหากฉันต้องการสิ่งอื่นบนจอแสดงผลของฉัน ฉันสามารถทำได้ นอกจากนี้ หากฉันมีตรรกะของเซ็นเซอร์ ฉันอาจหยุดการทำงานนั้นชั่วคราวระหว่างการทำงานของเมนู เผื่อในกรณีที่มีบางอย่างขัดแย้งกัน ฉันมีตัวแปร menuNeedsPrint เพราะฉันต้องการพิมพ์เมนูตามเวลาที่กำหนด ไม่ใช่แค่ตลอดเวลา สุดท้าย ฉันมีตัวแปร optionSelected ดังนั้นฉันจึงสามารถติดตามตัวเลือกที่เลือกเมื่อฉันเข้าถึงได้ในหลายที่
มาดูฟังก์ชันชุดต่อไปกัน
ขั้นตอนที่ 8: การแยกย่อยโค้ด - การตั้งค่าและฟังก์ชันที่กำหนดเอง
ฟังก์ชัน setup() นั้นง่ายเพียงพอ เพียงสามการประกาศอินพุต:
การตั้งค่าเป็นโมฆะ () { pinMode (menuSelect, INPUT); โหมดพิน (menuSave, INPUT); pinMode (เลือกเมนู, อินพุต); Serial.begin(9600); }
ถัดไปคือฟังก์ชันแบบกำหนดเองสามแบบ ลองดูสองอันแรกแล้วอันสุดท้ายแยกกัน
เราต้องการสองฟังก์ชันที่ส่งคืนข้อมูลบางอย่าง เหตุผลก็คือ เราต้องการให้แน่ใจว่าสิ่งนี้สามารถอ่านได้โดยมนุษย์ นอกจากนี้ยังช่วยในการดีบักโค้ดหากเรามีปัญหา รหัส:
// ฟังก์ชันเพื่อคืนค่า optionchar ที่เลือกในปัจจุบัน *ReturnOptionSelected(){ ถ่าน *menuOption = menuOptions[optionSelected]; // Return option เมนูส่งคืนที่เลือก ตัวเลือก; } // ฟังก์ชันส่งคืนสถานะของตัวเลือกที่เลือกในปัจจุบัน ถ่าน *ReturnOptionStatus(){ bool optionSetting = featureSetting[optionSelected]; ถ่าน *ตัวเลือกSettingVal; ถ้า (optionSetting == false) { optionSettingVal = "False"; }อื่น{ optionSettingVal = "จริง"; } // Return optionSetting return optionSettingVal; }
ฟังก์ชัน char *ReturnOptionSelected() จะตรวจสอบตัวเลือกที่เลือก (หากคุณเห็นด้านบน เราจะตั้งค่าตัวแปรเพื่อติดตามสิ่งนั้น) และดึงสตริงตามตัวอักษรจากอาร์เรย์ที่เราสร้างไว้ก่อนหน้านี้ จากนั้นส่งคืนเป็นประเภทอักขระ เราทราบสิ่งนี้เนื่องจากฟังก์ชันระบุประเภทการส่งคืน
ฟังก์ชันที่สอง char *ReturnOptionStatus() จะอ่านสถานะของตัวเลือกที่บันทึกไว้ในอาร์เรย์และส่งกลับสตริงตัวอักษรที่แสดงค่า ตัวอย่างเช่น หากการตั้งค่าที่เราเก็บไว้เป็น false ฉันจะคืนค่าเป็น "False" นี่เป็นเพราะเราแสดงให้ผู้ใช้เห็นตัวแปรนี้ และเป็นการดีกว่าที่จะรวมตรรกะทั้งหมดนี้ไว้ด้วยกัน ฉันสามารถทำได้ในภายหลัง แต่มันสมเหตุสมผลกว่าที่จะทำที่นี่
// ฟังก์ชันเพื่อสลับตัวเลือกปัจจุบัน ToggleOptionSelected (){ featureSetting[optionSelected] = !featureSetting[optionSelected]; คืนค่าจริง; }
ฟังก์ชัน bool ToggleOptionSelected() เป็นฟังก์ชันอำนวยความสะดวกในการเปลี่ยนค่าของการตั้งค่าที่เราได้เลือกไว้ในเมนู มันแค่พลิกค่า หากคุณมีชุดตัวเลือกที่ซับซ้อนกว่านี้ อาจแตกต่างกันมาก ฉันคืนค่า true ในฟังก์ชันนี้ เนื่องจากการโทรกลับของฉัน (การโทรในภายหลังในโค้ดที่เรียกใช้ฟังก์ชันนี้) คาดว่าจะมีการตอบกลับจริง/เท็จ ฉันแน่ใจ 100% ว่าจะใช้งานได้ ดังนั้นฉันจึงไม่ได้พิจารณาว่ามันไม่ทำงาน แต่ฉันจะทำในแอปพลิเคชันที่ปรับใช้ (ในกรณีนี้)
ขั้นตอนที่ 9: วนรอบ…
ฟังก์ชัน loop() ค่อนข้างยาว ดังนั้นเราจะทำเป็นส่วนๆ คุณสามารถสมมติทุกอย่างด้านล่างซ้อนกันภายในฟังก์ชันนี้:
วงเป็นโมฆะ () {
// ทำงานที่นี่ <----- }
ตกลง เราเห็นสิ่งนี้มาก่อน:
// อ่านปุ่ม int menuButtonPressed = digitalRead(menuButton); int menuSelectPressed = digitalRead(menuSelect); int menuSavePressed = digitalRead (menuSave); // รับเวลาปัจจุบัน long int currentTime = millis(); if(menuButtonPressed == LOW && menuSelectPressed == LOW && menuSavePressed == LOW){ //รีเซ็ตเวลานับในขณะที่ไม่ได้กดปุ่ม lastDebounceTime = currentTime; menuButtonPreviousState = ต่ำ; menuSelectPreviousState = ต่ำ; menuSavePreviousState = ต่ำ; }
ทั้งหมดที่ฉันต้องทำคือเพิ่มการเรียก digitalRead() สามครั้ง และตรวจดูให้แน่ใจว่าฉันได้คำนึงถึงข้อเท็จจริงที่ว่าหากปุ่มทั้งหมดเหลือน้อย เราควรรีเซ็ตตัวจับเวลา (lastDebounceTime = currentTime) และตั้งค่าสถานะก่อนหน้าทั้งหมดเป็นต่ำ ฉันยังเก็บ millis() ใน currentTime
ส่วนถัดไปซ้อนอยู่ภายในเส้น
if(((currentTime - lastDebounceTime) > debounceTimeout)){
//ทำงานที่นี่ <---- }
มีสามส่วน ใช่ ฉันสามารถย้ายพวกมันไปยังฟังก์ชันของตัวเองได้ แต่เพื่อความเรียบง่าย ฉันจึงเก็บอัลกอริธึมปุ่มหลักสามปุ่มไว้ที่นี่
if((menuButtonPressed == HIGH) && (menuButtonPreviousState == LOW)){ if(menuMode == false){ menuMode = true; // แจ้งให้ผู้ใช้ทราบ Serial.println("เมนูใช้งานได้"); } else if (menuMode == true && optionSelected = 1){ // รีเซ็ตตัวเลือก optionSelected = 0; } // พิมพ์เมนู menuNeedsPrint = true; // สลับปุ่มก่อนหน้า กำหนดให้แสดงเฉพาะเมนู // หากปล่อยปุ่มแล้วกดอีกครั้ง menuButtonPreviousState = menuButtonPressed; // น่าจะสูง }
อันแรกนี้จะจัดการเมื่อ menuButtonPressed เป็น HIGH หรือเมื่อกดปุ่มเมนู นอกจากนี้ยังตรวจสอบเพื่อให้แน่ใจว่าสถานะก่อนหน้าเป็น LOW เพื่อให้ต้องปล่อยปุ่มก่อนที่จะกดอีกครั้ง ซึ่งจะทำให้โปรแกรมหยุดการทำงานของเหตุการณ์เดิมซ้ำแล้วซ้ำอีก
จากนั้นจะตรวจสอบว่าถ้าเมนูไม่ทำงานก็จะเปิดใช้งาน มันจะพิมพ์ตัวเลือกแรกที่เลือก (ซึ่งเป็นรายการแรกในอาร์เรย์ menuOptions โดยค่าเริ่มต้น หากคุณกดปุ่มครั้งที่สองหรือสาม (อื่นๆ) คุณจะได้รับตัวเลือกถัดไปในรายการ สิ่งที่ฉันแก้ไขได้คือ ที่เมื่อถึงจุดสิ้นสุด มันจะวนกลับมาที่จุดเริ่มต้น สิ่งนี้สามารถอ่านความยาวของอาร์เรย์และทำให้การวนกลับง่ายขึ้นหากคุณเปลี่ยนจำนวนตัวเลือก แต่ตอนนี้ ง่ายสำหรับตอนนี้
ส่วนเล็ก ๆ สุดท้าย (// พิมพ์เมนู) จะพิมพ์เมนูอย่างชัดเจน แต่ยังตั้งค่าสถานะก่อนหน้าเป็น HIGH ดังนั้นฟังก์ชันเดียวกันจะไม่วนซ้ำ (ดูหมายเหตุของฉันด้านบนเกี่ยวกับการตรวจสอบว่าปุ่มก่อนหน้านี้เป็น LOW หรือไม่)
// กด menuSelect ให้ logicif((menuSelectPressed == HIGH) && (menuSelectPreviousState == LOW)){ if(menuMode){ // เปลี่ยนตัวเลือกที่เลือก // ในขณะนี้ นี่เป็นเพียง true/false // แต่ อาจเป็นอะไรก็ได้ สลับบูล = ToggleOptionSelected(); ถ้า (สลับ) { menuNeedsPrint = true; }อื่น{ Serial.println("มีบางอย่างผิดพลาด โปรดลองอีกครั้ง"); } } // สลับสถานะเป็นสลับเฉพาะเมื่อปล่อยและกดอีกครั้ง menuSelectPreviousState = menuSelectPressed; }
โค้ดบิตนี้จัดการปุ่ม menuSelectPressed ในลักษณะเดียวกัน ยกเว้นเวลานี้ เราเพิ่งเรียกใช้ฟังก์ชัน ToggleOptionSelected() อย่างที่ฉันพูดไปก่อนหน้านี้ คุณสามารถเปลี่ยนฟังก์ชันนี้เพื่อให้ทำงานได้มากขึ้น แต่นั่นคือทั้งหมดที่ฉันต้องทำ
สิ่งสำคัญที่ควรทราบคือตัวแปรสลับ ซึ่งติดตามความสำเร็จของการโทรกลับและพิมพ์เมนูหากเป็นจริง หากไม่ส่งคืนสิ่งใดหรือเป็นเท็จ ระบบจะพิมพ์ข้อความแสดงข้อผิดพลาด นี่คือที่ที่คุณสามารถใช้การโทรกลับเพื่อทำสิ่งอื่นได้
if((menuSavePressed == HIGH) && (menuSavePreviousState == LOW)){ // ออกจากเมนู // คุณสามารถจัดระเบียบอะไรก็ได้ // หรือบันทึกลงใน EEPROM menuMode = false; Serial.println("ออกจากเมนู"); // สลับสถานะเพื่อให้เมนูออกเพียงครั้งเดียว menuSavePreviousState = menuSavePressed; } }
ฟังก์ชันนี้จัดการปุ่ม menuSave ซึ่งเพิ่งออกจากเมนู นี่คือที่ที่คุณสามารถมีตัวเลือกในการยกเลิกหรือบันทึก อาจทำการล้างข้อมูลหรือบันทึกลงใน EEPROM ฉันเพิ่งพิมพ์ "ออกจากเมนู" และตั้งค่าสถานะปุ่มเป็น HIGH เพื่อไม่ให้วนซ้ำ
if(menuMode && menuNeedsPrint){ // เราพิมพ์เมนูแล้ว เว้นแต่จะมีอะไรเกิดขึ้น // ไม่จำเป็นต้องพิมพ์ใหม่อีกครั้ง menuNeedsPrint = false; ถ่าน *optionActive = ReturnOptionSelected(); ถ่าน *optionStatus = ReturnOptionStatus(); Serial.print("เลือกแล้ว: "); Serial.print (optionActive); Serial.print(": "); Serial.print (ตัวเลือกสถานะ); Serial.println(); }
นี่คืออัลกอริธึมของ menuPrint ซึ่งจะเริ่มทำงานเฉพาะเมื่อเมนูเปิดใช้งานอยู่และเมื่อตัวแปร menuNeedsPrint ถูกตั้งค่าเป็น true
สิ่งนี้สามารถย้ายไปยังฟังก์ชั่นของตัวเองได้อย่างแน่นอน แต่เพื่อความเรียบง่าย..!
แค่นั้นแหละ! ดูขั้นตอนถัดไปสำหรับบล็อกโค้ดทั้งหมด
ขั้นตอนที่ 10: Final Code Block
// กำหนดค่าคงที่
#define menuปุ่ม 2 #define menuSelect 3 #define menuSave 4 #define debounceTimeout 50 int menuButtonPreviousState = LOW; int menuSelectPreviousState = ต่ำ; int menuSavePreviousState = ต่ำ; // กำหนดตัวแปร long int lastDebounceTime; bool lightSensor = จริง; bool tempSensor = จริง; // ตัวเลือกเมนู char * menuOptions = {"Check Temp", "Check Light"}; bool featureSetting = {เท็จ เท็จ}; bool menuMode = เท็จ; เมนูบูลNeedsPrint = false; int optionSelected = 0; // ฟังก์ชั่นการตั้งค่า
การตั้งค่าเป็นโมฆะ () { pinMode (menuSelect, INPUT); โหมดพิน (menuSave, INPUT); pinMode (เลือกเมนู, อินพุต); Serial.begin(9600); }
// ฟังก์ชันเพื่อคืนค่าตัวเลือกที่เลือกในปัจจุบัน ถ่าน *ReturnOptionSelected(){ ถ่าน *menuOption = menuOptions[optionSelected]; // Return option เมนูส่งคืนที่เลือก ตัวเลือก; } // ฟังก์ชันส่งคืนสถานะของตัวเลือกที่เลือกในปัจจุบัน ถ่าน *ReturnOptionStatus(){ bool optionSetting = featureSetting[optionSelected]; ถ่าน *ตัวเลือกSettingVal; ถ้า (optionSetting == false) { optionSettingVal = "False"; }อื่น{ optionSettingVal = "จริง"; } // Return optionSetting return optionSettingVal; } // ฟังก์ชันเพื่อสลับบูลตัวเลือกปัจจุบัน ToggleOptionSelected(){ featureSetting[optionSelected] = !featureSetting[optionSelected]; คืนค่าจริง; } // ลูปหลัก
วงเป็นโมฆะ () { // อ่านปุ่ม int menuButtonPressed = digitalRead (menuButton); int menuSelectPressed = digitalRead(menuSelect); int menuSavePressed = digitalRead (menuSave); // รับเวลาปัจจุบัน long int currentTime = millis(); if(menuButtonPressed == LOW && menuSelectPressed == LOW && menuSavePressed == LOW){ //รีเซ็ตเวลานับในขณะที่ไม่ได้กดปุ่ม lastDebounceTime = currentTime; menuButtonPreviousState = ต่ำ; menuSelectPreviousState = ต่ำ; menuSavePreviousState = ต่ำ; } if(((currentTime - lastDebounceTime) > debounceTimeout)){ // หากหมดเวลา ให้กดปุ่ม!
// กดเมนูแล้วให้ตรรกะ
// ยิงเฉพาะเมื่อปุ่มถูกปล่อยออกมาก่อนหน้านี้ if((menuButtonPressed == HIGH) && (menuButtonPreviousState == LOW)){ if(menuMode == false){ menuMode = true; // แจ้งให้ผู้ใช้ทราบ Serial.println("เมนูใช้งานได้"); } else if (menuMode == true && optionSelected = 1){ // รีเซ็ตตัวเลือก optionSelected = 0; } // พิมพ์เมนู menuNeedsPrint = true; // สลับปุ่มก่อนหน้า กำหนดให้แสดงเฉพาะเมนู // หากปล่อยปุ่มแล้วกดอีกครั้ง menuButtonPreviousState = menuButtonPressed; // จะสูง } // กด menuSelect ให้ตรรกะ if((menuSelectPressed == HIGH) && (menuSelectPreviousState == LOW)){ if(menuMode){ // เปลี่ยนตัวเลือกที่เลือก // ในขณะนี้คือ แค่ true/false // แต่อาจเป็นอะไรก็ได้ที่สลับบูล = ToggleOptionSelected(); ถ้า (สลับ) { menuNeedsPrint = true; }อื่น{ Serial.print("มีบางอย่างผิดพลาด โปรดลองอีกครั้ง"); } } // สลับสถานะเป็นสลับเฉพาะเมื่อปล่อยและกดอีกครั้ง menuSelectPreviousState = menuSelectPressed; } if((menuSavePressed == HIGH) && (menuSavePreviousState == LOW)){ // ออกจากเมนู // คุณสามารถจัดระเบียบอะไรก็ได้ // หรือบันทึกลงใน EEPROM menuMode = false; Serial.println("ออกจากเมนู"); // สลับสถานะเพื่อให้เมนูออกเพียงครั้งเดียว menuSavePreviousState = menuSavePressed; } } // พิมพ์ตัวเลือกเมนูปัจจุบันที่เปิดใช้งาน แต่พิมพ์เพียงครั้งเดียวหาก (menuMode && menuNeedsPrint){ // เราพิมพ์เมนูแล้ว ดังนั้นเว้นแต่จะมีอะไรเกิดขึ้น // ไม่จำเป็นต้องพิมพ์อีกครั้ง menuNeedsPrint = false; ถ่าน *optionActive = ReturnOptionSelected(); ถ่าน *optionStatus = ReturnOptionStatus(); Serial.print("เลือกแล้ว: "); Serial.print (optionActive); Serial.print(": "); Serial.print (ตัวเลือกสถานะ); Serial.println(); } } }
วงจรมีอยู่ในเว็บไซต์ Tinkercad ได้ฝังวงจรด้านล่างมาให้ชมกันด้วย!
เช่นเคย หากคุณมีคำถามหรือปัญหา โปรดแจ้งให้เราทราบ!
แนะนำ:
อะแดปเตอร์ Arduino Nano เป็น Arduino Uno: 6 ขั้นตอน (พร้อมรูปภาพ)
อะแดปเตอร์ Arduino Nano เป็น Arduino Uno: Arduino Nano เป็นสมาชิกที่ดี ขนาดเล็ก และราคาถูกของตระกูล Arduino มันขึ้นอยู่กับชิป Atmega328 สิ่งที่ทำให้มีประสิทธิภาพเท่ากับ Arduino Uno พี่ชายที่ใหญ่ที่สุดของเขา แต่สามารถรับเงินน้อยกว่า ในอีเบย์ตอนนี้เวอร์ชั่นภาษาจีนสามารถข
Bolt - DIY Wireless Charging Night Clock (6 ขั้นตอน): 6 ขั้นตอน (พร้อมรูปภาพ)
Bolt - DIY Wireless Charging Night Clock (6 ขั้นตอน): การชาร์จแบบเหนี่ยวนำ (เรียกอีกอย่างว่าการชาร์จแบบไร้สายหรือการชาร์จแบบไร้สาย) เป็นการถ่ายโอนพลังงานแบบไร้สาย ใช้การเหนี่ยวนำแม่เหล็กไฟฟ้าเพื่อจ่ายกระแสไฟฟ้าให้กับอุปกรณ์พกพา แอปพลิเคชั่นที่พบบ่อยที่สุดคือ Qi Wireless Charging st
Arduino ที่ถูกที่สุด -- Arduino ที่เล็กที่สุด -- Arduino Pro Mini -- การเขียนโปรแกรม -- Arduino Neno: 6 ขั้นตอน (พร้อมรูปภาพ)
Arduino ที่ถูกที่สุด || Arduino ที่เล็กที่สุด || Arduino Pro Mini || การเขียนโปรแกรม || Arduino Neno:…………………………… โปรดสมัครสมาชิกช่อง YouTube ของฉันสำหรับวิดีโอเพิ่มเติม……. โปรเจ็กต์นี้เกี่ยวกับวิธีเชื่อมต่อ Arduino ที่เล็กที่สุดและถูกที่สุดเท่าที่เคยมีมา Arduino ที่เล็กที่สุดและถูกที่สุดคือ arduino pro mini คล้ายกับ Arduino
4 ขั้นตอน Digital Sequencer: 19 ขั้นตอน (พร้อมรูปภาพ)
4 ขั้นตอน Digital Sequencer: CPE 133, Cal Poly San Luis Obispo ผู้สร้างโปรเจ็กต์: Jayson Johnston และ Bjorn Nelson ในอุตสาหกรรมเพลงในปัจจุบัน ซึ่งเป็นหนึ่งใน “instruments” เป็นเครื่องสังเคราะห์เสียงดิจิตอล ดนตรีทุกประเภท ตั้งแต่ฮิปฮอป ป๊อป และอีฟ
ป้ายโฆษณาแบบพกพาราคาถูกเพียง 10 ขั้นตอน!!: 13 ขั้นตอน (พร้อมรูปภาพ)
ป้ายโฆษณาแบบพกพาราคาถูกเพียง 10 ขั้นตอน!!: ทำป้ายโฆษณาแบบพกพาราคาถูกด้วยตัวเอง ด้วยป้ายนี้ คุณสามารถแสดงข้อความหรือโลโก้ของคุณได้ทุกที่ทั่วทั้งเมือง คำแนะนำนี้เป็นการตอบสนองต่อ/ปรับปรุง/เปลี่ยนแปลงของ: https://www.instructables.com/id/Low-Cost-Illuminated-