概要
オープンソースのリアルタイムOSとしてTOPPERS/ASPをGR-PEACHで動かすことができます。Webコンパイラでの使い方をご紹介します。
こちらのgithub wikiにサンプルプログラムの説明がありますので、合わせて参照してください。
準備
GR-PEACH、USBケーブル(マイクロBタイプ)の2つを準備します。
サンプル実行までの手順
プロジェクト作成
WebコンパイラにTOPPERS/ASP用のプロジェクトテンプレートがありますので、それを利用してプロジェクトを作成します。Webコンパイラが初めての方は「Webコンパイラでスケッチ」を参照してください。
テンプレートの「GR-PEACH_TOPPERS_ASP_***.zip」(xxxは任意のバージョン)を選択し、適当にプロジェクト名を付けてプロジェクト作成ボタンを押します。
スケッチの表示
デフォルトの状態ではプロジェクトにあるサンプル「examples/blinky」がビルドされるようになっています。blinkyフォルダにblinky.cppがありますので、ダブルクリックしてファイルを開いてみましょう。
ビルドから書き込み
ビルドボタンを押してください。初回のビルドは全てのソースをコンパイルするため30秒ほど時間がかかります。
ビルドが終了すると、プロジェクトツリーにblinky.binが生成されますので、ダウンロードしてGR-PEACHに書き込んでください。赤、緑、青、ユーザーLEDがそれぞれ定めれた時間ごとに点滅を繰り返します。
マルチタスクなArduinoスケッチ
Arduinoでは基本的に1回のsetup関数と繰り返し実行されるloop関数からなりますが、loop関数の中で並列に行いたい処理をプログラミングするのは困難です。
TOPPERS/ASPによるスケジューラにより、複数のloop関数を並列で動かすサンプルがありますので試してみましょう。
ビルドプロジェクトの切り替え
ビルドするプロジェクトの切り替えをします。プロジェクトツリーにある「build_target」を開いてください。デフォルトでは「./examples/blinky」が記載されています。
「./examples/multitask_arduino」に書き換えてください。
スケッチの表示
プロジェクトツリーのexamples/multitask_arduinoフォルダにあるmultitask_arduino.cppを開いてみてください。loop, loop1, loop2の3つのloop関数があることが分かります。
ビルドから書き込み
ビルド実行するとmultitask_arduino.binが生成されますので、GR-PEACHに書き込んでみてください。loopが赤LED、loop1が緑LED、loop2が青LEDをそれぞれ点滅させています。
loopの追加
loopを追加するには、examples/multitask_arduinoフォルダにある「arduino_app.h」にあるマクロ「ADDITIONAL_LOOP_NUM」の値を増やします。例えば数値を5にした場合、loop3, loop4, loop5が追加できます。
温湿度計測サンプル
参考として、以下のプログラムは温湿度センサーHDC1000のシリアル出力、LED制御を独立して行う例です。動作するにはHDC1000のSCL/SDAをWireのピン、RDYをピン2につなげる必要があります。
#include <kernel.h>
#include <t_syslog.h>
#include <t_stdlib.h>
#include "syssvc/serial.h"
#include "syssvc/syslog.h"
#include "kernel_cfg.h"
#include "arduino_app.h"
#include "arduino_main.h"
#include <Arduino.h>
#include <Wire.h>
#define HDC1000_ADDRESS 0x40
#define HDC1000_RDY_PIN 2
#define HDC1000_TEMPERATURE_POINTER 0x00
#define HDC1000_HUMIDITY_POINTER 0x01
#define HDC1000_CONFIGURATION_POINTER 0x02
#define HDC1000_SERIAL_ID1_POINTER 0xfb
#define HDC1000_SERIAL_ID2_POINTER 0xfc
#define HDC1000_SERIAL_ID3_POINTER 0xfd
#define HDC1000_MANUFACTURER_ID_POINTER 0xfe
#define HDC1000_CONFIGURE_MSB 0x10 /* Get both temperature and humidity */
#define HDC1000_CONFIGURE_LSB 0x00 /* 14 bit resolution */
void getTemperatureAndHumidity(float *temperature, float *humidity) {
unsigned int tData, hData;
Wire.beginTransmission(HDC1000_ADDRESS);
Wire.write(HDC1000_TEMPERATURE_POINTER);
Wire.endTransmission();
while (digitalRead(HDC1000_RDY_PIN) == HIGH);
Wire.requestFrom(HDC1000_ADDRESS, 4);
while (Wire.available() < 4);
tData = Wire.read() << 8;
tData |= Wire.read();
hData = Wire.read() << 8;
hData |= Wire.read();
*temperature = tData / 65536.0 * 165.0 - 40.0;
*humidity = hData / 65536.0 * 100.0;
}
#define INTERVAL 100
#define INTERVAL_RED 100
#define INTERVAL_BLUE 150
#define INTERVAL_GREEN 200
void setup()
{
pinMode(PIN_LED_RED , OUTPUT);
pinMode(PIN_LED_GREEN , OUTPUT);
pinMode(PIN_LED_BLUE , OUTPUT);
pinMode(PIN_LED_USER , OUTPUT);
pinMode(PIN_SW , INPUT);
pinMode(HDC1000_RDY_PIN, INPUT);
Serial.begin(9600);
//Put the HDC1000 IC into the correct operating mode
Wire.beginTransmission(HDC1000_ADDRESS);
Wire.write(HDC1000_CONFIGURATION_POINTER);
Wire.write(HDC1000_CONFIGURE_MSB);
Wire.write(HDC1000_CONFIGURE_LSB);
Wire.endTransmission();
}
void loop(){
float temperature, humidity;
getTemperatureAndHumidity(&temperature, &humidity);
Serial.print("Temperature = ");
Serial.print(temperature);
Serial.print(" degree, Humidity = ");
Serial.print(humidity);
Serial.println("%");
Serial.flush();
delay(1000);
}
void loop1()
{
while(digitalRead(PIN_SW) == 0){
digitalWrite(PIN_LED_USER, 1);
delay(INTERVAL);
digitalWrite(PIN_LED_USER, 0);
delay(INTERVAL);
}
}
void loop2(){
digitalWrite(PIN_LED_BLUE, 1);
delay(INTERVAL_BLUE);
digitalWrite(PIN_LED_BLUE, 0);
delay(INTERVAL_BLUE);
}
/*
* Cyclic Handler
*
* This handler is called every 10 [ms] as specified in
* multitask_arduino.cfg.
*/
void cyclic_handler(intptr_t exinf) {
irot_rdq(LOOP_PRI); /* change the running loop. */
}