Pengaturcara dan Kelewatan Pengekodan di Arduino

Kemas kini 5 Sept 2019: Mengalih keluar kelewatan () panggilan adalah langkah pertama untuk mencapai pelbagai tugas mudah pada mana-mana papan Arduino. Mudah-mudahan Mudah Multi-tugas di Arduino di mana-mana Lembaga meliputi semua langkah-langkah lain yang diperlukan.

Kemas kini 5 Mei 2019: Dinamakan semula IsFinished () kepada justFinished (), kerana ia hanya kembali TRUE sekali selepas selesai penangguhan. Menambah contoh pendedahan / Jeda sementara

Pengenalan

Jangan gunakan kelewatan ()

Menggunakan kelewatan () menyebabkan sistem anda terperangkap ketika menunggu penangguhan berakhir. Namun menggantikan penangguhan memerlukan perhatian. Halaman ini menerangkan dengan langkah demi langkah cara mengganti kelewatan Arduino () dengan versi tidak menghalang yang membolehkan anda kod untuk terus berjalan sambil menunggu penangguhan ke waktu.

Berikut adalah beberapa lakaran mudah yang masing-masing mengubah Led pada apabila papan Arduino dikuasakan (atau ditetapkan semula) dan kemudian 10sec kemudiannya mematikannya. Yang pertama ialah contoh bagaimana anda TIDAK perlu menulis kod itu. Yang kedua ialah contoh kod kerja dan yang ketiga ialah contoh menggunakan perpustakaan millisDelay untuk mempermudahkan kod. Terdapat juga contoh single-shot dan pengulang masa.

Jika anda sudah mengerti mengapa anda tidak perlu menggunakan kelewatan () dan sudah biasa dengan Arduino, pentingnya menggunakan longs unsigned, limpahan dan penolakan yang tidak ditandatangani, maka anda hanya boleh melompat ke Menggunakan pustaka millisDelay (Langkah 4)

Perpustakaan millisDelay menyediakan kelewatan dan pemasa fungsi, mudah digunakan dan mudah difahami bagi mereka yang baru untuk Arduino.

Ini boleh dipelajari juga dalam talian di Bagaimana untuk kod Pemasa dan Kelewatan dalam Arduino

Langkah 1: Bagaimana Tidak Kod Keterlambatan dalam Arduino

Inilah caranya TIDAK untuk mengodkan kelewatan dalam lakaran.

 int led = 13; 
kelewatan lama yang tidak ditandatanganiStart = 0; // masa kelewatan mula kelewatan boolRunning = false; // benar jika masih menunggu penangguhan selesai
void setup () {pinMode (led, OUTPUT); // Inisikan pin digit sebagai output. digitalWrite (diketuai, TINGGI); / // berpaling menangguhkan kelewatanStart = millis (); // memulakan kelewatan tundaRunning = true; / belum selesai}
void loop () {// check if delay has been timed after 10sec == 10000mS if (delayRunning && ((millis () - delayStart)> = 10000)) {delayRunning = false; // // mencegah kod ini berjalan lebih lama sekali apabila digitalWrite (led, LOW); // berpaling menghidupkan Serial.println ("Turned LED Off"); } // Kod gelung lain di sini. . . Serial.println ("Jalankan Kod Lain"); }

Dalam kaedah persediaan (), yang Arduino panggilan sekali memulakan, pukulan dihidupkan. Setelah persediaan () selesai, Arduino memanggil kaedah gelung () berulang-ulang. Ini adalah di mana kebanyakan kod anda pergi, membaca sensor menghantar output dan lain-lain. Dalam lakaran di atas, gelung kali pertama () dipanggil, kelewatan (10000) menghentikan segala-galanya selama 10secs sebelum mematikan dan meneruskan. Sekiranya anda menjalankan kod ini, anda akan melihat bahawa Run Code lain tidak dicetak untuk 10sec selepas permulaan, tetapi selepas yang dipimpin dimatikan (ledOn sama dengan palsu) maka dicetak dengan cepat seperti gelung () dipanggil lebih dari satu sekali lagi.

Titik yang perlu diperhatikan di sini adalah bahawa anda tidak sepatutnya tidak menangguhkan () fungsi sama sekali dalam gelung () kod. Ia kadang-kadang mudah untuk menggunakan kelewatan () dalam kod persediaan () dan anda sering boleh lari dengan sangat kecil menggunakan penangguhan yang sangat kecil beberapa milisaat dalam kod gelung (), tetapi anda benar-benar harus mengelakkan menggunakan sama sekali dalam kaedah gelung ()

Langkah 2: Cara Menulis Kelewatan Tidak Menyekat di Arduino

Lakaran terdahulu menggunakan kelewatan menyekat, iaitu satu yang menghentikan kod tersebut daripada melakukan apa-apa lagi sementara kelewatan itu menunggu untuk tamat tempoh. Lakaran seterusnya ini menunjukkan kepada anda cara menulis kelewatan tanpa penyekat yang membolehkan kod tersebut terus berjalan sambil menunggu penangguhan berakhir.

 int led = 13; 
kelewatan lama yang tidak ditandatanganiStart = 0; // masa kelewatan mula kelewatan boolRunning = false; // benar jika masih menunggu kelewatan untuk menyelesaikan persetujuan tidak sah () {pinMode (dipimpin, OUTPUT); // Inisikan pin digit sebagai output. digitalWrite (diketuai, TINGGI); / // berpaling menangguhkan kelewatanStart = millis (); // memulakan kelewatan tundaRunning = true; // belum selesai} void loop () {// periksa jika kelewatan telah tamat selepas 10sec == 10000mS jika (delayRunning && ((millis () - delayStart)> = 10000)) {delayRunning = false; // // mencegah kod ini berjalan lebih lama sekali apabila digitalWrite (led, LOW); // berpaling menghidupkan Serial.println ("Turned LED Off"); } // Kod gelung lain di sini. . . Serial.println ("Jalankan Kod Lain"); }

Dalam lakaran di atas, dalam kaedah persediaan (), pemboleh ubah LarianStart ditetapkan kepada nilai semasa millis () .

millis () adalah kaedah terbina dalam yang mengembalikan jumlah milisaat sejak lembaga dikuasakan. Ia bermula sebagai 0 setiap kali papan ditetapkan semula dan ditambah setiap millisecond oleh kaunter perkakasan CPU. Lebih lanjut mengenai millis () kemudian. Setelah persediaan () selesai, Arduino memanggil kaedah gelung () berulang-ulang.

Setiap gelung masa () dipanggil cek kod
a) bahawa kelewatan masih berjalan, dan
b) jika millis () telah bergerak ke atas 10000 mS (10sec) dari nilai yang disimpan dalam kelewatan Mula .

Apabila masa telah dipindahkan oleh 10000mS atau lebih, maka delayRunning ditetapkan kepada palsu untuk menghalang kod dalam pernyataan jika dijalankan lagi dan yang dipimpin dimatikan.

Sekiranya anda menjalankan lakaran ini, anda akan melihat Run Kod Lain yang dicetak dengan cepat dan selepas 10sec Led akan dimatikan dan jika anda cepat anda mungkin melihat mesej Turned LED Off sebelum ia menatal dari skrin.

Lihat Langkah 4, di bawah untuk bagaimana perpustakaan millisDelay memudahkan kod ini

Langkah 3: Penolakan Panjang, Limpahan dan Unsigned Unsigned

Sekiranya anda sudah biasa dengan jangka panjang yang tidak ditandatangani, limpahan, aritmetik yang tidak ditandatangani dan kepentingan menggunakan pemboleh ubah lama yang tidak ditandatangani, maka anda boleh melangkau ke Langkah 4 Menggunakan perpustakaan millisDelay.

Bahagian penting lakaran sebelumnya adalah ujian

 (millis () - delayStart)> = 10000 

Ujian ini perlu dikodkan dengan cara yang sangat spesifik untuk berfungsi.

Unsigned Long and Overflow

Pemboleh ubah dan bilangan penundaanStart yang kembali dari millis () fungsi terbina dalam adalah panjang tidak ditandatangani . Itu nombor dari 0 hingga 4, 294, 967, 295.

Sekiranya anda menambah 1 kepada yang tidak ditandatangani lama yang memegang nilai maksimum 4, 294, 967, 295 jawapannya akan menjadi 0 (sifar). Itulah angka yang melimpah dan dibungkus kembali ke 0. Anda boleh bayangkan sedikit limpahan itu hanya akan jatuh. contohnya dalam 3 bit unsigned 111 adalah nilai maksimum (7) dan menambahkan 1 memberikan 1000 (8) tetapi yang pertama 1 melimpahi penyimpanan 3 bit dan dijatuhkan sehingga membungkus kembali ke 000.

Ini bermakna, akhirnya, apabila cpu menambahkan satu lagi pembolehubah yang memegang hasil millis () maka ia akan membungkus ke 0. Itu adalah millis () akan mula mengira dari 0 lagi. Ini akan berlaku jika anda meninggalkan papan Arduino anda berjalan untuk 4, 294, 967, 295mS iaitu kira-kira 49 hari 17hrs, katakan 50 hari.

Sekarang mari kita pertimbangkan satu lagi cara pengekodan ujian (millis () - delayStart)> = 10000

Arithmetically ujian ini sama dengan millis ()> = (delayStart + 10000)

Walau bagaimanapun, jika anda memulakan kelewatan selepas hampir 50 hari, contohnya apabila millis () mengembalikan 4, 294, 966, 300 mS, maka delayStart + 10000 akan melimpah ke 995 dan ujian, millis ()> = (delayStart + 10000), akan segera menjadi benar dan di sana tidak akan ditangguhkan sama sekali. Jadi bentuk ujian ini tidak selalu berfungsi.

Sayangnya, anda tidak dapat menemui ini semasa ujian anda, tetapi untuk itu mungkin timbul un-expectedly dalam peranti yang lama, seperti kawalan pintu garasi yang berterusan selama berbulan-bulan. Anda akan mendapat masalah yang sama jika anda cuba dan menggunakannya
delayEnd = millis () + 10000
dan kemudian ujian (millis ()> = delayEnd)

Akhirnya pemboleh ubahStart yang sepatutnya mesti panjang tidak bertanda . Sekiranya anda sebaliknya menggunakan int panjang (ie int panjang ) atau int atau unsigned, nilai maksima yang boleh dipegang adalah lebih kecil daripada panjang unsigned yang dikembalikan daripada millis () . Akhirnya nilai retuned dari millis () akan melimpahkan pembolehubah yang lebih kecil yang disimpan di dalamnya dan anda akan mendapati masa telah tiba-tiba pergi ke belakang. Sebagai contoh, jika anda menggunakan int unsigned untuk startDelay, ini akan berlaku selepas 65 saat pada papan Uno.

Penolakan Unsigned

Satu lagi perkara yang menarik adalah apa yang berlaku akibat millis () - delayLangkah apabila kelewatanStart dikatakan 4, 294, 966, 300 dan kami ingin penundaan 10000mS.

millis () akan membungkus hingga 0 sebelum itu berlaku. Ingat bahawa menambahkan 1 kepada nilai maksimum yang tidak ditandatangani panjang boleh menyimpan bungkus sekitar kembali ke 0. Jadi satu cara untuk melihat pengiraan millis () - delayStart, di mana millis () telah dibalut dan lebih kecil kemudian delayStart, adalah untuk mengatakan "W nombor topi yang perlu saya tambah untuk menangguhkanStart ke millis sama () (selepas overflow)? "iaitu apakah X dalam kelewatan persamaanStart + X == millis ()

Contohnya dengan menggunakan pemboleh ubah 3 bit sekali lagi, untuk mengira 2 - 4 (unsigned), fikirkan wajah jam bermula pada 0 dan tambah 1 sepanjang jalan ke 111 (7) dan kemudian kembali ke 0. Sekarang untuk mendapatkan dari 4 hingga 2 anda perlu menambah 6 (5, 6, 7, 0, 1, 2) sehingga 2-4 = 6 dan ini berlaku bagaimana perhitungan berfungsi, walaupun CPU akan melakukan pengiraan dengan cara yang berbeda.

Oleh itu, perbezaan dua lagu yang tidak ditandatangani akan sentiasa menjadi nombor positif dalam julat 0 hingga 4, 294, 967, 295. Sebagai contoh jika startDelay adalah 1 dan millis () telah dibalut ke 0 (selepas 50 hari) maka millis () - startDelay akan sama dengan 4, 294, 967, 295. Ini bermakna anda boleh menentukan DELAY_TIME di mana saja di julat 0 hingga 4, 294, 967, 295 mS dan (millis () - delayStart)> = DELAY_TIME akan sentiasa berfungsi seperti yang diharapkan, tanpa mengira waktu penangguhan bermula.

Langkah 4: Menggunakan Perpustakaan MillisDelay

Untuk memasang perpustakaan millisDelay. Muat turun fail millisDelay.zip.

Unzip fail ini ke direktori Arduino / perpustakaan anda (buka IDE File-> pilihan tetingkap untuk melihat di mana direktori Arduino anda adalah). Beberapa kali arahan untuk Memasang Perpustakaan - Kerja pemasangan automatik, tetapi tidak semestinya. Mengosongkan fail secara manual adalah yang paling selamat. Sebaik sahaja anda memasang perpustakaan millisDelay, terdapat tiga contoh interaktif yang tersedia yang boleh anda muatkan pada papan Arduino anda dan kemudian buka Monitor Serial (dalam 5sec) pada 9600baud untuk menggunakannya. Ini adalah lakaran penangguhan yang tidak dilarang sebelumnya yang dilarang menggunakan perpustakaan millisDelay.

 #include "millisDelay.h" int led = 13; millisDelay ledDelay; void setup () {pinMode (led, OUTPUT); // Inisikan pin digit sebagai output. digitalWrite (diketuai, TINGGI); / // berpaling mengetuai ledDelay.start (10000); / / memulakan kelewatan 10sec} void loop () {// periksa jika kelewatan telah tamat masa jika (ledDelay.justFinished ()) {digitalWrite (led, LOW); // berpaling menghidupkan Serial.println ("Turned LED Off"); } // Kod gelung lain di sini. . . Serial.println ("Jalankan Kod Lain"); } 

Sekiranya anda melihat kod pustaka millisDelay, anda akan melihat bahawa kod lakaran sebelum ini baru sahaja dipindahkan ke permulaan () dan kaedah Selesai () di perpustakaan.

Adakah ini ledDelay atau leadTimer? Anda boleh menggunakan istilah yang anda suka. Saya cenderung untuk menggunakan ... kelewatan untuk penangguhan tunggal-tembakan yang melaksanakan sekali dan menggunakan ... timer untuk mengulangi.

Langkah 5: Contoh Kelewatan dan Pemasa

Berikut adalah dua penangguhan dasar dan lakaran pemasa dan setara millisDelay perpustakaan mereka. Contoh-contoh ini untuk kelewatan satu kali sahaja dan kelewatan / pemasa yang berulang.

Kelewatan Tunggal-Shot

Kelewatan ditembak tunggal adalah satu yang hanya berjalan sekali dan kemudian berhenti. Ini adalah penggantian paling langsung untuk kelewatan Arduino () . Anda memulakan penangguhan dan kemudian apabila selesai anda melakukan sesuatu. BasicSingleShotDelay adalah kod biasa dan SingleShotMillisDelay menggunakan perpustakaan millisDelay.

BasicSingleShotDelay

Lakaran ini boleh didapati di BasicSingleShotDelay.ino

 int led = 13; // Pin 13 mempunyai LED yang terhubung pada kebanyakan papan Arduino. 
unsigned lama DELAY_TIME = 10000; / // 10 sec lengah lama tidak ditandatanganiStart = 0; // masa kelewatan mula kelewatan boolRunning = false; // benar jika masih menunggu kelewatan untuk menyelesaikan persetujuan tidak sah () {pinMode (dipimpin, OUTPUT); // Inisikan pin digit sebagai output. digitalWrite (diketuai, TINGGI); / // berpaling menghidupkan // memulakan kelewatan kelewatanStart = millis (); delayRunning = true; } void loop () {// check if delay has set out if (delayRunning && ((millis () - delayStart)> = DELAY_TIME)) {delayRunning = false; // penangguhan selesai - satu tembakan, sekali sahaja digitalWrite (led, LOW); // berpaling daripada mati}}

Dalam kod di atas gelung () terus berjalan tanpa terperangkap menunggu penangguhan berakhir.
Semasa setiap pas gelung (), perbezaan antara millis semasa () dan masa kelewatan Masa berbanding dengan DELAY_TIME . Apabila pemasa melebihi nilai selang, tindakan yang diinginkan diambil. Dalam contoh ini pemasa tunda dihentikan dan LED dimatikan.

SingleShotMillisDelay

Berikut adalah lakaran BasicSingleShotDelay yang ditulis semula menggunakan perpustakaan millisDelay. Lakaran ini boleh didapati dalam SingleShotMillisDelay.ino

Berikut adalah versi millisDelay di mana kod di atas telah dibungkus dalam kaedah kelas kelas millisDelay.

 #include 

int led = 13; // Pin 13 mempunyai LED yang terhubung pada kebanyakan papan Arduino. millisDelay ledDelay; void setup () {// memulakan pin digit sebagai output. pinMode (dipimpin, OUTPUT); digitalWrite (diketuai, TINGGI); / // berpaling mengetuai // memulakan kelewatan ledDelay.start (10000); } void loop () {// cek jika kelewatan telah tamat jika (ledDelay.justFinished ()) {digitalWrite (led, LOW); // berpaling daripada mati}}

Berulang Kali

Ini adalah contoh mudah bagi kelewatan / pemasa yang berulang. BasicRepeatingDelay adalah kod biasa dan RepeatingMillisDelay menggunakan perpustakaan millisDelay.

BasicRepeatingDelay

Lakaran ini boleh didapati di BasicRepeatingDelay.ino

 int led = 13; // Pin 13 mempunyai LED yang terhubung pada kebanyakan papan Arduino. 
unsigned lama DELAY_TIME = 1500; // 1.5 sec lengah lama tidak ditandatanganiStart = 0; // masa kelewatan mula kelewatan boolRunning = false; // benar jika masih menunggu kelewatan untuk menyelesaikan bool ledOn = false; // menjejaki persediaan kekosongan negeri yang dipimpin () {pinMode (dipimpin, OUTPUT); // Inisikan pin digit sebagai output. digitalWrite (led, LOW); / // berpaling mengetuai ledOn = false; // memulakan kelewatan tundaStart = millis (); delayRunning = true; } void loop () {// check if delay has set out if (delayRunning && ((millis () - delayStart)> = DELAY_TIME)) {delayStart + = DELAY_TIME; // ini menghalang hanyutan dalam kelewatan // toggle yang diterajui ledOn =! ledOn; jika (ledOn) {digitalWrite (diketuai, TINGGI); / // berpaling pada} else {digitalWrite (led, LOW); // berpaling dari}}}

Sebab untuk menggunakannya
delayStart + = DELAY_TIME;
untuk menetap semula kelewatan untuk berjalan lagi, adakah ia membolehkan kemungkinan bahawa millis () - delayStart mungkin> DELAY_TIME kerana millis () baru bertambah atau disebabkan oleh beberapa kod lain dalam gelung () yang melambatkannya. Contohnya pernyataan cetak panjang. (Lihat Menambah Loop Montor di Langkah 7)

Satu lagi perkara ialah memulakan kelewatan pada akhir permulaan () . Ini memastikan pemasa adalah tepat pada permulaan gelung (), walaupun permulaan () mengambil sedikit masa untuk dilaksanakan.

MengulangiMillisDelay

Berikut adalah lakaran BasicRepeatingDelay yang ditulis semula menggunakan perpustakaan millisDelay. Lakaran ini boleh didapati di RepeatingMillisDelay.ino

 #include 
int led = 13; // Pin 13 mempunyai LED yang terhubung pada kebanyakan papan Arduino. bool ledOn = false; // menjejaki pimpinan negeri yang diketuai millisDelay ledDelay; void setup () {// memulakan pin digit sebagai output. pinMode (dipimpin, OUTPUT); // Inisikan pin digit sebagai output. digitalWrite (led, LOW); / // berpaling mengetuai ledOn = false; // memulakan kelewatan ledDelay.start (1500); } void loop () {// check if delay has been timed out (ledDelay.justFinished ()) {ledDelay.repeat (); / / memulakan penundaan sekali lagi tanpa drift // toggle yang diketuai ledOn =! ledOn; jika (ledOn) {digitalWrite (diketuai, TINGGI); / // berpaling pada} else {digitalWrite (led, LOW); // berpaling dari}}}

Langkah 6: Fungsi Perpustakaan MillisDelay Lain

Sebagai tambahan kepada permulaan (kelewatan), hanya fungsi Selesai () dan ulangan () yang digambarkan di atas, perpustakaan millisDelay juga mempunyai
berhenti () untuk menghentikan penangguhan masa,

isRunning () untuk memeriksa sama ada ia belum selesai dan belum dihentikan,

mulakan semula () untuk memulakan semula kelewatan dari sekarang, menggunakan selang kelewatan yang sama,

selesai () untuk memaksa kelewatan untuk tamat tempoh awal,

baki () untuk mengembalikan bilangan milisaat sehingga penangguhan selesai dan

kelewatan () untuk mengembalikan nilai kelewatan yang diluluskan untuk memulakan ()

Versi mikrosekun perpustakaan

millisDelay mengira kelewatan dalam milisaat. Anda juga boleh menggunakan microseconds. Ia dibiarkan sebagai latihan kepada pembaca untuk menulis kelas itu. ( Petunjuk: menamakan semula kelas untuk microDelay dan menggantikan kejadian millis () dengan micros () )

Pembekuan / Menghentikan Kelewatan

Anda boleh membekukan atau menjeda kelewatan dengan menjimatkan baki () milisaat dan menghentikan kelewatan itu dan kemudian tidak membekukannya dengan memulakan semula dengan baki mS sebagai kelewatan. contohnya, lihat contoh FreezeDelay.ino

 mainRemainingTime = mainDelay.remaining (); / / ingat berapa lama dibiarkan berjalan dalam utama utama delayDelay.stop (); // stop mainDelay NOTA: mainDelay.justFinished () TIDAK PERNAH benar selepas berhenti () ... mainDelay.start (mainRemainingTime); / / restart selepas membekukan 

Langkah 7: Kata Amaran - Tambah Monitor Gelung

Malangnya kebanyakan perpustakaan Arduino standard menggunakan kelewatan () atau memperkenalkan jeda, seperti AnalogRead dan SoftwareSerial. Biasanya kelewatan ini diperkenalkan adalah kecil tetapi mereka boleh menambah sehingga saya cadangkan anda menambah monitor di bahagian atas gelung anda () untuk memeriksa seberapa cepat ia berjalan.

Monitor gelung sangat mirip dengan contoh berkedip. Satu sekeping kecil kod di bahagian atas gelung () kaedah hanya bertukar gelung Led setiap masa () dilaksanakan. Anda boleh menggunakan multimeter digital dengan skala Hz untuk mengukur kekerapan output pada pin LED (pin 13 dalam kes ini)

Kod ini ialah: -

 / / Loop Monitor - ini memeriksa bahawa gelung () dilaksanakan sekurang-kurangnya sekali setiap 1mS 
// (c) 2013 Pengkomputeran Hadapan dan Kawalan Pty Ltd // www.forward.com.au> // // Kod contoh ini berada dalam domain awam. int led = 13; / / jangan gunakan pada FioV3 apabila bateri tersambung // Pin 13 mempunyai LED yang terhubung pada kebanyakan papan Arduino. // jika menggunakan Arduino IDE 1.5 atau lebih tinggi, anda boleh menggunakan pra-jelas // LED_BUILTIN daripada 'dipimpin' / rutin persediaan dijalankan sekali apabila anda menekan semula: void setup () {// memulakan pin digit sebagai output. pinMode (dipimpin, OUTPUT); // tambah kod persediaan lain di sini} // rutin gelung berlari terus-menerus selama-lamanya: kekosongan gelung () {// toggle output yang dipimpin setiap gelang Kekerapan yang diketuai mesti mengukur> 500Hz (iaitu <1mS dan <1mS pada ) jika (digitalRead (dipimpin)) {digitalWrite (dipimpin, LOW); // Matikan LED dengan membuat voltan LOW} else {digitalWrite (led, HIGH); / / putar LED pada (TINGGI ialah tahap voltan)} // tambah seluruh kod gelung anda di sini}

Anda boleh memuat turun kod monitor di sini. Apabila saya menjalankan kod ini pada papan Uno saya, multimeter pada rangkaian Hz yang disambungkan antara pin 13 dan GND membaca 57.6Khz. iaitu kira-kira 100 kali> 500jz.

Apabila anda menambah kod anda ke gelung () bacaan Hz akan berkurangan. Hanya semak ia tetap jauh di atas 500Hz (1mS per gelung () pelaksanaan) dalam semua keadaan.

Artikel Berkaitan