マルチタスク

はじめに

マルチタスクのプログラムを作成する.タスクは 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