ค้นหาโค้ด

บทเรียน 17/31: วิธีขัดจังหวะการหน่วงเวลาใน Arduino และตัวต้านทานที่ไวต่อแสง LDR | Robojax

บทเรียนนี้เป็นส่วนหนึ่งของ: หลักสูตร Arduino ที่ใช้ชุดการเรียนรู้ 3-in-1 ของ SunFounder

บทเรียน 17/31: วิธีขัดจังหวะการหน่วงเวลาใน Arduino และตัวต้านทานที่ไวต่อแสง LDR | Robojax

ในคู่มือนี้ เราจะสำรวจแนวคิดสำคัญสองประการของ Arduino ได้แก่ อินเทอร์รัปต์และตัวต้านทานที่ไวต่อแสง (LDR) คุณจะได้เรียนรู้วิธีขัดจังหวะดีเลย์ในโค้ดของคุณ เพื่อให้ Arduino ตอบสนองต่อการกดปุ่มได้ทันที จากนั้นเราจะสร้างวงจรตรวจจับแสงที่สามารถเปิดออดหรือไฟโดยอัตโนมัติในเวลากลางคืน โปรเจกต์นี้เหมาะสำหรับผู้ที่ต้องการก้าวข้ามการเขียนโค้ดกระพริบ LED พื้นฐาน และเริ่มสร้างโปรเจกต์อัตโนมัติที่ตอบสนองต่อโลกจริง คุณสามารถนำทักษะเหล่านี้ไปประยุกต์ใช้เพื่อสร้างไฟกลางคืนอัจฉริยะสำหรับโถงทางเดิน สัญญาณเตือนความปลอดภัยง่ายๆ ที่ดังเมื่อประตูเปิด ไฟสวนพลังงานแสงอาทิตย์ที่เปิดเมื่อพลบค่ำ หรือม่านอัตโนมัติที่ปิดเมื่อพระอาทิตย์ตกดิน บทเรียนนี้อ้างอิงจากชุด Arduino 3-in-1 ของ SunFounder แต่แนวคิดนี้ใช้ได้กับบอร์ด Arduino มาตรฐานทุกตัว

LDR_12708_orig
LDR Illustration and symbol

ฮาร์ดแวร์และอุปกรณ์

เพื่อทำตามโปรเจกต์นี้ คุณจะต้องมีอุปกรณ์ดังต่อไปนี้ Arduino Uno หรือ Nano มาตรฐานเหมาะสำหรับการสร้างนี้

  • Arduino Uno หรือ Nano
  • ตัวต้านทานที่ไวต่อแสง (LDR) เช่น Kweeds KM601
  • ตัวต้านทาน 10k โอห์ม
  • ปุ่มกด
  • ออด
  • เบรดบอร์ดและสายจัมเปอร์

ทำความเข้าใจอินเทอร์รัปต์ของ Arduino

ในสเก็ตช์ Arduino มาตรฐาน ฟังก์ชัน loop() จะทำงานอย่างต่อเนื่อง โดยดำเนินการทีละบรรทัด เมื่อคุณใช้ delay() Arduino จะหยุดทำอย่างอื่นทั้งหมดในช่วงเวลานั้น นี่เป็นปัญหาหากคุณต้องตอบสนองต่อเหตุการณ์สำคัญ เช่น การกดปุ่ม ขณะที่งานอื่นกำลังทำงานอยู่ ตัวอย่างเช่น หากคุณมีดีเลย์หนึ่งวินาทีเพื่อกระพริบ LED การกดปุ่มอาจไม่ถูกรับรู้นานถึงหนึ่งวินาที ซึ่งรู้สึกว่าตอบสนองช้า (ในวิดีโอที่ 08:13)

อินเทอร์รัปต์ของ Arduino แก้ปัญหานี้ได้ อินเทอร์รัปต์เป็นคุณสมบัติฮาร์ดแวร์ที่อนุญาตให้พินเฉพาะ "ขัดจังหวะ" โปรแกรมหลัก หยุดสิ่งที่กำลังทำอยู่ชั่วคราว และรันฟังก์ชันพิเศษที่เรียกว่า Interrupt Service Routine (ISR) ซึ่งช่วยให้ Arduino ตอบสนองต่อเหตุการณ์ที่มีความสำคัญสูงได้ทันที ไม่ว่าสิ่งอื่นจะเกิดขึ้นอะไรก็ตาม สิ่งสำคัญคือต้องทราบว่าไม่ใช่ทุกพินที่รองรับอินเทอร์รัปต์ บน Arduino Uno และ Nano มีเพียงพิน 2 และ 3 เท่านั้นที่ใช้เพื่อจุดประสงค์นี้ได้ (ในวิดีโอที่ 02:37) บอร์ดอื่นๆ เช่น Mega มีตัวเลือกมากกว่า แต่สำหรับโปรเจกต์นี้ เราจะใช้พิน 2

อินเทอร์รัปต์สามารถถูกกระตุ้นได้จากการเปลี่ยนแปลงสถานะต่างๆ บนพิน: LOW, CHANGE, RISING และ FALLING โหมด CHANGE จะกระตุ้นอินเทอร์รัปต์เมื่อใดก็ตามที่สถานะของพินเปลี่ยนจาก HIGH เป็น LOW หรือ LOW เป็น HIGH ซึ่งเหมาะสำหรับการสลับด้วยปุ่มกด

คู่มือการเดินสายไฟ

buzzer_push_button_schematic
lcd1602_I2C_wiring_sunfounder

เราจะสร้างวงจรสองวงจรในบทเรียนนี้ วงจรแรกสาธิตอินเทอร์รัปต์ด้วยปุ่มกดและออด และวงจรที่สองใช้ LDR เพื่อตรวจจับระดับแสง เริ่มต้นด้วยวงจรอินเทอร์รัปต์กันก่อน

วงจรที่ 1: ปุ่มกดและออดสำหรับสาธิตอินเทอร์รัปต์

วงจรนี้ตรงไปตรงมา ปุ่มกดเชื่อมต่อกับพิน 2 ซึ่งเป็นพินอินเทอร์รัปต์ของเรา ตัวต้านทาน 10k โอห์มแบบ pull-down ช่วยให้พินอ่านค่า LOW เมื่อไม่ได้กดปุ่ม และ HIGH เมื่อกดปุ่ม ออดเชื่อมต่อกับพิน 8

สำหรับการสาธิตอินเทอร์รัปต์ ให้เชื่อมต่ออุปกรณ์ดังนี้:

  • ปุ่มกด: เชื่อมต่อขาหนึ่งเข้ากับ 5V และอีกขาเข้ากับดิจิทัลพิน 2 เชื่อมต่อตัวต้านทาน 10k โอห์มจากพิน 2 ไปยัง GND
  • ออด: เชื่อมต่อขาลบเข้ากับ GND และขาบวกเข้ากับดิจิทัลพิน 8

วงจรที่ 2: LDR และออดสำหรับการตรวจจับแสง

สำหรับวงจร LDR เราใช้การจัดเรียงแบบตัวแบ่งแรงดันไฟฟ้า ความต้านทานของ LDR เปลี่ยนแปลงตามแสง ซึ่งจะเปลี่ยนแรงดันไฟฟ้าที่พินแอนะล็อก เมื่อมืด LDR จะมีความต้านทานสูง (ประมาณ 10k โอห์ม) และเมื่อสว่าง ความต้านทานจะลดลงอย่างมาก (ในวิดีโอที่ 16:25) การเปลี่ยนแปลงความต้านทานนี้คือสิ่งที่เราวัด

ตัวแบ่งแรงดันไฟฟ้าจำเป็นเพราะ Arduino อ่านได้เฉพาะแรงดันไฟฟ้า ไม่ใช่ความต้านทาน โดยการวาง LDR อนุกรมกับตัวต้านทานคงที่ 10k โอห์ม แรงดันไฟฟ้าที่จุดระหว่างทั้งสองจะเปลี่ยนแปลงตามสัดส่วนกับความต้านทานของ LDR แรงดันไฟฟ้านี้จะถูกอ่านโดยตัวแปลงแอนะล็อกเป็นดิจิทัล (ADC) ของ Arduino

สำหรับการสาธิต LDR ให้เชื่อมต่ออุปกรณ์ดังนี้:

  • LDR: เชื่อมต่อขาหนึ่งเข้ากับ 5V และอีกขาเข้ากับแอนะล็อกพิน A0
  • ตัวต้านทาน 10k โอห์ม: เชื่อมต่อจากขา LDR ที่ไปยัง A0 ลงไปยัง GND เพื่อสร้างตัวแบ่งแรงดันไฟฟ้า
  • ออด: เชื่อมต่อขาลบเข้ากับ GND และขาบวกเข้ากับดิจิทัลพิน 8

หมายเหตุ: การกำหนดพินที่แน่นอนถูกกำหนดไว้ในโค้ดและสามารถเปลี่ยนแปลงได้ตามการตั้งค่าของคุณ

คำอธิบายโค้ด

เราจะเน้นที่ส่วนที่ผู้ใช้สามารถกำหนดค่าได้ของโค้ดที่ให้มา ซึ่งควบคุมพฤติกรรมของโปรเจกต์ โปรแกรมเต็มรูปแบบสามารถดาวน์โหลดได้ด้านล่างบทความ

โค้ดถูกออกแบบมาให้แก้ไขได้ง่าย ที่ด้านบนของสเก็ตช์ คุณจะพบตัวแปรสำคัญที่คุณสามารถปรับได้

const byte buzzerPin = 8;
const byte interruptPin = 2;
volatile byte state = LOW;
int count=0;

ที่นี่ buzzerPin ถูกตั้งค่าเป็นพิน 8 ซึ่งเป็นจุดที่คุณเชื่อมต่อออด interruptPin ถูกตั้งค่าเป็นพิน 2 ซึ่งเป็นพินที่จะคอยฟังการกดปุ่ม ตัวแปร state เป็นไบต์แบบ volatile ที่เก็บสถานะปัจจุบันของออด (HIGH หรือ LOW) มันถูกทำเครื่องหมายเป็น volatile เพราะมันถูกแก้ไขภายในรูทีนบริการอินเทอร์รัปต์ (ISR) และคีย์เวิร์ดนี้ช่วยให้แน่ใจว่า Arduino อ่านค่าล่าสุดเสมอ ตัวแปร count เป็นตัวนับง่ายๆ ที่เพิ่มขึ้นในลูปหลักเพื่อแสดงว่าลูปยังคงทำงานอยู่ขณะที่อินเทอร์รัปต์ทำงาน

ในฟังก์ชัน setup() พินของออดถูกตั้งเป็น OUTPUT และพินอินเทอร์รัปต์ถูกตั้งเป็น INPUT บรรทัดที่สำคัญคือ attachInterrupt() ซึ่งเป็นจุดที่คุณกำหนดค่าอินเทอร์รัปต์ ฟังก์ชันนี้บอก Arduino ว่าต้องเฝ้าดูพินใด เรียกฟังก์ชันใดเมื่อเกิดอินเทอร์รัปต์ และใช้เงื่อนไขการทริกเกอร์แบบใด

attachInterrupt(digitalPinToInterrupt(interruptPin), noisy, CHANGE);

บรรทัดนี้แนบอินเทอร์รัปต์เข้ากับพินที่ระบุ ฟังก์ชัน digitalPinToInterrupt() แปลงหมายเลขพินเป็นหมายเลขอินเทอร์รัปต์ที่ถูกต้อง noisy คือชื่อของฟังก์ชันที่จะถูกเรียกเมื่ออินเทอร์รัปต์ถูกทริกเกอร์ สุดท้าย CHANGE คือโหมด ซึ่งทริกเกอร์อินเทอร์รัปต์เมื่อมีการเปลี่ยนแปลงสถานะใดๆ ของพิน คุณสามารถเปลี่ยนเป็น RISING, FALLING หรือ LOW ได้ตามความต้องการของคุณ

ฟังก์ชัน noisy() คือ ISR มันเป็นฟังก์ชันสลับสถานะง่ายๆ ที่พลิกสถานะของออด เมื่อกดปุ่ม อินเทอร์รัปต์จะทริกเกอร์ฟังก์ชันนี้ ซึ่งจะกลับค่าตัวแปร state และเขียนมันไปยังพินของออด ซึ่งช่วยให้คุณเปิดและปิดออดได้ด้วยการกดปุ่มแต่ละครั้ง แม้ว่าลูปหลักจะยุ่งอยู่กับการนับและหน่วงเวลา

เพื่อเปลี่ยนพฤติกรรมของโปรเจกต์ให้เปิดออดในเวลากลางคืนแทนกลางวัน คุณจะต้องแก้ไขตรรกะเงื่อนไขในลูปหลัก โดยสลับคำสั่ง digitalWrite() สำหรับสถานะ HIGH และ LOW

โปรเจกต์สดและการสาธิต

ในการสาธิต คุณจะเห็นการทดลองสำคัญสองอย่าง อันดับแรก วงจรอินเทอร์รัปต์ถูกแสดงโดยไม่ใช้โค้ดอินเทอร์รัปต์ ซึ่งการหน่วงเวลาในลูปทำให้การตอบสนองของปุ่มช้า สิ่งนี้เน้นปัญหาที่อินเทอร์รัปต์แก้ไข

จากนั้น เมื่อโหลดโค้ดอินเทอร์รัปต์แล้ว จอภาพอนุกรมแสดงตัวนับที่เพิ่มขึ้นทุกวินาที เมื่อกดปุ่ม ออดจะสลับเปิดหรือปิดทันที โดยไม่คำนึงถึงการหน่วงเวลาในลูปหลัก สิ่งนี้พิสูจน์ว่าอินเทอร์รัปต์สามารถเลี่ยงเวลารอและทำงานทันที (ในวิดีโอที่ 14:07)

สำหรับส่วน LDR จอภาพอนุกรมพิมพ์ค่าแอนะล็อกดิบ คุณจะเห็นว่าค่ามีค่าสูง (ประมาณ 960) ในแสงสว่าง และลดลงอย่างมาก (ถึงประมาณ 400 หรือต่ำกว่า) เมื่อเซนเซอร์ถูกบัง สิ่งนี้แสดงให้เห็นว่าความต้านทานของ LDR เปลี่ยนแปลงตามความเข้มของแสงอย่างไร จากนั้นโค้ดใช้ค่าเกณฑ์เพื่อกำหนดว่าเป็น "กลางวัน" หรือ "กลางคืน" และควบคุมออดตามนั้น โดยการบังเซนเซอร์เพื่อจำลองกลางคืน คุณสามารถทริกเกอร์ออด และโดยการให้แสงส่อง คุณสามารถปิดมันได้

บทต่างๆ

  • [00:00] แนะนำอินเทอร์รัปต์ Arduino และ LDR
  • [01:43] ปัญหาของการหน่วงเวลาในโค้ด Arduino
  • [03:37] ทำความเข้าใจพินและโหมดอินเทอร์รัปต์
  • [04:20] การเดินสายวงจรปุ่มและออด
  • [06:22] คำอธิบายโค้ดสำหรับการสาธิตการหน่วงเวลา
  • [07:48] การสาธิตปัญหาการหน่วงเวลา
  • [09:26] การติดตั้งและเขียนโค้ดอินเทอร์รัปต์
  • [11:50] วิธีการทำงานของฟังก์ชันอินเทอร์รัปต์
  • [14:26] แนะนำตัวต้านทานไวแสง (LDR)
  • [15:44] การวัดความต้านทาน LDR ด้วยมัลติมิเตอร์
  • [17:22] การเดินสายวงจร LDR และออด
  • [19:55] โค้ดสำหรับอ่านค่า LDR
  • [20:49] การสาธิตการเปลี่ยนแปลงค่า LDR
  • [22:08] การตั้งค่าเกณฑ์กลางวันและกลางคืน
  • [23:40] โค้ดควบคุมออดด้วย LDR
  • [25:21] การสาธิตไฟกลางคืนอัตโนมัติ

ภาพ

An LDR
An LDR
LDR Illustration and symbol
LDR Illustration and symbol
lcd1602_I2C_wiring_sunfounder
lcd1602_I2C_wiring_sunfounder
buzzer_push_button_schematic
buzzer_push_button_schematic
buzzer_push_button_wiring
buzzer_push_button_wiring
ldr
ldr
LDR_12708_orig
LDR_12708_orig
913-Lesson 17/31: interrupt a delay in Arduino and Light Dependent Resistor LDR
ภาษา: C++
/*
Lesson 20/31: interrupt a delay in Arduino and Light Dependent Resistor LDR
Get this code and watch video Download and resource page https://robojax.com/RJT600
YouTube video https://www.youtube.com/watch?v=N_L11m1v_yk
 
  
 * This code is "AS IS" without warranty or liability. Free to be used as long as you keep this note intact.* 
 * This code has been download from Robojax.com
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
const byte buzzerPin = 8;
const byte interruptPin = 2;
volatile byte state = LOW;
int count=0;

void setup() {
  pinMode(buzzerPin, OUTPUT);
  pinMode(interruptPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(interruptPin), noisy, CHANGE);
  Serial.begin(9600);
  digitalWrite(buzzerPin, state);
}

void loop() {
  count++;
  Serial.println(count);
  delay(1000);
}

void noisy() {
  state = !state;
  digitalWrite(buzzerPin, state);
}

สิ่งที่คุณอาจต้องการ

แหล่งข้อมูลและเอกสารอ้างอิง

ไฟล์📁

ไลบรารี Arduino (zip)