Hanya sebulan yang lalu, saya menemukan artikel
ini , yang menceritakan tentang mengayuh Vim. Beberapa saat kemudian, setelah lama belajar selama tiga menit, saya mengetahui bahwa topik ini tidak lagi baru dan cukup populer. Saya sendiri menggunakan Vim hanya dalam keadaan darurat (jika saya harus bekerja di konsol, saya lebih suka Nano), tetapi Anda dapat melakukan hal yang sama untuk aplikasi lain.
Awalnya, saya ingin membuat artikel kecil, tapi saya mendapat seluruh tutorial tentang cara membuat perangkat ini dengan penulisan kode langkah-demi-langkah dan penjelasan tentang apa dan bagaimana. Agar tidak mengembang artikel, di bawah spoiler akan ada berbagai informasi yang tampaknya menarik dan layak menjadi perhatian pendatang baru ke Arduino, pengguna mahir dan terutama terburu-buru mungkin tidak membuang waktu untuk itu. Kode sumber lengkap juga disajikan di akhir artikel.
Mengapa saya membutuhkannya?
Jika Anda tidak ragu tentang perlunya dan kegunaan perangkat ini, maka Anda dapat melewati item ini. Untuk selebihnya, saya pertama-tama ingin berbicara tentang prasyarat untuk membuat perangkat ini.
Setiap saat, programmer dan desainer telah mencoba membuat antarmuka yang nyaman dan ramah-pengguna sehingga pengguna dapat bekerja dengan aplikasi menggunakan mouse dan keyboard tanpa masalah yang tidak perlu, jadi mengapa kita perlu manipulator lain? Baiklah, mari kita melihat sedikit ke dalam sejarah, atau lebih tepatnya, pada awal abad ke-18, ketika alat musik seperti piano diciptakan. Seperti yang Anda tahu, kata ini secara harfiah diterjemahkan sebagai "keras dan tenang," tetapi beberapa orang berpikir bahwa master Italia yang pandai menerima instrumen seperti itu, sebenarnya "memanfaatkan" harpsichord yang ada saat itu, yang memungkinkan untuk mengontrol volume suara sampai batas tertentu, tanpa mengambil tangan dari kunci.
Ada banyak contoh. Mobil memiliki pedal agar tidak melempar setir jika perlu menambahkan bensin. Drum kit juga memiliki pedal untuk mengetuk bass drum dan simbal. Dan apa yang bisa diberikan pedal saat menggunakan komputer? Misalnya, Anda dapat mengatur beberapa kombinasi tombol pintas, atau bahkan menambahkan kunci yang tidak ada di sana, seperti menyalakan dan mematikan suara. Pedal dapat membantu jika tangan Anda sibuk: Saya bermain gitar sendiri, dan kadang-kadang dengan iringan, akan sangat nyaman bagi saya untuk menggulung backing tanpa berusaha terus-menerus meraih keyboard. Dan akhirnya, pengontrol dapat memberikan kemungkinan yang sama sekali tidak manusiawi dalam permainan: akan keren untuk membangun seluruh basis Anda dalam strategi dengan satu klik atau hancurkan musuh dengan kecepatan selusin detak per detik dalam penembak, bukan?
Secara umum, saya harap saya meyakinkan Anda, yang berarti saatnya untuk mulai langsung ke pengembangan itu sendiri.
Sumber daya yang dibutuhkan
- Sebenarnya, pedal. Beberapa kesulitan segera muncul karena saya tidak dapat memikirkan nama untuk pedal seperti itu. Saya hanya tahu bahwa hal-hal seperti itu digunakan dalam mesin jahit. Secara umum, atas permintaan pedal listrik, saya masih berhasil menemukan apa yang saya butuhkan di Aliexpress, dan tanpa berpikir dua kali, saya memesan 3 buah.
- Pengendali Pedboard harus meniru keyboard dan, mungkin, mouse untuk dapat terhubung ke PC tanpa driver yang tidak perlu. Untuk ini, papan Micro Arduino Pro sempurna, yang, meskipun tidak memiliki beberapa kesimpulan, itu dibuat sekompak mungkin. Kami pergi ke Aliexpress yang sama, dan membeli versi Cina dari keajaiban ini.
- Kabel. Untuk menempatkan 3 pedal di bawah meja, Anda membutuhkan setidaknya empat kawat dengan panjang setidaknya satu meter. Di sini, saya pikir, masalah tidak boleh muncul.
- RGB LED dan tombol. Yang pertama diperlukan untuk menunjukkan mode, dan yang kedua adalah untuk mengubahnya.
- Yah, tentu saja, kita membutuhkan Arduino IDE, besi solder dan lengan lurus.
Diagram perangkat
Bahkan sebelum parsel tiba, saya mulai membuat diagram perangkat. Meskipun ini dikatakan banyak, karena saya hanya harus menghubungkan pedal, dioda dan tombol. Ternyata entah bagaimana seperti ini:

Untuk pedal, saya memutuskan untuk mengalokasikan 4 port PB1-PB4 sekaligus, yaitu, dua untuk kiri, dan dua untuk kaki kanan, meskipun sejauh ini saya hanya memiliki 3 pedal.Selain itu, mereka semua dalam kelompok yang sama dan berada di satu tempat. Di bawah LED, saya mengambil output PD0, PD1 dan PD4, di bawah tombol - PD7.
Dalam hal ini, kita tidak memerlukan resistor pull-up, jika Anda menggunakan resistor yang ada di controller. Benar, kemudian, ketika Anda menekan tombol atau pedal, input akan rendah, dan ketika dilepaskan, itu akan tinggi, yaitu, tekanan akan terbalik, dan Anda tidak boleh melupakan ini.
Penulisan kode
Tahap ini adalah yang paling sulit: karena beberapa kesalahan dalam petunjuk saya menghapus bootloader beberapa kali dan sebagai hasilnya saya hampir gagal papan pada tingkat perangkat lunak. Di bawah semua tahap pembuatan firmware dijelaskan secara rinci, bagi mereka yang hanya ingin mendapatkan kode yang berfungsi, itu akan berada di akhir artikel.
Persiapan
Pertama-tama kita perlu memahami apa itu pedal dalam hal program. Saya memutuskan untuk memungkinkan untuk mengatur pedal salah satu dari dua mode - real-time dan pemicu. Pada saat yang sama, setiap pedal memiliki dua program: yang pertama dilakukan ketika pedal dipegang secara real time atau dengan penekanan ganjil dalam mode pemicu, yang kedua adalah ketika pedal dilepaskan secara real time atau ketika pedal ditekan secara merata dalam mode pemicu. Pedal juga memiliki port, keadaan, dan dua variabel - posisi saat ini di program 1 dan 2. Saya mendapatkan struktur ini:
struct pedal { char port;
Arduino memiliki cukup banyak memori dan juga 8-bit, jadi yang terbaik adalah mencoba menggunakan char daripada int jika memungkinkan.
Kita juga membutuhkan pustaka Keyboard standar untuk berfungsi sebagai keyboard.
Klik Memproses
Sekarang kita perlu membuat juru bahasa yang akan membaca data dari array dan mengirimkannya dalam bentuk penekanan tombol ke mesin, serta memilih beberapa nilai untuk berbagai perintah internal. Kami membuka
halaman dengan kode kunci, dan melihat apa dan bagaimana kita bisa mengklik. Saya tidak menggali lebih dalam dan mempelajari segala macam standar keyboard, karena informasi di sini bagi saya cukup untuk proyek semacam itu. Babak pertama dicadangkan untuk karakter ASCII standar (meskipun beberapa dari mereka tidak dapat dicetak atau tidak digunakan), babak kedua adalah untuk berbagai kunci pengubah. Bahkan ada kode terpisah untuk tombol kiri dan kanan, yang sangat menyenangkan, tetapi saya tidak melihat kode khusus untuk angka-angka dari nampad, meskipun, sejauh yang saya tahu, mereka dianggap secara khusus dalam sistem daripada angka biasa. Mungkin kode mereka ada di suatu tempat di "lubang", di antara rentang, tetapi sekarang bukan tentang itu. Jadi, kode terbesar adalah tombol atas - 218, yang berarti bahwa rentang 219-255 dapat dianggap gratis, baik, atau setidaknya tidak ada kunci penting.
void pedalAction() {
Saya pikir bahkan orang yang tidak memiliki tingkat pengetahuan C tertinggi tidak akan memiliki pertanyaan tentang apa yang terjadi di sini. Pertama, fungsi memilih pedal yang diinginkan dan menentukan, tergantung pada mode dan kondisi pedal, program mana yang harus dilakukan. Saat membaca setiap elemen array, jika itu bukan karakter kontrol, fungsi Keyboard.write () dipanggil, yang mengemulasi menekan dan melepaskan kunci. Karakter kontrol diproses secara terpisah dan diperlukan untuk menjepit kombinasi tombol dan menavigasi program.
Beberapa fitur mode keyboardKeyboard.write () memiliki beberapa nuansa sederhana, tetapi tidak jelas untuk pemula, berdasarkan fakta bahwa kami mengirim data tidak dalam bentuk mentah, tetapi sebagai penekanan tombol. Pertama, anehnya, tanpa driver tambahan, komputer hanya dapat menerima karakter dari keyboard yang ada di keyboard, yang berarti bahwa kami tidak akan dapat mengirim 0x03 (sinyal interupsi) atau 0x1B (awal urutan ESCAPE). Kedua, kita dapat menyesuaikan huruf besar seperti pada tabel ASCII, tetapi mesin akan mendapatkan kombinasi tombol Shift + <huruf kecil>. Ini bisa menjadi masalah jika CapsLock diaktifkan dan kami "secara tak terduga" akan menerima huruf kecil, bukan huruf besar dan sebaliknya. Ketiga, kami tidak dapat menggunakan bahasa Rusia, juga bahasa lainnya. Ini terjadi lagi karena hal-hal yang mengganggu seperti kode kunci . Meskipun Keyboard.write () menerimanya sebagai argumen, kode yang sesuai dengan kunci yang ada dalam tata letak bahasa Inggris standar masih dikirim melalui USB, dan jika kami mencoba mengirim alfabet Cyrillic, kami tidak akan tahu apa. Karena itu, jika kita ingin menyapa teman-teman kita yang berbahasa Rusia melalui Arduino, maka dalam kode kita perlu menulis "Ghbdtn", dan kemudian mengirimkannya, setelah memilih tata letak Rusia. "Ucapan" seperti itu akan bekerja dalam tata letak Ukraina, tetapi dalam bahasa Bulgaria, terlepas dari kenyataan bahwa ada juga alfabet Cyrillic, tidak ada yang akan datang darinya, karena huruf-hurufnya ada di tempat yang sama sekali berbeda. (Saya pernah mendengar pendapat bahwa bagi banyak pengembang Amerika dan Inggris tidak dapat dipahami bahwa seseorang bahkan mungkin perlu menggunakan beberapa tata letak, tetapi juga mengubahnya.)
Jadi, kami memiliki juru bahasa dan pemahaman kasar tentang bagaimana pedalboard kami berinteraksi dengan komputer. Sekarang kita perlu membawa semua ini ke keadaan firmware penuh dan memeriksa kinerja dengan satu pedal. Jika Anda membuat instance dari pedal dan secara otomatis memanggil pedalAction (), maka secara teori kami akan menjalankan program yang ditentukan dalam struktur.
struct pedal *pedal1 = {15, 0, 0, 0, 0, 0, "Hello, world!\0", 0}; void prepare () { pinMode(15, 2);
Ngomong-ngomong, jangan pernah lupakan terminator nol dalam "program" ini jika panjangnya kurang dari ukuran array dan jika mereka bukan siklus, karena Arduino tidak hanya akan mencoba menginterpretasikan data yang tidak diatur, tetapi juga akan mengirimnya ke mesin dengan kecepatan tinggi, dan itu sama dengan memberi monyet keyboard.
Satu pedal baik, dan dua lebih baik
Sekarang saatnya berurusan dengan pemrosesan sinyal dari beberapa pedal, serta menambahkan mode switching. Pada awal artikel, 4 port dialokasikan untuk pedal, yang masing-masing harus diizinkan untuk bekerja dalam tujuh mode. Mengapa 7? Karena tanpa menggunakan PWM, LED kami hanya bisa memberi 7 warna, dan yang kedelapan. Jumlah ini cukup bagi pengguna rata-rata, tetapi dalam kasus-kasus ekstrem dapat dengan mudah ditingkatkan. Jadi kita akan menyimpan pedal dalam array dua dimensi 7 x 4. Agar tidak menyumbat memori, nilai-nilai yang umum untuk beberapa struktur, seperti nomor port, dapat dikeluarkan dalam array yang terpisah. Akibatnya, kami mendapatkan sesuatu seperti ini:
struct pedal { unsigned char type; unsigned char act1[16]; unsigned char act2[16]; }; struct pedal pedals[7][4] = { { { 255, {"Hello, world!\0"}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} }, { { 255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} }, { { 255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} }, { { 255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} }, { { 255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} }, { { 255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} }, { { 255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} } }; char ports[4] = {15, 16, 14, 8}; char pos1[4] = {0, 0, 0, 0}; char pos2[4] = {0, 0, 0, 0}; char state[4] = {0, 0, 0, 0}; char oldState[4] = {0, 0, 0, 0}; char mode = 0;
Keajaiban nomor 255Anda mungkin memperhatikan bahwa dalam artikel nomor 255 sering muncul, di mana akan lebih logis untuk menempatkan 0. Ke depan, saya akan mengatakan bahwa ini diperlukan untuk kenyamanan menyimpan pedal di EEPROM, karena dari pabrik masing-masing selnya tidak mengandung 0, tetapi hanya 255, yang berarti bahwa angka ini akan jauh lebih nyaman digunakan untuk menunjukkan variabel yang tidak terdefinisi daripada 0, sehingga Anda tidak menimpa memori setiap kali.
Penting bagi kita untuk mengetahui hanya tipe pedal dan dua program, jadi kita akan membiarkannya hanya secara langsung dalam struktur, biarkan otomasi melakukan sisanya. Metode persiapan dan putaran sekarang akan terlihat seperti ini:
void prepare(){ pinMode(2, 1); pinMode(3, 1); pinMode(4, 1); pinMode(6, 2); for (int i : ports) pinMode(i, 2); Keyboard.begin(); } void loop() { for (int i = 0; i < 6; i++) { int current; if ((current = digitalRead(modeButton)) != last) { if (!current) { if (++mode >= 7) mode = 0; while (pedals[mode][0].type == 255 && pedals[mode][1].type == 255 && pedals[mode][2].type == 255 && pedals[mode][3].type == 255) if (++mode >= 7) { mode = 0; break; } } last = current; digitalWrite(2, (mode + 1) & 0b001); digitalWrite(3, (mode + 1) & 0b010); digitalWrite(4, (mode + 1) & 0b100); for (int i = 0; i < 4; i++) { pos1[i] = 0; pos2[i] = 0; state[i] = 0; oldState[i] = 0; } delay(50); } curPedal = i; pedalAction } } }
Pengontrol akan mempertimbangkan mode yang tidak digunakan jika tidak ada pedal tunggal yang dideklarasikan di dalamnya (mode = 255), yang berarti bahwa ketika dipukul, itu akan langsung menuju ke yang berikutnya, tetapi mode pertama akan selalu ada. Ketika beralih mode, semua nilai dalam array dibatalkan, karena kita tidak perlu menyimpannya untuk setiap mode (kan?), Dan kemudian loop memotong semua pedal dan memanggil pedalAction untuk mereka.
Juga, di awal metode pedalAction (), Anda perlu menambahkan baris berikut ini agar mengerti struktur mana yang harus ditangani:
struct pedal *pedal1 = &pedals[mode][curPedal];
Struktur pedal1 yang ada dapat dilepas sebagai tidak perlu.
Semua ini juga berfungsi dengan baik, namun, saya menemui satu masalah: beberapa program tidak punya waktu untuk menerima klik pada kecepatan yang dikirim Arduino. Solusi yang paling jelas adalah menambahkan kemampuan untuk mengatur penundaan antara tindakan jika perlu. Hanya ketika kita duduk untuk menulis program untuk mikrokontroler bahwa semua chip, seperti multithreading perangkat keras, tetap berada di suatu tempat di sana, di komputer tingkat tinggi, ketika kita menambahkan penundaan, seluruh program berhenti hingga pengontrol menghitung jumlah siklus yang tepat. Karena kita tidak memiliki multithreading, kita harus membuatnya.
Sulit dikatakan ya mudah dilakukan
Saya tidak menciptakan sepeda, tetapi mengambil perpustakaan ArduinoThread yang sudah jadi.
Di sini Anda dapat membaca sedikit tentang cara kerjanya dan mengunduhnya. Anda dapat mengunduh perpustakaan dari Arduino IDE itu sendiri. Singkatnya, ini memungkinkan Anda untuk secara berkala melakukan fungsi dengan interval tertentu, sementara tidak memungkinkan Anda untuk masuk ke loop tak terbatas jika eksekusi memakan waktu lebih lama dari interval. Apa yang kamu butuhkan Buat array lain dengan utas untuk setiap pedal:
Thread pedalThreads[6] = {Thread(pedalAction, 10), Thread(pedalAction, 10), Thread(pedalAction, 10), Thread(pedalAction, 10), Thread(pedalAction, 10), Thread(pedalAction, 10)};
Sekarang kita memiliki 6 utas virtual yang identik, tetapi pada saat yang sama mereka adalah objek yang berbeda.
Mari kita menulis ulang siklus bypass pedal agar berfungsi dengan fungsi baru:
... for (int i = 0; i < 4; i++) { if (pedalThreads[i].shouldRun()) { curPedal = i; pedalThreads[i].run(); } } ...
Sekarang nilai 252 dalam array program, yang sesuai dengan "tidak melakukan apa-apa," akan memberikan penundaan 10 milidetik (meskipun sebenarnya sedikit lebih, karena eksekusi kode juga membutuhkan waktu). Menambahkan beberapa baris ke juru bahasa akan memungkinkan untuk mengatur penundaan pada beberapa "kuanta" ini, hanya menghabiskan 2 byte array:
... if (wait[num]) { wait[num]--; return; } else if (prg[*pos] == 250) { wait[num] = prg[++*pos]; } ...
Tidak seperti perintah lain, instruksi ini harus ditambahkan tepat di awal penerjemah, yaitu, segera setelah "sementara (1) {", karena penundaan harus diproses sebelum penerjemah melanjutkan membaca program. Array tunggu harus dideklarasikan dengan cara yang sama seperti yang dilakukan dengan port, status, dll. dan juga mengatur ulang sel-selnya saat beralih mode, sehingga penundaan tidak pergi ke program lain.
Sekarang, dengan kemungkinan pengaturan penundaan hingga 2,55 detik, masalah dengan definisi kunci oleh program seharusnya tidak muncul.
Pemrograman on-the-go
Pada prinsipnya, di sini dimungkinkan untuk menyelesaikan dengan kode dan mulai merakit perangkat, tetapi dalam hal ini, jika seseorang tiba-tiba ingin memprogram ulang pedal, ia harus membuka IDE Arduino, mengedit kode, dan mengunduh firmware lagi. Tentu saja, opsi ini bukan yang terbaik, jadi saya memutuskan untuk menambahkan kemampuan untuk mengubah program dari port serial Arduino, dan menyimpan program itu sendiri di EEPROM. Untuk bekerja dengan memori non-volatile, Anda harus menghubungkan EEPROM.h perpustakaan standar. Kode mode pemrograman adalah sebagai berikut:
... if (!digitalRead(modeButton)) {
Apa yang dilakukan kode ini dijelaskan oleh bantuan yang terkandung di dalamnya: nomor spasi dimasukkan untuk nomor mode, nomor pedal, dan perintah, yang ada 3 - membaca, menulis, dan
mengeksekusi penghapusan program. Semua data pada pedal disimpan satu demi satu dalam urutan 33 byte, yaitu jenis pedal, dan dua program, dan bahwa kami menempati 7 * 4 * 33 = 924 dari 1024 byte EEPROM. Saya membuang opsi menggunakan ukuran dinamis dari pedal dalam memori, karena dalam hal ini ketika memprogram ulang satu pedal Anda harus menimpa hampir semua sel, dan ada sejumlah siklus penulisan ulang yang terbatas, jadi kami sarankan melakukan ini sesedikit mungkin.
Fitur kerja dengan EEPROMSaya juga ingin menarik perhatian pada garis-garis bentuk:
PORTD = 0b00000010 + (PORTD & 0b11101100); ... PORTD = 0b00000001 + (PORTD & 0b11101100);
Berkat pustaka ini, dari sudut pandang programmer, memori non-volatile adalah array char biasa, tetapi, sebagai "Arduino", kita perlu memahami bahwa menulis ke ROM adalah operasi yang sangat sulit, yang memakan waktu ~ 3 detik dari controller, dan disarankan untuk tidak menghentikan ini proses. Desain ini membuat dioda bersinar merah selama operasi tersebut, dan kemudian mengembalikan warna hijau "aman".
Dalam mode perekaman program, input dibuat langsung oleh nilai byte dalam sistem angka desimal dengan spasi. Ternyata sangat parah, tetapi Anda tidak perlu menulis parser yang rumit. Selain itu, pemrograman ulang tidak sering terjadi, dan dalam kasus ini sangat mungkin untuk melihat tabel ASCII.
Dengan pelestarian struktur yang diurutkan, sekarang kita perlu mengeluarkan data dari sana dan mengubahnya menjadi tampilan "pedal":
... for (int i = 0; i < 7; i++) { for (int j = 0; j < 4; j++) { struct pedal *p = &pedals[i][j]; int beginAddress = sizeof(struct pedal) * (i * 6 + j); int curAddress = beginAddress; unsigned char type = EEPROM[curAddress++]; if (type == 0 || type == 1) { p->type = type; for (int k = 0 ; k < 16; k++) { p->act1[k] = EEPROM[curAddress++]; } for (int k = 0 ; k < 16; k++) { p->act2[k] = EEPROM[curAddress++]; } } } } ...
Tidak ada hal supernatural yang terjadi di sini: controller membaca data dari memori dan mengisi struktur yang ada dengannya.
Keuntungan pemrograman melalui UART adalah kita kembali tidak memerlukan driver khusus, sehingga Anda dapat mengatur perilaku manipulator bahkan dari telepon.
Demonstrasi
Kode sumber lengkap
Dia disini #include <Keyboard.h> #include <Thread.h> #include <EEPROM.h> #define modeButton 6 struct pedal { unsigned char type; //0 — , 1 — , 255 — unsigned char act1[16]; unsigned char act2[16]; }; struct pedal pedals[7][4] = { { { 255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} }, { { 255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} }, { { 255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} }, { { 255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} }, { { 255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} }, { { 255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} }, { { 255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}}, {255, {255}, {255}} } }; char ports[4] = {8, 16, 15, 14}; char pos1[4] = {0, 0, 0, 0}; char pos2[4] = {0, 0, 0, 0}; char state[4] = {0, 0, 0, 0}; char oldState[4] = {0, 0, 0, 0}; char wait[4] = {0, 0, 0, 0}; void pedalAction(); char mode = 0; char curPedal; Thread pedalThreads[6] = {Thread(pedalAction, 10), Thread(pedalAction, 10), Thread(pedalAction, 10), Thread(pedalAction, 10), Thread(pedalAction, 10), Thread(pedalAction, 10)}; void setup() { pinMode(2, 1); pinMode(3, 1); pinMode(4, 1); pinMode(modeButton, 2); if (!digitalRead(modeButton)) { // Serial.begin(9600); while (!Serial) { PORTD = 0b00000000 + (PORTD & 0b11101100); delay(250); PORTD = 0b00010000 + (PORTD & 0b11101100); delay(250); } Serial.println(F("***Programming mode***")); Serial.println(F("Write the command as <m> <p> <c>")); Serial.println(F("m - number of mode, one digit")); Serial.println(F("p - number of pedal, one digit")); Serial.println(F("c - command, it can be:")); Serial.println(F("\tr - read pedal info")); Serial.println(F("\tw - enter to writing mode and change pedal programm")); Serial.println(F("\te - erase pedal programm and delete it")); Serial.println(F("There are up to 7 modes and 6 pedals per mode can be configured")); Serial.println(F("Mode will be incative if there is no pedal configured in it")); while (1) { while (Serial.available()) { Serial.read(); delay(1); } PORTD = 0b00000001 + (PORTD & 0b11101100); Serial.println(""); Serial.println(F("Enter command")); while (!Serial.available()); PORTD = 0b00000010 + (PORTD & 0b11101100); delay(3); if (Serial.available() == 3) { int curMode = Serial.read() - 48; int curPedal = Serial.read() - 48; char cmd = Serial.read(); if (curMode > 6 || curMode < 0) { Serial.print(F("Mode must be in 0-6. You entered ")); Serial.println(curMode); continue; } if (curPedal > 3 || curPedal < 0) { Serial.print(F("Pedal must be in 0-3. You entered ")); Serial.println(curPedal); continue; } Serial.println(); if (cmd == 'r') { int beginAddress = sizeof(struct pedal) * (curMode * 6 + curPedal); Serial.print("type: "); int curAddress = beginAddress; Serial.println(EEPROM[curAddress++]); Serial.print("act1: "); for (int i = curAddress ; i < curAddress + (sizeof(struct pedal) - 1) / 2; i++) { Serial.print(EEPROM[i]); Serial.print("\t"); } Serial.println(); curAddress = beginAddress + 1 + (sizeof(struct pedal) - 1) / 2; Serial.print("act2: "); for (int i = curAddress ; i < curAddress + (sizeof(struct pedal) - 1) / 2; i++) { Serial.print(EEPROM[i]); Serial.print("\t"); } Serial.println(); } else if (cmd == 'w') { Serial.println(F("Enter type:")); PORTD = 0b00000001 + (PORTD & 0b11101100); while (!Serial.available()); int beginAddress = sizeof(struct pedal) * (curMode * 6 + curPedal); int curAddress = beginAddress; PORTD = 0b00000010 + (PORTD & 0b11101100); EEPROM[curAddress++] = (char)Serial.parseInt(); PORTD = 0b00000001 + (PORTD & 0b11101100); Serial.println(F("Enter act1 in DEC divided by space:")); while (Serial.available()) { Serial.read(); delay(1); } while (!Serial.available()); PORTD = 0b00000010 + (PORTD & 0b11101100); while (Serial.available()) { EEPROM[curAddress++] = (char)Serial.parseInt(); delay(1); } PORTD = 0b00000001 + (PORTD & 0b11101100); curAddress = beginAddress + 1 + (sizeof(struct pedal) - 1) / 2; Serial.println(F("Enter act2 in DEC divided by space:")); while (Serial.available()) { Serial.read(); delay(1); } while (!Serial.available()); PORTD = 0b00000010 + (PORTD & 0b11101100); while (Serial.available()) { EEPROM[curAddress++] = (char)Serial.parseInt(); delay(1); } PORTD = 0b00000001 + (PORTD & 0b11101100); Serial.println(F("Finished, don't forget to verify written data!")); } else if (cmd == 'e') { int beginAddress = sizeof(struct pedal) * (curMode * 6 + curPedal); Serial.println(F("Disabling pedal...")); PORTD = 0b00000010 + (PORTD & 0b11101100); EEPROM[beginAddress] = 255; PORTD = 0b00000001 + (PORTD & 0b11101100); Serial.println(F("Pedal disabled")); } } else { Serial.println(F("Incorrect command, please read help above")); } }; } for (int i : ports) pinMode(i, 2); pinMode(17, 1); for (int i = 0; i < 7; i++) { for (int j = 0; j < 4; j++) { struct pedal *p = &pedals[i][j]; int beginAddress = sizeof(struct pedal) * (i * 6 + j); int curAddress = beginAddress; unsigned char type = EEPROM[curAddress++]; if (type == 0 || type == 1) { p->type = type; for (int k = 0 ; k < 16; k++) { p->act1[k] = EEPROM[curAddress++]; } for (int k = 0 ; k < 16; k++) { p->act2[k] = EEPROM[curAddress++]; } } } } Keyboard.begin(); } int last = 0; void loop() { int current; if ((current = digitalRead(modeButton)) != last) { if (!current) { if (++mode >= 7) mode = 0; while (pedals[mode][0].type == 255 && pedals[mode][1].type == 255 && pedals[mode][2].type == 255 && pedals[mode][3].type == 255) if (++mode >= 7) { mode = 0; break; } } last = current; digitalWrite(2, (mode + 1) & 0b001); digitalWrite(3, (mode + 1) & 0b010); digitalWrite(4, (mode + 1) & 0b100); for (int i = 0; i < 4; i++) { pos1[i] = 0; pos2[i] = 0; state[i] = 0; oldState[i] = 0; wait[i] = 0; } delay(50); } for (int i = 0; i < 4; i++) { if (pedalThreads[i].shouldRun()) { curPedal = i; pedalThreads[i].run(); } } } void pedalAction() { struct pedal *pedal1 = &pedals[mode][curPedal]; if (pedal1->type == 255) return; unsigned char *prg; char *pos; if (pedal1->type) { int current; if ((current = digitalRead(ports[curPedal])) != oldState[curPedal]) { if (!current) state[curPedal] = !state[curPedal]; oldState[curPedal] = current; } if (!state[curPedal]) { //act1 pos2[curPedal] = 0; pos = &(pos1[curPedal]); prg = pedal1->act1; } else { //act2 pos1[curPedal] = 0; pos = &(pos2[curPedal]); prg = pedal1->act2; } } else { if (!digitalRead(ports[curPedal])) { //act1 pos2[curPedal] = 0; pos = &(pos1[curPedal]); prg = pedal1->act1; } else { //act2 pos1[curPedal] = 0; pos = &(pos2[curPedal]); prg = pedal1->act2; } } while (1) { if (wait[curPedal]) { wait[curPedal]--; return; } else if (prg[*pos] == 250) { wait[curPedal] = prg[++*pos]; } else if (prg[*pos] == 254) { // , *pos Keyboard.press(prg[++*pos]); } else if (prg[*pos] == 253) { // , *pos Keyboard.release(prg[++*pos]); } else if (prg[*pos] == 252) { delay(10); //" ", ++*pos; return; } else if (prg[*pos] == 251) { // *pos+1 *pos = prg[*pos + 1]; return; } else if (prg[*pos] == 255 || prg[*pos] == 0) { // , return; } else { // Keyboard.write(prg[*pos]); } // , if (++*pos >= 16) pos = 0; } }
Kata penutup
Meskipun pada awalnya saya membuat pedalboard untuk kemungkinan menggulung rekaman sambil bermain gitar, namun, secara pribadi saya merasa nyaman menggunakan pedal dalam tugas-tugas biasa, hal utama adalah sedikit terbiasa dengan manipulator yang tidak biasa. Dan di sini ada masalah lain: tanpa pedal favorit, bekerja sebaliknya menjadi lebih sulit, karena Anda harus mengingat apa, di mana dan mengapa harus menekan. Jika pedal masih bisa dipakai dan dihubungkan ke kantor, maka berlari di ruang kelas di institut sudah lebih sulit. Jadi menggunakan perangkat ini untuk tujuan lain selain dari tujuan semula adalah risiko dan risiko Anda sendiri.Pedal dirakit: