ラベル Raspberry Pi の投稿を表示しています。 すべての投稿を表示
ラベル Raspberry Pi の投稿を表示しています。 すべての投稿を表示

2017年2月27日月曜日

ラズベリー・パイでSST26VF032Bの読み書き(node.js)その4

前回1/前回2/前回3からの続き

アドレス範囲指定もJpGridにしてみた。
読み込み時の進捗表示も追加。

データをファイルに保存したり、ファイルから書き込めるように機能追加中
丁度今、ファイルダウンロード機能が作り終わったところ。
 ファイルから書き込みができれば、ようやく本題に戻れるわけだ・・・。

なかなかまとまった時間が取れないけど、コツコツ頑張ろう。

2017年2月11日土曜日

ラズベリー・パイでSST26VF032Bの読み書き(node.js)その3

前回1/前回2からの続き

DataViewを手作りしていたけど、思うところがあって、jqgridに変更中


スタイルが崩れているのは、fundationと干渉しているから。
別途、調整する。 まずは『巨人の肩に乗る』
右側にACSIIビューつけた。こちらももろもろ別途調整する。

まずはデータ操作がそれなりにできるようにして、早くファイルから読み書きができるようにする。
やりたいことはたくさんある。時間は有限だ!

2017年2月5日日曜日

ラズベリー・パイでSST26VF032bの読み書き(node.js)その2

前回からの続き

ようやくデータの読み書きができるようになった。
ファイルが多すぎて公開するのが少し面倒。なにかよい方法が無いか検討中。

あとは、ファイルに書き出す、ファイルから書き込みができれば、
当初の目的?だった、FONのFlash交換の実験ができそう!
どんだけ遠回りしてるんだOrz

2月に入ってまとまった時間がなかなか取れない。

その他
しばらくは「頑張らないことを頑張りたい」と思う


2017年1月30日月曜日

ラズベリー・パイでSST26VF032bの読み書き(node.js)

昨年12月からFON2405EのSPIフラッシュメモリを交換すべくコツコツと作業をしている。
最近あまり更新できなかったけど、少し進展があった。

経緯
前回 c++でSPI制御プログラムを作成した。簡易的な動作確認はできたけど、
いろいろ機能を試したりとなると作るのも操作するのも大変なことに気づいた。

CUIで対話式もめんどいし、electron使うのも大げさだし・・・。
かといってwebサーバー建てるのもな・・・と思っていたけど、
一念発起してnode.jsを使ってwebアプリで行こうと思った。

まだソース貼れるほどできていないけど、こんな感じ。

自分の想像力の無さなのかもしれないけど、GUIの方がわかりやすい。


構成は
・node.js + express
・CSSフレームワークはfundation
・SPI通信はrpi-spi
と、おんぶに抱っこ いや『巨人の肩に乗る』状態

その他
公私ともに忙しいけど、ガンバロー

2017年1月5日木曜日

ラズベリー・パイのクロス開発環境(Eclipse)構築メモ

昨年から、少しづつクロス環境でのプログラムを行っている。
小規模なものはテキストエディタやVScodeでなんとかなるレベルだったけど、
ちょっと規模が大きくなると途端に面倒になってしまい、筆が進まなくなってしまう。
2017年の1発目・・・開発環境の見直し!

Eclipse使ってエレガントにラズベリー・パイのプログラミンを行う

前提
・クロスコンパイル環境→ここ
・Eclipse
・ ラズベリー・パイとSSH接続可能

手順<要点のみ抜粋>

1.ツールチェーンは「Cross GCC」を選択
2.クロスGCCコマンド
   接頭部:arm-linux-gnueabihf-
   パス:/var/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
   ※環境に合わせる


3.Eclipseからラズベリー・パイにSSH接続
  「ウィンドウ」→「 ビューの表示」→「その他」
  「リモート・システム」→「リモート・システム」でタブが追加される
  右クリで新規接続
   「SSHのみ」を選択しその後は良きに計らう
   「Sshシェル」を右クリし「シェルの起動」で接続できればOK

4.リモートデバッグ準備
  「デバッグ の構成」にて各種設定
   メイン
   ・接続を「ローカル」→3で作成した接続先に変更
   ・リモート絶対ファイルパス
   ・Commands to execute before application

   デバッガ−
    GDBデバッガ−:arm-linux-gnueabihf-gdb

5.リモートデバッグ開始
   こんな感じでステップ実行!

 参考
先人に感謝!!ありがとうございます。
http://qiita.com/atchy@github/items/fb9df9e5865d8c7f7a72

2016年12月25日日曜日

ラズベリー・パイでSST26VF032の読み書き

11月の末頃にFONのフラッシュ容量拡張のために
SST26VF032Bを入手した。 
microchipのオンラインストアから注文できるし、3日程度で到着した気がする。
しかし、そのまま交換してもフラッシュに書き込みができなかった。Orz

注意
 SST26VF032はSPIモードでの書き込みに対応していないので、「B」有りが必要。
http://www.microchip.co.jp/support/faq_sst-fm.html
このあたりをあまり気にせずに購入していた。危なかった。。。

基礎知識
をあまり持っていなかったので、他の型番の日本語のデータシートなどを読んで雰囲気を学習
http://www.onsemi.jp/pub_link/Collateral/ENA2097JP-D.PDF
http://japan.xilinx.com/xcell/xl55/jp55xcell_13.pdf


そしてSST26VF032Bについて
・データシート
http://ww1.microchip.com/downloads/jp/DeviceDoc/jp566514.pdf
 ・サンプルプログラム
http://www.microchip.com/wwwproducts/jp/SST26VF032B
 →末尾のソフトウェア

初期化
Quad I/Oとか特殊なものを使わないのであれば、初期化すべき項目は少ないと思う。
01H WRSRでIOCとWPENの設定くらい
JEDEC-IDを読んで対象のデバイスかどうかを確認しておく

読み込み方法
03H Readですんなりと読み出すことができる

書き込み方法
一番手こずった
PinのWriteProtectや06H WREN、そしてBlockProtectなんてものもあるOrz
最後のBlockProtectを失念していたために半月くらい悩んだ。
前述のサンプルプログラムを最初から見ておけばよかった。
こんな流れ
1.06H WREN WriteEnable
2.42H WBPR BlockProtection解除
3.02H PP PageProgram
4.05H RDSR BUSYチェック

こんな感じ。


2016年11月14日月曜日

ラズベリー・パイのカーネルビルドとクロスコンパイル環境のメモ

時間がたつと忘れそうなので、メモ

 カーネルビルドとクロスコンパイル環境の作成
https://www.raspberrypi.org/documentation/linux/kernel/building.md

Raspiのバージョンによって手順が異なるので注意。
以下はRaspi1の場合
git clone --depth=1 https://github.com/raspberrypi/linux
cd linux
KERNEL=kernel
make bcmrpi_defconfig

2016年10月23日日曜日

ラズベリー・パイで自力シリアル通信(ドライバー編)

随分と時間がかかってしまったけど、ようやく動くものになってきた。

概要
カーネルモジュール(ドライバー?)を作成して、GPIOをパタパタさせる。
8月からやっているヤツのデバドラ版。

デバイスとして扱われるので、echoやcatで入出力ができたり、既存の通信プログラムでも使えると思う。
出力されるクロックはdelayを使っているので、安定していると思う。
データのポーリングはカーネルタイマーを使っているので、
ラズベリー・パイの場合は100Hzが(10ms)が限界。
性能評価はこれから。

cat /dev/zero > /dev/MySFR9km0

とやってみると、大体350 Char/Secくらい。意外と遅い。

PIC側の設計上は960Char/Secまで行けるのはずなのだが??



メモ
request_mem_regionが毎回失敗するのはなぜだろう
早速Amisでも移植してみるか?

2016年8月31日水曜日

ラズペリーパイで自力シリアル通信

ひょんなことから、過去にFONのGPIOを使ったなんちゃってシリアル通信を実装したのを思い出した。過去の投稿
 当時は、ラズベリーパイが注目されていて、いいな−と思いつつ、ちょっと高いなと感じており、中古で@500円程度で入手できるFONを何とか拡張できなかと思っていた。
結局受信エラーが抑えきれなくて、途中興味を失ってしまった。

最近になって、
1.2014年7月 トランジスタ技術
2.LINUXデバイスドライバ
3.RaspberryPiで学ぶARMデバイスドライバープログラミング
 を読む機会があって、FONでやりたかったことを再度挑戦してみようと思った。

そのまえに、情報が豊富なラズベリーパイで準備運動をしてみた記録。



 概要
ユーザーランドでGPIOをパタパタさせて、同期型シリアル通信を行い、
PICマイコンにて、UARTに変換する。

ラズピでuname -aを実行してPIC経由のURATで受信した結果。


ラズピ側
ユーザーランドでGPIOをパタパタさせるプログラム
ほとんど前述の 「3」のとおり
GPIO7 - CLK OUT
GPIO8 - DATA OUT
PIC側
RB0 - CLK IN (割り込み)
RB5 - DATA IN
RB2 - TX
なんとなく達成感があるね。
次はPICからラズピ側に送信する機能を作ってみよう。

2015年2月1日日曜日

GW-USMicroNとWLI-UC-GNをラズベリーパイで使う

この前、リサイクルショップで、GW-USMicroNが300円で売られていた。
小さくて可愛いのでついつい買ってしまった。

以前から持っているWLI-UC-GNと同じくらいの大きさ!
この大きさはラズベリー・パイに丁度いいと思い、早速接続ー

結論から書くと、2つとも同じドライバーで使えたのだ。

ベンダーIDとプロダクトIDは以下の通り。
GW-USMicroN は2019 ed14
WLI-UC-GNは0411 015d
 
一時的に使うのであれば、

modprobe rt2800usb
echo 2019 ed14 > /sys/bus/usb/drivers/rt2800usb/new_id

恒久的に使うのであれば、
/etc/udev/rules.d/99-wireless.rules

# PLANEX GW-USMicroN
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="2019", ATTR{idProduct}=="ed14", RUN+="/sbin/modprobe -qba rt2800usb"

# BUFFALO WLI-UC-GN
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0411", ATTR{idProduct}=="015d", RUN+="/sbin/modprobe -qba rt2800usb"


/etc/modprobe.d/wireless.conf

# PLANEX GW-USMicroN
install rt2800usb /sbin/modprobe --ignore-install rt2800usb $CMDLINE_OPTS; /bin/echo "2019 ed14" > /sys/bus/usb/drivers/rt2800usb/new_id

# BUFFALO WLI-UC-GN
install rt2800usb /sbin/modprobe --ignore-install rt2800usb $CMDLINE_OPTS; /bin/echo "0411 015d" > /sys/bus/usb/drivers/rt2800usb/new_id


やっぱり、ラズベリー・パイは情報が多くていいね!


----------------------------
ちなみに、前書いたGPIOの制御、ネットで調べたら使い方が書いてあった。
処理中(0.2s点灯、0.1s消灯を繰り返す)
gpio l <gpio> 2 1 4000 0 4000

エラー(0.1s点灯、0.1s消灯を繰り返す)
gpio l <gpio> 1 1 4000 0 4000

ふーん。使えるかも!

2014年12月29日月曜日

ラズベリーパイとしりとりで遊ぶよ

もう年末で、今日は早く仕事が終わったので、
すこしラズベリーパイで遊んでみた。

以前にダウンロードしたことがあった、Wikipediaのデータを使って
なにかできないかと思い、
巨大なWikipediaデータからタイトルとそのよみがな、概要だけを抽出して、データベース化。
それをラズベリーパイに覚えてもらって、「しりとり」でもやってみようと思う。


Wikipediaのデータはここにあって
http://dumps.wikimedia.org/jawiki/latest/

以下のURLに説明があった。
http://www.mwsoft.jp/programming/munou/wikipedia_data_list.html

入手したのは「jawiki-latest-abstract.xml」というもので、
タイトルや概要が記載れている1.5GB程度のファイル。
 xml形式になっており、ちょっと困った。

xml2csv的なものはいろいろありそうだけど、phpの勉強を兼ねて自作。
(その他に、いくつかフィルタしたいこともあったので)

先ほどのファイルはこんな感じ
<title>Wikipedia: 言語</title>
<url>http://ja.wikipedia.org/wiki/%E8%A8%80%E8%AA%9E</url>
<abstract>言語(げんご)とは、コミュニケーションのための記号の体系である。</abstract>
<links> …省略

 これの、<title>のWikipedia:以降〜</title>までを名称として、
<abstract>内を概要とした。
よみがなは、以下のルールで生成した。
1.タイトルがすべてひらがな→タイトルをよみがな
2.タイトルがすべてカタカナ→ひらがなに変換してよみがなとする
3.アブストラクトにタイトル(説明) があれば、説明をひらがなにしてみる
3−1.そのさい、スペースや-・などの区切り文字があったら、そこまでで切り取る

そのほか「〜の一覧」などのまとめページは除外した。
全容がこれ
<>
<?php
    mb_language('Japanese');
    mb_internal_encoding('UTF-8');
    mb_regex_encoding("UTF-8");
    
    //タイトル
    $title_start_string="Wikipedia: ";
    $title_start_string_len = mb_strlen($title_start_string);
    $title_end_string="";
    $title_end_string_len   = mb_strlen($title_end_string);
    //アブスト
    $abst_start_string="";
    $abst_start_string_len = mb_strlen($abst_start_string);
    $abst_end_string="";
    $abst_end_string_len   = mb_strlen($abst_end_string);
    //
    $mode = 0;
    $testval_tit = '';
    $testval_abs = '';
    $testval_kana = '';
    $cnt_k = 0;
    $cnt_r = 0;
    $cnt_ng = 0;
    if($argc > 1){
        try {
            $pdo = new PDO('mysql:dbname=test;host=192.168.4.135', 'username', 'password',array(PDO::MYSQL_ATTR_LOCAL_INFILE => true));
        } catch (PDOException $e) {
            exit('データベースに接続できませんでした。' . $e->getMessage());
        }
        
        $stmt = $pdo->query('SET NAMES utf8');
        if (!$stmt) {
            $info = $pdo->errorInfo();
            exit($info[2]);
        }
        $stmt = $pdo->query('set character_set_database=utf8');
        if (!$stmt) {
            $info = $pdo->errorInfo();
            exit($info[2]);
        }
        
        echo "読み取り開始・・・\n";
        $time_start = microtime(true);
        $fp = fopen($argv[1], "r");
        $temp_file = tempnam(sys_get_temp_dir(), 'Tux');
        $fpw = fopen($temp_file, "w");
        while ($line = fgets($fp)) {
            if($mode == 0){
                //タイトル探し
                $testval_tit = searchStr($line,$title_start_string,$title_start_string_len,$title_end_string,$title_end_string_len);
                if($testval_tit !== ''){
                    //echo "->".$line;
                    //echo "名称=".$testval_tit."\n";
                    $cnt_k = $cnt_k + 1;
                    $mode = 1;
                }
            }elseif($mode == 1){
                //アブスト探し
                $testval_abs = searchStr($line,$abst_start_string,$abst_start_string_len,$abst_end_string,$abst_end_string_len);
                if($testval_abs !== ''){
                    //echo "->".$line;
                    //echo " 概要=".$testval_abs."\n";
                    
                        $testval_kana = seikei2($testval_abs,$testval_tit);
                        if($testval_kana !== ''){
                            /*echo "==============================\n";
                            echo "名称=".$testval_tit."\n";
                            echo " 概要=".$testval_abs."\n";
                            echo " よみがな=".$testval_kana."\n";
                            echo "==============================\n";*/
                            fwrite($fpw,$pdo->quote($testval_kana).",".$pdo->quote($testval_tit).",".$pdo->quote($testval_abs)."\n");
                            $cnt_r = $cnt_r + 1;
                            //if($cnt_r > 1000) break;
                        }else{
                        
                            /*echo "【NG】名称=".$testval_tit."\n";
                            echo "【NG】よみがな=".$testval_kana."\n";
                            echo "【NG】概要=".$testval_abs."\n";*/
                            $cnt_ng = $cnt_ng + 1;
                        }
                    
                    $mode = 0;
                }
            }
            

        }
        fclose($fpw);
        fclose($fp);
        
        $timelimit = microtime(true) - $time_start;
        echo "\n".$timelimit." seconds\n";
        echo "総数:".$cnt_k." 有効数:".$cnt_r." 無効数:".$cnt_ng." ".(100*$cnt_r/$cnt_k)."%\n";
        
        echo "DBに書き込み開始・・・"."'".$temp_file."'\n";
        $time_start = microtime(true);
        
        $stmt = $pdo->query("LOAD DATA LOCAL INFILE ".
                            "'".$temp_file."' REPLACE INTO TABLE `test`.`wiki` ".
                            "FIELDS TERMINATED BY ',' ENCLOSED BY '\'' LINES TERMINATED BY '\n' (`kana`, `name`, `gaiyo`);");
        if (!$stmt) {
            $info = $pdo->errorInfo();
            exit($info[2]);
        }
        
        $timelimit = microtime(true) - $time_start;
        echo "\n".$timelimit." seconds\n";
        
        $pdo = null;

    }
    function seikei2($abs,$title){
        $retval = "";
        //〜の一覧ってやつはいらない
        if(!endsWith($title,"一覧")){
            $t_title = mb_convert_kana(seikei($title),"c");
            if(preg_match("/^[ぁ-ゞー]+$/u",$t_title)){
                //タイトルが全部ひらがなだった
                $retval = $t_title;
            //}elseif(preg_match("/^[ァ-ヶー]+$/u",$t_title)){
            //    //タイトルが全部カタカタだった→ひらがなに変換
            //   $retval = $t_title;
                
            }else{
                $testval_k = searchStr($abs,$title."(",mb_strlen($title)+1,")",1);
                    if($testval_k !== ''){
                    //ひらがなにしてみる
                    $testval_kana = mb_convert_kana(seikei($testval_k),"c");
                    if(preg_match("/^[ぁ-ゞー・]+$/u",$testval_kana)){
                        $retval = $testval_kana;
                    }
                }
            }
        }
        return $retval;
    }
    function seikei($str){
        //空白や-を削除、区切り文字があれば先頭を返す
        $retval = "";
        $str_s = mb_ereg_replace("[-\s\u00A0\u3000・]","",$str);
        //$str_s = mb_ereg_replace("・","",$str_s);
        //$str_s = mb_ereg_replace("-","",$str_s);
        //$str_s = mb_ereg_replace(" ","",$str_s);
        //$str_s = mb_ereg_replace("ー",ー",$str_s);
        $ary = mb_split("[、, (,]",$str_s);
        if(count($ary) > 0){
            $retval = $ary[0];
        }else{
            $retval = $str_s;
        }
        
        return $retval;
    }
    function searchStr($str,$start_str,$start_str_len,$end_str,$end_str_len){
        $retval ="";
        $pos_s = mb_strpos($str, $start_str);
        $pos_e = mb_strpos($str, $end_str);
        if(($pos_s === false) || ($pos_e === false)){
            //みつからず
        }else{
            //echo mb_strlen($str)."->s:".$pos_s."->e:".$pos_e;
            //$retval =  mb_substr($str,$pos_s+$start_str_len,mb_strlen($str) - $start_str_len - $end_str_len-1);
            $retval =  mb_substr($str, $pos_s+$start_str_len, $pos_e - $pos_s - $start_str_len);
        }
        return $retval;
    }
    /**
    * endsWith
    * http://blog.anoncom.net/2009/02/20/124.html
    * 
    * @param string $haystack
    * @param string $needle
    * @return boolean
    */
    function endsWith($haystack, $needle){
        $length = (strlen($haystack) - strlen($needle));
        if( $length <0 data-blogger-escaped-false="" data-blogger-escaped-haystack="" data-blogger-escaped-length="" data-blogger-escaped-needle="" data-blogger-escaped-return="" data-blogger-escaped-strpos="">
これを実行すると・・・
php wikicsv.php jawiki-latest-abstract.xml
読み取り開始・・・
29.402565956116 seconds
総数:943216 有効数:408613 無効数:534603 43.321254092382%
DBに書き込み開始・・・'/tmp/TuxUHAuGL'
768.0825881958 seconds

PCで実行しているので、やはり生成は29秒と早い。
でも、ラズベリーパイに転送するのは、768秒・・・なんとか改善できないかな。
で、中身はこんな感じ


んでもって、サーバー側のスクリプトは、
<>
<?php
        mb_language('Japanese');
        mb_internal_encoding('UTF-8');
        mb_regex_encoding("UTF-8");
        
        $s_talk = htmlspecialchars($_GET['talk'], ENT_QUOTES, "utf-8");
        $result = "";
        
        try {
                $pdo = new PDO('mysql:dbname=test;host=192.168.4.135', 'username', 'password');
        } catch (PDOException $e) {
                talk("データベースに接続できませんでした。");
                exit('データベースに接続できませんでした。' . $e->getMessage());
        }
        
        $stmt = $pdo->query('SET NAMES utf8');
        if (!$stmt) {
            $info = $pdo->errorInfo();
            exit($info[2]);
        }
        $stmt = $pdo->query('set character_set_database=utf8');
        if (!$stmt) {
            $info = $pdo->errorInfo();
            exit($info[2]);
        }
        
        if(strlen($s_talk) == 0){
                talk("WEBサーバーを起動しました。");
        }else{
                $result = "あなたの言葉は、".$s_talk."です。";
                if(preg_match("/^[ぁ-ゞー]+$/u",$s_talk)){
                        //ひらがなだった
                        $stmt = $pdo->prepare("select * from wiki where wiki.kana like :word and wiki.kana not like '%ん' order by rand() limit 1");
                        $stmt->bindValue(':word', mb_substr($s_talk,-1).'_%');
                        $flag = $stmt->execute();
                        if (!$flag) {
                                $info = $stmt->errorInfo();
                                exit($info[2]);
                        }
                        while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
                                $result=$result."
私の言葉は".$data['name']."(".$data['kana'].")です。

".$data['gaiyo'];
                                talk("あなたの言葉は、".$s_talk."です。そして、私の言葉は、".$data['kana']."です。");
                        }
                }else{
                        $result=$result."
申し訳ありませんが、すべて「ひらがなで」入力してください。";
                        talk("あなたの言葉は、".$s_talk."です。申し訳ありませんが、すべて「ひらがなで」入力してください。");
                }
                

        }
        
        $pdo = null;
        
        function talk($kotoba){
                exec('echo "'.$kotoba.'" | /home/pi/aquestalkpi/AquesTalkPi -v -f1 -f - | aplay > /dev/null &');
        }
        echo <<< EOD



    
    簡易しりとり
    

 
 

    

RasPiと「しりとり」で遊ぶ!

これは、Wikipediaのダウンロード可能なデータを利用した簡易的な「しりとり」です。
あなたの言葉: {$result}
EOD; ?>
そして、ブラウザからアクセス!

ちょっと楽しいかも。

2014年12月21日日曜日

ラズベリーパイがweb経由でしゃべるよ

しばらくラズベリーパイで遊んでいなかったので、
色々と忘れてしまっている。

年末はいろいろあるね。そして仕事もプライベートも停滞気味・・・
よく、仕事と家庭と趣味の3本柱で、どれか1つでも充実していれば、
やっていけるというけれど、なんとかならないかな。

と、現実逃避なのだけど、最近Mysql+PHP+Javascriptの構成で遊んでいる。
直接仕事には関係ないけど、いつか役立つ日が来るはず。

今日やることは、WEB経由でRasPiを喋らせること
node.jsとphpでそれぞれやってみた。



node.js
ar http = require('http');
http.createServer(
    function(req,res){
        res.writeHead(200,{'Content-Type':'text/html'});
        res.end('Raspberry Pi & Node.js');
    }
).listen(8000);


----------------------------------------------------
var http = require('http');
var fs = require('fs');
var url = require('url');
var exec = require("child_process").exec;

var server = http.createServer();
server.on('request', doRequest);
server.listen(8000);
console.log('Server running!');

var cmd = "echo 'ウェブサーバーを起動しました。' | ./aquestalkpi/AquesTalkPi  -v f1 -f - | aplay";
exec(
    cmd,
    function(err, stdout, stderr) {}
);

 
// リクエストの処理
function doRequest(req, res) {
    fs.readFile('./hello.html', 'UTF-8',
        function(err, data) {
            res.writeHead(200, {'Content-Type': 'text/html'});
            res.write(data);
            res.end();
        });
    if(req.method=='GET') {
        var url_parts = url.parse(req.url,true);
        console.log(url_parts.query);
        if('talk' in url_parts.query){
            cmd = "echo '要求" + url_parts.query['talk']+"' | ./aquestalkpi/AquesTalkPi  -v f1 -f - | aplay";
            exec(
                cmd,
                function(err, stdout, stderr) {}
            );
        }
    }
}

----------------------------------------------------



    
    sample
    

 
 

    

Sample Page

これはNode.jsのサンプルページです。
しゃべる内容:

php
 /dev/null &');
 }else{
  exec('echo '.$s_talk.' | /home/pi/aquestalkpi/AquesTalkPi -v -f1 -f - | aplay > /dev/null &');
 }
 echo <<< EOD


 
  
  AquesTalkのテスト
  
 
 
     

WebからRaspiを喋らせる

WebからAquesTalkPiを制御するサンプル。
しゃべる内容:
EOD; ?>

やっていて困ったこと、phpで外部プログラムを実行しようとしたら、
ALSA lib confmisc.c:768:(parse_card) cannot find card '0'
ALSA lib conf.c:4241:(_snd_config_evaluate) function snd_func_card_driver returned error: No such file or directory
ALSA lib confmisc.c:392:(snd_func_concat) error evaluating strings
ALSA lib conf.c:4241:(_snd_config_evaluate) function snd_func_concat returned error: No such file or directory
ALSA lib confmisc.c:1251:(snd_func_refer) error evaluating name
ALSA lib conf.c:4241:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:4720:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM default
aplay: main:682: audio open error: No such file or directory

とエラーが出てしまった。
どうやらapacheの権限では、aplayを実行できないような気がする。
そこで、apacheの実行ユーザーを一般ユーザー(pi)に変えてみた
(参考)http://j-caw.co.jp/blog/?p=1407

/etc/apache2/envvars の
export APACHE_RUN_USER=www-data これをpiに変更

これで動いた!


2014年11月10日月曜日

ラズベリーパイがICカードの残高をしゃべるよ

ICカードの残高を喋ってくれたら面白いと思ったので、早速やってみた。

ICカードのリーダーにはパソリPaSoRi(RC-S320)を使用した。

1.下準備
 a)libusb-devの インストール
apt-get install libusb-dev

 b)libpafeの インストール
wget http://homepage3.nifty.com/slokar/pasori/libpafe-0.0.8.tar.gz
tar xzvf libpafe-0.0.8.tar.gz
cd libpafe-0.0.8/
./configure
make
make install

 c)環境設定
 このままではrootでしか使えないので
/lib/udev/rules.d/60-libpafe.rulesを作成する

ACTION!="add", GOTO="pasori_rules_end"
SUBSYSTEM=="usb_device", GOTO="pasori_rules_start"
SUBSYSTEM!="usb", GOTO="pasori_rules_end"
LABEL="pasori_rules_start"

ATTRS{idVendor}=="054c", ATTRS{idProduct}=="006c", MODE="0664", GROUP="plugdev"
ATTRS{idVendor}=="054c", ATTRS{idProduct}=="01bb", MODE="0664", GROUP="plugdev"
ATTRS{idVendor}=="054c", ATTRS{idProduct}=="02e1", MODE="0664", GROUP="plugdev"

LABEL="pasori_rules_end"


そして、
udevadm control --reload-rules
これで、下準備はおしまい。

2.自作プログラムの実行
 動作確認として/libpafe-0.0.8/tests/内にsuica_zandaka.cを作成。

#include 
#include 
#include "libpafe.h"

int main(void){
 /*スイカの残高を表示する*/
 pasori* p;
 felica* f;
 int i;
 int m;
 int wk, wk2;
 uint8 b[16];
 uint8 idm[16];
 
 felica_block_info fbi;
 fbi.service = 0x090f;
 fbi.mode = 0;
 fbi.block = 0;
 
 printf("ICカードの残高は、");
 p = pasori_open();
 if(!p){
  fprintf(stderr,"error\n");
  exit(-1);
 }
 pasori_init(p);
 f = felica_polling(p,FELICA_POLLING_ANY,0,0);
 //printf("read test\n");

 felica_get_idm(f, idm);
  
        // IDm文字列を作成stdlib
 //printf("IDm = %02x%02x%02x%02x%02x%02x%02x%02x\n", idm[0], idm[1], idm[2], idm[3], idm[4], idm[5], idm[6], idm[7]);

 for(i=0;i!=32;i++){
  if(!felica_read(f,&i,&fbi,b)){
   /*printf("[%02d] : ",i);
                 printf("%02X ",b[0]);
   printf("%02X ",b[1]);
                 printf("%02X",b[2]);
                 printf("%02X",b[3]);
                 printf("%02X",b[4]);
                 printf("%02X ",b[5]);
                 printf("%02X-%02X -> ",b[6],b[7]);
                 printf("%02X-%02X      ",b[8],b[9]);
                 printf("%02X%02X - % 5d Yen        ",b[10],b[11],b[11]*256+b[10]);
                 printf("%02X%02X%02X%02X\n",b[12],b[13],b[14],b[15]);*/
   //printf("[%02d] : ",i);
   //printf("%d ",b[0]);
   if(((int)b[1] > 0) || ((int)b[2] > 0)){
     /*printf("%02X ",b[0]);
     printf("%02X ",b[1]);
     printf("%02X",b[2]);
     printf("%02X ",b[3]);
     wk=b[4]>>1;
     wk=wk&0x7F;
     printf("%02d/",wk);
     wk=b[4]&0x01;
     wk=wk<<3 data-blogger-escaped-wk2="b[5]">>5;
     wk2=wk2&0x07;
     wk=wk+wk2;
     printf("%02d/",wk);
     wk=b[5]&0x1F;
     printf("%02d ",wk);
     printf("%02X-%02X -> ",b[6],b[7]);
     printf("%02X-%02X      ",b[8],b[9]);*/
     printf("%6d円です。\n",b[11]*256+b[10]);
     pasori_close(p);
     return 0;
     //printf("%02X%02X%02X%02X\n",b[12],b[13],b[14],b[15]);
   }
  }
 }
 printf("読み取れませんでした。\n");
 pasori_close(p);
 return 0;
}



実行ファイルの作成はこんな感じ
gcc -DHAVE_CONFIG_H -I. -I..    -I../src -I../ -g -O2 -MT suica_zandaka-suica_zandaka.o -MD -MP -MF .deps/suica_zandaka-suica_zandaka.Tpo -c -o suica_zandaka-suica_zandaka.o `test -f 'suica_zandaka.c' || echo './'`suica_zandaka.c
mv -f .deps/suica_zandaka-suica_zandaka.Tpo .deps/suica_zandaka-suica_zandaka.Po
/bin/bash ../libtool --tag=CC   --mode=link gcc -I../src -I../ -g -O2   -o suica_zandaka suica_zandaka-suica_zandaka.o ../src/libpafe.la


プログラムの出力をAquesTalkPiにしゃべってもらう

./suica_zandaka | ../../aquestalkpi/AquesTalkPi  -v f1 -f - | aplay

こんな感じ


参考

2014年11月3日月曜日

ラズベリーパイが天気を教えてくれるよ

天気予報を喋ってくれたら面白いと思ったので、早速やってみた。

ヤフーの天気予報をローカルに保存して、
内容を解析し予報部分を音声合成してもらうというもの。

 tenki.shはこんな感じ

#!/bin/bash
wget -q -O - http://weather.yahoo.co.jp/weather/jp/13/4410.html > tenki.html
php tenki.php
tenki.phpはこんな感じ
<?php

$fp = fopen("tenki.html", "r");

$timezone_array = array();
$tenki_array    = array();
$kion_array     = array();
$situdo_array   = array();
$today_string   = "";
$find_mode=0;   //0:今日の天気 1:日付 2-3:時間 4:天気 5:気温 6:湿度

if ($fp){
    if (flock($fp, LOCK_SH)){
        while (!feof($fp)) {
            $buffer = fgets($fp);

                        if($find_mode == 0){
                                if(stristr($buffer,'<div id="yjw_pinpoint_today">')){
                                        $find_mode = 1;
                                    //print("■発見".$buffer);
                                        //echo "\n";
                                }
                        }else if($find_mode == 1){
                                if(stristr($buffer,'<span class="yjSt">')){
                                        $find_mode = 2;
                                    // <span class="yjSt"> - 6月30日(月)</span></h3>
                                        $b1 = str_replace('<span class="yjSt"> -', "", $buffer);
                                        $b2 = str_replace('</span></h3>', "", $b1);
         
                                        $b3 = str_replace('(', " ", $b2);
                                        $b4 = str_replace(')', "曜日", $b3);
                                        $today_string= trim($b4);
                                        //print("■日付".$today_string);
                                        //echo "\n";
                                }
                        }else if($find_mode == 2){
                                //<small>時間</small>を探す
                                if(ereg('<small>時間</small>', $buffer)){
                                        $find_mode = 3;
                                }
                        }else if($find_mode == 3){
                                if(ereg('<small><font color="#999999">.*時</font></small></td>', $buffer)){
                                        //print("■過去".$buffer);
                                        //echo "\n";
                                }else if(ereg("^<small>.*時</small></td>", $buffer)){
                                        $b1 = str_replace('<small>', "", $buffer);
                                        $b2 = str_replace('</small></td>', "", $b1);
                                        //print("■時間 ".trim($b2));
                                        //echo "\n";
                                        $timezone_array[] = trim($b2);
                                }
                                if(ereg('<small>天気</small>', $buffer)){
                                        //時間帯の探索は終わり
                                        $find_mode = 4;
                                }

                        }else if($find_mode == 4){
                                //<small><font color="#999999">曇り</font></small></td>
                                //<small>曇り</small></td>
                                if(ereg('<small><font color="#999999">.*</font></small></td>', $buffer)){
                                        //print("■過去".$buffer);
                                        //echo "\n";
                                }else if(ereg("^<small>.*</small></td>", $buffer)){
                                        $b1 = str_replace('<small>', "", $buffer);
                                        $b2 = str_replace('</small></td>', "", $b1);
                                        //print("■天気 ".trim($b2));
                                        //echo "\n";
                                        $tenki_array[] = trim($b2);

                                }
                                if(ereg('<small>気温(℃)</small>', $buffer)){
                                        //天気帯の探索は終わり
                                        $find_mode = 5;
                                }

                        }else if($find_mode == 5){
                                //<td><small><font color="#999999">98</font></small></td>
                                //<td><small>64</small></td>
                                if(ereg('<small><font color="#999999">.*</font></small></td>', $buffer)){
                                        //print("■過去".$buffer);
                                        //echo "\n";
                                }else if(ereg("^<td><small>.*</small></td>", $buffer)){
                                        $b1 = str_replace('<td><small>', "", $buffer);
                                        $b2 = str_replace('</small></td>', "", $b1);
                                        //print("■気温 ".trim($b2)."(℃)");
                                        //echo "\n";
                                        $kion_array[] = trim($b2);
                                }
                                if(ereg('<small>湿度(%)</small>', $buffer)){
                                        //天気帯の探索は終わり
                                        $find_mode = 6;
                                }

                        }else if($find_mode == 6){
                                if(ereg('<small><font color="#999999">.*</font></small></td>', $buffer)){
                                        //print("■過去".$buffer);
                                        //echo "\n";
                                }else if(ereg("^<td><small>.*</small></td>", $buffer)){
                                        $b1 = str_replace('<td><small>', "", $buffer);
                                        $b2 = str_replace('</small></td>', "", $b1);
                                        //print("■湿度 ".trim($b2)."(%)");
                                        //echo "\n";
                                        $situdo_array[] = trim($b2);
                                }
                                if(ereg('<small>降水量(mm/h)</small>', $buffer)){
                                        //天気帯の探索は終わり
                                        $find_mode = 7;
                                }

                        }

        }
                $result_array = array($timezone_array, $tenki_array,$kion_array,$situdo_array);
        //print_r($result_array);

                print($today_string."の天気をお伝えします。");
                //echo "\n";
                for($i=0;$i<count($result_array[0]);$i++){
                        print($result_array[0][$i]."は".$result_array[1][$i]."。 ".$result_array[2][$i]."度 ".$result_array[3][$i]."%です。");
                        //echo "\n";
                }

        flock($fp, LOCK_UN);
    }else{
        print('ファイルロックに失敗しました');
                echo "";
    }
}

$flag = fclose($fp);

if ($flag){
    print('おしまい。');
        echo "\n";
}else{
    print('クローズに失敗しました');
        echo "\n";
}

?>

実行はこんな感じで
./tenki.sh | ./AquesTalkPi  -v f1 -f - | aplay

すると天気予報をしてくれる!

ラズベリーパイが喋るよ

これがメインではなく、準備として
適当な文字列をラズベリーパイに喋ってもらうというもの。

AquesTalk Pi ↓を使わせてもらいました。
http://www.a-quest.com/products/aquestalkpi.html

インストール方法は上記が詳しいので省略。
動かし方としては、以下のような感じ。

echo "ラズベリーパイがしゃべるよ!" | aquestalkpi/AquesTalkPi  -v f1 -f - | aplay

こんな感じ。