マルチタスク
はじめに
マルチタスクのプログラムを作成する.タスクは Linux や Windows で言うと ころの「スレッド」とほぼ同じ意味である.OS がスレッドごとに CPU 時間の 割り当てをコントロールし、複数のスレッドを同時的に進行させる機能または その動作状態のことをマルチスレッドと呼ぶ.mruby/c には OS なしでマルチ タスクを実現する仕組みが含まれている.
プロジェクトの準備
基本的に ESP-IDF 環境と同じなので, ESP-IDF 環境がインストールされているディレクトリ (ここでは $HOME/esp) 以下にプロジェクト用のディレクトリを作る.
$ cd ~/esp $ git clone https://github.com/gfd-dennou-club/iotex-esp32-mrubyc.git mrubyc-09-task $ cd mrubyc-09-task
make menuconfig で “IoTeX ESP32 mrubyc Configuration” から GPIO, ADC, multi task の項目にチェック入れる.
$ make menuconfig
プログラムの例
mrblib/loops 以下に master.rb と slave.rb の 2 つのファイルを作成し, グローバル変数 $status を通して連携するように書けば良い.
以下はサーミスタ温度計で計測しつつ,温度が 30 度を超えた時に LED が点灯するプログラムである. おそらく ADC の課題として,シングルタスクで同様のプログラムを既に作成したと思うので, シングルタスクの場合とマルチタスクの場合で動作を比較してみると良い.
mrblib/loops/master.rb
1 # coding: utf-8 2 # A/D 変換 初期化 3 adc1 = ADC.new( 39, ADC::ATTEN_11DB, ADC::WIDTH_12BIT ) 4 adc2 = ADC.new( 4, ADC::ATTEN_11DB, ADC::WIDTH_12BIT ) 5 6 #温度計測用変数初期化 7 B = 3435.0 8 To = 25.0 9 V = 3300.0 10 Rref = 10.0 11 12 #グローバル変数 13 $status = "COLD" 14 15 while true 16 voltage1 = adc1.read() 17 voltage2 = adc2.read() 18 temp = 1.0 / ( 1.0 / B * Math.log( (V - voltage1) / (voltage1/ Rref) / Rref) + 1.0 / (To + 273.0) ) - 273.0 19 puts "adc1 : #{voltage1} mV, #{temp} °C" 20 puts "adc2 : #{voltage2} mV" 21 22 if temp > 30.0 23 $status = "HOT" 24 else 25 $status = "COLD" 26 end 27 puts $status 28 29 sleep 1 30 end
mrblib/loops/slave.rb
1 2 sleep 2 3 4 led1 = GPIO.new( 13, GPIO::OUT ) 5 6 while true 7 if $status == "HOT" 8 led1.write(1) 9 p "hot" 10 else 11 led1.write(0) 12 end 13 sleep 1 14 end
プログラムの実行
以下のように実行する.サーミスタ温度計で測定した温度に応じて LED が点灯することを確認せよ.
$ make $ make flash monitor