Tentang proyek ini
Dalam proyek saya sebelumnya, saya menunjukkan cara mengontrol beberapa LED menggunakan papan Arduino dan Server BitVoicer. Dalam proyek ini, saya akan membuat segalanya sedikit lebih rumit. Saya juga akan mensintesis ucapan menggunakan Arduino DUE digital-to-analog converter (DAC). Jika Anda tidak memiliki Arduino DUE, Anda dapat menggunakan papan Arduino lain, tetapi Anda memerlukan DAC eksternal dan beberapa kode tambahan untuk mengoperasikan DAC (library BVSSpeaker tidak akan membantu Anda dengan itu).
Dalam video di bawah ini, Anda dapat melihat bahwa saya juga membuat Arduino memainkan sedikit lagu dan mengedipkan LED seolah-olah itu adalah tuts piano. Maaf untuk keterampilan piano saya, tapi itu yang terbaik yang bisa saya lakukan :) . LED benar-benar berkedip dalam urutan dan waktu yang sama seperti kunci C, D, dan E asli, jadi jika Anda memiliki piano di sekitar Anda dapat mengikuti LED dan memainkan lagu yang sama. Ini adalah jingle dari pengecer lama (Mappin) yang bahkan tidak ada lagi.
Prosedur berikut akan dijalankan untuk mengubah perintah suara menjadi aktivitas LED dan ucapan yang disintesis:
- 1. Gelombang audio akan ditangkap dan diperkuat oleh papan Sparkfun Electret Breakout;
- 2. Sinyal yang diperkuat akan didigitalkan dan di-buffer di Arduino menggunakan analog-to-digital converter (ADC);
- 3. Sampel audio akan dialirkan ke BitVoicer Server menggunakan port serial Arduino;
- 4. Server BitVoicer akan memproses aliran audio dan mengenali ucapan yang dikandungnya;
- 5. Ucapan yang dikenali akan dipetakan ke perintah yang telah ditentukan yang akan dikirim kembali ke Arduino. Jika salah satu perintah terdiri dari mensintesis ucapan, Server BitVoicer akan menyiapkan aliran audio dan mengirimkannya ke Arduino;
- 6. Arduino akan mengidentifikasi perintah dan melakukan tindakan yang sesuai. Jika aliran audio diterima, itu akan dimasukkan ke dalam kelas BVSSpeaker dan diputar menggunakan DUE DAC dan DMA.
- 7. Amplifier Audio Mono SparkFun akan memperkuat sinyal DAC sehingga dapat menggerakkan speaker 8 Ohm.
Daftar Bahan:
- Sparkfun Electret Microphone Breakout:U$7,95
- SparkFun Mono Audio Amp Breakout:U$7,95
- Server BitVoicer 1.0:U$ 9,90
- Resistor 3 x 330 Ohm:~U$ 0,75
LANGKAH 1:Pengkabelan
Langkah pertama adalah memasangkan Arduino dan papan tempat memotong roti dengan komponen seperti yang ditunjukkan pada gambar di bawah ini. Saya harus meletakkan karet kecil di bawah speaker karena banyak bergetar dan tanpa karet kualitas audio sangat terpengaruh.
Di sini kita memiliki perbedaan kecil tapi penting dari proyek saya sebelumnya. Sebagian besar papan Arduino berjalan pada 5V, tetapi DUE berjalan pada 3.3V. Karena saya mendapatkan hasil yang lebih baik saat menjalankan Sparkfun Electret Breakout pada 3.3V, saya sarankan Anda menambahkan jumper antara pin 3.3V dan pin AREF JIKA Anda menggunakan papan Arduino 5V. DUE sudah menggunakan referensi analog 3.3V sehingga tidak perlu jumper ke pin AREF. Faktanya, pin AREF pada DUE terhubung ke mikrokontroler melalui jembatan resistor. Untuk menggunakan pin AREF, resistor BR1 harus disolder dari PCB.
LANGKAH 2:Mengunggah kode ke Arduino
Sekarang Anda harus mengunggah kode di bawah ini ke Arduino Anda. Untuk kenyamanan, sketsa Arduino juga tersedia di bagian Lampiran di bagian bawah posting ini. Sebelum mengupload kode, Anda harus menginstal library BitVoicer Server dengan benar ke Arduino IDE (Mengimpor Library .zip).
Sketsa Arduino :BVS_Demo2.ino
Sketsa ini memiliki tujuh bagian utama:
- Referensi pustaka dan deklarasi variabel :Empat baris pertama menyertakan referensi ke perpustakaan BVSP, BVSMic, BVSSpeaker, dan DAC. Pustaka ini disediakan oleh BitSophia dan dapat ditemukan di folder instalasi BitVoicer Server. Pustaka DAC disertakan secara otomatis saat Anda menambahkan referensi ke pustaka BVSSpeaker. Baris lain mendeklarasikan konstanta dan variabel yang digunakan di seluruh sketsa. Kelas BVSP digunakan untuk berkomunikasi dengan BitVoicer Server, kelas BVSMic digunakan untuk menangkap dan menyimpan sampel audio dan kelas BVSSpeaker digunakan untuk mereproduksi audio menggunakan DUE DAC.
- Fungsi penyetelan :Fungsi ini melakukan tindakan berikut:mengatur mode pin dan status awalnya; menginisialisasi komunikasi serial; dan menginisialisasi kelas BVSP, BVSMic, dan BVSSpeaker. Ini juga menetapkan "penangan acara" (mereka sebenarnya adalah penunjuk fungsi) untuk peristiwa frameReceived, modeChanged, dan streamReceived dari kelas BVSP.
- Fungsi lingkaran :Fungsi ini melakukan lima tindakan penting:meminta info status ke server (fungsi keepAlive()); memeriksa apakah server telah mengirim data apa pun dan memproses data yang diterima (fungsi receiver()); mengontrol perekaman dan pengiriman aliran audio (fungsi isSREAvailable(), startRecording(), stopRecording() dan sendStream()); memutar sampel audio yang dimasukkan ke dalam kelas BVSSpeaker (fungsi play()); dan memanggil fungsi playNextLEDNote() yang mengontrol bagaimana LED harus berkedip setelah perintah playLEDNotes diterima.
- Fungsi BVSP_frameReceived :Fungsi ini dipanggil setiap kali fungsi receiver() mengidentifikasi bahwa satu frame lengkap telah diterima. Di sini saya menjalankan perintah yang dikirim dari BitVoicer Server. Perintah yang mengontrol LED berisi 2 byte. Byte pertama menunjukkan pin dan byte kedua menunjukkan nilai pin. Saya menggunakan fungsi analogWrite() untuk mengatur nilai yang sesuai ke pin. Saya juga memeriksa apakah perintah playLEDNotes, yang bertipe Byte, telah diterima. Jika sudah diterima, saya set playLEDNotes ke true dan menandai waktu saat ini. Kali ini akan digunakan oleh fungsi playNextLEDNote untuk menyinkronkan LED dengan lagu.
- BVSP_modeFungsi yang diubah :Fungsi ini dipanggil setiap kali fungsi receiver() mengidentifikasi perubahan mode pada arah keluar (Server --> Arduino). WOW!!! Apa itu?! BitVoicer Server dapat mengirim data berbingkai atau aliran audio ke Arduino. Sebelum komunikasi berpindah dari satu mode ke mode lainnya, Server BitVoicer mengirimkan sinyal. Kelas BVSP mengidentifikasi sinyal ini dan memunculkan event modeChanged. Dalam fungsi BVSP_modeChanged, jika saya mendeteksi komunikasi beralih dari mode streaming ke mode bingkai, saya tahu audio telah berakhir sehingga saya dapat memberi tahu kelas BVSSpeaker untuk berhenti memutar sampel audio.
- Fungsi yang diterima BVSP_stream :Fungsi ini dipanggil setiap kali fungsi receiver() mengidentifikasi bahwa sampel audio telah diterima. Saya cukup mengambil sampel dan memasukkannya ke dalam kelas BVSSpeaker sehingga fungsi play() dapat mereproduksinya.
- fungsi playNextLEDNote :Fungsi ini hanya berjalan jika fungsi BVSP_frameReceived mengidentifikasi perintah playLEDNotes. Ini mengontrol dan menyinkronkan LED dengan audio yang dikirim dari BitVoicer Server. Untuk menyinkronkan LED dengan audio dan mengetahui waktu yang tepat, saya menggunakan Sonic Visualizer. Perangkat lunak gratis ini memungkinkan saya untuk melihat gelombang audio sehingga saya dapat dengan mudah mengetahui kapan tuts piano ditekan. Itu juga menunjukkan garis waktu dan begitulah cara saya menggunakan milidetik dalam fungsi ini. Kedengarannya seperti trik konyol dan memang begitu. Saya pikir itu mungkin untuk menganalisis aliran audio dan menyalakan LED yang sesuai, tetapi itu di luar jangkauan saya.
LANGKAH 3:Mengimpor Objek Solusi Server BitVoicer
Sekarang Anda harus mengatur Server BitVoicer untuk bekerja dengan Arduino. BitVoicer Server memiliki empat objek solusi utama:Lokasi, Perangkat, BinaryData, dan Skema Suara.
Lokasi mewakili lokasi fisik tempat perangkat dipasang. Dalam kasus saya, saya membuat lokasi bernama Home.
Perangkat adalah klien Server BitVoicer. Saya membuat perangkat Campuran, menamakannya ArduinoDUE dan memasuki pengaturan komunikasi. PENTING :bahkan Arduino DUE memiliki sedikit memori untuk menyimpan semua sampel audio yang akan dialirkan oleh BitVoicer Server. Jika Anda tidak membatasi bandwidth, Anda akan membutuhkan buffer yang jauh lebih besar untuk menyimpan audio. Saya mendapat beberapa buffer overflow karena alasan ini, jadi saya harus membatasi Kecepatan Data dalam pengaturan komunikasi hingga 8000 sampel per detik.
BinaryData adalah jenis perintah yang dapat dikirim oleh BitVoicer Server ke perangkat klien. Mereka sebenarnya adalah array byte yang dapat Anda tautkan ke perintah. Ketika BitVoicer Server mengenali ucapan yang terkait dengan perintah itu, ia mengirimkan array byte ke perangkat target. Saya membuat satu objek BinaryData untuk setiap nilai pin dan menamakannya ArduinoDUEGreenLedOn, ArduinoDUEGreenLedOff dan seterusnya. Saya berakhir dengan 18 objek BinaryData dalam solusi saya, jadi saya sarankan Anda mengunduh dan mengimpor objek dari VoiceSchema.sof file di bawah ini.
Skema Suara adalah tempat segala sesuatu menyatu. Mereka menentukan kalimat apa yang harus dikenali dan perintah apa yang harus dijalankan. Untuk setiap kalimat, Anda dapat menentukan perintah sebanyak yang Anda butuhkan dan urutan eksekusinya. Anda juga dapat menentukan penundaan antar perintah. Begitulah cara saya berhasil melakukan urutan tindakan yang Anda lihat di video.
Salah satu kalimat dalam Skema Suara saya adalah “mainkan lagu kecil”. Kalimat ini mengandung dua perintah. Perintah pertama mengirimkan byte yang menunjukkan perintah berikut akan menjadi aliran audio. Arduino kemudian mulai "memutar" LED saat audio sedang ditransmisikan. Audionya adalah jingle piano kecil yang saya rekam sendiri dan atur sebagai sumber audio dari perintah kedua. BitVoicer Server hanya mendukung audio 8-bit mono PCM (8000 sampel per detik) jadi jika Anda perlu mengonversi file audio ke format ini, saya sarankan alat konversi online berikut:http://audio.online-convert.com/convert -ke-wav.
Anda dapat mengimpor (Mengimpor Objek Solusi) semua objek solusi yang saya gunakan dalam proyek ini dari file di bawah ini. Satu berisi Perangkat DUE dan yang lainnya berisi Skema Suara dan Perintahnya.
File Objek Solusi :
LANGKAH 4:Kesimpulan
Ini dia! Anda dapat mengaktifkan semuanya dan melakukan hal yang sama seperti yang ditampilkan dalam video.
Seperti yang saya lakukan di proyek saya sebelumnya, saya memulai pengenalan suara dengan mengaktifkan perangkat Arduino di Manajer Server BitVoicer. Segera setelah diaktifkan, Arduino mengidentifikasi Mesin Pengenalan Suara yang tersedia dan mulai mengalirkan audio ke Server BitVoicer. Namun, sekarang Anda melihat lebih banyak aktivitas di Arduino RX LED saat audio sedang dialirkan dari BitVoicer Server ke Arduino.
Dalam proyek saya berikutnya, saya akan sedikit lebih ambisius. Saya akan menambahkan komunikasi WiFi ke satu Arduino dan mengontrol dua Arduino lainnya bersama-sama dengan suara. Saya sedang memikirkan semacam permainan di antara mereka. Saran sangat diharapkan!
Kode
Sketsa ArduinoArduino
#include #include #include #include // Mendefinisikan pin Arduino yang akan digunakan untuk menangkap audio #define BVSM_AUDIO_INPUT 7// Mendefinisikan pin LED#define RED_LED_PIN 6#define YELLOW_LED_PIN 9#define GREEN_LED_PIN 10// Mendefinisikan konstanta yang akan diteruskan sebagai parameter ke // fungsi BVSP.beginconst unsigned long STATUS_REQUEST_TIMEOUT =3000;const unsigned long STATUS_RE =4000 STATUS_RE Mendefinisikan ukuran mic audio buffer const int MIC_BUFFER_SIZE =64;// Mendefinisikan ukuran speaker audio bufferconst int SPEAKER_BUFFER_SIZE =128;// Mendefinisikan ukuran menerima bufferconst int RECEIVE_BUFFER_SIZE =2;// Menginisialisasi instance global baru dari kelas BVSP BVSP bvsp =BVSP();// Menginisialisasi instance global baru dari kelas BVSMic BVSMic bvsm =BVSMic();// Menginisialisasi instance global baru dari kelas BVSSpeaker BVSSpeaker bvss =BVSSpeaker();// Membuat buffer yang akan digunakan untuk membaca sampel yang direkam // dari t he BVSMic class byte micBuffer[MIC_BUFFER_SIZE];// Membuat buffer yang akan digunakan untuk menulis sampel audio // ke dalam BVSSpeaker class byte speakerBuffer[SPEAKER_BUFFER_SIZE];// Membuat buffer yang akan digunakan untuk membaca perintah yang dikirim// dari BitVoicer Server.// Byte 0 =nomor pin// Byte 1 =nilai pin receiverBuffer[RECEIVE_BUFFER_SIZE];// Variabel ini digunakan untuk mengontrol kapan harus memutar// "LED Notes". Catatan ini akan dimainkan bersama // lagu yang dialirkan dari BitVoicer Server.bool playLEDNotes =false;unsigned int playStartTime =0;void setup() { // Mengatur mode pin pinMode(RED_LED_PIN, OUTPUT); pinMode(KUNING_LED_PIN, KELUARAN); pinMode(GREEN_LED_PIN, OUTPUT); // Menyetel status awal semua LED digitalWrite(RED_LED_PIN, LOW); digitalWrite(KUNING_LED_PIN, RENDAH); digitalWrite(GREEN_LED_PIN, RENDAH); // Memulai komunikasi serial pada 115200 bps Serial.begin(115200); // Mengatur port serial Arduino yang akan digunakan untuk // komunikasi, berapa lama waktu yang dibutuhkan sebelum permintaan status // habis dan seberapa sering permintaan status harus dikirim ke // Server BitVoicer. bvsp.begin(Serial, STATUS_REQUEST_TIMEOUT, STATUS_REQUEST_INTERVAL); // Mendefinisikan fungsi yang akan menangani frameReceived // event bvsp.frameReceived =BVSP_frameReceived; // Menetapkan fungsi yang akan menangani modeChanged // event bvsp.modeChanged =BVSP_modeChanged; // Menetapkan fungsi yang akan menangani streamReceived // event bvsp.streamReceived =BVSP_streamReceived; // Menyiapkan pengatur waktu kelas BVSMic bvsm.begin(); // Menetapkan DAC yang akan digunakan oleh kelas BVSSpeaker bvss.begin(DAC);}void loop() { // Memeriksa apakah interval permintaan status telah berlalu dan jika // telah, mengirimkan permintaan status ke Server BitVoicer bvsp.keepAlive(); // Memeriksa apakah ada data yang tersedia di buffer port serial // dan memproses kontennya sesuai dengan spesifikasi // Protokol Server BitVoicer bvsp.receive(); // Memeriksa apakah ada satu SRE yang tersedia. Jika ada, // mulai merekam. if (bvsp.isSREAvailable()) { // Jika kelas BVSMic tidak merekam, atur input audio // dan mulai merekam if (!bvsm.isRecording) { bvsm.setAudioInput(BVSM_AUDIO_INPUT, DEFAULT); bvsm.startRecording(); } // Memeriksa apakah kelas BVSMic memiliki sampel yang tersedia if (bvsm.available) { // Memastikan mode masuk adalah STREAM_MODE sebelum // mentransmisikan aliran if (bvsp.inboundMode ==FRAMED_MODE) bvsp.setInboundMode(STREAM_MODE); // Membaca sampel audio dari kelas BVSMic int byteRead =bvsm.read(micBuffer, MIC_BUFFER_SIZE); // Mengirim aliran audio ke BitVoicer Server bvsp.sendStream(micBuffer, bytesRead); } } else { // Tidak ada SRE yang tersedia. Jika kelas BVSMic sedang merekam, // menghentikannya. if (bvsm.isRecording) bvsm.stopRecording(); } // Memutar semua sampel audio yang tersedia di kelas BVSSpeaker // buffer internal. Contoh-contoh ini ditulis dalam event handler // BVSP_streamReceived. Jika tidak ada sampel // tersedia di buffer internal, tidak ada yang dimainkan. bvss.play(); // Jika playLEDNotes telah disetel ke true, // memainkan "LED note" bersama dengan musiknya. if (playLEDNotes) playNextLEDNote();}// Menangani event frameReceived void BVSP_frameReceived(byte dataType, int payloadSize) { // Memeriksa apakah frame yang diterima berisi data biner // 0x07 =Data biner (byte array) if (dataType ==DATA_TYPE_BINARY) { // Jika 2 byte diterima, proses perintah. if (bvsp.getReceivedBytes(receiveBuffer, RECEIVE_BUFFER_SIZE) ==RECEIVE_BUFFER_SIZE) { analogWrite(receiveBuffer[0], acceptBuffer[1]); } } // Memeriksa apakah frame yang diterima berisi tipe data byte // 0x01 =Tipe data byte else if (tipe data ==DATA_TYPE_BYTE) { // Jika nilai byte yang diterima adalah 255, set playLEDNotes // dan tandai waktu saat ini. if (bvsp.getReceivedByte() ==255) { playLEDNotes =true; playStartTime =milis(); } }}// Menangani event modeChanged void BVSP_modeChanged() { // Jika outboundMode (Server --> Device) telah berubah menjadi // FRAMED_MODE, tidak ada aliran audio yang seharusnya diterima. // Memberi tahu kelas BVSSpeaker untuk menyelesaikan pemutaran saat // buffer internalnya kosong. if (bvsp.outboundMode ==FRAMED_MODE) bvss.finishPlaying();} // Menangani acara streamReceived void BVSP_streamReceived(int size) { // Mendapatkan aliran yang diterima dari kelas BVSP int byteRead =bvsp.getReceivedStream(speakerBuffer, SPEAKER_BUFFER_S; // Mengantrekan aliran yang diterima untuk memutar bvss.enqueue(speakerBuffer, bytesRead);}// Menyalakan LED yang sesuai berdasarkan waktu // perintah untuk mulai memutar not LED diterima.// Pengaturan waktu yang digunakan di sini disinkronkan dengan the music.void playNextLEDNote(){ // Mendapatkan waktu yang telah berlalu antara playStartTime dan // waktu saat ini. unsigned long elapsed =milis() - playStartTime; // Mematikan semua LED allLEDsOff(); // Not terakhir telah dimainkan. // Mematikan LED terakhir dan berhenti memainkan not LED. if (berlalu>=11500) { analogWrite(RED_LED_PIN, 0); playLEDNotes =salah; } else if (berlalu>=9900) analogWrite(RED_LED_PIN, 255); // C catat else if (berlalu>=9370) analogWrite(RED_LED_PIN, 255); // C catat else if (berlalu>=8900) analogWrite(YELLOW_LED_PIN, 255); // D catat else if (berlalu>=8610) analogWrite(RED_LED_PIN, 255); // C catat else if (berlalu>=8230) analogWrite(YELLOW_LED_PIN, 255); // D catat else if (berlalu>=7970) analogWrite(YELLOW_LED_PIN, 255); // D catat else if (berlalu>=7470) analogWrite(RED_LED_PIN, 255); // C catat else if (berlalu>=6760) analogWrite(GREEN_LED_PIN, 255); // E catat else if (berlalu>=6350) analogWrite(RED_LED_PIN, 255); // C catat else if (berlalu>=5880) analogWrite(YELLOW_LED_PIN, 255); // D catat else if (berlalu>=5560) analogWrite(RED_LED_PIN, 255); // C catat else if (berlalu>=5180) analogWrite(YELLOW_LED_PIN, 255); // D catat else if (berlalu>=4890) analogWrite(YELLOW_LED_PIN, 255); // D catat else if (berlalu>=4420) analogWrite(RED_LED_PIN, 255); // C catat else if (berlalu>=3810) analogWrite(GREEN_LED_PIN, 255); // E catat else if (berlalu>=3420) analogWrite(RED_LED_PIN, 255); // C catat else if (berlalu>=2930) analogWrite(YELLOW_LED_PIN, 255); // D catat else if (berlalu>=2560) analogWrite(RED_LED_PIN, 255); // C catat else if (berlalu>=2200) analogWrite(YELLOW_LED_PIN, 255); // D catat else if (berlalu>=1930) analogWrite(YELLOW_LED_PIN, 255); // D catat else if (berlalu>=1470) analogWrite(RED_LED_PIN, 255); // C catat else if (berlalu>=1000) analogWrite(GREEN_LED_PIN, 255); // E note}// Mematikan semua LEDs.void allLEDsOff(){ analogWrite(RED_LED_PIN, 0); analogWrite(KUNING_LED_PIN, 0); analogWrite(GREEN_LED_PIN, 0);}
Skema