2023年6月9日金曜日

[備忘録]r2rの購読処理コールバックで重い処理を書くと"error TrySendError { kind: Full }"が出る話

2023年6月6日火曜日

[備忘録]r2rをコンテナ環境下のROS2環境にてvscodeでデバック実行する

2023年6月3日土曜日

[備忘録]RustのVecの要素を変更する

2023年2月21日火曜日

[備忘録]macのTimeMachineでError 16でバックアップしなくなったときの対処(wdcloud)

みなさんこんにちは
MacのTimeMachine、便利ですよね
便利でおしゃなんですけど、よくコケるヽ(・ω・)/ズコー

今回はError 16がでて死んでました
んで、多分?原因がわかった?ので備忘録。

macOS 12.6.3
WDCoud Version 5.25.132
です。

  1. WDCloudにSSHでログイン
  2. cd /mnt/HD/HD_a2/TimeMachineBackup
  3. cd じぶんのmacのなまえ.sparsebundle
  4. rm lock

自分はこれで治りました。


頼む...もっと安定稼働してくれ...😫😫😫😫😫😫😫😫 

2022年12月27日火曜日

OrangePi5のOSをSSDにインストールする

3日連続連投!新記録!(笑)
それぐらいOrangePi5は魅力的ということで!^^;

さくっと本題。
まず、大前提としてnvmeのSSDであること!(SATAは保証しません、もしかしたらできるかも)
私はSK hynixの128GBの2230のpcie3x4を買いました。
あと、ブートローダーはSDに入るため、SSDにインストールしてもSDカードは必要である!!
  1. まず、普通にSDカードでブートして起動
  2. nvmeのSSDをフォーマットしてパーティションを認識させておく(ext4推奨)
  3. ターミナルを開き、
    sudo orangepi-config
  4. System→Install→Boot from SD - system on SATA, USB or NVMe→nvmeのデバイスを選択
  5. SDのイメージをSSDにコピーし始めるので終わるまで瞑想する
  6. 終わったら、再起動する
  7. 再起動すると、起動に失敗するので、rootのパスワードを入力(デフォはorangepi)し、/media/mmcbootをマウントし、exitするとデスクトップ環境が復活する
    mount /dev/disk/by-uuid/opi_bootのUUID /media/mmcboot
    exit
  8. デスクトップ環境でターミナルを開いて、/etc/fstabをスーパーユーザーで編集する
    1. /media/mmcbootの行のtypeをext4からvfatに変更
    2. /media/mmcbootの行のoptionsにあるcommit=600を削除する
    3. こんな感じ
  9. 保存する
  10. 再起動して、ちゃんと起動に成功したら終了
結構沼が深かった...
SD→SSDへのマイグレーションはすごい簡単にできるから、
お?いけんじゃん(^q^)
と思ったらMountに失敗する仕様とね\(^o^)/
まぁこんな感じでSSD化できればこっちのモンとね

公式サイトとかに手順が一切ないのは玄人志向だなと思いました^^;
SDとSSDでは速度も耐久性もレベチなので、SSD化できれはホビーの枠すら超えれると思います。
可能性無限大OrangePI5...

今度はNPUも使っていきたいし、
あとは、ORB-SLAMとかをステレオカメラ(ホントは3Dカメラがいいけど高価)でやれたらいいなぁ
そいえば、地味に手こずったMozcのインストール手順も記事のネタになりそうだ(・∀・)ニヤニヤ

今日はこんなところで、
ではでは。

2022年12月26日月曜日

OrangePi5の公式xfceイメージにビデオドライバーをあてる

今日はブラック★ロックシューターの誕生日らしいですよ
実はPSP版のゲームも、2012年版のアニメも、2022年版のアニメも、
昔、ニコニコ動画のアプリにあったぷちっと・ろっくしゅーたーというゲームも
ソシャゲもやってるのです
一応ファンなのかな?

さて、珍しく連投です
表題のやつ、さくっと行きます
ここを参考にしました
↑実はOrangePiのフォーラムではなく、同じくRK3588を積んだSBCのフォーラムをパクったらいけました

確認方法
glxinfo -B
↑こいつのDriverがllvmpipeのときはソフトウェアレンダリングです。
おさかなさんを見るとガクガクです...
  1. sudo apt update
  2. mali_csffw.binをダウンロードし、/lib/firmware に移動させておく
  3. sudo add-apt-repository ppa:liujianfeng1994/panfork-mesa
  4. sudo apt update ; sudo apt upgrade
以上!簡単だね!
glxinfo -B
↑こいつのDriverがMaliになってたらOK

おさかなさんを見るとヌルヌルになってるず!!
これでGPUもちゃんと使えたら怖いものなしですね!
OrangePi5つおスギィ...
まだ、RvizとかGazeboでの使い勝手を試してないのではやくやってみな
ちなみに、Rocker経由でGazeboしたのですが、Rocker上ではアクセラレータ効かなかったです...
↑やり方悪い説あり

ネイティブ汚したくないんだけどなぁ...(´Д`)ハァ…
ではでは。

2022年12月25日日曜日

OrangePi5にKVMでWindows11 (aarch64版)を入れて、GeekBench5でベンチマークしてみる

メリー㍆㌋㌉㌏㌉㌸㌾㌋㌞㌹㌅みなさま。
せいなる夜にひとり寂しく久々にブログ更新します_(:3」∠)_

さて、今月半ばにコスパの良いおもちゃを入手しました。 そう、OrangePi5です。
アリエクで8GBRAM版を1.2万円(送料込み)で買いました。
実はこいつ、半年ぐらい前から気になっていたガジェットで、
どうやらRK3588というSoCがクッソ優秀とか。
こいつを積んだSBCは実は他にもいくつか出てたのですが、
最低2万からでなかなか手を出す気になれず...

いやーまじでこれが1万ちょいはうれしい!!
表題の件をお話する前に私の環境でのうちの子のGeekBench5の結果をお伝えします。
スマホのカメラ越しでごめんなさいm(_ _)m 2504点です!!
これがどれぐらいのスコアかと言うと...
なんとスナドラ855相当なのですね!
つまり、Win11も動くぐらいの素性をもっているのです...オソロシヤ((((;゚Д゚))))ガクブル
(twitterで888相当の性能を期待っていってましたけど、実際測ってみたらこんなもんでしたわ)
というわけで本題。いってみよう!
  1. SDカードにデスクトップ版のUbuntu22.04イメージを焼く
  2. 公式が配布してるやつです(GUIがxfceのやつ)
  3. 上のやつをさして、起動
  4. ターミナルを開いて、
    docker pull yukimakura/windows_qemu_kvm_aarch64
    をする
  5.   sudo apt update
      sudo apt install python3-pip qemu-utils 
      pip3 install rocker off-your-rocker
    をする
  6. Win11のaarch64版を拾ってくる
  7. vhdxをqcow2に変換する
    qemu-img convert -O qcow2 win11.vhdx win11.qcow2
  8. 任意のフォルダを作って、そこに上で作成したqcow2をいれる
  9. UTMのサイトからゲストマシンのドライバーハッピーセットを拾って任意のフォルダにいれとく
  10. ~/.local/bin/rocker --x11 --oyr-run-arg "-v $(pwd)/任意のディレクトリ:/qcow --privileged -e OPTIONALARGS='-drive file=/qcow/spice-guest-tools-0.164.4.iso,media=cdrom,if=none,id=drivers -device usb-storage,drive=drivers' -e WINQCOWPATH=/qcow/win11.qcow2 " yukimakura/windows_qemu_kvm_aarch64
    ※今回は環境変数を通さずにrockerつかってますが、ちゃんとやりたい場合は好きに通してください
  11. これでWin11が起動するはずなので、あとはセットアップを進める
  12. このサイトを参考にオフラインセットアップする
  13. セットアップが終わったら、Administrator権限でターミナルを開いて、そこ経由でデバイスマネージャーをひらく(mmc devmgmt.msc)
  14. デバイスマネージャーからEthernetのドライバだけを当てる
    ※ディスクにあるExeで当てるとWin11が死ぬので注意
  15. GeekBenchのサイトからGeekBenchを拾ってベンチマーク!!
当方の環境ではこんな感じでした
VM環境でもこれだけ出るのすごすぎ...第五世代のラップトップi5と張り合える😲

ちなみに、yukimakura/windows_qemu_kvm_aarch64の構成は以下のようになっております
ENV周りは渡している引数でお察し下さい(いつもの)

いかがでしたか?
↑このワードつくサイトがあんまり参考にならないらしい(ついったーで見た)
まぁ参考にしないでください。備忘録なので(投げやり
↑備忘録というワードがあるサイトが参考になるらしい(ついったーで見た)

そもそもニッチすぎではありますが、
ラズパイがクッソ高騰してる今現在、OrangePi5はめっっちゃくちゃ魅力的です!!!!
すごいたのちい💖
NPUもついてるので推論とかやってみたいし、M.2PCIe端子もあるからSSDブートもしたい
あと、デフォだとGPUにドライバあたってなくってllvmpipe仕様だからGPU支援も有効化したい

...実はGPUのドライバもなんとか当てれたし、SSDブートもできてるですけどね
気が向いたら後日記事にします。

あと初ArmWin11だったのですが、amd64エミュレーションも試してみました
ギャルゲーぐらいなら全然余裕で動いちゃいましたわ...
すげぇ

では、よいクリスマスを。

2021年1月4日月曜日

JetsonNanoでPWM生成(C++にて)

あけましておめでとうございます🎉 
昨年はとんでもない年でしたね...(今年も落ち着いていないが...
 皆さんもしっかり免疫つけてウィルスに負けない体づくりをしていきましょうね!

 さて、今年お初(ほとんど更新してない)はJetsonNanoでPWM生成です。
 肝な部分としてはC++でやっている点でしょうか? 
Pythonは多いですけど、C++の記事は埋もれてるのかわかりませんが、 
日本語のブログがなかったので書いていこうかと思います。  

  1. まず、Jetsonのハードウェアな設定部分を変えないと行けないので変更します。
     「jetson pinmux pwm io tools」とかでググってください。(投げやり
    そのツール内で32、33ピンの設定を変えておいてください。(PWMにね

  2. いよいよコードの部分を触ります。
    JetsonGPIOをpull&make&installしてください。
    (README.MDに書いてあるヨ

  3. samples/simple_pwm.cppを編集して任意のPWMを生成してみます。
  4. 69行目にある
    
      GPIO::PWM p(output_pin, 50);
      
    第一引数は出力ピン(JetsonNanoは32,33番ピンのみ対応)、
    第二引数は周期(Hz)です。

    次に、70行目の
    
      p.start(50);
      
    引数に出力するduty比を0~100で入力。
    もとのソースだとdoubleになってるから0~1.0かとおもたけど違うみたい?(オシロで確認)

  5. これでコンパイル
    g++ simple_pwm.cpp -o simple_pwm -lJetsonGPIO


  6. 実行して出力されたかを確認してね★(オシロスコープやらテスターやらLEDやら
READMEによると権限周りもさわらないといけないってあったけど、 私は触らなくても行けました??(念の為やっておいたほうがいいと思います。)
まぁ、記事が少ないってことはニッチってことですかね?
私がこれをやろうと思い立った経緯としまして、
ROSのHardwareInterfaceを作ろうとして、
Pythonで媒介するノードを立てるのもなぁ...と思って
ダメ元で調べたらライブラリがあったので使ってみよー!となったわけです。
ニッチな皆様のお力に慣れたら幸いです。(笑)

PWMはマイコンで出せって?
それは言わないお約束♥
ちなみにロータリーエンコーダ付きのモーター使ってるのでstm32もついてますヽ(・ω・)/ズコー

ROS2やらなきゃ...(万年言ってる
ros2_controllerの正式版&gazeboが対応したらやるから(震え声

2020年5月11日月曜日

stm32(NUCLEO-F767ZI)でbeebotteを使ってMQTT通信する!

2020年お初の記事です。えぇ。
このブログはゆるくやるのがモットーなので(という言い訳

ということでまたまたstm32ネタでございます。
最近スマートホーム化を推進しておりまして、
既製品を買うのもいいのですが、今回は自作してみようかなといろいろ調べていました。
基本的にはIFTTTと連携するのが楽ちんそうだったのでラズパイでやろうと思ったのですが...

ラズパイ...壊れてる...OTZ

そんなわけで代替を考えていた所、そーえばstm32にはEthernet端子がついていたなと。
しかも調べてるうちにIPv6プラスでネット接続してる場合はポート開放が出来るルータが限られていて、
うちのTP-LINK A10ちゃんはポート開放に対応してないということが判明orz

そこでMQTT!!!٩(๑´3`๑)۶

毎度長い長い前置きごめんなさいね( ・´ー・`)どや

    環境

  • Cube MX ver.5.6.1
  • Atollic TrueSTUDIO® for STM32, Built on Eclipse Neon.1a. Version: 9.3.0 
  • NUCLEO-F767ZI

私のgithubのレポジトリをご参考ください。

大雑把に流れをお伝えすると
  • まずCubeMXのMiddlewareの欄にあるLWIPとFREERTOSを有効化
  • SystemCore欄にあるSYSのDebugをSerial Wireにし、Timebase SourceをTIM1あたりにしておく(ここは適当に
  • んで、GENERATE CODE!
  • 次に生成されたソースをIDEで開く
  • LWIPのdoxygenサイトに書いてある様にmain.cに追加していく
  • example_do_connect内のmqtt_client_connect()関数にbeebotteのIPアドレスを与える
  • example_do_connect内のci.client_id付近に ci.client_user = {beebotteのトークン名} を追加する
  • それぞれpublish,subscribe関数にトピック名を設定する{(beebotteの例)"test/res"}
  • (DHCPを設定している人向け)lwip.cに移動し、dhcp_start(&gnetif);の下部にある/* USER CODE BEGIN 3 */内に以下のコードを追加する。
  int mscnt =0;
  while (gnetif.ip_addr.addr==0) {
		   sys_msleep(DHCP_FINE_TIMER_MSECS);
		   dhcp_fine_tmr();
		   mscnt += DHCP_FINE_TIMER_MSECS;
		   if (mscnt >= DHCP_COARSE_TIMER_SECS*1000) {
				  dhcp_coarse_tmr();
				  mscnt = 0;
		   }
	}
  1. 有線LANケーブルをNucleoにぶっ刺して、Nucleoプログラムを書き込む
こんな感じです。
9、10番目でやってることはDHCPからIPアドレスやルート情報を取得するまで待機させています。(参考: AVR lwIP Example: How to enable a DHCP client on EVK1100)
これやらないと接続を確立できません(言われてみれば当たり前ですが、その仕様に気づかず頭を抱えました(笑)
あと私のgithubのレポジトリにあるようにdnsを用いてみるのも楽でいいと思います。


beebotteとIFTTTとGoogle Assistantを連携させればこの様にアクションを起こすことが出来ます。
 活用の幅が広がりますねぇ...フムフム
 ぜひ皆さんもお試しくださいませ。
実はDHCP問題がわからなかった頃に一度Micropythonに逃げてみたのですが、
 Micropythonで同じことをすると1分ぐらいでエラー吐いて落ちまくったり、
書き込みにくかったりと 沼沼で、諦めてC言語にしていろいろ悩み直して解決した次第でした。
 それでも定期的に応答しなくなるようなので、10分に1回ぐらいブローカーに再接続する処理を入れるといいのかと思います。  
気が向いたらMicropythonの方もブログネタにしようかと思います。 
ラズパイではなくマイコンボードでこのようなことをする最大のメリットは低消費電力である点かなと思います。 
 
そしてこの手の開発はESP32が情報量が多いし、安くていいと思います(超高速手のひら返し

2019年10月29日火曜日

playstation4 cameraをvisual studioを使わずにwindows10で使う(Python使用)

PS4カメラでSLAMとかを動かしたいと思ってメルカリで1000円でポチったので今回はそれをなるべく楽ちんにwindows10で使ってみた(備忘録)的な記事でございます。


まず、そもそもパソコンに物理的にコネクション出来るようにしなければいけません。
Aliとかebayで変換コネクタを買えるのですが、中古で1000円程度で買えるカメラなので壊しても許されるかと思って私はケーブルの端子をUSB3.0に付け替えました。

PS4カメラでは新版(CUH-ZEY2)と旧版(CUH-ZEY1)があるのですが、間違いなく動かしたい方は旧版をおすすめします。ただ、新版でも動くかもしれないです。

あと、USB3.0必須です。
USBコントローラによっては動作できないものもあるようです。(古い物では動かないものがあるらしい)

では、実際の作業をダラダラ書いていきます。
というか、コネクタの付け替えとドライバ周りについては
こちらのサイトを参考にさせていただきました。

コネクタの付け替えは他のケーブルとくっつけてる方も多かったですが、
初め、その方法でやった時コネクションロストがたまに起きたので、
コネクタで根本から配線することをおすすめしたいです。
(どちらにしろ絶縁処理はしっかりとね)

そんな感じで秋月電子で買ってきたコネクタをこんな感じでハンダ付けして…



次はドライバ周りですけど、Zdiagを開いて、
Driverをlibusb-winにして、インストールしてください。



次が参考にさせていただいた記事と違います。
まず、windowsにpythonをインストールしてください。(Windows storeのpython3でも可)
そのあとPowerShellを開いて、

pip install --pre pyusb

と入力してください。


その後、こちらをダウンロードして、解凍してください。

解凍したフォルダーのscriptディレクトリにPowerShellで移動して、

python ps4eye_init.py

を実行してください。


そうすると、PS4カメラにファームウェアがインストールされて
UVCカメラとして認識されるはずです。


お疲れ様でした!!



お気づきかと思われますが、この手法はmacでもlinux系でもpythonとpyusbがインストールできれば使えるはずです。

1000円ちょっとでハイスペックステレオカメラで遊べれるのはとっても魅力的!!(´艸`)
みなさんも挑戦されてはいかがですか?




2019年10月6日日曜日

stm32(NUCLEO-F767ZI)でUDP通信する!

stm32シリーズ第二弾ということで今回はUDP通信です。

nucleoボードの中にはEthernet端子がついていているものもあり、
お値段もピンきりではありますが、NUCLEO-F767ZIは3000円を切って購入できます。
そのくせメモリ豊富で動作周波数もなかなか高いのでとても夢広がる(?)マイコンボードです。

...ということでRTOSとLWIPもりもりで今回はお送りします!(笑)

まず毎度恒例動作環境です。

  • Windows 10 (ver 1903 build 18362.356)
  • STM32CubeMX (ver 5.3.0)
  • Atollic TrueSTUDIO® for STM32, Built on Eclipse Neon.1a.(ver 9.3.0 build id 20190212-0734)
  • 使用ボード: NUCLEO-F767ZI

まずはcubeMXでクロック周りやRTOSやLWIPなどを設定してください。
STM32でEthernetするっ!様のサイトがとっても参考になりました!
この場を借りて感謝申し上げますm(_ _)m

お次はソースコードです。
私の拙いコード(githubに繋がります)を用いてください。

このソースの肝はudp_easy_io.hとudp_easy_io.cです。
こいつらはLWIPの処理を丸めた関数群です。基本的には

  • 1.UDP_EASY_IO_init()関数でポート設定とアドレス設定をする。(初期化)
  • 2.自分のさせたい処理用(main関数に書きたい処理)に新しくRTOSでタスクを始動させる
  • 3.そのタスクの中でUDP_EASY_IO_write()関数を使って送信するなり、UDP_EASY_IO_read_char_prt()関数を使って受信するなりごにょごにょする。
といった感じで使います。
詳しくは私の拙いコードのなかにあるmain.cをご参照くださいませ。

あとはビルドして書き込んでPCとLANケーブル直挿ししてマイコン側の準備は完了!(ざっくり

今度はIPアドレス設定です。
cubeMXでDHCPに設定してarpコマンドからIPアドレス特定するとかでもいいのですが、
めんどくさい(おい)ので、今回の例では固定IPにしています。

まず、タスクバーのネットワークアイコンを右クリックして、出てきたメニューのなかにある「ネットワークとインターネットの設定を開く」をクリック

つぎに、「アダプターのオプションを変更する」をクリック
つぎに、マイコンと接続しているアダプタ以外(ここ大事)を右クリックで一覧にあるプロパティを選択

あとはネット共有をマイコンと接続してるアダプタに指定してあげるとな。

これでwindows側の設定は完了です。
コマンドプロンプトを開いてcubemxで設定したIPアドレスに向けてpingを送ってみて応答確認してください。
応答が...あるッ!!
こんどはUDPのパケットを送るツールの準備です。
Pythonとかでスクリプト書くなり好きにしてください(なげやり
私はUDP/IPテストツールを使わせていただきました。
こちらもこの場を借りて感謝申し上げますm(_ _)m

んで、メッセージを受信したり送ったりしてみます。
なお、今回の私の拙いコードではUDP通信で受信した文字列をUART経由で出力される仕様になっています。ボーレートは115200です。

んまぁこんな感じでごにょごにょすると↓の動画のようになってくれるはず??

お疲れさまでした!!



イーサネット通信は通信コストはいくらか掛かりますが、無線LAN子機を用いたりすることで容易に無線化できたり、IoTできたりするわけです。個人的に美味しい要素は

  • データをやりとりする上でデータの区切りがはっきりしている
  • 差動線通信であったりアダプタがぬけにくいため、不安要素がいくらか拭える
といったところでしょうかね。
あと今回はLWIPもですが、RTOSもstm32ではお初のテーマでした。
いろいろ調べていくうちにCMSIS2ってFreeRTOSをラッピングしてるだけだと知り、
そのままFreeRTOSのAPIを叩いちゃいました(笑)
だって情報量がFreeRTOSのほうが多いもん...(切実

こんな感じで夢が広がるマイコンボード、皆さんどうでしょう?(〆が雑

2019年9月15日日曜日

STM32とGY-BNO055でi2c通信

一年ぶりの更新です(笑)
いくつか記事にできそうな物はあったのですがどうも億劫になってしまって...(;´∀`)

さて本題に入りましょう!
今日はお初のSTM32を用いたBNO055とのi2c通信です。(タイトル通り

ざっくり当方の環境は

  • Windows 10 (ver 1903 build 18362.356)
  • STM32CubeMX (ver 5.3.0)
  • Atollic TrueSTUDIO® for STM32, Built on Eclipse Neon.1a.(ver 9.3.0 build id 20190212-0734)

といった感じです。
使用マイコンはSTM32F303K8でございます。
使用センサモジュールはAliexpressで購入したGY-BNO055でございます。

今回の最重要ポイントは実はGY-BNO055にありまして...(おい
右側のセンサが購入時の状態、左側が加工を施した状態
このセンサモジュールには何も書いてないですが、意味ありげなパターンが2箇所ございまして、どうやら購入する物によっては最初から2つともショートさせてあったりなかったりするらしいです。
結論から言うと、
i2cでコネクションする人はどちらもショートさせてください!
そうしないとi2cのアドレスを探索させても何も表示されません。

詳細はこちらをみてください。
UARTを用いる場合はメインICに近い方のパターンをショートさせなければ良いようです。

センサモジュールの下ごしらえさえできてしまえばもう何も怖くありません(フラグじゃないヨ

あとはフツーにモジュールに電源とGNDとSCLとSDAをつないでやれば配線はおk

配線図(概念
ここでもう一つ注意するならばセンサモジュールにSDA/TxのとなりにADDっていうピンがあると思います。
それをGNDにショートしてやると、モジュールのアドレスが変わるようです。
当方の環境ではショートさせたら0x28、そうでないときは0x29となりました。

マイコンのプログラムは下記参照(同じマイコンならそのまま動くはず
https://github.com/yukimakura/stm32F303K8_bno055_quat_reader_i2c


こんなかんじでひたすらクォータニオンを吐き続けてくれるはず...




このセンサモジュールはMPU6050とかMPU9250よりは値段は少々張ります。
ですが、センサとしての性能と利便性がずば抜けているので私はこのセンサいっぱいしゅきです(笑)
実際に触ってみるとわかりますが、パラメータの調整なしでドリフトが起きない姿勢情報を吐いてくれます。
こりゃ感動もんですなぁ...

あとはじめてmbed環境じゃないstm32の使い方をしましたが、以外となんとかなりました(笑)
TrueStudio使えば環境構築もあっという間に出来て好印象でしたね~
stm32いろんなバリエーションがあって、かつ高コスパなのでいいと思いますよ👍

2018年8月26日日曜日

mbedでMQTTのパブリッシュとサブスクライブ

今回はmbedをつかっていきまぁす。
mbedの記事は今回がお初かと。

今回は備忘録臭が強めです(笑)
ethernetケーブルは100均のケーブルを剥いで使うもよし、
RJ45買うもよし、(当方ではHR911105Aを使用)
そんなかんじで配線してください。(適当)

こちらのコードを大体パクった感じですが、一部RTOS仕様にして、
パブリッシャーを関数にくるめただけです。




いままで、マイコンとはUSB経由のシリアル通信でパソコンと
通信していたのですが、ポートが変わったり、
Ubuntuだとパーミッションなども気にしないといけなく、
結構うんざりしてたため、MQTTを用いた通信に踏み切ったわけです。
お察しだとは思いますが、MQTT-bridgeのROSパッケージのstd_msgs::Int32MultiArrayに
準拠したjsonの記述でパブリッシュのメッセージを記述しています(笑)
イーサネット特有の面倒くささなども出てきますが、
USBシリアル通信の癖の強さよりはマシかと。
んまぁ、おいおい使ってみてですかねぇ

2018年3月28日水曜日

FlutterでAndroidとiOSそれぞれに実機で実行させてみた

最近β版が出たばっかりのFlutter。
まだまだBluetoothなどのサポートがされていないことから
Flutterのみですべてのニーズに答えることはまだ難しそうですが、
実際ロードマップに対応予定となっておりますし、
面白そうな試みではあったわけで実際試してみました!

Flutter自体はマルチプラットフォームで開発できるわけですが、
iOSアプリケーションはXcodeを経由する都合上、
macOSが必要となるため、hackintosh Macが必要となります。

    環境

  • MacBook Air (11-inch, Mid 2011)
    • 1.6 GHz Intel Core i5
    • 4 GB 1333 MHz DDR3
    • Intel HD Graphics 3000 384 MB
    • macOS Sierra 10.12.6
    • Xcode 9.2
    • Android Studio 3.0.1
    • Visual Studio Code 1.21.1
  • Galaxy S8 (SM-F950FD)
    • 2.3 GHz Exynos Octa 8895
    • 4 GB RAM (詳細不明)
    • Mail-G71
    • Android 7.0
  • iPhone 6 plus(A1524)
    • 1.4 GHz Apple A8 Processor
    • 1GB(LPDDR3)
    • iOS 11.2.6 (15D100)
  • ※iPhoneにおいてはWikipediaを参照

XcodeAndroid Studioをいれておいてください。
(これは他のわかりやすいサイトをググってくださいm(_ _)m)

brew も入ってない人は入れてください。

Flutter自体の導入は公式を参考にしてください。

今回はVSCodeを使って環境構築してみました。

まず、例の如くDart CodeFlutter Snippets for vscodeを導入していきましょう。
それぞれ導入して再読み込みしたら、つぎにCommandキーと,を同時押ししてVSCodeの設定画面を
開きます。

画像の右側のエディタに注目してください。
私の場合はFlutterをhomeディレクトリの下にインストールしたのでこのように記述しています。

VSCodeの設定はこれで以上です。

あとはflutter doctorなりの依存関係などを解決すれば準備完了のはずです。

ではVSCodeのコマンドパレットをひらいて、New Projectしてみましょう!!


ここでプロジェクト名を指定しますが
Androidアプリのみ作成予定の方はいいですが、
iOSアプリを作成する方はできるだけオリジナリティのある方がいいです

...まぁいくらでも修正できますが(笑)


そしたらこんな感じで生成されます。

ここでAndroid端末をつないでみましょう!

そしたら右下に端末の名前が表示させると思われます。

Controlとshiftと@を同時押しするとVSCode内蔵のterminalが開くので
flutter run
と入力してください。
そしたら後は待つだけ!!


では、
つぎは問題のiOS編です。

まずXcode開きましょう!!


そこからメニューバーのfileタブからOpenをクリックすると
Xcodeのプロジェクトフォルダの選択を求められるので、
先程、Flutterにて自動生成されたiosという名前のフォルダーを選択します。


ここで急に思い出したので書き出しますが、
Xcode初めての方はAppleアカウントをXcodeに紐付ける必要があります。

Xcodeの環境設定(Preferences...)をクリック


Accountsタブをひらいてログインしてごにょごにょ…

ではここでFlutterの設定の方に戻りましょう!!



ここで先程設定したアカウントを設定しましょう。

あとBundle identifierですが、これは多分世界中でかぶらせては行けない感じなので、
完全にオリジナルのものを設定しないと書き込み時にエラーがでるので
気をつけてください!!


これでXcodeの設定はオッケーです。

あとはVSCodeのほうのterminalで
flutter run
をするとiOS端末に書き込まれます。

※iOS端末のほうは設定画面からデベロッパー認証しないと起動しないので注意してくださいね(^_^;)


こんな感じでどうでしょう??

hackintosh Macユーザーの方々、どうです?
一度お試しあれ〜(*^_^*)


いや〜やっぱり長くなってしまいましたねぇ
でも一つのソースでiOS端末とAndroid端末を同時に開発できるのは
非常に魅力的です。
ただ、Dartに関する情報が少ないのが玉に瑕ってところです。
GoogleはAndroidの次期OSにもFlutterを採用するとも言っている
ようなので、触っておいても無駄にはならないと思います。

あと、DartはJavaScriptの代わりとしても使えるので
実は結構優秀だったりして…?

|д゚)チラッ<ROSDartはよ

2018年2月12日月曜日

PSoC CreatorのUSBMIDIのデモについての考察

今日は建国記念の日が日曜日に入ったためか
振替休日ということで月曜日なのにおやすみというわけですが、
なんといいますか...
振替休日ってなんか都合がいいですね(何が言いたい)

というわけで、今回も短めにさっくり行きたいと思います。

PSoC5LPではUSBホスト機能が内蔵されていて、
その中でも少数ですがAPI(詳細はデータシートをご覧ください)
が存在するものがあります。

USBMIDIはその中の一つに当たるわけです。

ここで当方のPSoC周りの環境を記載しておきますと、
  • PSoC Creator 4.1 Update 1 (4.1.0.3210)
  • PSoC 5LP Development kit
    (CY8C5868AXI-LP035)
という環境です。

ではまずPSoCCreatorを開いて、Fileタブをクリックして、
そこの3行目あたりにあるCode Example...を開いてください。


USBあたりでフィルターかけてあげると出てくると思われます。

このコンテンツはどうやらダウンロードしないといけないらしいので
初回に開くときのみ左側に地球マークがあると思われるので
そこをクリックしてダウンロードしてください。


当方の環境の場合はその後にProjectタブのなかの
Device Selector...でPSoCを変更しています。

PSoCを変更したあとはピンアサインの確認を忘れずに(;´∀`)

今回は回路エディターの方はいじらないです。

あくまでソースコードの考察ということで悪しからず...

/*******************************************************************************
* Copyright 2012-2015, Cypress Semiconductor Corporation. All rights reserved.
* This software is owned by Cypress Semiconductor Corporation and is protected
* by and subject to worldwide patent and copyright laws and treaties.
* Therefore, you may use this software only as provided in the license agreement
* accompanying the software package from which you obtained this software.
* CYPRESS AND ITS SUPPLIERS MAKE NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* WITH REGARD TO THIS SOFTWARE, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT,
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*******************************************************************************/

#include <project.h>

#define BUTT1                 (0x01u)
#define BUTT2                 (0x02u)

#define DEVICE                  (0u)
#define MIDI_MSG_SIZE           (4u)

/*MIDI Message Fields */
#define MIDI_MSG_TYPE           (0u)
#define MIDI_NOTE_NUMBER        (1u)
#define MIDI_NOTE_VELOCITY      (2u)

/* MIDI Notes*/
#define NOTE_72                 (72u)
#define NOTE_76                 (76u)

/* MIDI Notes Velocity*/
#define VOLUME_OFF              (0u)
#define VOLUME_ON               (100u)

#define USB_SUSPEND_TIMEOUT     (2u)

/* Identity Reply message */
const uint8 CYCODE MIDI_IDENTITY_REPLY[] = {
    0xF0u,      /* SysEx */
    0x7Eu,      /* Non-real time */
    0x7Fu,      /* ID of target device (7F - "All Call") */
    0x06u,      /* Sub-ID#1 - General Information */
    0x02u,      /* Sub-ID#2 - Identity Reply */
    0x7Du,      /* Manufacturer's ID: 7D - Educational Use */
    0xB4u, 0x04u,               /* Family code */
    0x32u, 0xD2u,               /* Model number */
    0x01u, 0x00u, 0x00u, 0x00u, /* Version number */
    /*0xF7         End of SysEx automatically appended */
};

/* Need for Identity Reply message */
extern volatile uint8 USB_MIDI1_InqFlags;
extern volatile uint8 USB_MIDI2_InqFlags;

volatile uint8 usbActivityCounter = 0u;

uint8 csButtStates = 0u;
uint8 csButtStatesOld = 0u;
uint8 csButtChange = 0u;
uint8 inqFlagsOld = 0u;


/*******************************************************************************
* Function Name: SleepIsr
********************************************************************************
* Summary:
*  The sleep interrupt-service-routine used to determine a sleep condition.
*  The device goes into the Suspend state when there is a constant Idle 
*  state on its upstream-facing bus-lines for more than 3.0 ms. 
*  The device must be suspended drawing only suspend current from the 
*  bus after no more than 10 ms of the bus inactivity on all its ports.
*  This ISR is run each 4 ms, so after a second turn without the USB activity,  
*  the device should be suspended.
*
*******************************************************************************/
CY_ISR(SleepIsr)
{
    /* Check USB activity */
    if(0u != USB_CheckActivity()) 
    {
        usbActivityCounter = 0u;
    } 
    else 
    {
        usbActivityCounter++;
    }
    /* Clear Pending Interrupt */
    SleepTimer_GetStatus();
}


/*******************************************************************************
* Function Name: main
********************************************************************************
* Summary:
*       1. Starts the USBFS device and waits for enumaration.
*
*******************************************************************************/
int main()
{
    uint8 midiMsg[MIDI_MSG_SIZE];    

    /* Enable Global Interrupts */
    CyGlobalIntEnable;

    /* Start USBFS device 0 with VDDD operation */
    USB_Start(DEVICE, USB_DWR_VDDD_OPERATION); 

    while(1u)
    {
      
        /* Host can send double SET_INTERFACE request */
        if(0u != USB_IsConfigurationChanged())
        {
            /* Initialize IN endpoints when device configured */
            if(0u != USB_GetConfiguration())   
            {
                /* Power ON CY8CKIT-044 board */
                MIDI_PWR_Write(0u); 
                
                /* Start ISR to determine sleep condition */  
                Sleep_isr_StartEx(SleepIsr);
                
                /* Start SleepTimer's operation */
                SleepTimer_Start();
                
             /* Enable output endpoint */
                USB_MIDI_Init();
            }
            else
            {
                SleepTimer_Stop();
            }    
        }        
        
        /* Service USB MIDI when device is configured */
        if(0u != USB_GetConfiguration())    
        {
            /* Call this API from UART RX ISR for Auto DMA mode */
            #if(!USB_EP_MANAGEMENT_DMA_AUTO) 
                USB_MIDI_IN_Service();
            #endif
            /* In Manual EP Memory Management mode OUT_EP_Service() 
            *  may have to be called from main foreground or from OUT EP ISR
            */
            #if(!USB_EP_MANAGEMENT_DMA_AUTO) 
                USB_MIDI_OUT_Service();
            #endif

            /* Sending Identity Reply Universal System Exclusive message 
             * back to computer */
            if(0u != (USB_MIDI1_InqFlags & USB_INQ_IDENTITY_REQ_FLAG))
            {
                USB_PutUsbMidiIn(sizeof(MIDI_IDENTITY_REPLY), \
                            (uint8 *)MIDI_IDENTITY_REPLY, USB_MIDI_CABLE_00);
                USB_MIDI1_InqFlags &= ~USB_INQ_IDENTITY_REQ_FLAG;
            }
            #if (USB_MIDI_EXT_MODE >= USB_TWO_EXT_INTRF)
                if(0u != (USB_MIDI2_InqFlags & USB_INQ_IDENTITY_REQ_FLAG))
                {
                    USB_PutUsbMidiIn(sizeof(MIDI_IDENTITY_REPLY), \
                            (uint8 *)MIDI_IDENTITY_REPLY, USB_MIDI_CABLE_01);
                    USB_MIDI2_InqFlags &= ~USB_INQ_IDENTITY_REQ_FLAG;
                }
            #endif /* End USB_MIDI_EXT_MODE >= USB_TWO_EXT_INTRF */
            
            
            
            //ここから
            /* Service Keys */
      if (0u == SW1_Read()) 
            {
                csButtStates |= BUTT1;
            }
            else
            {
                csButtStates &= ~BUTT1;
            }
      if (0u == SW2_Read()) 
            {
                csButtStates |= BUTT2;
            }
            else
            {
                csButtStates &= ~BUTT2;
            }
            /* Process any button change
            ボタンのステータスが変更されたとき*/
      if (0u != (csButtChange = csButtStates ^ csButtStatesOld)) 
            {
       csButtStatesOld = csButtStates;

       /* All buttons are mapped to Note-On/Off messages */
       midiMsg[MIDI_MSG_TYPE] = USB_MIDI_NOTE_ON;
       
       /* Button 1 */
                
                /*
                midiMsg[MIDI_NOTE_NUMBER] = NOTE;
                midiのノートナンバー。
                60がc3(ド)
                69が440Hz(時報の音)

                midiMsg[MIDI_NOTE_VELOCITY]
                midiのvelocity、つまり音の強弱(鍵盤を押す強弱なイメージ)
                
                midiMsg[MIDI_MSG_TYPE]
                midiのデータ・タイプを格納する
                */
       if (0u != (csButtChange & BUTT1)) 
                {
        /* Button determines note number */   
        midiMsg[MIDI_NOTE_NUMBER] = 60u;
        if (0u != (csButtStates & BUTT1))
                    {
                        /* Note On */
                        midiMsg[MIDI_NOTE_VELOCITY] = VOLUME_ON;  
                    }
        else
                    {
                        /* Note Off */
                        midiMsg[MIDI_NOTE_VELOCITY] = VOLUME_OFF;   
                    }    
           /* Put MIDI Note-On/Off message into input endpoint */
                    USB_PutUsbMidiIn(USB_3BYTE_COMMON, midiMsg, USB_MIDI_CABLE_00);
       }

       /* Button 2 */
       if (0u != (csButtChange & BUTT2))
                {
        /* Button determines note number */   
        midiMsg[MIDI_NOTE_NUMBER] = 72;//c4
        if (0u != (csButtStates & BUTT2))
                    {
                        /* Note On */
                        midiMsg[MIDI_NOTE_VELOCITY] = VOLUME_ON;  
                        //midimsgはuint8
                    }
        else
                    {
                        /* Note Off */
                        midiMsg[MIDI_NOTE_VELOCITY] = VOLUME_OFF; 
                    }    
           /* Put MIDI Note-On/Off message into input endpoint 
                    多分、送信処理*/
        USB_PutUsbMidiIn(USB_3BYTE_COMMON, midiMsg, USB_MIDI_CABLE_00);
                    /* Second Note message */
                    midiMsg[MIDI_MSG_TYPE] = USB_MIDI_NOTE_ON;
                 midiMsg[MIDI_NOTE_NUMBER] = NOTE_72;
                    if (0u != (csButtStates & BUTT2))
                    {
                        /* Note On */
                        midiMsg[MIDI_NOTE_VELOCITY] = VOLUME_ON;      
                    }
        else
                    {
                        /* Note Off */
                        midiMsg[MIDI_NOTE_VELOCITY] = VOLUME_OFF;   
                    }    
           /* Put MIDI Note-On/Off message into input endpoint */
                    USB_PutUsbMidiIn(USB_3BYTE_COMMON, midiMsg, USB_MIDI_CABLE_00);
       }
                #if(USB_EP_MANAGEMENT_DMA_AUTO) 
                   #if (USB_MIDI_EXT_MODE >= USB_ONE_EXT_INTRF)
                        MIDI1_UART_DisableRxInt();
                        #if (USB_MIDI_EXT_MODE >= USB_TWO_EXT_INTRF)
                            MIDI2_UART_DisableRxInt();
                        #endif /* End USB_MIDI_EXT_MODE >= USB_TWO_EXT_INTRF */
                    #endif /* End USB_MIDI_EXT_MODE >= USB_ONE_EXT_INTRF */            
                    USB_MIDI_IN_Service();
                    #if (USB_MIDI_EXT_MODE >= USB_ONE_EXT_INTRF)
                        MIDI1_UART_EnableRxInt();
                        #if (USB_MIDI_EXT_MODE >= USB_TWO_EXT_INTRF)
                            MIDI2_UART_EnableRxInt();
                        #endif /* End USB_MIDI_EXT_MODE >= USB_TWO_EXT_INTRF */
                    #endif /* End USB_MIDI_EXT_MODE >= USB_ONE_EXT_INTRF */                
                #endif
      }
            
            //ここまでがあやしい
            
        
            /* Check if host requested USB Suspend */
            if( usbActivityCounter >= USB_SUSPEND_TIMEOUT ) 
            {
                MIDI1_UART_Sleep();
                MIDI2_UART_Sleep();
                
                /* Power OFF CY8CKIT-044 board */
                MIDI_PWR_Write(1u);     
                
                /***************************************************************
                * Disable USBFS block and set DP Interrupt for wake-up 
                * from sleep mode. 
                ***************************************************************/
                USB_Suspend(); 
                /* Prepares system clocks for sleep mode */
                CyPmSaveClocks();
                /***************************************************************
                * Switch to the Sleep Mode for the PSoC 3 or PSoC 5LP devices:
                *  - PM_SLEEP_TIME_NONE: wakeup time is defined by PICU source
                *  - PM_SLEEP_SRC_PICU: PICU wakeup source 
                ***************************************************************/
                CyPmSleep(PM_SLEEP_TIME_NONE, PM_SLEEP_SRC_PICU);
                /* Restore clock configuration */
                CyPmRestoreClocks();
                /* Enable USBFS block after power-down mode */
                USB_Resume();
                
                /* Enable output endpoint */
                USB_MIDI_Init();
                
                /* Power ON CY8CKIT-044 board */
                MIDI_PWR_Write(0u);
                
                MIDI1_UART_Wakeup();
                MIDI2_UART_Wakeup();
                usbActivityCounter = 0u; /* Re-init USB Activity Counter*/
            }
        }
    }
}


/*******************************************************************************
* Function Name: USB_callbackLocalMidiEvent
********************************************************************************
* Summary: Local processing of the USB MIDI out-events.
*
*******************************************************************************/
void USB_callbackLocalMidiEvent(uint8 cable, uint8 *midiMsg) CYREENTRANT
{
    /* Support General System On/Off Message. */
    if((0u == (USB_MIDI1_InqFlags & USB_INQ_SYSEX_FLAG)) \
            && (0u != (inqFlagsOld & USB_INQ_SYSEX_FLAG)))
    {
        if(midiMsg[USB_EVENT_BYTE0] == USB_MIDI_SYSEX_GEN_MESSAGE)
        {
            if(midiMsg[USB_EVENT_BYTE1] == USB_MIDI_SYSEX_SYSTEM_ON)
            {
                MIDI_PWR_Write(0u); /* Power ON */
            }
            else if(midiMsg[USB_EVENT_BYTE1] == USB_MIDI_SYSEX_SYSTEM_OFF)
            {
                MIDI_PWR_Write(1u); /* Power OFF */
            }
        }
    }
    inqFlagsOld = USB_MIDI1_InqFlags;
    cable = cable;
}    


/*******************************************************************************
* Function Name: USB_MIDI1_ProcessUsbOut_EntryCallback
********************************************************************************
* Summary:  Turn the LED_OutA on at the beginning of the function
* USB_MIDI1_ProcessUsbOut() when data comes to be put in the UART1 out
* buffer.
* 
*******************************************************************************/
void USB_MIDI1_ProcessUsbOut_EntryCallback(void)
{
    LED_OutA_Write(1);
}


/*******************************************************************************
* Function Name: USB_MIDI1_ProcessUsbOut_ExitCallback
********************************************************************************
* Summary:  Turn the LED_OutA off at the end of the function  
* USB_MIDI1_ProcessUsbOut() when data is put in the UART1 out-buffer.
* 
*******************************************************************************/
void USB_MIDI1_ProcessUsbOut_ExitCallback(void)
{
    LED_OutA_Write(0);
}


/*******************************************************************************
* Function Name: USB_MIDI2_ProcessUsbOut_EntryCallback
********************************************************************************
* Summary:  Turn the LED_OutB on at the beginning of the function  
* USB_MIDI2_ProcessUsbOut() when data comes to be put in the UART2 out- 
* buffer  
* 
*******************************************************************************/
void USB_MIDI2_ProcessUsbOut_EntryCallback(void)
{
    LED_OutB_Write(1);
}


/*******************************************************************************
* Function Name: USB_MIDI2_ProcessUsbOut_ExitCallback
********************************************************************************
* Summary:  Turn the LED_OutB off at the end of the function  
* USB_MIDI2_ProcessUsbOut() when data is put in the UART2 out-buffer.
* 
*******************************************************************************/
void USB_MIDI2_ProcessUsbOut_ExitCallback(void)
{
    LED_OutB_Write(0);
}


/*******************************************************************************
* Function Name: MIDI1_UART_RXISR_EntryCallback
********************************************************************************
* Summary:  Turn the LED_InA on at the beginning of the MIDI1_UART_RXISR ISR  
* when data comes to UART1 to be put in the USBFS_MIDI IN endpoint
* buffer.
*
*******************************************************************************/
void MIDI1_UART_RXISR_EntryCallback(void)
{
    /* These LEDs indicate MIDI input activity */
    LED_InA_Write(1);
}


/*******************************************************************************
* Function Name: MIDI1_UART_RXISR_ExitCallback
********************************************************************************
* Summary:  Turn the LED_InA off at the end of the MIDI1_UART_RXISR ISR  
* when data is put in the USBFS_MIDI IN endpoint buffer.
*
*******************************************************************************/
void MIDI1_UART_RXISR_ExitCallback(void)
{
    #if (USB_EP_MANAGEMENT_DMA_AUTO) 
        USB_MIDI_IN_Service();
    #endif /* (USB_EP_MANAGEMENT_DMA_AUTO) */
    
    LED_InA_Write(0);
}


/*******************************************************************************
* Function Name: MIDI2_UART_RXISR_EntryCallback
********************************************************************************
* Summary:  Turn the LED_InB on at the beginning of the MIDI2_UART_RXISR ISR  
* when data comes to UART2 to be put in the USBFS_MIDI IN endpoint  
* buffer.
*
*******************************************************************************/
void MIDI2_UART_RXISR_EntryCallback(void)
{
    /* These LEDs indicate MIDI input activity */
    LED_InB_Write(1);
}


/*******************************************************************************
* Function Name: MIDI2_UART_RXISR_ExitCallback
********************************************************************************
* Summary:  Turn the LED_InB off at the end of the MIDI2_UART_RXISR ISR  
* when data is put in the USBFS_MIDI IN endpoint buffer
*
*******************************************************************************/
void MIDI2_UART_RXISR_ExitCallback(void)
{
    #if (USB_EP_MANAGEMENT_DMA_AUTO) 
        USB_MIDI_IN_Service();
    #endif /* (USB_EP_MANAGEMENT_DMA_AUTO) */
    
    LED_InB_Write(0);
}


/* [] END OF FILE */


コメントで
//ここから(167行目)
//ここまでがあやしい(278行目)
と記述されているところ(露骨過ぎますかね??)以外は基本ノータッチです。

ここでざっくりとMIDIについておさらいしましょう。
MIDIの詳細についてはggrばたくさん出てくるので割愛しますが、
  • ノートオン・オフ
    ここにはチャンネルの番号が格納されている)
  • ノートナンバー
    (音程のデータが入っている)
  • ベロシティー
    (音の強弱データが入っている)
という解釈で大体合ってますかね。

ノートナンバーの方はこちらのサイトを参考にさせていただきました。


このやっつけ感満載のおさらい通りにやっていけばなんとなくは
コメントでくくったあたりを弄くれば、
オリジナルMIDIデバイスが作れそうな気がしますねぇ




PSoCCreatorでバージョン管理系統が搭載されてないのは少しめんどくさいと感じるわけです。
その他にも今回のを見る限りボタンが多そうなデバイスを制作するにあたって
オブジェクト指向プログラムができないのも少しやりづらいかなと。

もっとコードエディターの補完機能とか充実していただけませんかね??
あと正式にC++対応お願いしますm(_ _)m

2018年2月10日土曜日

node.jsのURL追加をクラスで実装してみる。

ブログには大きい記事しか載せるべきではないかと思ってはいたのですが、
備忘録などに使えるしどうせ見る人もそんなにいないであろう(笑)と思ったので、
これからは小さいネタも載せて更新頻度の向上も目指したいと思ってます(^_^;)

さて、今回はひょんなことからWebアプリを作らないといけなくなったわけなのですが、
その際にnode.jsを使わせて頂いているわけです。

そこでまぁnpmを使って他のパッケージを利用するのもいいのですが、
今回はJsのクラスで勉強がてら(というか興味)に実装しようと考えたわけです。

まぁこのwebアプリ自体公にするものではなさそうなので大丈夫かなと(おい)

var http = require('http');
var fs = require('fs');

var server = http.createServer();
server.on('request', getJs);
console.log('Server running ...');

var Link_creator = function(source,linkname,type){
    this.source = source;
    this.linkname = linkname;
    this.type = type;
}

Link_creator.prototype.add = function(url,Res){
    
    console.log("function in");
    console.log(url);
    console.log("type is "+this.type);
    if(this.type == 'html'){

        if (this.linkname == url) {
            fs.readFile(this.source, 'UTF-8', function (err, data) {
                Res.writeHead(200, {'Content-Type': 'text/html'});
                Res.write(data);
                Res.end();
            });
        }
        return Res;
    }else if(this.type == 'js'){
        if (this.linkname == url) {
            fs.readFile(this.source, 'UTF-8', function (err, data) {
                Res.writeHead(200, {'Content-Type': 'application/javascript'});
                Res.write(data);
                Res.end();
            });
        }
        return Res;
    }else if(this.type == 'jpg'){
        if (this.linkname == url) {
            Res.writeHead(200, {'Content-Type': 'image/jpeg'});
                Res.end(fs.readFileSync(this.source, 'binary' ),'binary');
        }
        return Res;
    }else if(this.type == 'gif'){
        if (this.linkname == url) {
            Res.writeHead(200, {'Content-Type': 'image/gif'});
                Res.end(fs.readFileSync(this.source, 'binary' ),'binary');
        }
        return Res;
    }else if(this.type == 'css'){
        if (this.linkname == url) {
            fs.readFile(this.source, 'UTF-8', function (err, data) {
                Res.writeHead(200, {'Content-Type': 'text/css'});
                Res.write(data);
                Res.end();
            });
        }
        return Res;
    }
}
// new Link_creator('ローカルファイルの指定','URIの指定','タイプの指定')
var sites = [new Link_creator('./main.html','/index.html','html')
            ,new Link_creator('./home.html','/','html')];



function getJs(req, res) {
    var url = req.url;
    console.log(url);
    sites.forEach(function(site){
        if(site.linkname == url){
            console.log(site.source);
            res = site.add(url,res);
        }
    });
}


server.listen(8080);


とまぁこんな感じになります。
ミソは
new Link_creator('ローカルファイルの指定','URIの指定','タイプの指定')
ですね。
タイプの指定はクラス内のadd関数をゴニョゴニョしてオリジナルのものを
追加すればいいです。

やっぱりオブジェクト指向便利だなぁ…(しみじみ)

2017年11月14日火曜日

ROSとPSoC5LPでUSBUART通信(PSoC編)

前回の投稿からどれだけだったんでしょうね…(^_^;)
第30回ロボットコンテストから早1ヶ月が経とうとしています。
あまり良い成果を残せずに終わってしまった大会でしたが、今回のロボコンを経て学んだことをすこし備忘録として残そうかと思いました。
そしてこれを来年にも活かせるようにしなければな…と思っているわけです。ハイ。
というわけでブログタイトルのようにやって行きたいと思います。
ではでは…
環境
PSoC Creator 4.1
PSoC 5LP Development Kit
ぐらいでいいですかね?(もちろんPrototyping Kitでもできますよ~)

とりあえずぱぱっとUSBUARTのスケッチとコードを貼り付けときます。
(正直USBUARTではわかってないまま使ってる部分が...(;´∀`))

#include<project.h>
#include<stdio.h>


int main()
{
       CyGlobalIntEnable; /* Enable global interrupts. */

      LCD_Char_Start();

      USBUART_Start(0,USBUART_5V_OPERATION);
      while(!USBUART_bGetConfiguration()){}
      USBUART_CDC_Init();

      int count = 0;
      uint8 buff[64] = "";


      while(1)//main loop
      {   

            if(0 != USBUART_GetConfiguration())
            {

                  if(0 != USBUART_DataIsReady())
                  {
                        count = USBUART_GetAll(buff);
                        if( count != 0){

                        while(0 == USBUART_CDCIsReady()){}

                        USBUART_PutChar(buff[0]);

                        LCD_Char_Position(0,0);
                        LCD_Char_PrintNumber(count);
                        LCD_Char_PrintString(buff);

                        if(64 == count){
                              while(0 == USBUART_CDCIsReady()){}
                              //sent zero packet
                              USBUART_PutData(NULL,0);
                        }      
                  }
            }     
       }
}    
}



配線図は以下の通りです。
超シンプル(*´∀`)


この記事と連携させればこぉんな感じで通信できるはずです...





...次の更新はいつになることやら(;´∀`)

2017年11月12日日曜日

ROSとPSoC5LPでUSBUART通信(ROS編)

今回はROS編です。はい。
とりあえず、環境のほうをざっくり書いときます。
環境
MacBook Air (11-inch, Mid 2011)
・プロセッサ  1.6 GHz Intel Core i5(多分3世代?)
・メモリ    4 GB 1333 MHz DDR3
・グラフィック Intel HD Graphics 3000 384 MB
・シリアル番号…っと危ない危ない(;´∀`)

macos Sierra 10.12.5(16F73)とUbuntu 16.04.2を
デュアルブートさせてます。

Ubuntu 16.04ということでROS界でのLTS版とされる
Kinetic KAMEを使用しています。

まずディレクトリ構造から
※いじる必要のないフォルダ、ファイルは非表示にしています。

├── catkin-ws
│   ├── build
│   ├── devel  
│   └── src
│       ├── CMakeLists.txt
│       ├── USBUART_comm
│       │   ├── CMakeLists.txt
│       │   ├── include
│       │   │   └── USBUART_comm
│       │   ├── package.xml
│       │   └── src
│       │       └── USBUART_comm.cpp
│       └── 
└──       

下はUSBUART_comm.cppのソースです。

#include <ros/ros.h>
#include <string>

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>

int str_counter (char *str){
  int counter = 0;
  while(*str++){
    counter++;
  }

  return counter;
}

int main(int argc, char **argv){
  std::string dev = "/dev/ttyACM0",str_str;
  int baudrate = B9600;

  char str[64] = "Hello ROS & PSoC";

  ros::init(argc, argv, "UART_comm");

  ros::NodeHandle arg_nh("~");
  ros::NodeHandle nh;

  arg_nh.getParam("device", dev);
  arg_nh.getParam("baudrate", baudrate);
  arg_nh.getParam("message",str_str);

  strcpy(str,str_str.c_str());

//-------シリアルポート設定-------------------------
      int fd;                           /* ファイルディスクリプタ */
      struct termios oldtio, newtio;    /* シリアル通信設定 */
      int baudRate = B57600;
      fd = open(dev.c_str(), O_RDWR);   /* デバイスをオープンする */

      ioctl(fd, TCGETS, &oldtio);       /* 現在のシリアルポートの設定を待避させる */
      newtio = oldtio;                  /* ポートの設定をコピー */
      newtio.c_cflag = baudRate | CS8 | CREAD;
  	  newtio.c_iflag = IGNPAR | ICRNL;
  	  newtio.c_oflag = 0;
  	  newtio.c_lflag = 0;          /* ポートの設定をおこなう 詳細はtermios参照 */
      ioctl(fd, TCSETS, &newtio);       /* ポートの設定を有効にする */
//--------------------------------------------------------

  while(ros::ok()){

    printf("%s\n%d\n",str, str_counter(str));

    if(str_counter(str)>64){
      ROS_INFO("Warning!! \nThe amount of data that PSoC5 can receive is up to 64bytes.");
      //PSoC5のUSBUARTは一度に最大64バイトまでしか受け付けない。
    }

    if(fd<0){
      ROS_INFO("Error ! serialport open error!");
      return -1;
    }



    write(fd,str,sizeof(str)); //送信

    ros::spinOnce();

  }
  ioctl(fd, TCSETS, &oldtio);       /* ポートの設定を元に戻す */
  close(fd);                        /* デバイスのクローズ */

  return 0;
}
下はUSBUART_commフォルダー内のCMakeLists.txtです。
cmake_minimum_required(VERSION 2.8.3)
project(USBUART_comm)

add_compile_options(-std=c++11)


find_package(catkin REQUIRED COMPONENTS
  roscpp
  std_msgs
)


catkin_package(
 INCLUDE_DIRS include
 LIBRARIES USBUART_comm
 CATKIN_DEPENDS roscpp std_msgs
 DEPENDS system_lib
)


include_directories(
include
  ${catkin_INCLUDE_DIRS}
)


add_executable(${PROJECT_NAME}_node src/USBUART_comm.cpp)


add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})


target_link_libraries(${PROJECT_NAME}_node
  ${catkin_LIBRARIES}
)
あとは記述する必要はなさそうですが、 一応USBUART_commフォルダー内のpackage.xmlも晒しときます。
<?xml version="1.0"?>
<package>
  <name>USBUART_comm</name>
  <version>0.0.0</version>
  <description>The USBUART_comm package</description>

  <maintainer email="yukimakura@todo.todo">yukimakura</maintainer>


  <license>TODO</license>


  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>std_msgs</build_depend>
  <run_depend>roscpp</run_depend>
  <run_depend>std_msgs</run_depend>


  <export>


  </export>
</package>

ソースコードを見たら一目瞭然ですが、 ROSのソースにそのままlinuxのシリアル通信のソース乗っけただけという簡単なものです。 ですが、応用すれば別ノードやサービスから購読したデータをPSoCや別のシリアル通信できる マイコンと通信することができます...
えぇ、そうですとも。



絶対同等以上のことできるパッケージってもう存在してますよね!?

というわけでもし誰かご存知でしたら
教えてくださるとすごくありがたいです...m(_ _)m
あと素人ながら書かせて頂いたのでぜひご指摘等ございましたらビシバシ叩いていただくと光栄です。
参考にさせていただいたサイト様
FAQ : シリアル通信をおこなうプログラムを作成するには?
https://armadillo.atmark-techno.com/faq/serial-programming


2017年3月20日月曜日

PSoC CreatorでPWMサーボを制御(2017東海北陸ミニロボ)



2017/03/19から2日間に渡って
ロボコンの東海北陸地域の高専の交流会がありました。

今回の交流会は第二回ということでまだまだ歴史の浅い交流会
でしたが、私は今回が初参加ということで
正直あんまり期待していませんでしたが、
思いの外皆さんのプレゼンが面白くて、
そして私も良い刺激を受けることができました。
この場を借りて幹事の方々、イベント関係者様に感謝申し上げますm(_ _)m

さて、二日目の展示で釣れるかわからないですが、
富山射水のテーブルでPSoC5LPで書いた
PWMサーボのソースを公開しておりました。

みなさんのお話を聞いてると、存在は知っているが
ほとんど使ってないという方が結構おられて
正直知ってる人が割りといて驚きました(笑)

きっと皆さんがPSoCに手を出してない大きな理由として
情報が少ないというのがあると思います。
私も最初はそれに手こずりましたが、
基礎的な部分の壁を超えると、応用の方は
結構ググれば情報が出てきました。

なのでそこはなんとか気合でがんばって乗り切りましょう
(;´∀`)

PSoCは昔の開発環境としてPSoCDesignerと言うものがありましたが、
2010年頃にCypressはPSoC Creatorという全くあたらしい
開発環境を発表すると同時に後発のPSoCもPSoCCreatorに対応したものとなりました。

まあ、それはいいのですが、PWMのサーボの情報が
昔のPSoCDesignerの方のものしか無い!!
という状況に陥り、悩んだという事態に陥りました。
ですが、なんとかPSoCCreatorにてPWMサーボを扱えたので
備忘録として残しておこうと思います。

とりあえずC++にしてますが、
もしCのほうがいいという方がおられたら、
コメントいただけるとなんとかCのもあげます。
なお、修正点や改善点等ございましたら、
ぜひコメントいただけるとすごくうれしいです。

環境はPSoCCreator4.0
PSoC5LP prototyping kit
ifdef __cplusplus
extern "C" {
#endif
#include <project.h>
#ifdef __cplusplus
}
#endif


class CompareConverter{
    public:
        int us2compare(int servonum){

            if(635>servonum){
                return 316;
            }
            if(2350<servonum){
                return 1175;
            }
            return 315+((servonum-635)/2);
            
        }
        int degree2compare(int Servonum){
        
            float servonum = (float)Servonum;
           
            if(0>servonum){
                return 316;
            }
            if(180<servonum){
                return 1175;
            }
            return 315+((servonum)*4.77);
        }
};



int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
    CompareConverter compconv;
    
    //通電確認用
    power_Write(1);

    for(;;)
    {
        PWM_1_WriteCompare(compconv.degree2compare(90));
       
     
    }
}


ピン配置、PGAの配置等


PWM自体の設定


電源はPSoCのVCCとGNDで
PWMの信号は1_6ピンに刺すと
サーボモータが90度を指すところに回転する...はず(笑)
只今帰宅途中のバスで書いてるので実際試してないです(おい

ちなみに2_1のピンに設定してあるpowerってのは
ただのPSoC通電確認用です。

2017年1月19日木曜日

GTX980mを無理矢理にVRReadyに引き上げてみた(ベンチマーク編)

前回の投稿でGPUの限界を開放したわけなので
せっかくですからベンチマークをしてみました~ \(*´∀`)/ワーイ

使用したソフトは言わずもがな知れた
SteamのSteamVR Perfomance Testです。

ではデフォ(OCなし)の状態でレッツゴー



Oh...惜しい!
あとちょっとでVRReadyなのに...
まぁ、ぶっちゃけ全然VRできるスペックなんですけどね(^_^;)

ではOCを早速やってみましょう!!
私はOCにNVIDIA Inspectorを使用しております。

ではコアの電力を30mVほど上げまして
GPUは240MHzほどOCと。

その結果は...


ドコドコドコドコドコドコドコドコドコドコドコドコ...









VRReadyキタ━━━━(゚∀゚)━━━━!!

とまぁ...ギリギリ到達と。

このパソコンは重量を引き換えに冷却性能だけはいいので
75℃にも達していないようですね。
(ファンは手動で全開の状態でベンチを回しました)

この際もっと限界を....

ということでめざせ1.4GHz動作を目標にやってみました。


こちらが結果です。

なんとか完走しました。
ですが、しばらくするとwindowsが応答なくしました(っておい

で、どうやらいろいろ調査してみると意外な原因が...

これ以上OCする場合には330W電源が必要

...トホホ

こいつのデフォは230Wの電源なのですが、さすがclevo!グローバルに展開しているだけあって、
330Wのアダプターもあるのです。
GPUをOCするとどうやら230Wじゃぁ足りなくなってくる模様...

怖い、怖すぎるぜOC!

そんな感じで電源アダプターやGPUが死んだ場合は一応
Eurocomの方で購入できますので(安いとは言ってない

あともはや常套句ですが、一応...

完全に自己責任でお願いします。
もし失敗してGPUがお釈迦になっても
私、ゆきまくらは一切責任を負いません。




ではみなさま、楽しいノートPCOCライフを!(*^^*)ノシ