Độ chính xác thời gian tuần tự MIDI sử dụng Arduino


11

Tôi xây dựng các phần tiếp theo âm nhạc .

nhập mô tả hình ảnh ở đây

Chỉ có điều nó không chính xác là trình sắp xếp chuỗi, đó là giao diện vật lý cho trình phân tích. Trình sắp xếp thứ tự là một ứng dụng chạy trên máy tính xách tay mà trình sắp xếp kết nối với, điều này cho phép người dùng tạo các vòng lặp trống khi đang di chuyển. Điều này khá thú vị, nhưng nó đòi hỏi một máy tính xách tay vì trình sắp xếp không phải là 'trên tàu'.

Những gì tôi thích là thực hiện tuần tự trên thiết bị của tôi.

Bây giờ hãy giả sử tôi biết cách giải quyết tuân thủ lớp cho kết nối USB MIDI và cũng giả sử tôi có thể tìm ra cách nối dây arduino để gửi ghi chú MIDI từ cổng DIN 5 chân. Điều tôi quan tâm nhất là nhịp độ trôi theo thời gian do thời gian không nhất quán tính theo số phút trong mỗi lần chạy vòng lặp sự kiện.

Một số điều tôi biết:

  1. Bạn không nên dựa vào delay()để kiểm soát vòng lặp nhịp độ. Trì hoãn dừng tất cả hoạt động của phần sụn và điều đó không thể hoạt động vì tôi cần thăm dò giao diện người dùng vật lý để thay đổi trong khi trình tự đang chạy.

  2. Tính toán dựa trên millis()là tốt hơn bởi vì phần sụn có thể tiếp tục hoạt động và hành động khi một số lượng nhất định đã trôi qua.

  3. Mặc dù không có điều khiển vật lý nào của tôi kích hoạt các thói quen gián đoạn, một số thao tác có thể trì hoãn hoạt động chính loop(). Nếu tôi thiết kế một chức năng chờ đầu vào của người dùng, điều đó rõ ràng có thể gây ra vấn đề thiếu "thời hạn" để hành động nếu millis()số lượng đã hết. Tôi biết vấn đề này là do thiết kế của riêng tôi ...

Câu hỏi:

A. Có phải arduino dựa trên AVR là một vi điều khiển thích hợp để thăm dò giao diện người dùng và chạy một vòng lặp thời gian quan trọng không? Tôi biết có một Arduino dựa trên ARM bây giờ nhanh hơn rất nhiều. Một Teensy 3.0 sẽ là một sự thay thế tốt hơn? Cả hai đều là bo mạch 3.3V, vì vậy đó là một loạt vấn đề khác cần giải quyết ... nhưng bây giờ tôi sẽ bỏ qua vấn đề đó.

B. Tôi có nên chia nhiệm vụ thành hai bộ vi xử lý? Một để xử lý bỏ phiếu và cập nhật giao diện người dùng và một cho nhiệm vụ vòng lặp thời gian quan trọng.

c. Thứ gì khác?

Mục tiêu chính của tôi là không phải sử dụng máy tính. Tôi cũng muốn tính toán cho swing, nhưng trong trường hợp này, swing không có nghĩa là nếu tôi không có nhịp độ chính xác bị khóa và thời gian. Cảm ơn lời khuyên của bạn!


1
Arduino luôn thiết lập một số thói quen ngắt, gây ra jitter. Trong nhiều trường hợp đây không phải là một vấn đề, nhưng thật tốt khi nhận thức được nó. noInterrupts();dừng jitter, nhưng cũng dừng tất cả các ngắt mong muốn.
jippie

1
Khi bạn nói "thực hiện tuần tự trên tàu", điều đó có nghĩa là thiết lập các nhịp trên mỗi thanh, BPM và một dấu vết trên tàu? Sau đó, có lẽ bạn muốn nhớ các lần nhấn nút xảy ra trong thanh để "bộ não" của thiết bị có thể cung cấp ghi chú midi cho máy tính xách tay của bạn? Sau đó, bạn có muốn loại bỏ một số âm thanh bộ gõ nhất định nếu bạn nhấn chúng một lần nữa qua ghi chú đã được ghi lại trước đó không? V.v .. bạn muốn đi bao xa? Lưu trữ nhịp đập của bạn? Tạo một chuỗi các thanh tương ứng với một bản nhạc đầy đủ? Chỉnh sửa thanh cụ thể? Thay đổi nhịp độ của các thanh cụ thể? Tất cả đều ăn CPU vì vậy hãy tìm CPU tốt nhất.
Andy aka

Đúng, tất cả của nó.
Steve Cooley

2
Đó là một trường hợp ngọt ngào bạn đã thực hiện!
shuckc

3
Ngoài những gì người khác đã nói, điều này trông giống như một suy nghĩ rằng có thể bạn có ý định sản xuất và bán. Một Arduino có giá 20 đô la, trong khi một chiếc AVR có giá 2 đô la. Bạn không chỉ giành được quyền kiểm soát phần cứng mà ứng dụng của bạn yêu cầu, mà bạn sẽ tiết kiệm được rất nhiều tiền.
Phil Frost

Câu trả lời:


5

Ngắt là bạn của bạn để xác định thời gian cho các nhiệm vụ nhạy cảm, nhưng chỉ khi bạn đặt các khía cạnh quan trọng về thời gian vào ngắt, và không có ngắt nào khác xảy ra có mức độ ưu tiên cao hơn. Các bộ vi điều khiển trên Arduino "dựa trên AVR" (ví dụ ATmega328P) có các ưu tiên ngắt cố định như chi tiết trên trang 58ff của biểu dữ liệu . Vì vậy, nếu bạn đã sử dụng TIMER2 COMPA làm gián đoạn thời gian quan trọng của bạn và không có ngắt nào khác, bạn sẽ ổn (vì nó có mức ưu tiên cao nhất). Nếu bạn cũng muốn sử dụng các ngắt ưu tiên thấp hơn, bạn cần đảm bảo rằng tất cả chúng đều kích hoạt lại các ngắt toàn cầu khi vào thói quen dịch vụ ngắt của chúng:

Khi xảy ra gián đoạn, I-bit cho phép ngắt toàn cầu sẽ bị xóa và tất cả các ngắt bị vô hiệu hóa. Phần mềm người dùng có thể ghi logic một vào I-bit để cho phép các ngắt lồng nhau. Tất cả các ngắt được kích hoạt sau đó có thể làm gián đoạn thói quen ngắt hiện tại.

(trang 14 của biểu dữ liệu )

Điều này hơi khác so với Arduinos dựa trên ARM vì lõi Cortex-M3 của họ có "Bộ điều khiển ngắt Vector lồng nhau", trong đó các ưu tiên không cố định (có thể được đặt trong phần mềm) và xử lý ngắt lồng nhau là tiêu chuẩn. Vì vậy, để định thời cho các ứng dụng quan trọng, Arduino dựa trên ARM sẽ giúp bạn linh hoạt hơn. Tuy nhiên, tôi không nghĩ rằng điều đó thực sự cần thiết cho ứng dụng của bạn.

Câu hỏi lớn hơn là những thứ này có thể được thực hiện dễ dàng như thế nào với các thư viện Arduino. Để có được hiệu suất tốt nhất, có lẽ bạn sẽ phải mã bên ngoài các thư viện ở một mức độ nào đó, ít nhất là đối với các bit quan trọng về thời gian, tức là tránh những thứ như delay () hoặc millis () hoàn toàn.

Việc bạn có cần chia hay không phụ thuộc vào mức độ xử lý của bạn. Một lần nữa, đi ra ngoài các thư viện có khả năng cung cấp cho bạn hiệu suất tốt hơn.


3

Điều này có thể, với lập trình thích hợp, chắc chắn được thực hiện trên ATmega328P (phụ thuộc phần nào vào độ phức tạp của vòng lặp trống. Tôi giả sử ~ <50 sự kiện trống trong vòng lặp. Điều đó có hợp lý không?).

Lưu ý rằng tôi đã nói ATmega328P , không nhất thiết phải là Arduino .

Môi trường Arduino có rất nhiều thứ mặc định đang diễn ra trong nền, điều đó khiến cho việc lập trình cực kỳ mang tính quyết định (vì bạn sẽ cần một thứ gì đó quan trọng về thời gian).

Câu hỏi thực sự bạn cần đặt ra ở đây là bạn quan tâm đến lập trình như thế nào, so với việc bạn quan tâm đến việc phát triển một nhạc cụ như thế nào?

Mặc dù tôi khá tự tin rằng có thể làm mọi thứ bạn muốn trên một ATmega duy nhất (vòng lặp trống, nhiều đầu vào tương tự, LCD, nút, giao diện MIDI), câu hỏi thực sự là nó sẽ tốn bao nhiêu công sức để ép mọi thứ vào? Một lần nữa, bạn có muốn tìm hiểu để tối ưu hóa mã MCU nhúng hoặc xây dựng các công cụ không? Đó là khá dễ dàng chỉ đơn giản là đi đến một nhanh hơn MCU nếu cần thiết, nhưng bạn cần phải xác định hiệu suất MCU bạn cần tại , vì vậy trong sáu tháng của công việc, bạn không nhận ra bạn có thể không hoàn toàn có được tất cả mọi thứ để làm việc càng nhanh càng tốt nhu cầu.


Nếu tôi là bạn, điều đầu tiên tôi làm là làm cho nó hoạt động mà không cần công cụ arduino (về cơ bản, coi nó như một ATmega thô và sử dụng studio AVR hoặc tương tự). Sau đó, bạn có thể phân tích hiệu quả hơn loại hiệu suất bạn cần và nếu ATmega có thể quản lý nó.

Khi bạn không sử dụng công cụ arduino, bạn sẽ thoải mái hơn khi sử dụng các MCU khác nhau (chúng thường giống nhau hơn thì khác nhau. Nếu bạn có thể tìm ra một từ tài liệu của nó, bạn có thể làm tương tự cho những người khác).

Gần đây tôi đã làm việc với các thiết bị ATxmega rất nhiều và chúng thực sự rất tuyệt. Bạn nhận được ba ưu tiên ngắt, điều này làm cho việc quản lý công cụ quan trọng về thời gian chờ đợi dễ dàng hơn. Chúng cũng rất tuyệt khi làm việc với (Thiết kế ngoại vi Sane! Cấu trúc cổng thuận tiện! V.v ...).

Ngoài ra còn có các thiết bị LPC từ NXP, dựa trên ARM, cũng như một số thiết bị ARM của Atmel (như được sử dụng trên Arduino Do), hoặc MCU STM32 từ ST. Bất kỳ trong số này sẽ có hiệu suất cao hơn đáng kể sau đó là ATmega, hoặc thậm chí là ATxmega.

Nhược điểm chính của bộ xử lý lớn hơn, mạnh hơn là giá, nhưng trừ khi bạn tạo ra hàng nghìn đơn vị đó, chi phí lắp ráp và sản xuất trên mỗi đơn vị sẽ vượt quá mức chênh lệch chi phí (có thể sẽ chỉ vài đô la ) về cơ bản là không liên quan.


Nói một cách chính xác - đối với một sản phẩm thương mại, Arduino đơn giản không phải là hướng đi - chúng đói điện, chậm và IDE không được thiết kế cho mã tối ưu (nhanh / nhỏ), thay vào đó là sự tiện lợi và dễ học. Với chi phí thấp hơn, bạn thậm chí có thể có STM32 F4 (Cortex M4 32 bit> 100 MHz) hoặc tương tự, mặc dù điều này sẽ là quá mức cần thiết. Tôi nghĩ rằng một cái gì đó giống như một trong những PIC32 nhỏ hơn, Cortex M3s hoặc AVR32 có lẽ là cách để đi, như bạn đề cập. Vô số ưu tiên ngắt, DMA, các thiết bị ngoại vi tinh vi, năng lượng nhanh / thấp và nhiều RAM khiến nó trở thành một lựa chọn dễ dàng so với Arduino.
Oli Glaser

@OliGlaser - Tôi nghĩ bạn cần phân định rõ ràng giữa ArduinoATmega . Bạn có thể thực hiện mã nhỏ, nhanh trên ATmega và ATmega đó thậm chí có thể nằm trên bo mạch Arduino. Arduino "IDE", mặt khác, là một trong những trình soạn thảo mã nhỏ nhất mà tôi từng sử dụng. Mặt khác, bộ tải khởi động OptiBoot rất đẹp. Chỉ vì một số phần là tào lao không có nghĩa là bạn nên vứt bỏ toàn bộ.
Sói Connor

Hoàn toàn - Tôi đã đề cập đến toàn bộ Arduino, bao gồm cả bo mạch và IDE - không phải ATmega, mà tôi chắc chắn là tốt như bất kỳ uC so sánh nào khác (PIC16 / 18F, v.v.) tôi sẽ đưa nó vào danh sách của mình nhưng Tôi nghĩ rằng với mức giá từ 8 bit đến 16/32 bit hiện nay rất gần, có lẽ nên chi thêm 1 đô la và biết rằng bạn có sức mạnh của bộ xử lý để dự phòng (trừ khi bạn đề cập, chúng tôi đang nói về những con số khổng lồ và được xây dựng ở mức giá thấp nhất tuyệt đối, nhưng sau đó tôi nghi ngờ một Arduino sẽ được xem xét :-))
Oli Glaser

1

Tôi cần phải đọc lên bộ tính giờ trước khi tôi bắt đầu nghĩ về độ chính xác của thời gian (cũng xây dựng trình sắp xếp bước midi với arduino, mặc dù nó được đảm bảo trông kém mát hơn so với những thứ đó ^^). Loạt bài viết này đã được nhiều thông tin nhất:

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

Ngay bây giờ tôi nghĩ rằng giải pháp của tôi để có được thời gian chính xác sẽ được.

A. Sử dụng arduino AVR

B. Giữ nhiệm vụ trên một bộ vi xử lý

C. Sử dụng khôn ngoan các bộ đếm gộp trước, bộ hẹn giờ và ngắt để có được độ chính xác cần thiết.

CẬP NHẬT

Sử dụng hướng dẫn midi cơ bản cho Arduino và sau khi xem bài viết này về bộ hẹn giờ và bộ đếm trước, đoạn mã sau đây là những gì tôi nghĩ ra. Mã này sử dụng chế độ timer1 và CTC để phát một ghi chú midi trên mỗi quý thứ hai và một ghi chú tắt mỗi quý thứ hai (nên chính xác là 120 bpm). Đáng buồn thay, điều này vẫn đến chỉ chậm hơn 120bpm mặc dù đây là lần gần nhất tôi đã nhận được ...

// 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);
}

CẬP NHẬT

Tôi đã vật lộn với điều này trong ~ 24 giờ và cuối cùng đã nhận được một số câu trả lời từ diễn đàn. Tôi nghĩ rằng mã mà tôi đã sử dụng ở trên ^^ là khá tốt. Sử dụng ISR, sử dụng chế độ CTC và bộ tiền xử lý, v.v. Sau khi tiếp cận diễn đàn, tôi nghĩ rằng giải pháp ít hơn về việc đạt được độ chính xác trên trình sắp xếp midi, nhưng nhận được toàn bộ thiết lập phần cứng của tôi (bộ tổng hợp và bộ lấy mẫu của tôi) được nối với nhau Đồng hồ midi, có hay không đồng hồ đến từ Arduino.


0

Tùy thuộc vào mức độ dần dần bạn muốn thực hiện quá trình chuyển đổi từ máy tính bị trói sang hệ thống dựa trên PatrickC, bạn có thể xem xét đưa Raspberry Pi vào trong hộp đó ( bán lẻ $ 25-35 ). Bằng cách đó, bạn có thể có một máy tính dựa trên linux đầy đủ (mặc dù có công suất thấp) với các cổng USB và chân GPIO.


Tôi chắc chắn có khiên mở rộng hoặc bất cứ thứ gì họ gọi chúng cho Pi, nhưng bảng chứng khoán có 17 chân GPIO. Tôi đang sử dụng mọi pin đơn trên arduino mega. 31 đèn + 30 đèn LED, 10 đèn tương tự. 70+ I / O.
Steve Cooley

Ồ, ý tôi là nếu mục tiêu trước mắt là loại bỏ máy tính bên ngoài, bạn có thể giữ "trình phân tích [đó] là một ứng dụng chạy trên máy tính xách tay" và chạy nó trên Pi, được kết nối nội bộ với hệ thống hiện tại của bạn giống như cách kết nối ngay bây giờ
Rob Starling

@SteveCooley - Âm thanh như bạn cần xem xét về ghép kênh / ma trận nút IO. Bạn không cần một dòng IO chuyên dụng cho mỗi nút.
Sói Connor

@SteveCooley - Chết tiệt, bạn thậm chí không cần một nút matrice, thực sự. Bạn có thể thực hiện TẤT CẢ IO kỹ thuật số của mình chỉ bằng 4 chân rPi. Chỉ cần treo tất cả các nút và đèn LED khỏi một số thanh ghi thay đổi (nối tiếp song song cho các nút, song song nối tiếp cho đèn LED) và lái các thanh ghi thay đổi từ cổng SPI của rPi's. Bạn sẽ dễ dàng nhận được tốc độ cập nhật> 1Khz cho toàn bộ ma trận với sự trợ giúp của phần cứng SPI.
Sói Connor

Nếu lý do duy nhất bạn sử dụng Arduino Mega là IO, thì bạn đang chi rất nhiều tiền cho một thứ gì đó có thể được thực hiện rất dễ dàng với một vài thiết bị bên ngoài, với giá <$ 3.
Sói Connor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.