工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Arduinoをマルチスレッド化する方法(プロトスレッドチュートリアル)

コンポーネントと消耗品

>
Arduino UNO
× 1
Sunfounder Blue 16x2液晶ディスプレイ(LCD)
× 1
ブレッドボード(汎用)
そしてもちろんワイヤー。
× 1
ロータリーポテンショメータ(汎用)
抵抗率がわからない場合は、おそらく1Kohmで十分です。
× 1

このプロジェクトについて

このビデオは、新進のプロトタイピングのキャリアの中でやりたかったかもしれないことを描いています。シングルコアのarduinoを使って一度に3つのことを実行します。この場合、私たちは次のようになります:

  • バックライトを中断することなく一定の速度でパルスする
  • 1秒ごとに整数をインクリメントし、中断することなくディスプレイに書き込みます
  • 数秒ごとにいくつかのメッセージを回転させ、中断することなくディスプレイに書き込みます

タイトルを見ました!

プロトスレッディングは、Arduinoで通常はマルチタスク操作(2つ以上のことを同時にまたは異なる間隔で実行する)を実行する方法です 。言い換えれば、それは「マルチスレッド」です!しかし、Sparkyを保持してください。Arduinoは手続き型コードを備えたシングルコアチップであるため、真のマルチスレッド化は不可能です。なぜですか?プロトスレッドはどのように異なりますか?

「実際の」マルチスレッドとプロトスレッド

プロトスレッディングを理解するには 適切に、最初に、それが実際にはマルチスレッドではない理由を理解する必要があります。

IntelがPentiumプロセッサでこの新しい「ハイパースレッディング」を販売していた当時のことを覚えていますか?番号?あなたはまだ生まれていませんか?それでは、歴史の授業の時間です、息子!ハイパースレッディングは、インテルがプロセッサー上のシングルコアを2コアのように「動作」させたり、2コアを4コアのように「動作」させたりするために採用しているテクノロジーです。答えはサイクルです。

マイクロコントローラーとCPUはどちらも「サイクル」で動作します。それらを実行する速度(1秒間にいくつ)がクロックレートです。 CPUのGhz定格を見たことがありますが、それが速度に関係していることはおそらくご存知でしょう。ギガヘルツが多ければ多いほど良いでしょう?しかし、なぜ?これは、プロセッサが達成できる1秒あたりのサイクル数であるためです(過熱したり発火したりすることなく、本当に!)

あなたがデータシートオタクなら、ArduinoUnoのマイクロプロセッサチップであるAtmelATMega328Pが箱から出して16Mhzで動作することをご存知かもしれません。 20Mhzの能力がありますが、ダイヤルバックされるので、メモリへのデータの書き込みなどを台無しにすることはありません(または、ご存知のとおり、発火します)。 16Mhzは、毎秒、Arduinoが16,000,000サイクルを処理していることを意味します。つまり、1600万個の作業を実行しています。さて、これらはコード行ではありません-それは非常に速く、Arduinoは比較的遅いでしょう。これらは、レジスタへのデータの移動やレジスタからのデータの移動などのプロセッサ命令です。この概要よりも低いレベルになると、かなり技術的になるので、読者に演習として任せますが、それが要点です:)

それで、利用可能な最高のチップが発火する前にコア上で非常に速く進むことができるだけである場合、私たちは永遠にその速度で立ち往生していますか?それは私たちが仕事をすることができる最速ですか?結局のところ、違います!マルチコアCPUとマルチスレッドを入力してください。コンピューターのCPUでは、マルチスレッドアプリケーションは、CPUの異なるコア上で互いに並行して動作する2つの別個のプロセスです。これらのプロセスは相互作用して作業をまとめますが、想定どおりに作業を均等に分割する必要はありません。通常、他のスレッドのマネージャーとして機能するメインプロセス/「スレッド」があり、次にそれが管理する1つ以上のワーカースレッドがあり、それぞれが特定のタスクを実行する場合があります。良い例はChromeです。 ChromeはすべてのWebページタブ(スレッド)のマネージャーですが、Chromeはマルチスレッドであるため、各タブは独自の小さなプログラムです。つまり、各タブを分散するコアが複数ある場合は実行速度が速くなるだけでなく、1つのタブがクラッシュしたときにブラウザ全体がクラッシュしないなどの利点もあります。これが、プロトスレッディングがマルチスレッディングではない最初の理由です。MCUで動作するコアは1つしかないため、従来のマルチスレッディングはまったく不可能です。単一のコアでのみ作業を管理する必要がありますが、それでも一度に複数のことを実行します。プロトスレッディングが必要です。

では、プロトスレッディングはどのように違うのですか?

プロトスレッディングは、ある程度、私が言及したハイパースレッディングと非常によく似ています。ハイパースレッディングは、2番目のコアをエミュレートし、2つの仮想コアのふりをして、1つのコアが実行している作業を文字通り分割します。これは、実際には同じコア上に存在し、同じリソーススペースを共有しているために機能しました。 arduino MCUはハイパースレッディングをサポートしていないため、ここではそれを行うことができません。プロトスレッディングも同様ですが、CPUサイクルと命令の代わりに、スケッチによって実行されるコードの「ループ」または「行」によって作業を分割できる点が異なります。ご想像のとおり、より多くの作業を行うと、ループにかかる時間が長くなるため、プロジェクトごとに「1秒あたりのループ数」が大きく異なります。プロトスレッディングにはさまざまな実装があり、ここで使用しているものは確かに見苦しいものですが、機能します。 基本的に、各ループには他に行う作業はありません。メインループでは、要求の少ない、または頻度の低い作業を行います(またはまったく行いません)。 忙しくないときは、他の作業の1つをまだ実行する時間かどうかを確認しています。もしそうなら、私たちは分岐してそれを行います。 「ブロック」しているアクションは、中断することなく一度に完了する必要があるため、MCUを一定期間拘束する必要があることに注意することが重要です(SDカードからのデータの読み取りやその他のいくつかのタスクなど)引き続きブロックします 他のプロトスレッドは「時間通りに」発生しませんが、変数の変更や出力値の変更などの迅速なアクションを同時に実行する2つのループのような単純なものの場合、それは見事に機能します。これは多かれ少なかれここで行うことです。一部のMCUは、「ブロッキング」タスクによって引き起こされる問題を軽減するのに役立つ、よりハイパースレッディングのようなマルチタスク機能を提供できるリアルタイムオペレーティングシステム(RTOS)をサポートしています。

始めましょう。

まず、実行する必要のあるタスクを把握します。私の場合、(a)LCDパネルのバックライトをフェードインおよびフェードアウトして、きちんとした「パルス」効果を出し、(b)はるかに遅い(場合によっては分割できない)間隔で数値をカウントし、 (c)さらに遅い間隔でいくつかの文字列メッセージをローテーションします。このプロセスがスムーズに機能するようにするために従うべきいくつかのガイドラインは、関数を最小のブロックから最大のブロックまで評価することです。データの読み取りやその他の長い遅延など、時間がかかるアクション(この時点から「関数」と呼びます)、および起動時の間隔が長い関数が最もブロックする関数です。すべてのループではないにしても、非常に頻繁に起動し、完了するのに時間がかからない関数は、最もブロックの少ない関数です。最小限のブロッキング関数は、プライマリ「スレッド」として使用する必要があるものです。上にあるものを推測できますか?

そうです、それは「a」であり、バックライトを出し入れします。これは定期的で非常に速い間隔で行われ、作業を完了する以外に火災の合間に遅延がなく永続的であり、作業自体は非常に高速です。完璧なマネージャースレッド。

このスレッド(およびその中のループ)を使用して、他のスレッドが何らかの作業を行う必要があるかどうかを確認します。この時点でコードを読むのがおそらく最善です-それは詳細に文書化されています。下に向かってメインループを見てください。 numberThread.check()を呼び出すと、スレッドに作業が必要かどうかを確認できます。 および textThread.check()

メインスレッドのループ内でもこれを行う必要があります。そうしないと、完了するまでブロックされます。 initまたはコードのセットアップ部分でスレッドを初期化するときにスレッドを起動する必要がある間隔を設定しました。これらのスレッドを起動するときは、 .check() メインスレッドを続行する前に、それを確認して作業を実行します。

簡単に言うと、それだけです。残りの部分は、コードをステップ実行することでおそらく自分で理解できます。最後に、私はそのように聞こえるかもしれませんが、私は決してプロトスレッディングのプロではありません。これは私がハックした単純な例にすぎません。ヒントがある場合、または私が何かについて間違っていた場合は、フィードバックと修正をお勧めします!ありがとう:)

コード

  • マルチスレッドLCDコード-multithread.ino(更新、v1.1)
マルチスレッドLCDコード-multithread.ino(更新、v1.1) Arduino
このコードビットは、ライブラリを使用して、1つのArduinoUnoプロセッサで同時に別々の間隔で3つの繰り返しアクションを実行します。 (a)バックライトをフェードインおよびフェードアウトし、(b)数値をインクリメントし、(c)テキストのいくつかの文字列間を回転します。デモについては上のビデオを参照してください:)
 / * Arduinoプロトスレッディングの例v1.1byDrew Alden(@ReanimationXP)1/12 / 2016-更新:v1.1-8 / 18/17 Arduino1.6.6 +プロトタイピングが変更されました、小さな修正。 (使用前に関数を作成し、foreachおよび関連ライブラリを削除します)。 TimedActionは現在古くなっていることに注意してください。 TimedActionおよびWProgram.h / Arduino.hエラーに関するメモを必ずお読みください。* /// COMPONENTS / *このコードは、SunfounderArduinoスターターキットの青いLCDを使用して作成されました。Amazon.comでさまざまなキットに含まれています。 。* ///サードパーティライブラリ//これらはArduinoIDEインストールに手動で追加する必要があります// TimedAction //別々の時間間隔で実行するアクションを設定できます//http://playground.arduino.cc/Code /TimedAction//http://wiring.uniandes.edu.co/source/trunk/wiring/firmware/libraries/TimedAction#include  //注:このライブラリには、Arduinoの新しいバージョンで問題があります。 //ライブラリをダウンロードした後、ライブラリディレクトリに移動し、// TimedAction.hを編集する必要があります。その中で、WProgram.hをArduino.h // NATIVE LIBRARIES#include  / * LiquidCrystalライブラリで上書きします-HelloWorldは16x2LCDディスプレイの使用を示しています。 LiquidCrystalライブラリは、HitachiHD44780ドライバーと互換性のあるすべてのLCDディスプレイで動作します。それらの多くはそこにあり、通常は16ピンインターフェイスでそれらを知ることができます。一例の回路:* LCDRSピンからデジタルピン12。* LCD Enable / E / ENピンからデジタルピン11 * LCDD4ピンからデジタルピン5 * LCDD5ピンからデジタルピン4 * LCDD6ピンからデジタルピン3 * LCDD7ピンからデジタルピン2 * LCD R / Wピンからグランド* LCDVSSピンからグランド* LCD VCC / VDDピンから5V * 10K抵抗:*エンドは+ 5V、グランド*ワイパー(中央)からLCD VOピン(ピン3)*バックライト付きディスプレイ:* LCD Kピンをアースに接続(存在する場合)* LCD Aピンを220オーム(赤赤黒黒(茶色))の抵抗に、次に抵抗をピン9に接続このサンプルコードはパブリックドメインにあります。 http://www.arduino.cc/en/Tutorial/LiquidCrystal * /// GLOBALSintbackbackPin =9; //バックライトのフェージングに使用inttimerCounter =0; //カウンタをインクリメントします。最終的にクラッシュします。intstringNo=0; //表示するテキスト文字列// "16 CHARACTER MAX" char * stringArray [] ={"チェックアウト..."、 "スレッドが3つあります"、 "一度に実行します..."、 "かっこいい、ハァッ。 ?!:D "}; // INIT //これはおそらくsetup()内で実行する必要がありますが、何でもかまいません。//LCDライブラリをインターフェイスピンの番号で初期化しますLiquidCrystal lcd(12、11、5、4、3、2); // FUNCTIONS / /これが最初のタスクです。増分番号をLCDに出力しますvoidincrementNumber(){//カーソルを列0の1行目に設定します//(注:カウントは0から始まるため、1行目は2行目です):lcd。 setCursor(0、1); //カウンターに1つ追加して、表示します。 timerCounter =timerCounter + 1; lcd.print(timerCounter);} // 2番目のタスクは、数秒ごとに起動し、テキスト文字列を回転しますvoid changeText(){//メッセージをLCDに出力します。 lcd.setCursor(0、0); lcd.print(stringArray [stringNo]); //配列要素の数を取得するための厄介なハックif(stringNo> =sizeof(stringArray)/ sizeof(char *)){stringNo =0; changeText(); } else {stringNo =stringNo + 1; }} // x msごとに繰り返し起動するタイマーをいくつか作成します//編集:これらの行は、incrementNumber関数とchangeText //関数の前にありました。関数がまだ定義されていないため、これは機能しませんでした!TimedAction numberThread =TimedAction(700、incrementNumber); TimedAction textThread =TimedAction(3000、changeText); // 3番目のタスクはどこですか?まあ、それはメインループ自体です:)最も頻繁に繰り返されるタスク//はループとして使用する必要があります。 other //タスクは、最も速く繰り返されるタスクを「中断」することができます。voidsetup(){// LCDの列と行の数を定義します:lcd.begin(16、2); // changeTextを1回起動して、最初の文字列をペイントします[0] changeText();} void loop(){//スレッドをチェックします。システムが//実行されている時間に基づいて、システムを起動して動作させる必要がありますか?もしそうなら、それをしなさい! numberThread.check(); textThread.check(); // 3番目のタスク、バックライトを最小から最大の明るさにフェードイン// 5ポイント刻み:digitalWrite(13、HIGH); for(int decodeValue =0;およびfadeValue <=255;およびfadeValue + =10){//ちょっと待ってください、なぜここでスレッドをチェックしているのですか? //これはforループだからです。メインのループを含め、発生する//ループ中にスレッドをチェックする必要があります。 numberThread.check(); textThread.check(); //値を設定します(0から255の範囲):analogWrite(backlightPin、fadeValue); // 20ミリ秒待って、調光効果を確認します//メインループの遅延をSHORTに保ちます。これらは//他のスレッドが時間通りに起動するのを防ぎます。 delay(20); } // 5ポイント刻みで最大から最小にフェードアウトします:digitalWrite(13、LOW); for(int decodeValue =255;およびfadeValue> =0;およびfadeValue- =10){//スレッドを再度チェックしますnumberThread.check(); textThread.check(); //値を設定します(0から255の範囲):analogWrite(backlightPin、fadeValue); // 20ミリ秒待って、調光効果を確認しますdelay(20); } / *将来のスクロールメッセージの楽しみのために... lcd.setCursor(15,0); //カーソルを列15、行0に設定しますfor(int positionCounter1 =0; positionCounter1 <26; positionCounter1 ++){lcd.scrollDisplayLeft(); //表示の内容を1スペース左にスクロールします。 lcd.print(array1 [positionCounter1]); //メッセージをLCDに出力します。 delay(tim); // 250マイクロ秒待つ} lcd.clear(); // LCD画面をクリアし、カーソルを左上隅に置きます。 lcd.setCursor(15,1); //カーソルを列15、行1に設定しますfor(int positionCounter =0; positionCounter <26; positionCounter ++){lcd.scrollDisplayLeft(); //表示の内容を1スペース左にスクロールします。 lcd.print(array2 [positionCounter]); //メッセージをLCDに出力します。 delay(tim); // 250マイクロ秒待つ} lcd.clear(); // LCD画面をクリアし、カーソルを左上隅に置きます。 * /} 

製造プロセス

  1. OpenSensorsで空気の質を測定する方法
  2. ArduinoRFIDロックチュートリアル
  3. IRリモコンをハックする方法
  4. あなたの身長はどれくらいですか?
  5. サーミスタの使い方は簡単ですか?!
  6. Arduinoで音楽を作る方法
  7. ArduinoでNMEA-0183を使用する方法
  8. Arduino指紋センサーチュートリアル
  9. ArduinoでModbusを使用する方法
  10. Arduinoチュートリアル:ミニピアノ
  11. Arduinoチュートリアル01:はじめに