Saat ini saya sedang mengerjakan proyek # 14 dari buku proyek Arduino.
Saya mencoba mengendalikan sketsa pemrosesan di laptop saya menggunakan Arduino saya. Ini dilakukan dengan menggunakan potensiometer untuk mengontrol latar belakang suatu gambar.
Kode Arduino:
void setup(){
Serial.begin(9600);
}
void loop(){
Serial.write(analogRead(A0)/4);
}
Pengolahan:
//imports serial library
import processing.serial.*;
//setups the serial object
Serial myPort;
//creates an object for the image
PImage logo;
//variable to store background color
int bgcolor = 0;
void setup(){
colorMode(HSB,255);
logo = loadImage("http://arduino.cc/logo.png");
size(logo.width,logo.height);
println("Available serial ports");
println(Serial.list());
myPort = new Serial(this,Serial.list()[0],9600);
}
//equivalent of arduino's loop function
void draw(){
if(myPort.available() > 0)
{
bgcolor = myPort.read();
println(bgcolor);
}
background(bgcolor,255,255);
image(logo,0,0);
}
Sekarang, ketika kode bekerja, dan warna latar belakang berubah ketika saya mengaktifkan potensiometer, ada jeda yang sangat besar antara memutar potensiometer dan melihat warna latar belakang berubah, dan nilai-nilai dari Arduino / potensiometer berubah pada monitor serial pemrosesan.
Apa yang saya coba:
- Mengubah kecepatan komunikasi serial
Saya perhatikan bahwa ketika saya mengurangi kecepatan komunikasi serial, misalnya sekitar 100, penundaan antara memutar potensiometer dan melihatnya berubah pada laptop saya berkurang sekitar 1 detik. Namun, ketika saya mengurangi kecepatan komunikasi Serial lebih jauh, misalnya nilai 1, penundaan meningkat lagi.
Di sisi lain, pada kecepatan standar 9600, penundaan sangat besar, kira-kira 5 detik ++ sebelum perubahan potensiometer muncul di laptop / pemrosesan.
Mengapa mengurangi kecepatan komunikasi (hingga titik tertentu) mengurangi jeda waktu, dan meningkatkannya meningkatkan jeda waktu? Juga, adakah di sana saya bisa membuatnya dekat sesaat?
sumber
loop()
. Sangat mungkin bahwa program Pemrosesan Anda tidak berjalan cukup cepat untuk mengikutinya. Coba tundaloop()
kode Arduino Anda untuk memperlambatnya; misdelay(50)
.Jawaban:
Anda menghasilkan bacaan setiap saat di sekitar Arduino
loop()
, jadi sepertinya program Pemrosesan Anda tidak berjalan cukup cepat untuk mengikutinya. Coba tundaloop()
kode Arduino Anda untuk memperlambatnya, misalnya:Sejauh yang saya tahu, Memproses bertujuan untuk berjalan pada framerate yang konsisten, yang dapat Anda modifikasi menggunakan
frameRate()
fungsi. Secara default, ini 60 frame per detik, meskipun mungkin berjalan lebih lambat pada sistem yang lebih lama (atau di mana Anda menjalankan program intensif). Anda dapat memeriksa seberapa cepat itu berjalan dengan membacaframeRate
variabel.Memperkenalkan penundaan 50 milidetik ke dalam loop Arduino berarti akan memperbarui sedikit di bawah 20 kali per detik. Itu berarti harus cukup cepat untuk keperluan antarmuka pengguna, tetapi juga harus sesuai dengan kemampuan program Pemrosesan Anda.
Sejauh baud rate (kecepatan komunikasi) yang bersangkutan, menyesuaikannya dengan jumlah yang sewenang-wenang cenderung memiliki hasil yang tidak terduga. Itu karena perangkat keras hanya akan mendukung kecepatan tertentu, dan mencoba menggunakan hal lain dapat menyebabkan data tampak kacau di ujung yang lain. The
Serial.begin()
dokumentasi memiliki beberapa informasi lebih lanjut tentang tarif baud yang didukung.sumber
Seperti yang sudah ditunjukkan, Arduino Anda mengatakan terlalu cepat. Menambahkan
delay()
akan memperlambatnya, tetapi tetap saja berteriak pada Pemrosesan. Idealnya, Anda ingin Memproses meminta nilai ketika itu nyaman, dan kemudian menerima satu jawaban dari Arduino Anda.Masukkan
SerialEvent()
.Berbeda dengan
loop()
di Arduino Anda dandraw()
di Pemrosesan, semua yang ada di dalamnyaserialEvent()
hanya mengeluarkan ketika ada sesuatu yang baru di buffer serial. Jadi, alih-alih Memproses mengajukan pertanyaan secepat mungkin dan Arduino Anda berteriak lebih cepat, mereka dapat melakukan percakapan yang baik, sopan (tidak sinkron).Baik Processing dan Arduino memiliki serialEvent. Ini adalah serialEvent () pada Arduino dan ini adalah serialEvent () dalam Pemrosesan. Menggunakan serialEvent di kedua sisi, inilah yang akan terjadi:
Memproses mengirim karakter ke koneksi serial. Ini bisa berupa karakter apa saja, tetapi jika kita menentukan sebelumnya, kita dapat menyaring permintaan yang tidak diinginkan yang disebabkan oleh misalnya sinyal berisik. Untuk contoh ini, mari kirim
V
setiap kali kami ingin membaca potmeter baru Anda. Setelah karakter dikirim, kami melanjutkan bisnis kami seperti biasa. Tidak menunggu jawaban di sini!Di sisi Arduino tidak ada yang terjadi, sampai menerima data dalam buffer serial. Ia memeriksa apakah karakter yang masuk adalah
V
, dan beruntung kita, itu. Arduino membaca nilai potmeter satu kali, menampilkan nilai itu ke serial sekali, dan kembali ke bersantai, maxing santai semua keren. Protip: mengakhiri nilai dengan karakter (*
dalam kasus kami). Ini akan membantu Anda pada langkah selanjutnya.Pemrosesan sedang melakukan bisnis pixel antarmuka-nya yang biasa ketika tiba-tiba ada
gangguan pada kekuatandata baru di buffer serial. Itu beralih keserialEvent()
, dan mulai membaca data serial, sampai penghentian kami*
ditemui. Mengetahui dengan pasti ini adalah karakter terakhir yang layak dibaca, kita sekarang dapat menyimpan nilai yang masuk dalam variabel yang menyimpan bacaan Arduino.Itu dia. Pemrosesan sekarang tahu nilai sensor baru dan melanjutkan dengan apa pun yang kami perintahkan. Sementara itu, Arduino Anda menikmati cuaca atau merenungkan keberadaannya hingga ada data serial yang masuk.
sumber
Putaran polling Anda berjalan dengan kecepatan penuh dari prosesor Anda, dan menulis ke port serial di setiap putaran.
Dengan cara ini, Anda menulis lebih sering ke port serial daripada yang bisa ditangani.
Port menulis data secepat Anda mengkonfigurasinya, dan buffer data yang masuk dari program Anda terlalu cepat , untuk menuliskannya sesegera mungkin. Jika buffer sudah penuh, itu hanya akan menjatuhkan data baru.
Yang penting di sini adalah bahwa hal itu akan menjaga urutan nilai-nilai: Ini adalah buffer FIFO , bekerja dalam urutan First In / First Out.
Yang terjadi adalah:
Loop mengisi buffer port, dan membuatnya 100% penuh.
Jika Anda mengaktifkan potensiometer, nilai yang diubah dapat ditulis ke akhir buffer , port bekerja secepat mungkin untuk menuliskan semua elemen dalam buffer, yang masih memiliki nilai lama.
Dan akhirnya nilai yang Anda minati. Nilai terbaru yang ingin kami lihat segera adalah di akhir FIFO, dan first in / first out juga berarti last in / last out. Kebalikan dari yang kita inginkan.
Frekuensi maksimum yang masuk akal untuk membaca data Anda, adalah frekuensi Anda dapat menuliskannya, jadi Anda harus menggunakan setidaknya penundaan yang cukup lama untuk menulis byte pada kecepatan port saat ini.
Sebagai ukuran lain yang independen untuk mencegah keterlambatan semacam ini secara umum,
Anda juga dapat mengatur buffer penulisan port ke minimum.
Itu akan menyebabkan data akan turun lebih awal, daripada banyak buffer terlebih dahulu.
Tentu saja, dalam banyak aplikasi bukan itu yang Anda butuhkan; Dengan nasib buruk, itu bisa tetap bekerja di awal, dan menjadi tidak stabil dalam beberapa situasi ketika waktu berubah berdasarkan pada hal-hal seperti beban prosesor, dan hanya ada beberapa sampel data acak yang turun. Buffer besar umumnya berperilaku jauh lebih deterministik, jadi gunakan buffer besar secara default .
sumber
Alih-alih terus mengirim data serial, hanya mengirim data ketika nilai potensiometer telah berubah pada ambang batas tertentu.
sumber
loop()
tidak mengisi buffer output dengan sampel yang sama, itu bagus. Tetapi masih berjalan dengan kecepatan penuh dari prosesor, yang mungkin 100 kali lebih cepat dari yang dibutuhkan. Itu berarti masih dapat mengisi buffer ke batas dengan cepat jika input sering berubah, misalnya dari kebisingan di atasthreshold
, atau perubahan terus-menerus dalam resolusi tinggi (yang tidak terjadi dalam contoh aplikasi di sini)Dua solusi sederhana yang dijamin bekerja untuk siapa saja yang masih mencari: -
Tingkatkan penundaan hingga 50 hingga 100 milidetik.
Tambahkan ini setelah
Serial.begin(9600)
disetup()
;Langkah kedua adalah yang paling penting. Ini bekerja untuk saya hanya setelah saya menambahkan kode di atas. Ini tidak disebutkan sangat sering di banyak forum lain yang saya lihat ketika saya memiliki masalah yang sama persis.
sumber