Ruby関西76 gr citrusの使い方#2

34
Wakayama.rb たろサ (山本三七男) RubyボードGR- CITRUSの紹介 #2

Transcript of Ruby関西76 gr citrusの使い方#2

Wakayama.rbたろサ(山本三七男)

RubyボードGR-CITRUSの紹介 #2

2

自己紹介

たちうお

和歌山県 有田市 在住

みかん

3

自己紹介

今月 1月 28日 和歌山市内で開催します。

毎月1回ハードとソフトの勉強会

Ruby勉強会@和歌山の主催

4

50mm

20m

mGR-CITRUS

Ruby Inside

5

Rubyファミリー

          消費メモリ   プラットホーム

Ruby(CRuby)  数MB     パソコンなど OS上で走る

mruby       数百kB  32ビットマイコンなど

mruby/c     数十kB  16ビットマイコンなど

今年発表!mrubyを更に小型化して省電力化の実現

6

入手方法

秋月電子さんで発売中

http://akizukidenshi.com/catalog/top.aspx

2,200円

1,300円CITRUS用WiFiボード

WA-MIKAN

7

入手方法

大阪では共立電子さんで発売中

本題です実装について

9

mrbgem

バインドしているmrbgem

mruby-math #->Math.sinmruby-numeric-ext #->10.chr 0.zero?

10

Ruby Class

GR-CITRUS単体 ・カーネルクラス   (Arduino互換) ・システムクラス ・ファイルクラス   (Flash用) ・シリアルクラス ・I2Cクラス ・サーボクラス ・RTCクラス

WA-MIKAN装着 ・SDカードクラス ・WiFiクラス ・MP3クラス

独自実装です

11

mruby組込み方法

mrubyをmake

mrubyのソースをgithubからclone

mrubyのlibmruby.a 生成

クロスコンパイルになります

libmruby.a を独自プログラムにリンク

GR-CITRUSのmrubyファーム完成

12

mrbgemの独自追加

mrubyのソースをgithubからclone

githubのwrbb-v2lib-firmにある build_config.rbをmrubyのbuild_config.rbに上書きコピーする

build_config.rbを書き換える。欲しいmrbgemのコメントアウトを外す。

mrubyをmake以下同じです。

13

クロスコンパイル方法

macの場合:

GR-CITRUSのFirmwareをビルドする方法 for macOS

GR-CITRUSに組み込むmrubyをビルドする方法 for macOShttp://qiita.com/takjn/items/0ef3d46107ac8faaf621

http://qiita.com/takjn/items/f25251f355fba49245b4

WIndowsの場合:

GR-CITRUSのFirmwareをビルドする方法 for Windowshttp://qiita.com/takjn/items/4838dc0c3f879a0e3291

Linuxの場合:

x64 Ubuntu でスケッチをビルドしてみました

http://japan.renesasrulz.com/gr_user_forum_japanese/f/gr-citrus/3447/x64-ubuntu?pi5348=2

14

citrus_sketch.bin が最新版

最新バージョン取得

コードを読みます

16

mrb実行の仕組み

//xmlに指定された最初に起動するmrubyファイル名・char RubyStartFileName[RUBY_FILENAME_SIZE];

//現在実行されているファイルのパス名・char ExeFilename[RUBY_FILENAME_SIZE];

・char RubyFilename[RUBY_FILENAME_SIZE];

この3つのchar配列で管理されています。

17

起 動 時

(0)RubyStartFileName[] =null ExeFilename[] =null RubyFilename[] =null

(1)wrbb.xml ファイルを検索する。見つかれば そのファイル名を、見つからなければ、main.mrbを入れる。 RubyStartFileName[]=”main.mrb” ExeFilename[] =null RubyFilename[] =null

(2)RubyStartFileName[]の内容をRubyFilename[]に入れる。 これ以降、RubyStartFileName[]は使われない。 RubyStartFileName[]=”main.mrb” ExeFilename[] =null RubyFilename[] =”main.mrb”

18

起 動 ~ 実 行

(3)Rubyプログラムの実行モードになったとき、RubyFilename[]をExeFilename[]に入れる。 RubyStartFileName[]=”main.mrb” ExeFilename[] =”main.mrb” RubyFilename[] =”main.mrb”

(4)RubyFilename[]を nullにする。 RubyStartFileName[]=”main.mrb” ExeFilename[] =”main.mrb” RubyFilename[] =null

(5)ExeFilename[]のファイル内容をメモリに読み込む。 RubyStartFileName[]=”main.mrb” ExeFilename[] =”main.mrb” RubyFilename[] =null

(6)メモリに読み込んだプログラムを、  mrb_load_irep(mrb,(const uint8_t *)RubyCode);に渡す。

(7)プログラムが終了したら(3)に戻る

これで、rubyスクリプトをCプログラムから実行できます。

19

一巡時

RubyStartFileName[]=”main.mrb” ExeFilename[] =”main.mrb” RubyFilename[] =null(3)Rubyプログラムの実行モードになったとき、RubyFilename[]をExeFilename[]に入れる。 RubyStartFileName[]=”main.mrb” ExeFilename[] =null RubyFilename[] =null

(3-1)ExeFilename[]がnullのときは、ファイルメニューを出す。 RubyStartFileName[]=”main.mrb” ExeFilename[] =null RubyFilename[] =null

(3-2)コマンドでのRubyFilename[]書き込み待ち。 RubyStartFileName[]=”main.mrb” ExeFilename[] =null RubyFilename[] =null

20

一巡時

(3-3)実行コマンドを受け付けたら、RubyFilename[]をExeFilename[]に入れる。 RubyStartFileName[]=”main.mrb” ExeFilename[] =”foo.mrb” RubyFilename[] =”foo.mrb”

(4)RubyFilename[]を nullにする。 RubyStartFileName[]=”main.mrb” ExeFilename[] =”main.mrb” RubyFilename[] =null

(5) 以降同じ

(6-1)実行時にRubyプログラム内で、RubyFilename[]がセットされたとき RubyStartFileName[]=”main.mrb” ExeFilename[] =”foo.mrb” RubyFilename[] =”Sample.mrb”

ExeFilename[]を保持しているのは、Rubyプログラムからの実行ファイルの問い合わせに答えるため

21

一巡時

(7)プログラムが終了したら(3)に戻る。 RubyStartFileName[]=”main.mrb” ExeFilename[] =”foo.mrb” RubyFilename[] =”Sample.mrb”

(3)RubyFilename[]をExeFilename[]に入れる。 RubyStartFileName[]=”main.mrb” ExeFilename[] =”Sample.mrb” RubyFilename[] =”Sample.mrb”

(4)RubyFilename[]を nullにする。 RubyStartFileName[]=”main.mrb” ExeFilename[] =”Sample.mrb” RubyFilename[] =null

(5) 以降同じRubyFilename[]をExeFilename[]にコピーして回す機構により、少ない内部メモリを使いまわしながら、Rubyプログラムを実行でき環境を作っている。

22

クラスの書き方

mrb_state *mrb = mrb_open();if(mrb == NULL){

Serial.println( "Can not Open mrb!!" );return false;

}

global_Init(mrb); //グローバル変数の設定kernel_Init(mrb); //カーネル関連メソッドの設定sys_Init(mrb); //システム関連メソッドの設定serial_Init(mrb); //シリアル通信関連メソッドの設定mem_Init(mrb); //ファイル関連メソッドの設定i2c_Init(mrb); //I2C関連メソッドの設定servo_Init(mrb); //サーボ関連メソッドの設定

始めからメモリに置いておくクラスは、mrb_open()したあと、直ぐにクラス設定している。

robot_Init(mrb); //ロボットクラスの追加

23

クラスの書き方

void global_Init(mrb_state *mrb){

mrb_define_global_const(mrb, "ON", mrb_fixnum_value(1));mrb_define_global_const(mrb, "OFF", mrb_fixnum_value(0));mrb_define_global_const(mrb, "HIGH", mrb_fixnum_value(1));mrb_define_global_const(mrb, "LOW", mrb_fixnum_value(0));mrb_define_global_const(mrb, "INPUT", mrb_fixnum_value(0));mrb_define_global_const(mrb, "OUTPUT", mrb_fixnum_value(1));

}

Rubyで使うグローバル変数の設定です。

24

クラスの書き方

void kernel_Init(mrb_state *mrb){ mrb_define_method(mrb, mrb->kernel_module, "pinMode", mrb_kernel_pinMode, MRB_ARGS_REQ(2));

mrb_define_method(mrb, mrb->kernel_module, "tone", mrb_kernel_tone, MRB_ARGS_REQ(2)|MRB_ARGS_OPT(1));

mrb_define_method(mrb, mrb->kernel_module, "millis", mrb_kernel_millis, MRB_ARGS_NONE());}

カーネルクラスの設定です。

25

クラスの書き方

void sys_Init(mrb_state *mrb){ struct RClass *systemModule = mrb_define_module(mrb,"System");

mrb_define_module_function(mrb, systemModule, "exit", mrb_system_exit, MRB_ARGS_NONE());

mrb_define_module_function(mrb, systemModule, "use", mrb_system_use, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));

mrb_define_module_function(mrb, systemModule, "use?", mrb_system_use_p, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));}

Systemクラスの設定です。静的なクラスを作るとき

26

クラスの書き方

struct RClass *serialModule = mrb_define_class(mrb, "Serial", mrb->object_class);

MRB_SET_INSTANCE_TT(serialModule, MRB_TT_DATA);

mrb_define_method(mrb, serialModule, "initialize", mrb_serial_initialize, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));

mrb_define_method(mrb, serialModule, "print", mrb_serial_print, MRB_ARGS_OPT(1));

Serialクラスの設定です。動的なクラスを作るとき

27

クラスの書き方

static struct mrb_data_type serial_type = { "Serial", serial_free };

static mrb_value mrb_serial_initialize(mrb_state *mrb, mrb_value self){ //Initialize data type first, otherwise segmentation fault occurs. DATA_TYPE(self) = &serial_type; DATA_PTR(self) = NULL;

Serialc* serialc = new Serialc();

DATA_PTR(self) = serialc; return self;}

この構造体の意味が、よくわかっていないです・・・。

動的なクラスを作るとき

Rubyプログラム

S = Serial.new()

28

クラスの書き方

mrb_value mrb_serial_print(mrb_state *mrb, mrb_value self){mrb_value text;

 Serialc* serialc = static_cast<Serialc*>(mrb_get_datatype(mrb, self,                               &serial_type)); mrb_get_args(mrb, "S", &text);

 serialc->write((const unsigned char *)RSTRING_PTR(text), RSTRING_LEN(text));

return mrb_nil_value();}

printメソッド動的なクラスを作るとき

Rubyプログラム

S = Serial.new()S.print 'Hello'

29

クラスの書き方

自作のuse()メソッドから、クラス設定した xxxx_Init(mrb_state *mrb)を呼び出すことにより、クラスをメモリに展開する。

mrb_define_module_function(mrb, systemModule, "use", mrb_system_use, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); mrb_define_module_function(mrb, systemModule, "use?", mrb_system_use_p, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));

mrb_value mrb_system_use_p(mrb_state *mrb, mrb_value self){

return Is_use(mrb, self, 1);}

メモリ上に、

クラスを展開するRubyプログラムから、クラスを読み込ませる

Rubyプログラムif(System.use?("WiFi") == false)then System.exit() end

30

クラスの書き方

mrb_value Is_use(mrb_state *mrb, mrb_value self, int mode){mrb_value vName, vOptions;char *strName;int ret = 0;

int n = mrb_get_args(mrb, "S|A", &vName, &vOptions);

strName = RSTRING_PTR(vName);

if(strcmp(strName, WIFI_CLASS) == 0){ if(mode == 0){ return Is_useWiFi(mrb, self, 0); } else{ return Is_useWiFi(mrb, self, 1); } }

メモリ上に、

クラスを展開するRubyプログラムから、クラスを読み込ませる

31

クラスの書き方

//**************************************************// WiFiモジュールESP8266ボードを使えるようにします//**************************************************mrb_value Is_useWiFi(mrb_state *mrb, mrb_value self, int mode){int ret = 0;

ret = esp8266_Init(mrb); //ESP8266ボード関連メソッドの設定

return (mode == 0?mrb_fixnum_value(ret):mrb_bool_value(ret == 1));}

メモリ上に、

クラスを展開するRubyプログラムから、クラスを読み込ませる

Rubyプログラムif(System.use?("WiFi") == false)then System.exit() end

32

引数の展開

時間が無いので、またの機会に・・・

ソースを見てね!

ソースを見たら、直ぐわかります。https://github.com/wakayamarb/wrbb-v2lib-firm/tree/master/firmware_develop/wrbb_mruby

33

戻り値の生成方法

時間が無いので、またの機会に・・・

ソースを見てね!

ソースを見たら、直ぐわかります。https://github.com/wakayamarb/wrbb-v2lib-firm/tree/master/firmware_develop/wrbb_mruby

34

ご清聴ありがとうございました

CITRUS号です。