2017年3月26日日曜日

Raspberry Pi kernel 4.9でServoBlaster(その2 非推奨)

前回の暫定的な処置を少し変更。
"/proc/cpuinfo"の"Hardware"情報を元にする方法はkernel 4.9では通用しないので、
"/proc/device-tree/soc/ranges"を読み込んで、"board_model"を判定するように変更してみた。

参考:下のリンク、pelwellさんのコメントを参考にしました。
https://github.com/raspberrypi/linux/issues/1902#issuecomment-287365600

 ※以下は非推奨です!! Raspberry Pi 2 Model Bでしか確認していません!※

"servod.c"をエディタで開き、958行目からの
if (strstr(modelstr, "BCM2708"))
            board_model = 1;
else if (strstr(modelstr, "BCM2709"))
            board_model = 2;
else
            fatal("servod: Cannot parse the hardware name string\n");
ここを下のように書き換える。
char buffer[5];
  FILE *file;
        
  file = fopen("/proc/device-tree/soc/ranges", "rb");
  fread(buffer, 1, sizeof(buffer), file);
  fclose(file);

  if (buffer[4] == 0x20)
        board_model = 1;
  else if (buffer[4] == 0x3f)
        board_model = 2;
  else
        fatal("servod: Cannot parse the board model\n");
※追記1(2017/04/22 20:20)※
本当は"hardware name"を読んでいる訳ではないので、最後のメーッセージは
"servod: Cannot parse the board model\n"
 とでもすれば良いですかね

※追記2(2017/04/27 20:25)※
"char buffer[8]"から"char buffer[5] "へ変更

以前の"servod"を削除して、改めて"make"し、"servod"を起動する。



※追記3(2017/05/03 21:40)※
下記にて、"/proc/device-tree/soc/ranges"を開けなかった場合の処理を追加。
fseekでファイル読込開始位置を指定し、配列への読み込みを限定してみた。
(特に意味は無い)

char buffer[1];
  FILE *file;
 
  file = fopen("/proc/device-tree/soc/ranges", "rb");
 
  if (!file)
        fatal("Unable to open /proc/device-tree/soc/ranges: %m\n");
 
  fseek(file, 4, SEEK_SET);
  fread(buffer, 1, sizeof(buffer), file);
  fclose(file);

  if (buffer[0] == 0x20)
        board_model = 1;
  else if (buffer[0] == 0x3f)
        board_model = 2;
  else
        fatal("servod: Cannot parse the board model\n");

2017年3月13日月曜日

ラズパイ kernel 4.9でServoBlaster(非推奨)

Raspberry Pi 2 Model Bで使っているArch Linux ARMのkernelが、4.9系に上がりましたが、、、。
ServoBlasterは4.9系に対応しておらず、
"servod: Cannot parse the hardware name string"
エラーを吐いて起動しません。


ServoBlasterは、"/proc/cpuinfo"から情報を取ってRaspberry Piの機種ボードモデルを判別しているらしいのですが、
kernel 4.9になってから、"/proc/cpuinfo"での情報が変わったようです。
これに対応させるように、応急処置をしてみました。

※追記1(2017/03/26 16:55)※
Raspberry Piのボードモデル判別の方法を修正したものが、次にあります。
 http://aoo10yan.blogspot.jp/2017/03/raspberry-pi-kernel-49servoblaster.html


※以下は非推奨です!! Raspberry Pi 2 Model Bでしか確認していません!※

"servod.c"をエディタで開き、
else if (strstr(modelstr, "BCM2709"))
この行を下のように書き換える。
else if (strstr(modelstr, "BCM2709") || strstr(modelstr, "BCM2835"))
以前の"servod"を削除して、改めて"make"し、"servod"を起動する。


自分の環境では、これで動きました。

2017年3月10日金曜日

Scratch 1.4へテキストファイルを読み込む

前回、Scratchのブロックを追加して、Linuxコマンドを送るようにしたので、
コマンドの出力結果をScratchへ読み込むブロックも作ってみる。

※言うまでもないですが、Scratchの改造は自己責任で!※
通常は、直接外部ファイルを読み込むためのブロックは用意されていないので、
ScratchをSmalltalkのレベルで改造する必要があり、以下を参考にして、
ブロックの追加を行った。情報を公開してくださった方々に感謝。
参考
http://itpro.nikkeibp.co.jp/article/COLUMN/20111019/371085/
http://oohito.com/nqthm/archives/2243
http://d.hatena.ne.jp/minekoa/20080314/1205484707


ブロックの追加。

('addFile %s to %L' #- #addfile:toList: 'filename')

外部ファイルを読み込んで、Scratch側のリストに追加するメソッドを設定する。
読み込むファイルまでのパスを抽出し 、空ならデフォルトのパスにする。
空でなければ、抽出したパスを使う。その上でファイルの有無を確認して処理を進める。
一行ごとに指定したリストに追加して行く。
この、リストに追加して行く処理は、まるごとScratchの「(なにか)を(リスト)に追加する」
利用する。

リストに追加して行く処理を考えている最中に、内容をTwitterにつぶやいたところ、
Smalltalkに詳しいsumimさんからスマートな方法をご教示頂きました。 有難うございました。

addfile: t1 toList: t2 
    | path file |
    path _ FileDirectory dirPathFor: t1.
    path = '' ifTrue: [path _ FileDirectory default pathName].
    ((FileDirectory on: path)
        fileExists: t1)
        ifTrue: 
            [file _ FileStream readOnlyFileNamed: t1.
            file contentsOfEntireFile lines do: [:line | self append: line toList: t2]]


先に格納用のリストを作っておく。
前回追加したブロックで、コマンドの出力をファイルにリダイレクトする文字列を実行。
リダイレクトで指定したファイルを、格納用のリストに追加するように実行。

"ls > /home/o10yan/lstest.txt"で"ls"コマンドの結果をファイルにして、
それをScratchのリストに読み込む一連の流れをやってみた。

勿論、出力結果にこだわらなくても、平文テキストファイルの読み込み用としても使える。

2017年3月5日日曜日

Scratch 1.4からLinuxコマンドを使う

前回では、ServoBlasterと言う限られた条件化で動かしたが、
少しだけ書き換えて、Linuxコマンド全般を使えるようにしてみる。

※言うまでもないですが、Scratchの改造・シェルスクリプトの実行は自己責任で!※
通常は、直接Linuxコマンドを動かすためのブロックは用意されていないので、
ScratchをSmalltalkのレベルで改造する必要があり、以下を参考にして、
ブロックの追加を行った。情報を公開してくださった方々に感謝。
参考
http://itpro.nikkeibp.co.jp/article/COLUMN/20111019/371085/
http://oohito.com/nqthm/archives/2243
http://d.hatena.ne.jp/minekoa/20080314/1205484707


ブロックの追加。

('shell %s' #- #shell: '')

メソッドで、保存するファイル名を変更。
(ホームディレクトリは私の環境の場合なので、そこは御自分の環境に読み替えて下さい)

shell: t1 
    | file |
    file _ FileStream fileNamed: '/home/o10yan/Scratch/shell'.
    file nextPutAll: t1.
    file close.
    (Delay forMilliseconds: 100) wait


シェルスクリプトの指定ファイルも変更。
読み込んだ文字列(コマンド)をそのまま"eval"で評価して実行。

#!/bin/bash

if [ ! -e /home/o10yan/Scratch/shell ]; then
    touch /home/o10yan/Scratch/shell
fi

while inotifywait -e modify /home/o10yan/Scratch/shell; do
    text_line=$(cat /home/o10yan/Scratch/shell)

    if [ -n '$text_line' ]; then
         echo '' > /home//o10yan/Scratch/shell
         eval $text_line
    fi
done

Scratchから"gpio readall"を送って見たところ
SLを走らせてみた

まとめ
やってることは非常に単純。
Scratchから文字列をファイルに保存する。
シェルスクリプトで、文字列をコマンドとして実行する。

現実的には、「遠隔センサー接続」を利用したり、scratchClient と言うソフトで
できるようなので、そちらを使った方が楽だと思います。
が、実験としては、面白かったです。

2017年3月3日金曜日

Scratch 1.4からServoBlasterを使う

Arch Linux ARMに入っているScratch 1.4のブロックを使ってServoBlasterを動かそうという試み。

※言うまでもないですが、Scratchの改造・シェルスクリプトの実行は自己責任で!※

通常は、直接ServoBlasterを動かすためのブロックは用意されていないので、
ScratchをSmalltalkのレベルで改造する必要があり、以下を参考にして、
ブロックの追加を行った。情報を公開してくださった方々に感謝。
参考
http://itpro.nikkeibp.co.jp/article/COLUMN/20111019/371085/
http://oohito.com/nqthm/archives/2243
http://d.hatena.ne.jp/minekoa/20080314/1205484707

概要
ServoBlasterは、"echo 0=50% > /dev/servoblaster"と言った形式のコマンドで、
"/dev/servoblaster"に値を送る事でサーボモータを動かす。
 なので、Scratch側から上記のコマンド相当(ファイルへの書き込み)を実行できれば、
ServoBlasterが動くはず。

だったが、、、。

やってみたところ、Scratchで直接ファイル(/dev/servoblaster)への書き込みを
実行しても、ServoBlasterで拾わなかった。
そこで、Scratch外部のシェルスクリプトから"echo 0=50% > /dev/servoblaster"を送ってみた。
動作確認ができたので、この方法を使うことにした。

手順
①・ScratchからSmalltalkへ降りて、ブロックの追加をする。
②・追加したブロックに任意のファイルへの書き込みのメソッド(?)を設定する。
③・任意のファイルの更新を監視し、変更があった場合にファイル内容(文字列)を読み込んで、
"echo"コマンドで"/dev/servoblaster"へ送る為のシェルスクリプトを作成する。


手順①は上述の参考サイトを見て、適当なブロックのカテゴリに追加。


('servo %s' #- #servo: '0=50%')

ブロックができたことを確認。


手順②では、今回は任意のファイルを"/home/o10yan/Scratch/servo"と決めうちする。
(ホームディレクトリは私の環境の場合なので、そこは御自分の環境に読み替えて下さい)
書き込む文字列は引数"t1"で渡されていると推測。

servo: t1 
    | file |
    file _ FileStream fileNamed: '/home/o10yan/Scratch/servo'.
    file nextPutAll: t1.
    file close.
    (Delay forMilliseconds: 10) wait

(注:上記"file _"は、Scratchでは"file ←"と表示される)


Scratch側の準備は以上で終了。
試しに動かしてみて、ファイルができているかを確認。



手順③で以下のように、ファイル監視のシェルスクリプトを作成。
ファイルの更新監視用に"inotifywait"を使うので、予め"inotify-tools"をインストールしておく。
先ずは、監視用のファイルが存在するかを確認して、無ければ作っておく。
"inotifywait"で指定のファイルに更新があるかを監視し、更新があった場合、
ファイルの内容を変数(text_line)に読み込んで、それを"/dev/servoblaster"へ送る。
ファイルに文字列が残ってしまうと気持ち悪いので、空白を書き込んでおく。

#!/bin/bash

if [ ! -e /home/o10yan/Scratch/servo ]; then
    touch /home/o10yan/Scratch/servo
fi

while inotifywait -e modify /home/o10yan/Scratch/servo; do
    text_line=$(cat /home/o10yan/Scratch/servo)

    if [ -n '$text_line' ]; then
         echo '' > /home//o10yan/Scratch/servo
         echo $text_line > /dev/servoblaster
    fi
done

出来上がったシェルスクリプトを実行し、監視状態になることを確認し、
Scratchのブロックを動かす。


今回は、ServoBlasterを動かすための改造を行ったが、次回はLinuxコマンドを
送るような改造を行う。

※お願い※
私は、Smalltalkについて全然分かっていないので、コピペ主体で改造してます。
Smalltalkに詳しい方で、「ここは間違っている」「こうした方が良い」と言う
指摘がありましたら、コメントを頂けると有難いです。
よろしくお願いします。