ความแม่นยำในการจับเวลาซีเควน MIDI โดยใช้ Arduino


11

ฉันสร้างเหล่านี้sequencers เพลง

ป้อนคำอธิบายรูปภาพที่นี่

มันไม่ใช่ซีเควนเท่านั้นมันเป็นส่วนต่อประสานทางกายภาพสำหรับซีเควน ซีเควนเซอร์เป็นแอปพลิเคชั่นที่ทำงานบนแล็ปท็อปที่ซีเควนเซอร์เชื่อมต่อด้วยสิ่งนี้ช่วยให้ผู้ใช้สร้างลูปกลองได้ทันที มันสนุกดี แต่มันต้องใช้แล็ปท็อปเพราะซีเควนเซอร์ไม่ใช่ 'บนบอร์ด'

สิ่งที่ฉันชอบก็คือการจัดลำดับอุปกรณ์ของฉัน

ทีนี้สมมติว่าฉันรู้วิธีแก้ปัญหาเรื่องความสอดคล้องของคลาสสำหรับการเชื่อมต่อ USB MIDI และสมมติว่าฉันสามารถหาวิธีวางสาย Arduino เพื่อส่งโน้ต MIDI จากพอร์ต DIN 5 พินได้ สิ่งที่ฉันกังวลมากที่สุดคือจังหวะล่องลอยไปตามกาลเวลาเนื่องจากเวลาไม่สอดคล้องกันในจำนวนนาทีในทุกรอบของการวนรอบเหตุการณ์

บางสิ่งที่ฉันรู้:

  1. คุณไม่ควรพึ่งพาdelay()การควบคุมจังหวะจังหวะ การหน่วงเวลาหยุดการทำงานของเฟิร์มแวร์ทั้งหมดและไม่สามารถทำงานได้เพราะฉันต้องสำรวจส่วนต่อประสานผู้ใช้ทางกายภาพเพื่อทำการเปลี่ยนแปลงในขณะที่ลำดับกำลังทำงาน

  2. การคำนวณตามmillis()ดีกว่าเนื่องจากเฟิร์มแวร์สามารถทำงานต่อไปและดำเนินการต่อไปเมื่อจำนวนที่แน่นอนได้ผ่านไปแล้ว

  3. แม้ว่าการควบคุมทางกายภาพของฉันจะไม่มีการเรียกใช้รูทีนการขัดจังหวะการดำเนินการบางอย่างสามารถชะลอการloop()ทำงานหลักได้ หากฉันออกแบบฟังก์ชั่นที่รอการป้อนข้อมูลจากผู้ใช้นั่นอาจทำให้เกิดปัญหาว่า "วันครบกำหนด" ที่ขาดหายไปเพื่อดำเนินการถ้าmillis()จำนวนนั้นเกิน ฉันรู้ว่าปัญหานี้เกิดจากการออกแบบของตัวเอง ...

คำถาม:

A. Arduino ที่ใช้ AVR เป็นไมโครคอนโทรลเลอร์ที่เหมาะสมในการหยั่งเสียงส่วนต่อประสานผู้ใช้และเรียกใช้ภารกิจวนรอบเวลาที่สำคัญหรือไม่? ฉันรู้ว่ามี ARM based Arduino ตอนนี้เร็วขึ้นมาก Teensy 3.0 จะเป็นทางเลือกที่ดีกว่าหรือไม่? ทั้งสองนี้เป็นบอร์ด 3.3V ดังนั้นนั่นเป็นอีกหนึ่งปัญหาที่จะทำงานร่วมกับ ... แต่ฉันจะไม่สนใจมันในตอนนี้

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

ค. อื่น ๆ อีก?

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


1
Arduino มักจะตั้งค่าอินเตอร์รัปต์บางอย่างทำให้เกิดความวุ่นวาย ในหลายกรณีนี่ไม่ใช่ปัญหา แต่เป็นการดีที่ต้องระวัง noInterrupts();หยุดกระวนกระวายใจ แต่ยังหยุดการขัดจังหวะที่ต้องการทั้งหมด
jippie

1
เมื่อคุณพูดว่า "do sequencing on-board" นั่นหมายถึงการตั้งค่าการเต้นต่อบาร์ BPM และการทำเครื่องหมายบนกระดานหรือไม่? ถ้าอย่างนั้นคุณต้องการที่จะจำปุ่มกดที่เกิดขึ้นภายในแถบเพื่อให้ "สมอง" ของอุปกรณ์สามารถป้อน midi-notes ไปยังแล็ปท็อปของคุณ? จากนั้นคุณต้องการลบเสียงกระทบบางอย่างหากคุณกดอีกครั้งผ่านโน้ตที่บันทึกไว้ก่อนหน้านี้หรือไม่ ฯลฯ .. คุณต้องการไปไกลแค่ไหน? การจัดเก็บจังหวะของคุณ? สร้างลำดับของแท่งที่สอดคล้องกับเพลงเต็มหรือไม่? กำลังแก้ไขบาร์เฉพาะ? การเปลี่ยนแปลง Tempo ของบาร์เฉพาะ? มันกินซีพียูทั้งหมดเพื่อให้ได้ CPU ที่ดีที่สุด
แอนดี้อาคา

ใช่ทุกอย่าง
Steve Cooley

2
นั่นเป็นเคสที่ดูดีที่คุณทำ!
shuckc

3
นอกจากสิ่งที่คนอื่นพูดแล้วนี่เป็นความคิดที่คุณตั้งใจจะผลิตและขาย Arduino มีราคา 20 ดอลลาร์ในขณะที่ AVR ราคา 2 ดอลลาร์ ไม่เพียง แต่คุณจะสามารถควบคุมฮาร์ดแวร์ที่แอพพลิเคชั่นของคุณต้องการ แต่คุณจะประหยัดเงินได้มาก
ฟิลฟรอสต์

คำตอบ:


5

การขัดจังหวะเป็นเพื่อนของคุณสำหรับงานที่มีความอ่อนไหวต่อเวลา แต่ถ้าคุณใส่ช่วงเวลาที่สำคัญลงในการขัดจังหวะและไม่มีการขัดจังหวะอื่น ๆ เกิดขึ้นที่มีลำดับความสำคัญสูงกว่า ไมโครคอนโทรลเลอร์ที่ "AVR-based" Arduino (เช่น ATmega328P) มีการแก้ไขลำดับความสำคัญของการขัดจังหวะตามรายละเอียดใน 58ff หน้าของแผ่นข้อมูล ดังนั้นหากคุณใช้ TIMER2 COMPA เป็นช่วงเวลาวิกฤติของคุณและไม่มีการขัดจังหวะอื่น ๆ คุณควรจะตกลง (เนื่องจากมีลำดับความสำคัญสูงสุด) หากคุณต้องการใช้การขัดจังหวะลำดับความสำคัญต่ำกว่าคุณต้องตรวจสอบให้แน่ใจว่าพวกเขาทั้งหมดเปิดใช้งานการขัดจังหวะทั่วโลกอีกครั้งเมื่อเข้าสู่รูทีนบริการขัดจังหวะของพวกเขา:

เมื่อการขัดจังหวะเกิดขึ้น Global Interrupt Enable I-bit จะถูกล้างและการขัดจังหวะทั้งหมดจะถูกปิดใช้งาน ซอฟต์แวร์ผู้ใช้สามารถเขียนตรรกะหนึ่งไปยัง I-bit เพื่อเปิดใช้งานอินเตอร์รัปต์ซ้อน การขัดจังหวะที่เปิดใช้งานทั้งหมดสามารถขัดจังหวะชุดคำสั่งการขัดจังหวะปัจจุบัน

(หน้า 14 ของแผ่นข้อมูล )

สิ่งนี้แตกต่างกันเล็กน้อยใน Arduinos ที่ใช้ ARM เนื่องจากแกน Cortex-M3 มี "Nested Vector Interrupt Controller" ซึ่งลำดับความสำคัญไม่คงที่ (สามารถตั้งค่าในซอฟต์แวร์) และการจัดการอินเตอร์รัปต์ซ้อนเป็นบรรทัดฐาน ดังนั้นสำหรับแอพพลิเคชั่นช่วงเวลาที่สำคัญ Arduino ที่ใช้ ARM จะให้ความยืดหยุ่นมากกว่า อย่างไรก็ตามฉันไม่คิดว่ามันจำเป็นสำหรับแอปพลิเคชันของคุณจริงๆ

คำถามที่ใหญ่กว่าคือความจริงที่ว่าสิ่งเหล่านี้สามารถนำไปใช้กับห้องสมุด Arduino ได้ง่ายเพียงใด เพื่อให้ได้ประสิทธิภาพที่ดีที่สุดคุณอาจต้องเขียนโค้ดนอกไลบรารีในระดับหนึ่งอย่างน้อยก็สำหรับบิตวิกฤติที่กำหนดเวลาเช่นหลีกเลี่ยงสิ่งต่าง ๆ เช่น delay () หรือ millis () ทั้งหมด

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


3

สิ่งนี้สามารถทำได้ด้วยการตั้งโปรแกรมที่เหมาะสมที่สุดแน่นอนใน ATmega328P (ขึ้นอยู่กับความซับซ้อนของกลองวน) ฉันสมมติว่า ~ <50 เหตุการณ์กลองในวงวนนั่นสมเหตุสมผลไหม)

หมายเหตุที่ผมกล่าวว่าATmega328Pไม่จำเป็นต้องเป็นArduino

สภาพแวดล้อม Arduino มีสิ่งต่าง ๆ เริ่มต้นมากมายที่เกิดขึ้นในพื้นหลังซึ่งทำให้การเขียนโปรแกรมกำหนดขึ้นอย่างมาก (เนื่องจากคุณต้องใช้สิ่งที่ท้าทายเวลา)

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

ในขณะที่ฉันค่อนข้างมั่นใจว่าเป็นไปได้ที่จะทำทุกสิ่งที่คุณต้องการใน ATmega เดียว (กลองลูปอินพุตแบบอะนาล็อกหลายจอ LCD ปุ่ม MIDI ส่วนต่อประสาน) คำถามที่แท้จริงคือมันจะบีบงานทุกอย่างมากแค่ไหน? อีกครั้งคุณต้องการเรียนรู้เพื่อเพิ่มประสิทธิภาพรหัสฝังตัว MCU หรือสร้างเครื่องมือ? มันค่อนข้างง่ายที่จะเพียงแค่ไปที่เร็ว MCU ถ้าจำเป็น แต่คุณจำเป็นต้องตรวจสอบประสิทธิภาพการทำงานของ MCU ที่คุณต้องการในขณะนี้ดังนั้นหกเดือนของการทำงานในคุณไม่ได้ตระหนักถึงคุณไม่สามารถค่อนข้างได้รับทุกอย่างในการทำงานเป็นอย่างที่คุณ ความต้องการ.


ถ้าฉันเป็นคุณสิ่งแรกที่ฉันจะทำคือทำให้มันทำงานได้โดยไม่ต้องใช้อาร์ดิโน (โดยทั่วไปถือว่าเป็น ATmega แบบดิบและใช้ AVR studio หรือที่คล้ายกัน) จากนั้นคุณสามารถวิเคราะห์ประสิทธิภาพที่คุณต้องการได้อย่างมีประสิทธิภาพมากขึ้นและหาก ATmega สามารถจัดการได้

เมื่อคุณเป็นอิสระจากสิ่งอาร์ดิโนคุณจะมีอิสระมากขึ้นที่จะใช้ MCU ที่แตกต่างกัน (โดยทั่วไปแล้วพวกมันจะคล้ายกันมากกว่านั้นและแตกต่างกันถ้าคุณสามารถหาได้จากเอกสารของมัน

เมื่อไม่นานมานี้ฉันได้ทำงานกับอุปกรณ์ ATxmega และพวกเขาก็ดีมาก คุณได้รับการจัดลำดับความสำคัญสามครั้งซึ่งทำให้การจัดการสิ่งที่สำคัญต่อเวลาง่ายขึ้น พวกเขายังดีมากที่ได้ทำงานร่วมกับ (การออกแบบอุปกรณ์ต่อพ่วง Sane! struct พอร์ตที่สะดวก! ฯลฯ )

นอกจากนี้ยังมีอุปกรณ์ LPC จาก NXP ซึ่งใช้ ARM เช่นเดียวกับอุปกรณ์ ARM ของ Atmel (ตามที่ใช้กับ Arduino Due) หรือ STM32 MCU จาก ST ใด ๆ เหล่านี้จะมีนัยสำคัญประสิทธิภาพมากขึ้นแล้ว ATMEGA หรือแม้กระทั่ง ATxmega

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


ใส่อย่างดี - สำหรับผลิตภัณฑ์เชิงพาณิชย์ Arduino ไม่ใช่วิธีที่จะไป - พวกเขากำลังหิวช้าและ IDE ไม่ได้ออกแบบมาสำหรับรหัส (เร็ว / เล็ก) ที่ดีที่สุดค่อนข้างสะดวกและเรียนรู้ได้ง่าย สำหรับค่าใช้จ่ายที่น้อยลงคุณยังสามารถใช้ STM32 F4 (Cortex M4> 100MHz) หรือคล้ายกันได้แม้ว่าจะเป็นค่าที่มากเกินไปก็ตาม ฉันคิดว่าบางอย่างเช่นหนึ่งใน PIC32 ขนาดเล็ก, Cortex M3s หรือ AVR32 น่าจะเป็นวิธีที่จะไปตามที่คุณพูดถึง ลำดับความสำคัญของอินเตอร์รัปต์จำนวนมาก, DMA, อุปกรณ์ต่อพ่วงที่ทันสมัย, พลังงานต่ำ / เร็วและ RAM มากมายทำให้เป็นตัวเลือกที่ง่ายเมื่อเทียบกับ Arduino
Oli Glaser

@OliGlaser - ฉันคิดว่าคุณต้องวิเคราะห์อย่างชัดเจนระหว่างArduinoและATMEGA คุณสามารถทำโค้ดขนาดเล็กและรวดเร็วบน ATmega และ ATmega นั้นสามารถอยู่บนบอร์ด Arduino ได้ Arduino "IDE" ในทางกลับกันเป็นหนึ่งในตัวแก้ไขโค้ดที่เล็กที่สุดที่ฉันเคยใช้ ในทางตรงกันข้าม bootloader OptiBoot นั้นดีมาก เพียงเพราะบางส่วนเป็นเรื่องไร้สาระไม่ได้หมายความว่าคุณควรทิ้งเรื่องทั้งหมดไป
Connor Wolf

อย่างแน่นอน - ฉันหมายถึง Arduino โดยรวมแล้วมีบอร์ดและ IDE - ไม่ใช่ ATmega ซึ่งฉันแน่ใจว่าดีพอ ๆ กับ uC อื่น ๆ (PIC16 / 18F ฯลฯ ) ฉันจะรวมไว้ในรายการของฉัน แต่ ฉันคิดว่าราคาระหว่าง 8 บิตและ 16/32 บิตอยู่ใกล้มากในปัจจุบันมันอาจเป็นความคิดที่ดีที่จะใช้จ่ายเพิ่ม $ 1 และรู้ว่าคุณมีพลังประมวลผลที่จะสำรองไว้ (เว้นแต่คุณจะพูดถึงเรากำลังพูดถึงจำนวนมาก) และสร้างขึ้นเพื่อราคาต่ำสุดที่แน่นอน แต่จากนั้นฉันสงสัยว่า Arduino จะได้รับการพิจารณา :-))
Oli Glaser

1

ฉันต้องอ่านตัวนับก่อนที่ฉันจะเริ่มคิดเกี่ยวกับความแม่นยำของเวลา (รวมถึงการสร้างซีเควนต์ขั้นตอน midi ด้วย arduino ถึงแม้ว่ามันจะรับประกันว่าดูเท่ห์กว่า ^^) บทความชุดนี้เป็นบทความที่ให้ข้อมูลมากที่สุด:

http://maxembedded.com/category/microcontrollers-2/atmel-avr/avr-timers-atmel-avr/

ตอนนี้ฉันคิดว่าวิธีแก้ปัญหาของฉันในการรับช่วงเวลาที่แม่นยำจะเป็น

A. ใช้ AVR arduino

B. เก็บงานไว้ในไมโครโปรเซสเซอร์เดียว

C. ใช้ตัวตั้งเวลาล่วงหน้าตัวจับเวลาและอินเทอร์รัปต์อย่างชาญฉลาดเพื่อให้ได้ความแม่นยำที่ต้องการ

UPDATE

ด้วยการใช้ midi tutorial พื้นฐานสำหรับ Arduino และหลังจากดูบทความนี้เกี่ยวกับตัวจับเวลาและพรีสเกลเลอร์แล้วรหัสต่อไปนี้คือสิ่งที่ฉันคิดขึ้นมา รหัสนี้ใช้โหมด timer1 และ CTC เพื่อเล่น midi note ทุกไตรมาสที่สองและ note off ทุกไตรมาสที่สอง (ซึ่งควรจะเท่ากับ 120 bpm) น่าเศร้าที่นี่ยังคงมาช้ากว่า 120bpm แม้ว่านี่จะใกล้เคียงที่สุดที่ฉันได้รับ ...

// Includes
#include <avr/io.h>
#include <avr/interrupt.h>

int last_action=0;

void setup()
{
    //  Set MIDI baud rate:
    Serial.begin(31250);

    // initialize Timer1
    cli();          // disable global interrupts
    TCCR1A = 0;     // set entire TCCR1A register to 0
    TCCR1B = 0;     // same for TCCR1B

    // set compare match register to desired timer count:
    OCR1A = 15624;
    // turn on CTC mode:
    TCCR1B |= (1 << WGM12);
    // Set CS12 bits for 256 prescaler:
    TCCR1B |= (1 << CS12);
    // enable timer compare interrupt:
    TIMSK1 |= (1 << OCIE1A);
    // enable global interrupts:
    sei();
}

void loop()
{
    // do some crazy stuff while my midi notes are playing
}

ISR(TIMER1_COMPA_vect)
{
  // Turn notes on
  if (last_action == 0) {
    send_note(0x90, 60, 0x45);
    last_action = 1;

  // Turn notes off
  } else {
    send_note(0x90, 60, 0x00);
    last_action = 0;
  }
}

//  plays a MIDI note
void send_note(int cmd, int pitch, int velocity) {
  Serial.write(cmd);
  Serial.write(pitch);
  Serial.write(velocity);
}

UPDATE

ฉันดิ้นรนกับสิ่งนี้มาประมาณ 24 ชั่วโมงแล้วและในที่สุดก็ได้รับคำตอบจากฟอรัม ฉันคิดว่ารหัสที่ฉันใช้ด้านบน ^^ นั้นค่อนข้างดี การใช้ ISR ใช้โหมด CTC และพรีเซลเลอร์เป็นต้นหลังจากเอื้อมไปที่ฟอรัมฉันคิดว่าวิธีการแก้ปัญหาเกี่ยวกับความแม่นยำของ midi sequencer น้อยลง แต่การตั้งค่าฮาร์ดแวร์ทั้งหมดของฉัน (ซินธิไซเซอร์และแซมเพลอร์) นาฬิกา midi ไม่ว่านาฬิกาจะมาจาก Arduino หรือไม่


0

ทั้งนี้ขึ้นอยู่กับว่าคุณต้องการเปลี่ยนจากคอมพิวเตอร์ที่ใช้อินเทอร์เน็ตเป็นระบบ graduallyC คุณสามารถลองวาง Raspberry Pi ลงในช่องนั้นได้ ( ขายปลีก $ 25-35 ) ด้วยวิธีนี้คุณสามารถมีคอมพิวเตอร์ที่ใช้ linux เต็มรูปแบบ (แม้ว่าจะใช้พลังงานต่ำ) พร้อมพอร์ต USB และพิน GPIO


ฉันแน่ใจว่ามีแผ่นป้องกันการขยายตัวหรืออะไรก็ตามที่พวกเขาเรียกพวกเขาว่าสำหรับ Pi แต่บอร์ดหุ้นมีพิน GPIO 17 อัน ฉันใช้พินทุกอันบนเมกะอาร์ดิโน 31 tacts + 30 LEDs, 10 analog analog. 70+ I / O
Steve Cooley

โอ้ฉันหมายความว่าหากเป้าหมายในทันทีคือการลบคอมพิวเตอร์ภายนอกคุณสามารถรักษา "ซีเควนเซอร์ [นั่น] เป็นแอปพลิเคชันที่ทำงานบนแล็ปท็อป" และรันบน Pi ที่เชื่อมต่อกับระบบที่มีอยู่ภายในของคุณ เชื่อมต่อทันที
Rob Starling

@SteveCooley - ฟังดูเหมือนคุณจะต้องมองเข้าไปในระบบมัลติเพล็กซิ่ง IO / ปุ่ม-matrix คุณไม่จำเป็นต้องใช้สาย IO ทั้งหมดโดยเฉพาะสำหรับแต่ละปุ่ม
Connor Wolf

@SteveCooley - เฮ้คุณไม่ต้องใช้ปุ่มเลยแม้แต่นิดเดียว คุณสามารถทำ IO ดิจิตอลทั้งหมดของคุณได้โดยใช้พินเพียง 4 rPi เพียงแค่แขวนปุ่มและ LED ทั้งหมดออกจากการลงทะเบียน shift (แบบขนานสำหรับปุ่ม, serial-ขนานสำหรับ LED) และขับการลงทะเบียน shift จากพอร์ต SPI ของ rPi คุณควรได้รับอัตราการอัปเดต> 1Khz สำหรับเมทริกซ์ทั้งหมดด้วยความช่วยเหลือของฮาร์ดแวร์ SPI
Connor Wolf

หากเหตุผลเดียวที่คุณใช้ Arduino Mega ก็คือ IO คุณจะใช้เงินจำนวนมากกับบางสิ่งที่สามารถทำได้อย่างง่ายดายด้วยอุปกรณ์ภายนอกไม่กี่ตัวสำหรับ <$ 3
Connor Wolf
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.