ฉันจะสร้างตัวจับเวลาขัดจังหวะด้วย Arduino ได้อย่างไร


9

ฉันพยายามสร้างการหน่วงเวลาขัดจังหวะด้วย Arduino ฉันต้องการใช้ฟังก์ชั่นการขัดจังหวะ () เพราะเป็นการขัดจังหวะภายใน

ตัวอย่าง: สมมุติว่าฉันต้องการเปิดและปิดไฟกะพริบโดยมีเพียงช่วงเวลาของการขัดจังหวะเท่านั้น

มีโค้ดตัวอย่าง แต่ใช้อินเตอร์รัปต์ภายนอก (attachInterrupt ()) ฉันต้องการใช้อินเทอร์รัปต์ภายในต่อไป


2
ผมคิดว่าจุดที่ยัง Kortuk แสดงให้เห็นว่า attachInterrupt เป็นสิ่งที่เป็นนามธรรมที่คุณไม่ได้แนบองค์ประกอบภายนอกใด ๆ :)
clabacchio

บทความนี้อาจช่วยคุณได้ engblaze.com/…
Seth Archer Brown

คำตอบ:


10

บล็อกของโนอาห์ Stahl มีตัวอย่างของการกระพริบไฟ LED กับ Timer2 ด้วยสิ่งนั้นและแผ่นข้อมูลคุณควรจะสามารถปรับให้เข้ากับสิ่งที่คุณต้องการใช้ขัดจังหวะ - นั่นคือการขัดจังหวะที่มีฟังก์ชั่นปกติที่คุณสามารถยอมแพ้หรือเต็มใจที่จะปรับเปลี่ยน โดยปกติแล้ว Timer2 จะใช้สำหรับฟังก์ชั่น PWM บางอย่าง

ตัวอย่างของเขาอ้างถึง ATmega2560; ฉันสามารถยืนยันได้ว่ามันทำงานได้กับ ATmega328p เช่นกัน ดูรอบ ๆ เว็บไซต์ของเขาเพื่อดูตัวอย่างการขัดจังหวะ Arduino ที่มีประโยชน์มากกว่า

แก้ไข:

นี่คือการแก้ไขเล็กน้อยของฉัน - ส่วนใหญ่อยู่ในความคิดเห็น - รหัสของโนอาห์ โทร Timer2init () จากฟังก์ชั่นการตั้งค่า Arduino () หลังจากที่คุณเริ่มต้นโครงสร้างข้อมูลหรือฮาร์ดแวร์ใด ๆ ที่เกี่ยวข้องเนื่องจากเวลา - และการขัดจังหวะ - จะเริ่มขึ้นเมื่อคุณทำ

F / ex ฉันใช้เพื่อมัลติเพล็กซ์จอแสดงผล 7 ส่วน 3 หลักดังนั้นฉันก่อนที่จะเริ่มการจับเวลาฉันเริ่มต้นการลงทะเบียน I / O ของจอแสดงผลและลบข้อมูลการแสดงผลในสถานที่ที่ ISR จะมองหา

มีตารางในความคิดเห็นของข้อมูลเวลาที่มีประโยชน์บางอย่างจากแผ่นข้อมูลและการคำนวณของฉันเองสำหรับการอ้างอิงเพื่อตั้งค่ารูปแบบเวลาอื่น

มาโคร ISR () ดูแลการสร้างรายการอินเตอร์รัปต์และโค้ดออกสำหรับ ISR แทนการเข้าและออกของฟังก์ชั่นปกติและเชื่อมโยงกับอินเทอร์รัปต์เวกเตอร์ที่เหมาะสม ส่วนที่เหลือของฟังก์ชั่นนั้นคือ 1) รหัสที่จะใช้ในการขัดจังหวะแต่ละครั้งและ 2) รหัสรหัสเพื่อรีเซ็ตตัวจับเวลาสำหรับการขัดจังหวะครั้งต่อไป

ตามที่เขียนไว้สิ่งนี้ควรอยู่ในไฟล์. pde หรือ. inino (หรือไฟล์. cpp หากคุณใช้ eclipse, f / ex) ร่างต้อง #define LEDPIN และการตั้งค่า () ต้องเรียก Timer2init () ฟังก์ชันลูปอาจว่างเปล่าหรือไม่ LED ควรเริ่มกระพริบเมื่อดาวน์โหลด (อย่างแท้จริงหลังจาก Timer2init () ถูกเรียก)

/*
 * From sample interrupt code published by Noah Stahl on his blog, at:
 * http://arduinomega.blogspot.com/p/arduino-code.html
 * 
 */


/*** FUNC

Name:           Timer2init

Function:       Init timer 2 to interrupt periodically. Call this from 
                the Arduino setup() function.

Description:    The pre-scaler and the timer count divide the timer-counter
                clock frequency to give a timer overflow interrupt rate:

                Interrupt rate =  16MHz / (prescaler * (255 - TCNT2))

        TCCR2B[b2:0]   Prescaler    Freq [KHz], Period [usec] after prescale
          0x0            (TC stopped)     0         0
          0x1                1        16000.        0.0625
          0x2                8         2000.        0.500
          0x3               32          500.        2.000
          0x4               64          250.        4.000
          0x5              128          125.        8.000
          0x6              256           62.5      16.000
          0x7             1024           15.625    64.000


Parameters: void

Returns:    void

FUNC ***/

void Timer2init() {

    // Setup Timer2 overflow to fire every 8ms (125Hz)
    //   period [sec] = (1 / f_clock [sec]) * prescale * (255-count)
    //                  (1/16000000)  * 1024 * (255-130) = .008 sec


    TCCR2B = 0x00;        // Disable Timer2 while we set it up

    TCNT2  = 130;         // Reset Timer Count  (255-130) = execute ev 125-th T/C clock
    TIFR2  = 0x00;        // Timer2 INT Flag Reg: Clear Timer Overflow Flag
    TIMSK2 = 0x01;        // Timer2 INT Reg: Timer2 Overflow Interrupt Enable
    TCCR2A = 0x00;        // Timer2 Control Reg A: Wave Gen Mode normal
    TCCR2B = 0x07;        // Timer2 Control Reg B: Timer Prescaler set to 1024
}



/*** FUNC

Name:       Timer2 ISR

Function:   Handles the Timer2-overflow interrupt

Description:    Maintains the 7-segment display

Parameters: void

Returns:    void

FUNC ***/

ISR(TIMER2_OVF_vect) {
    static unsigned int led_state = 0; // LED state

    led_state = !led_state;         // toggles the LED state
    digitalWrite(TOGGLE_PIN, led_state);

    TCNT2 = 130;     // reset timer ct to 130 out of 255
    TIFR2 = 0x00;    // timer2 int flag reg: clear timer overflow flag
};

(@Kortuk: ความคิดเห็นที่คุณอ้างถึงคือการสังเกตผู้วิจารณ์หลายคนที่นี่และไม่ได้มุ่งเป้าไปที่คุณเป็นการส่วนตัวและมันก็ไม่จำเป็นฉันขอโทษและฉันก็ลบมันออกไป) ฉันขยายคำตอบตามที่คุณแนะนำและหวังว่า ตอนนี้ไม่เพียงสาธิต แต่ให้คำแนะนำเช่นกัน มันรวมถึงความคิดเห็นที่ฉันเขียนลงในรหัสสำหรับการใช้งานของฉันเอง (ความหมาย: ถ้าฉันสามารถเข้าใจพวกเขาได้ 6 เดือนนับจากนี้คนอื่นจะสามารถทำได้เช่นกัน) รวมถึงคำแนะนำ "วิธีใช้" ใน ตอบ. ขอบคุณสำหรับคำแนะนำของคุณ
JRobert

โปรดทราบว่า prescales ที่ 32 และ 128 ไม่สามารถใช้งานได้สำหรับ timer0 และ timer1 (atleast with atmega328)
tuupola

เป็นเรื่องดีที่รู้ - ขอบคุณ ฉันใช้สิ่งนี้กับ Timer2 (จนถึงตอนนี้) และมันเป็นแบบดรอปอิน
JRobert

5

attachInterrupt ()ฟังก์ชั่นจริงจะแนบไปขัดจังหวะการเปลี่ยนแปลงของรัฐภายนอกในขาก็ไม่ได้มีตัวเลือกอื่น ๆ

ในหน้าเดียวกันตัวเลือกโหมดจะแสดงรายการเป็น:

โหมดจะกำหนดเมื่อการขัดจังหวะควรจะถูกเรียก ค่าคงที่สี่ถูกกำหนดไว้ล่วงหน้าเป็นค่าที่ถูกต้อง:

  • ต่ำเพื่อกระตุ้นการขัดจังหวะเมื่อใดก็ตามที่พินอยู่ในระดับต่ำ
  • เปลี่ยนเพื่อเรียกการขัดจังหวะเมื่อใดก็ตามที่พินเปลี่ยนค่า
  • เพิ่มขึ้นเพื่อกระตุ้นเมื่อพินไปจากต่ำไปสูง
  • ตกหล่นเมื่อหมุดเคลื่อนที่จากสูงไปต่ำ

ขออภัยที่เป็นผู้ถือข่าวร้ายนั่นคือสิ่งแรกที่ฉันมองหา


ฉันคิดว่าเขาหมายถึงว่าเขาต้องการใช้ตัวจับเวลาภายในแทนที่จะเป็นอุปกรณ์ภายนอก ... แต่ฉันไม่รู้จัก Arduino อย่างดีดังนั้นฉันจึงไม่สามารถพูดได้ว่าเป็นไปได้
clabacchio

@clacacchio ฉันกำลังบอกว่าตัวเลือกเดียวคือการใช้ทริกเกอร์ภายนอกไม่มีฟังก์ชั่นจับเวลาภายใน
Kortuk

อืมดี :) แต่อย่างน้อยบอร์ด Arduino มีตัวจับเวลาหรือไม่?
clabacchio

ใช่นั่นคือวิธีที่พวกเขาบรรลุสิ่งต่าง ๆ เช่นความล่าช้า
Kortuk

1
@ icarus74 ATMega328 มีตัวจับเวลา 3 ตัว (หนึ่งตัวคือ 16b และสองตัวคือ 8b) แต่ทั้งหมดนั้นใช้โดย Arduino หนึ่งใช้สำหรับฟังก์ชั่นเช่น delay () และ millis () และทั้งสามถูกใช้สำหรับ PWM (คุณสามารถค้นหาข้อมูลเพิ่มเติมในฟังก์ชั่น 'init ()', ไฟล์ 'wiring.c' ใน Arduino IDE)
vasco

2

นี้บทความเกี่ยวกับ PWMจะชัดเจนมากของข้อสงสัยของคุณเกี่ยวกับการใช้งานของตัวนับ Arduino มีตัวจับเวลา 8 บิตสองตัวและตัวจับเวลา 16 บิตหนึ่งตัวบน Arduino ไม่มี API ระดับสูงในการขอฟังก์ชั่น ISR โดยตรงไปยังตัวนับที่มาพร้อมกับ Arduino SDK (เช่นเป็นห้องสมุดมาตรฐาน) แต่วิธีการที่ค่อนข้างต่ำกว่าระดับของการตั้งค่าฟังก์ชั่นพิเศษลงทะเบียนและบิตเลขคณิต / การดำเนินงานกับพวกเขา อย่างไรก็ตามมีผู้ใช้ห้องสมุดมีส่วนที่เรียกว่าตั้งเวลาหนึ่ง


ในความเป็นจริงมีการรวมตัวจับเวลาที่แตกต่างกันหลายอย่างขึ้นอยู่กับว่า Arduino นั้นถูกอ้างอิง คำตอบคือทำให้เข้าใจผิด
ดูเหมือนว่าดังนั้น

@SiminglySo ดังนั้นจะทำอย่างละเอียด? หากคุณกำลังพูดถึงฮาร์ดแวร์ Arduino โปรดทราบว่าคำตอบนั้นอยู่ในบริบทของคำถามและเวลาที่ถามคำถามด้วย
icarus74

Arduino Mega (อิง ATmega1280 based) เปิดตัวเมื่อวันที่ 26 มีนาคม 2552 และ Mega 2560 (ATmega2560) เปิดตัวเมื่อวันที่ 24 กันยายน 2553 ทั้งคู่ก่อนที่คำถามนี้จะถูกถาม ไมโครคอนโทรลเลอร์ทั้งสองนั้นมีตัวจับเวลา / ตัวนับมากกว่า 2x8 บิตและ 1x16 บิตที่ระบุไว้ในคำตอบ
ดูเหมือนว่าดังนั้น

การโต้ตอบส่วนใหญ่ที่ฉันเคยเห็นมามีการอ้างอิงที่ไม่คลุมเครือกับ Arduino เพื่อหมายถึงชอบของ Duemilanove หรือ Uno เช่นบอร์ดที่ใช้ชุด 328 บอร์ดอื่น ๆ ได้รับการรับรองอย่างชัดเจนโดยหมายเลข uP เสมอ หรือ Mega, Nano, Micro ฯลฯ อย่างไรก็ตามฉันจะยอมรับการแก้ไขอย่างถ่อมใจ ในบริบทนี้การชี้แจงจะดีกว่า
icarus74

1

Arduino ใช้ตัวจับเวลาทั้งสามใน ATMega328 Timer1(16 บิต) ใช้สำหรับฟังก์ชั่นเช่นdelay()และmillis()และสำหรับเอาต์พุต PWM บนพิน 5 และ 6 ตัวจับเวลาอีกสองตัว - Timer0และTimer2ใช้สำหรับเอาต์พุต PWM บนหมุด 3, 9, 10, 11

ดังนั้นจึงไม่มีฟังก์ชั่น Arduino สำหรับการจับเวลาขัดจังหวะ แต่มีวิธีหนึ่งคือ คุณสามารถใช้รหัสนี้เพื่อเปิดใช้งานการขัดจังหวะตัวจับเวลาTimer2:

ISR(TIMER2_OVF_vect) {
  // Interrupt routine.
}

void setup() {
  // Enable Timer2 interrupt.
  TIMSK2 = (0<<OCIE2A) | (1<<TOIE2);
}

void loop() {
  // Your main loop.
}

ฉันเขียนโค้ดนี้โดยไม่มีการทดสอบดังนั้นจึงเป็นไปได้ว่าฉันทำผิดพลาด ในกรณีที่ตรวจสอบแผ่นข้อมูล, p.156

หากคุณต้องการเปลี่ยนความถี่จับเวลา (prescaler) TCCR2Aเพียงแค่การเปลี่ยนแปลงการลงทะเบียน สําหรับข้อมูลเพิ่มเติมดูในแผ่นข้อมูลหน้า 153 แต่ถ้าคุณเปลี่ยนความถี่ของตัวจับเวลาคุณจะเปลี่ยนความถี่ของสัญญาณ PWM บนเอาต์พุตพินสองตัว!


AFAIK บน ATmega328 Timer0และTimer2เป็น 8 บิตและเพียงTimer116 บิต
tuupola

ไม่ไม่ถูกต้อง มันคือ Timer0 ไม่ใช่ Timer1 ที่ใช้สำหรับ delay () และ millis () และสำหรับเอาต์พุต PWM บนพิน 5 และ 6 Timer0 เป็นตัวจับเวลา 8 บิต ดูเช่นArduino ตัวจับเวลาและอินเตอร์รัปต์
Peter Mortensen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.