Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Manufacturing Technology >> Proses manufaktur

Cara Multithread pada Arduino (Tutorial Protothreading)

Komponen dan persediaan

Arduino UNO
× 1
Layar Kristal Cair (LCD) 16x2 Biru Sunfounder
× 1
Breadboard (generik)
dan tentu saja kabel.
× 1
Potensiometer putar (generik)
Tidak yakin dengan peringkat resistensi, mungkin 1Kohm bisa.
× 1

Tentang proyek ini

Video ini menggambarkan sesuatu yang mungkin ingin Anda lakukan selama karir prototyping pemula Anda, membujuk arduino inti tunggal untuk melakukan 3 hal sekaligus. Dalam hal ini, kami:

  • Menyedihkan lampu latar dengan kecepatan konstan tanpa gangguan
  • Menambahkan bilangan bulat setiap detik dan menuliskannya ke layar tanpa gangguan
  • Memutar beberapa pesan setiap beberapa detik dan menuliskannya ke layar tanpa gangguan

Anda melihat judulnya!

Protothreading adalah cara melakukan apa yang biasanya menjadi operasi multitasking (melakukan dua atau lebih hal sekaligus atau pada interval yang berbeda) pada Arduino . Dengan kata lain, ini "multithreaded"! Tapi tunggu dulu Sparky, Arduino adalah chip inti tunggal dengan kode prosedural, jadi multithreading yang sebenarnya tidak mungkin. Mengapa? Apa bedanya protothreading?

Multithreading "Nyata" vs Protothreading

Untuk memahami protothreading benar, pertama-tama kita perlu memahami mengapa itu TIDAK benar-benar multithreading.

Ingat kembali pada hari ketika Intel menjual kami hal "Hyperthreading" baru ini pada prosesor Pentium? Tidak? Anda belum lahir? Nah waktu untuk pelajaran sejarah itu, Nak! Hyperthreading adalah teknologi yang digunakan Intel untuk membuat satu inti pada prosesor "bertindak" seperti dua inti, atau dua inti "bertindak" seperti 4 inti, dll. Tapi mengapa, dan bagaimana itu relevan dengan Arduino? Jawabannya adalah siklus.

Baik Mikrokontroler maupun CPU bekerja dalam "siklus". Seberapa cepat mereka melakukannya (berapa banyak dalam satu detik) adalah kecepatan jam. Anda telah melihat peringkat Ghz CPU, dan Anda mungkin tahu itu terkait dengan seberapa cepatnya. Semakin Ghz, semakin baik, bukan? tapi kenapa? Karena itulah jumlah siklus per detik yang dapat dicapai prosesor (tanpa terlalu panas dan terbakar - sungguh!).

Jika Anda seorang kutu buku datasheet, Anda mungkin tahu bahwa chip mikroprosesor Arduino Uno, Atmel ATMega328P, berjalan pada 16Mhz di luar kotak. Ini mampu 20Mhz, tetapi dipanggil kembali sehingga tidak akan mengacaukan hal-hal seperti menulis data ke memori (atau, Anda tahu, terbakar). 16Mhz berarti setiap detik, Arduino Anda memproses 16.000.000 siklus, alias melakukan 16 juta keping pekerjaan. Sekarang, ini BUKAN baris kode - itu akan sangat cepat dan Arduino relatif lambat. Ini adalah instruksi prosesor seperti memindahkan data masuk dan keluar dari register. Pergi ke tingkat yang lebih rendah dari gambaran umum ini cukup teknis jadi saya akan meninggalkan itu sebagai latihan untuk pembaca, tapi itu intinya :)

Jadi, jika kita hanya bisa melaju begitu cepat pada inti sebelum chip terbaik yang tersedia terbakar, apakah kita akan terjebak pada kecepatan itu selamanya? Apakah itu pekerjaan tercepat yang bisa kita lakukan? Ternyata, tidak! Masukkan CPU multicore, dan multithreading. Pada CPU komputer, aplikasi multithreaded adalah dua proses terpisah yang bekerja secara paralel satu sama lain pada inti CPU yang berbeda. Proses-proses ini berinteraksi untuk menyelesaikan pekerjaan bersama-sama, tetapi tidak harus membagi pekerjaan secara merata seperti yang mungkin Anda asumsikan. Biasanya ada proses utama / "utas" yang berfungsi sebagai pengelola utas lainnya, dan kemudian satu atau lebih utas pekerja yang dikelolanya, yang masing-masing dapat melakukan tugas tertentu. Contoh yang bagus adalah Chrome. Chrome adalah pengelola semua tab halaman web Anda (utas), tetapi karena chrome memiliki banyak utas, setiap tab adalah program kecilnya sendiri. Itu berarti tidak hanya dapat berjalan lebih cepat jika Anda memiliki beberapa inti untuk mendistribusikan setiap tab, tetapi juga memiliki manfaat lain seperti tidak membuat seluruh browser mogok saat satu tab mogok. Ini adalah alasan pertama mengapa Protothreading bukan multithreading - kami hanya memiliki satu inti untuk bekerja dengan MCU, jadi multithreading tradisional tidak mungkin. Kita perlu mengelola pekerjaan hanya pada satu inti, tetapi masih melakukan banyak hal sekaligus. Kami membutuhkan protothreading.

Oke, apa bedanya Protothreading?

Protothreading sangat mirip dengan hal Hyperthreading yang saya sebutkan, sampai batas tertentu. Hyperthreading akan meniru inti kedua dan secara harfiah membagi pekerjaan yang dilakukan satu inti dengan berpura-pura menjadi dua inti virtual. Ini berhasil karena mereka benar-benar ada pada inti yang sama dan dengan demikian berbagi ruang sumber daya yang sama. Karena MCU arduino tidak mendukung hyperthreading, kami tidak dapat melakukannya di sini. Protothreading serupa, kecuali bahwa sebagai pengganti siklus dan instruksi CPU, kita dapat memecah pekerjaan dengan 'loop' atau 'baris' kode yang dieksekusi oleh sketsa kita. Seperti yang Anda bayangkan, jika kita melakukan lebih banyak hal, loop akan memakan waktu lebih lama, sehingga setiap proyek akan memiliki 'loop per detik' yang sangat berbeda. Ada implementasi protothreading yang berbeda, dan yang saya gunakan di sini memang mungkin jelek, tetapi berhasil. Pada dasarnya, setiap loop kami tidak memiliki pekerjaan lain untuk dilakukan, kami melakukan beberapa pekerjaan yang tidak terlalu menuntut atau lebih jarang dilakukan di loop utama (atau tidak sama sekali). Saat kami tidak sibuk, kami memeriksa apakah sudah waktunya untuk melakukan salah satu pekerjaan lain itu. Jika demikian, kami bercabang dan melakukannya. Penting untuk dicatat bahwa tindakan yang "memblokir", artinya tindakan tersebut harus diselesaikan sekaligus tanpa gangguan dan dengan demikian mengikat MCU untuk jangka waktu tertentu (seperti membaca data dari kartu SD dan beberapa tugas lainnya) akan tetap memblokir protothreads lain dari terjadi "tepat waktu", tetapi untuk hal-hal sederhana seperti dua loop sekaligus melakukan tindakan cepat seperti perubahan variabel atau mengubah nilai output, itu akan bekerja dengan luar biasa. Kurang lebih inilah yang akan kita lakukan di sini. Beberapa MCU mendukung sistem operasi real-time (RTOS) yang dapat memberikan lebih banyak kemampuan multitasking seperti hyperthreading yang dapat membantu mengurangi masalah yang disebabkan oleh tugas "memblokir".

Mari kita mulai.

Pertama-tama kita mencari tahu tugas apa yang perlu kita lakukan. Dalam kasus saya, saya memilih (a) memudarkan lampu latar panel LCD saya masuk dan keluar untuk efek "berdenyut" yang rapi, sementara (b) menghitung angka pada interval yang jauh lebih lambat, (dan mungkin tidak dapat dibagi), dan (c) memutar beberapa pesan string pada interval yang jauh lebih lambat. Beberapa panduan yang harus diikuti untuk memastikan proses ini bekerja dengan lancar adalah dengan menilai fungsi Anda dari yang paling sedikit memblokir hingga yang paling banyak memblokir. Tindakan (sebut saja "fungsi" mulai saat ini) yang membutuhkan waktu lebih lama, seperti membaca data atau memiliki penundaan lama lainnya, dan fungsi dengan interval yang lebih besar antara saat diaktifkan adalah fungsi yang paling memblokir. Fungsi yang sangat sering diaktifkan, jika tidak setiap loop, dan tidak membutuhkan waktu lama untuk diselesaikan adalah fungsi yang paling tidak memblokir. Fungsi pemblokiran yang paling tidak adalah apa yang harus Anda gunakan sebagai "utas" utama Anda. Bisakah Anda menebak yang mana yang di atas?

Itu benar, itu "a", menggerakkan lampu latar masuk dan keluar. Ini akan menjadi interval yang teratur dan sangat cepat, terus-menerus tanpa penundaan di antara kebakaran selain menyelesaikan pekerjaan, dan pekerjaan itu sendiri sangat cepat. Utas manajer yang sempurna.

Kami akan menggunakan utas ini (dan loop apa pun di dalamnya) untuk memeriksa apakah utas lainnya perlu melakukan pekerjaan apa pun. Mungkin yang terbaik adalah membaca kode pada saat ini - kode ini banyak didokumentasikan. Lihat loop utama ke arah bawah. Anda dapat melihat saya memeriksa apakah utas memerlukan pekerjaan di mana saya memanggil numberThread.check() dan textThread.check() .

Saya perlu melakukan ini dalam setiap loop di utas utama juga, karena mereka akan memblokir sampai selesai jika saya tidak melakukannya. Saya mengatur interval di mana utas perlu diaktifkan ketika saya menginisialisasi mereka selama init atau bagian pengaturan kode. Jika sudah waktunya untuk mengaktifkan utas ini, .check() akan melihat itu dan melakukan pekerjaan mereka sebelum melanjutkan utas utama.

Itu benar-benar singkatnya, sisanya Anda mungkin bisa mencari tahu sendiri dengan melangkah melalui kode. Biarkan saya mengakhiri dengan mengatakan sementara saya mungkin terdengar seperti itu, saya BUKAN protothreading dengan cara apa pun, ini hanya contoh sederhana yang saya retas. Jika Anda memiliki tip atau jika saya salah tentang apa pun, saya mendorong umpan balik dan koreksi! Terima kasih :)

Kode

  • Kode LCD Multithread - multithread.ino (Diperbarui, v1.1)
Kode LCD Multithread - multithread.ino (Diperbarui, v1.1)Arduino
Sedikit kode ini menggunakan library untuk melakukan 3 tindakan berulang dengan interval terpisah pada waktu yang sama pada satu prosesor Arduino Uno. Ini akan (a) Memudar dan mematikan lampu latar, sementara (b) menambah angka, dan (c) berputar di antara beberapa string teks. Lihat video di atas untuk demo :)
/*Arduino Protothreading Contoh v1.1by Drew Alden (@ReanimationXP) 1/12/2016- Pembaruan:v1.1 - 8/18/17 Arduino 1.6.6+ prototyping berubah , perbaikan kecil. (buat fungsi sebelum digunakan, hapus foreach dan perpustakaan terkait). Perhatikan bahwa TimedAction sekarang kedaluwarsa. Pastikan untuk membaca catatan tentang kesalahan TimedAction dan WProgram.h / Arduino.h.*///COMPONENTS/*Kode ini dibuat menggunakan LCD biru starter kit Arduino Sunfounder. Kode ini dapat ditemukan di Amazon.com dalam berbagai kit .*///THIRD-PARTY LIBRARIES//ini harus ditambahkan secara manual ke instalasi Arduino IDE Anda//TimedAction//memungkinkan kami untuk mengatur tindakan untuk dilakukan pada interval waktu yang terpisah//http://playground.arduino.cc/Code /TimedAction//http://wiring.uniandes.edu.co/source/trunk/wiring/firmware/libraries/TimedAction#include //CATATAN:Library ini memiliki masalah pada versi Arduino yang lebih baru. Setelah// mengunduh perpustakaan Anda HARUS masuk ke direktori perpustakaan dan// mengedit TimedAction.h. Di dalamnya, timpa WProgram.h dengan Arduino.h//NATIVE LIBRARIES#include  /* LiquidCrystal Library - Hello World Mendemonstrasikan penggunaan layar LCD 16x2. Pustaka LiquidCrystal bekerja dengan semua layar LCD yang kompatibel dengan driver Hitachi HD44780. Ada banyak dari mereka di luar sana, dan Anda biasanya dapat memberi tahu mereka dengan antarmuka 16-pin. Salah satu contoh rangkaian:* LCD RS pin ke digital pin 12. * LCD Enable/E/EN pin ke digital pin 11 * LCD D4 pin ke digital pin 5 * LCD D5 pin ke digital pin 4 * LCD D6 pin ke digital pin 3 * Pin LCD D7 ke pin digital 2 * Pin LCD R/W ke ground * Pin LCD VSS ke ground * Pin LCD VCC/VDD ke 5V * Resistor 10K:* ujung ke +5V dan ground * wiper (tengah) ke pin VO LCD ( pin 3) *Backlit Menampilkan:* LCD K pin ke ground (jika ada) * LCD A pin ke 220ohm (merah merah hitam hitam (coklat)) resistor, kemudian resistor ke pin 9 Contoh kode ini dalam domain publik. http://www.arduino.cc/en/Tutorial/LiquidCrystal *///GLOBALSint backlightPin =9; // digunakan untuk backlight fadingint timerCounter =0; // menambah penghitung. akan crash pada akhirnya.int stringNo =0; //string teks mana yang akan ditampilkan// "16 CHARACTER MAX"char* stringArray[]={"Coba lihat... ", "Saya punya 3 utas", "sekaligus...", "Keren, ya ?! :D "}; //INIT// Ini mungkin harus dilakukan di dalam setup(), tapi terserah.// inisialisasi perpustakaan LCD dengan nomor antarmuka pinsLiquidCrystal lcd(12, 11, 5, 4, 3, 2);//FUNCTIONS/ /ini adalah tugas pertama kita, cetak angka yang bertambah ke LCDvoid incrementNumber(){ // atur kursor ke kolom 0, baris 1 // (catatan:baris 1 adalah baris kedua, karena penghitungan dimulai dengan 0):lcd. setCursor(0, 1); // tambahkan satu ke penghitung, lalu tampilkan. timerCounter =penghitung waktu + 1; lcd.print(timerCounter);}//tugas kedua kami, diaktifkan setiap beberapa detik dan memutar string teksvoid changeText(){ // Mencetak pesan ke LCD. lcd.setCursor(0, 0); lcd.print(stringArray[stringNo]); // hack jahat untuk mendapatkan jumlah elemen Array if (stringNo>=sizeof(stringArray)/sizeof(char *)){ stringNo =0; ubahTeks(); } else{ stringNo =stringNo + 1; }}//Buat beberapa timer yang akan menyala berulang kali setiap x ms//edit:baris ini dulunya berada di depan fungsi incrementNumber dan changeText//. ini tidak berhasil karena fungsinya belum ditentukan!TimedAction numberThread =TimedAction(700,incrementNumber);TimedAction textThread =TimedAction(3000,changeText);// di mana tugas ketiga kita? baik, itu loop utama itu sendiri :) tugas// yang paling sering berulang harus digunakan sebagai loop. other// tugas dapat "menginterupsi" pengulangan tercepat task.void setup() { //menentukan jumlah kolom dan baris LCD:lcd.begin(16, 2); //api changeText sekali untuk melukis string awal [0] changeText();}void loop() { //periksa thread kita. berdasarkan berapa lama sistem telah //berjalan, apakah mereka perlu menyala dan bekerja? jika demikian, lakukanlah! nomorThread.check(); textThread.check(); //tugas ketiga, memudarkan cahaya latar dari kecerahan min hingga maksimal //dengan penambahan 5 poin:digitalWrite(13, HIGH); for (int fadeValue =0; fadeValue <=255; fadeValue +=10) { //tunggu sebentar, mengapa saya memeriksa utas di sini? karena //ini adalah perulangan for. Anda harus memeriksa utas Anda selama APAPUN // loop yang terjadi, termasuk yang utama! nomorThread.check(); textThread.check(); //menetapkan nilai (berkisar dari 0 hingga 255):analogWrite(backlightPin, fadeValue); // tunggu selama 20 milidetik untuk melihat efek peredupan // pertahankan penundaan pada loop utama PENDEK. ini AKAN mencegah // utas lain menembak tepat waktu. penundaan (20); } //memudar dari maks ke min dengan penambahan 5 poin:digitalWrite(13, LOW); for (int fadeValue =255; fadeValue>=0; fadeValue -=10) { //periksa kembali thread kita numberThread.check(); textThread.check(); //menetapkan nilai (berkisar dari 0 hingga 255):analogWrite(backlightPin, fadeValue); //tunggu selama 20 milidetik untuk melihat efek peredupan delay(20); } /* Untuk beberapa pesan bergulir yang menyenangkan di masa depan... lcd.setCursor(15,0); // atur kursor ke kolom 15, baris 0 untuk (int positionCounter1 =0; positionCounter1 <26; positionCounter1++) { lcd.scrollDisplayLeft(); //Menggulir isi tampilan satu spasi ke kiri. lcd.print(array1[positionCounter1]); // Mencetak pesan ke LCD. penundaan (waktu); //tunggu selama 250 mikrodetik } lcd.clear(); //Mengosongkan layar LCD dan menempatkan kursor di sudut kiri atas. lcd.setCursor(15,1); // atur kursor ke kolom 15, baris 1 untuk (int positionCounter =0; positionCounter <26; positionCounter++){ lcd.scrollDisplayLeft(); //Menggulir isi tampilan satu spasi ke kiri. lcd.print(array2[positionCounter]); // Mencetak pesan ke LCD. penundaan (waktu); //tunggu selama 250 mikrodetik } lcd.clear(); //Mengosongkan layar LCD dan menempatkan kursor di sudut kiri atas. */ }

Proses manufaktur

  1. Cara Mengukur Kualitas Udara di OpenSensors
  2. Tutorial Kunci RFID Arduino
  3. Cara Meretas Remote IR
  4. Berapa Tinggi Anda?
  5. Seberapa Mudah Menggunakan Termistor?!
  6. Cara membuat musik dengan Arduino
  7. Cara Menggunakan NMEA-0183 dengan Arduino
  8. Tutorial Sensor Sidik Jari Arduino
  9. Cara Menggunakan Modbus dengan Arduino
  10. Tutorial Arduino 01:Memulai