Miho's Memory

組込みとアートとまぜまぜ

AI自動運転ちび&でかラジコンカー ~ 訓練からの自動走行編~

AI自動運転ちび&でかラジコンカー ~ 訓練からの自動走行編~

以前 2023/7/15 に 「AI自動運転ちび&でかラジコンカー ~ 訓練環境構築編~」のブログを書きました ^^#

AI自動運転ちび&でかラジコンカー ~ 訓練環境構築編~ - Miho's Memory

今回は その続きで「走行データを訓練させて自動走行」させてみようと思います ^^#

◆ ちび&でかラジコンカーに搭載したハードウェアとコントローラー

・    RaspberryPi4(でかminionに搭載),RaspberryPi3B+(ちびminionに搭載)
・    モータドライバ PCA9685(I2C でサーボとESCの制御信号 PWM を生成する基板)
・    スピードコントローラ(ちびminionに搭載のもの)
GoolRC RC ESC 20A ブラシモーター スピードコントローラー 切り替え可能 ブレーキ付 RC ラジコン カー ボート タンク用
https://www.amazon.co.jp/gp/product/B014RB6WS6/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1
・    WiFiルーター WMR-433W2-TB
バッファロー BUFFALO 無線LAN親機 11ac/n/a/g/b 433/150Mbps トラベルルーター
https://www.buffalo.jp/product/detail/wmr-433w2-tb.html
・    コントローラ F710

◆ ちび&でかラジコンカーの全体構成図

  

RaspberryPi4 は FPS 30 で、処理は十分追い付いてた。
RaspberryPi3B+ は FPS 30 では、処理が追い付かず、カメラ画像の遅延が3sほどとひどいw CPUクロック数は半分になっていた! というのも、『モバイルバッテリーで3B+を動かすとLowVoltageになってクロックが半分になる!』というのが原因なのだ。ということで、FPS を 20 に設定。
それで自動運転ができるか心配だったけど、私の操縦テクニックだと十分だったw

◆ RaspberryPiの既存作業フォルダを変更する

以前は、AI_Driverフォルダ を作業フォルダとし、そこに必要なファイルをダウンロードし環境を整え、走行データや、学習済みデータも置かれていた。

以前の設定について書いていた記事 参考:

https://miho-diary.hatenablog.com/entry/2023/10/27/132620

     11. 作業フォルダを作成してファイルをダウンロード
     12. WinSCP を 使って ~/.bashrc の最後に以下3行を追加


このたび、各種パラメータの変更が行いやすく、ファイルが役割ごとに分割され、きれいになった環境が用意されたので ^^
既存作業フォルダ AI_Driverフォルダ から、 新規作業フォルダ AI_Drivr2フォルダに変更し、AI_Driver2フォルダに、必要なファイルをダウンロードして、そこを作業場とする。

手順: RaspberryPi で以下のコマンドを実行

1. AI_Driver2フォルダを作成し、必要なファイルをダウンロードする
    mkdir ~/AI_Driver2
    cd ~/AI_Driver2
    wget http://ma2.la.coocan.jp/AI_Driver/roba/download/aidriver.zip
    unzip aidriver.zip

2. AI_Driver2フォルダ をカレントディレクトリにする
    ~/.bashrc に書かれている
    cd ~/AI_Driver を cd ~/AI_Driver2 に修正する

 

** 教師データを作成し、訓練させ自動運転へ **

1. コントローラ F710 の操作を確認する

2. 教師データ作成 つまり コントローラー走行 と 走行の記録

VNC起動する。
VNC環境で RaspberryPi の起動を確認したら、
コンソール画面を立ち上げ、以下コマンドを実行

最初の起動は少々時間がかかるが、
ほどなくして、車内カメラ映像がVNC上に現れる。カメラ映像ウインドウが選択されている状態で、青ボタン ⇒ 緑ボタン ⇒ 赤ボタン を押下。コントローラーで走行開始!データを 10,000個程度 とる。

とり終わったら、カメラ映像選択状態で、赤ボタン ⇒ 緑ボタン を押下。
続けて、キーボード「Qキー」押下。カメラ窓が閉じる。
続けて、キーボード「Ctrl+c」。プロンプトの画面に戻る。

 

3. RaspberryPi上の教師データ(logフォルダのデータ)をパソコンに転送

Ubuntuを起動し、以下のコマンドを実行。
pi@ホスト名(わたしだと pi@raspberrypi)でいいのだが、ホスト名で見つけてこなかった場合は、IPアドレスを指定すれば良い(わたしだと pi@192.168.13.*)。

    途中省略

* もし!こんな ↓ ↓ エラーがでてPCに持ってこれなかったら!!! *

① のディレクトリ内にある hostsファイルを削除しろ!というエラー
① のディレクトリ内をみてみると、確かに hosts の文字があるファイルが2つ。

なので、rmコマンドで削除する

4. 学習させる

Ubuntu画面から、エポック(第2引数に指定)をいくつにするか決めて、以下のコマンドを実行。今回は エポック 40 で実行。

    途中省略

    学習済データが生成されたことを確認

5. パソコンにある学習済みデータをRaspberryPiに転送

Ubuntu画面から、以下のコマンドを実行。

6. 自動走行

VNC RaspberryPi画面から、以下のコマンドを実行。

ほどなくして、車内カメラ映像がVNC上に現れる。カメラ映像ウインドウが選択されている状態で、
黄ボタン押下で、自動運転モードにセット。
赤ボタン押下で、記録をON。
緑ボタン押下で、自動走行開始!

再度、カメラ映像選択状態で、
緑ボタン押下で、車停止。
赤ボタン押下で、記録OFF。
続けて、キーボード「Qキー」押下。カメラ窓が閉じる。
続けて、キーボード「Ctrl+c」。プロンプトの画面に戻る。

自動走行は成功したかな?^^
つぎは、記録してあったデータから、”あなたの操縦テクニック診断/見える化!” してみたり、”車窓からの画像をつなげて動画に!” する方法をお伝えします♪

 

AI自動運転ちび&でかラジコンカー ~ 訓練環境構築編~

AI自動運転ちび&でかラジコンカー ~ 訓練環境構築編~

以前 2023/10/27 に 「AI自動運転ちびラジコンカー ~ 製作~」のブログを書きました ^^#

AI自動運転ちびラジコンカー ~ 製作~ - Miho's Memory

今回は その続きで「パソコンのローカルに訓練の環境を構築」しようと思います ^^#

なんと!!GPU搭載パソコンを買ったんです♪

◆ パソコン

【スペック】

OMEN by HP Transcend 14-fb0040TX 

・    インテル Core Ultra 7 プロセッサー 155H (最大 4.80GHz/24MB)
・    14.0インチ・ 2.8K ・OLEDディスプレイ
・    16GB オンボード (LPDDR5x-7467MHz)
・    1TB SSD (PCIe Gen4×4 NVMe M.2)
・    NVIDIA GeForce RTX 4060 Laptop グラフィックス

ということで、このパソコン内訓練の環境を構築します!

◆ 訓練の環境構築

【参考サイト】

http://ma2.la.coocan.jp/AI_Driver/

の、「あいちゃん TAMIYA TT-02」に進みます。
すると、以下のような画面になり、その中の「訓練:PC(Windows/wsl2)」に進みます

1. Windows Update をやっておく

     今回はGPU搭載パソコンに訓練の環境を構築

2. NVIDIAドライバの確認

    2-1 PowerShell を開き 「nvidia-smi」コマンドを実行

    2-2 「NVIDIAドライバダウンロードページを開き」、「自分パソコンの情報を入力」し、ドライバを「探す」

https://www.nvidia.com/ja-jp/drivers/

    2-3 世に出ているドライババージョンのほうが新しそうだ!
          なので、ドライバをダウンロードしてインストールする

3. VTx が有効になっているか確認する

    3-1 BIOS を立ち上げる 
           ※ OMEN by HP Transcend 14-fb0040TX は F10 で起動した

    3-1 Virtualization Technology(VTx)が有効になっていることを確認する
           ※ HP は出荷時は有効になっているかも
           ※ Spectre でも確認したことあったけど、どうだったかな ^^;  

4. Ubuntu22.04 をインストールする

    4-1 PowerShell を管理者で実行し、「wsl --install」コマンドを実行

    4-2 インストールが成功すると、以下のように再起動しろと言ってくる

    4-3 再起動後は、Ubuntu が自動で起動してくる

    4-4 しばらくすると、以下のように ユーザ名 と パスワード の設定を促される

5. CUDA Toolkit をインストールする

    5-1 TensorFlow , Python , CUDA それぞれのバージョンの組み合わせを確認

           https://www.tensorflow.org/install/source#gpu

    5-2 CUDA 11.8 が "いいらしい" ので、CUDA 11.8 をインストール

           CUDA Toolkit 11.8 Downloads | NVIDIA Developer

    上記画面↑の選択で間違いないか確認したのち、
    上記画面の下にある以下↓の Installation Instructions を実行する

6. cuDNN をインストールする

    6-1 8.7のUbuntu22.04用を以下サイトからダウンロードする
           注意!NVIDIAにログインが必要(わたし アカウント持ってた)

           https://developer.nvidia.com/downloads/c118-cudnn-local-repo-ubuntu2204-8708410-1amd64deb

           注意!ダウンロードがウイルス対策ソフトに引っかかった!
                      引っかかっても、確認した上でダウンロードすればよい

    6-2 ダウンロードしたファイルを Ubuntu のカレントディレクトリにコピー

    6-3 Ubuntu を起動し、以下のコマンドを順次実行

7. python の環境を構築

    7-1 Ubuntu を起動し、以下のコマンドを順次実行

    注意!実は「pip install numpy==1.26.4」をせずに進めていたら、
               動作確認 の時 NumPy に関する以下のようなエラーが出た。
               その時の NumPy の バージョンは 2.0
               なので、NumPy の バージョンは結構大切かも!

★自分メモ

    ● TensorFlow      2.14.0
    ● Python            3.10.12
    ● NumPy            1.26.4
    $ pip list で Package の Version を確認できる

8. 訓練の環境を構築

    8-1 Ubuntu を起動し、以下のコマンドを順次実行

9. ~/.bashrc の最後に以下を追加

★自分メモ    

    exit して再ログイン

10. 動作確認

    8-1 Ubuntu を起動し、以下のコマンドを順次実行

【おまけ!】

★ time python train.py log 6

     6 は エポック数

     40 でやってみた

     time python train.py log 40

     1分 ほどで終わってる!!

     7年前の Spectre x360 だったら、ゆうに30分はかかっていたのに! 

11. Windows にアプリケーションをインストール

    ● RealVNC Viewer
    ● TeraTerm
    ● WinSCP
    ● NetworkScanner
    ● VSCode + Remote-SSHプラグイン

今度は この でか minion BUS を実際に動かすところと、
動かして走らせたつもりで(家の中は狭くてムリw)学習させるところまでをやってみる!

最後までお付き合い下さりありがとうございました ^^#

なりきりアーニャ わくわくっ!!

なりきりアーニャ
       ~ あいてむ制作!!~

みんなだいすきアーニャになりきろう!あいてむ制作!!わくわく...っ!
※ ずっとまえから創ってたアーニャあいてむですw
   気まぐれブログなので今頃ブログに...

アーニャになるためには、みっつ!のアイテムを用意しよう!

★ ひとつは、とんがりさんかくかみかざり
★ もうひとつは、ステラ
★ さいごのひとつは、キメラさん

◆ 用意するもの

【とんがりさんかくかみかざり】
● 黒の薄手の厚紙
● 山吹色の薄手の厚紙
● 穴あけパンチ
● マグネット
● 耐熱電子ワイヤー
● リードスイッチ
   参考:
       秋月電子通商
       リードスイッチMKA-10110
       https://akizukidenshi.com/catalog/g/g103676/
● 黄色のLED や 黄色のLEDキャップ
● 抵抗
● CR2032用電池ケース と CR2032電池
   参考:
       秋月電子通商(※1)
       電池ケース CR2032×2個用 スイッチ付 PHコネクタ付
       https://akizukidenshi.com/catalog/g/g112666/

       SWITCH SCIENCE
       CR2032型コイン電池ホルダー (スイッチ付き)
       https://www.switch-science.com/products/7027?variant=42382135886022

※1
使うLEDによっては電池部分1つをアルミホイルで埋めるとか、配線するなど必要

★ 組み立て完成動画 ★
ノギスの裏はマグネット ^^#
https://youtu.be/_OSPwh5m-Os

【ステラ】
● プラバン
● 黄色の折り紙
● マグネット
● 耐熱電子ワイヤー
● リードスイッチ
● 黄色のLED
● 抵抗
● CR2032用電池ケース と CR2032電池

★ 組み立て完成動画 ★
https://youtube.com/shorts/1gnDv9JfgCk?feature=share

【キメラさん】
● キメラさん
● マグネット
micro:bit
● LED テープライト

★ 組み立て完成動画 ★
https://youtu.be/XAk9Lr7wvM0

組み立て途中の図

● とんがりさんかくかみかざり

1.   2.   3. 

4.   5.   6. 

7. 

● ステラ

1.  2.   3.  

4. 

● キメラさん
おしりを割いて、マグネットを仕込むw
https://youtu.be/LdvjPus1rDs

◆ 思い出 ^^# @ユニバ

 


メダルは可愛く(ღˇᴗˇ)。o♡

   

最後までみてくれて あざざます!!

AI自動運転ちびラジコンカー ~ 製作~

AI自動運転ちびラジコンカー ~ 製作~

以前 AI自動運転”でかっ!”ラジコンカー をつくりました ^^#

https://miho-diary.hatenablog.com/entry/2019/12/24/023430

今回は 手のひらサイズの AI自動運転ちびラジコンカー を作ろうと思います ^^#

◆ ハードウェア

【車体】
Fabo で数年前に購入済!2台!!

GeckoCar – FaBo Store

Gecko ただいま絶賛アップデート中! 

※ 大きくてもいいからラジコンカーを持っていたら、コントローラーとPCA9685 だけ買えばいいよ!

【Raspberrry Pi】
    車2台分
    ● Raspberry Pi 4 Model B(4GB RAM)
    ● Raspberry Pi 3 Model B v1.2

【無線ゲームコントローラ
    ロジクールF710

【カメラ】
    RaspberryPiカメラV1 広角レンズ

【micro SD】
    32MByte

【モバイルバッテリー】
    Raspberry Pi へ電源供給

【組み立て完成図】

           

   

      

 -----  と、今回は 車の組み立ては終わってる前提で、ここからが本題!  -----

参考にするのは、

CQ出版社 インターフェース 2023年3月号 記事』 

AIがピッタリ…人間の操作よりも安定して好タイム!学習データも作りやすい

自動運転ラジコン・カーの製作

https://interface.cqpub.co.jp/wp-content/uploads/if2303_151.pdf

◆ ソフトウェアのインストール

【事前準備 インストール】
    ● Raspberry Pi Imager:使用したバージョン  1.7.3
    ● RealVNC Viewer
    ● WinSCP
    ● NetworkScanner
    ● TeraTerm

Raspberry Pi OS セットアップ】

http://ma2.la.coocan.jp/AI_Driver/tt02/view.cgi?fname=install.txt&fsize=5

1. Raspberry Pi Imager を起動

2. 「OS を選ぶ」/ Debian Bullseye の Full でも Lite でもないやつ を 選択
   
    Raspberry Pi OS (other) を 選択
   
    Raspberry Pi OS (Legacy, 64-bit)を選択
   
         
3. 「詳細な設定」/ 画面右下の ギヤマーク を選択
   

   

   

   

4. ストレージを選択して書き込み!!

--- 書き込み終了! ---

5. SSH を有効にする
   1) Raspberrry Pi OS を書き込んだ micro SD を もう一度カードリーダーに
   2) 中身無し、拡張子無し、ファイル名 ssh のファイルを作成
   3) Raspberry Pi OSをインストールしたmicro SDカードのbootディレクトリ直下に、2) で作成した空の“ssh”ファイルをドラッグアンドドロップで置く
       というのも、bootディレクトリの下でファイルを作成しようとすると固まったからw
   4) NetworkScanner を起動し、現在のネットワーク環境を見ておく
   5) Raspberrry Pi に micro SD をセット、電源をいれる
   6) 最初は少し時間がかかるが、ある程度したら 再度 NetworkScanner を起動
       増えたものが Raspberrry Pi

6. TeraTerm で raspberrypi.local で接続!できた!

    サイトを見ながら。。。
    http://ma2.la.coocan.jp/AI_Driver/roba/view.cgi?fname=install.txt&fsize=5

7. Raspberrry Pi OS アップデート & アップグレード
    1) sudo apt-get update
    2) sudo apt-get upgrade

8. raspi-config による設定
    1) sudo raspi-config 
    2) 以下の項目を設定
        ・ 2 Display Options
                ⇒ D5 VNC Resolution
                     ⇒ 1024×768
                ⇒ D6 Composite→V2
                     ⇒ Yes
        ・ 3 Interface Options
                ⇒ I1 Legacy Camera
                     ⇒ Yes
                ⇒ I3 VNC
                     ⇒ Yes
        ・ 6 Advanced Options
                ⇒ A1 Expand Filesystem
                     ⇒ OK

9. python の仮想環境を作成
    1) python3 -m venv --system-site-packages ~/venv
    2) source ~/venv/bin/activate

10. ライブラリをインストール
    1) pip install --upgrade pip
    2) pip install tensorflow
    3) pip install tensorflow_io
    4) pip install tflite-runtime
    5) pip install opencv-python

    ※ 長い時があるけど、じっとガマン!

11. 作業フォルダを作成してファイルをダウンロード
    1) mkdir ~/AI_Driver
    2) cd ~/AI_Driver
    3) wget http://ma2.la.coocan.jp/AI_Driver/roba/download/aidriver.py
    4) wget http://ma2.la.coocan.jp/AI_Driver/roba/download/cfg.py
    5) wget http://ma2.la.coocan.jp/AI_Driver/roba/download/movie.py

12. WinSCP を 使って ~/.bashrc の最後に以下3行を追加
      source ~/venv/bin/activate
      cd ~/AI_Driver
      sudo pigpiod
     
      ※ WinSCP の 環境設定を変更:パネル - 隠しファイルを表示する

13. exit して再ログイン
      ※ exit すると、ヒストリ が溜まっていく / bash_history ファイルが更新される

14. 無線ゲームコントローラのドングルを RaspberryPi に挿す

15. RealVNC Viewer を起動し接続:raspberrypi.local または IPアドレス

16. コンソールを起動し、
      1) カメラ認識 の確認
          ls /dev
          video0  があれば OK!
      2) ゲームコントローラ認識 の確認
          ls /dev/input
          js0  があれば joystick OK!
      3) カメラとゲームコントローラの動作確認
          python aidriver.py 
          ※ 時間かかるけどガマン!!
         

 

【ためしてみよう!】

★ コントローラの赤ボタンを押すと画像が保存されるぞ!

     ⇒ 画面に枚数が表示される! 再 赤ボタン で止まる

     ⇒ WinSCP で AI_Drive フォルダを見ると log フォルダがあり .jpg でいっぱい!

★ 「Qキー」でプログラムが停止するぞ!

     ⇒ WinSCP で AI_Drive フォルダを見ると log フォルダがあり .csv あり!

★ 「ctrキー + Cキー」で止める!

⇒ .jgp(写真) と .csv(サーボやESC情報)を  TensorFlow で学習する

 

まだ、サーボはつないでないので、次回は、

● サーボの確認 & 手動走行

● 教示データ作成

● AI の学習/深層学習(google Colaboratory, TensorFlow)

 

そして、以前作ったモノもまた活躍するときがやってきた ^^#

【minion バスに大変身】

   

   

【minion カラーの可愛いト音記号のコース ^^#

   

【車窓から ^^#】

   

【ポテトのコース ^^#】

    

【走らせてみた ^^#】

    https://youtu.be/QqAq5oXCnt8


最後までお付き合い下さりありがとうございました ^^#

【鬼滅の刃】栗花落カナヲの光る刀の作り方

鬼滅の刃】栗花落カナヲの光る刃の作り方**

Merry Christmas!!

この記事は SeeedUG アドベントカレンダー2021の24日目のエントリになります。
サイトはこちら https://qiita.com/advent-calendar/2021/seeed_ug
はじめての SeeedUG への参加です ^^#
技術ガッツリのお話は、無理 ^^; なので、Seeeduino XIAO を使ってつくった、今流行りのアニメの刃を作ったのでそれを紹介したいと思います ^^#

きっと誰しもあっちいけ~思う鬼(人)がいるハズ。
そんなあなたと一緒に鬼退治用アイテムを一緒に創りたいと思います ^^#

そのアイテムは “刃” ^^

簡単に作りましょう!在り物を上手に使います。
さて、ダイソーの光る刀(\200)円を用意します。
ダイソー刀もすごいんですけど、上弦の鬼はヤレマセン。今回は上弦の鬼用の刀を創ります。

そこで、ダイソー刀の解体新書。
と、そのまえに!ダイソーオリジナル はこんな光り方です ^^#

で、解体新書。
いたってシンプル。LEDに至っては天才的なセンスです!
そしてとても綺麗です!
こんな感じ ↓↓

さて、この美しくデザインされた筐体に潜む精神の核たちをすっかり入れ替えてしまいましょう!

新しく精神の核になるモノ!
ダイソーの光る刀 \200
・ Seeeduino XIAO 1個
https://www.marutsu.co.jp/pc/i/2191155/
https://wiki.seeedstudio.com/jp/Seeeduino-XIAO/
・ 丸っ子ユニバーサル基板 1個
https://akizukidenshi.com/catalog/g/gP-09674/
・ タクト/モーメンタリスイッチ 1個
https://akizukidenshi.com/catalog/g/gP-03651/
・ ロックスイッチ 1個
https://www.aitendo.com/product/3600
・ Novonest アドレス指定可能な5V 3PIN RGB LEDライト 1本
https://www.amazon.co.jp/gp/product/B093D266QV/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1

見てください!
こんなにも美しく収まるんです(⋈◍>◡<◍)。✧♡

LEDだってこんなにすっぽり

おまけですが、刃の弧 を意識して、刃の背に小さな穴をあけてそこから針金差し込んで、LEDがすこし弧を描くように押しています。

もともとついてたスイッチ基板を使えるほどできる人じゃないんで、私はそれは使わない(使えないw)。
その代わりに自分が得意な工作の方へ!

今回使用した タクト/モーメンタリスイッチの足は4本だったので、ニッパでに2本に

今回使用しているロックスイッチは、足が両サイドに出たものだったw

ロックスイッチの取り付けは、もともとのスイッチの穴をニッパで切って拡大し、棒ヤスリでこすりながら穴を大きくロックスイッチが収まるように加工します。

【構成図】

【開発環境】

とか


+

今回は VSCode + PlatformIO を使ってみます。

プロジェクト作成の時、選ぶ Board名 はもちろん
Seeeduino XIAO
を選択します。
プロジェクト作成後 platformio.ini がこう↓なっていれば OK です。

つっこんだライブラリは

  • FastLED
  • Button 2
  • Adafruit NeoPixel

ライブラリをつっこんだ後 platformio.ini がこんな↓感じになっていれば OK です。

あとはこんな感じ↓でプログラミングします。

出来上がった刃と出来上がった私がこちら↓

出来上がった刀。それだけでも十分すごいけど、みためDAISOよりかっこよくつくっちゃえ!とデザインを施した。
そしてさらに、子どもたちにそれを見せるとき、もっと彼らが目を光らせるように、自分もなりきりろうと衣装をまとった。
小さい頃、ウルトラマンと一緒に写真を撮った。
あれが、中のお兄さんで胸にラーメンタイマーつけてても写真撮りたいとは思わんわ笑
子どもたちがこういったものに興味を示すために、どこまでどう何を創り込むかはその人次第(*^^*)

光り方はこちら Youtube で↓
鬼滅の刃】栗花落カナヲの光る刃作り方&デモ
youtu.be

ピアノ発表会の演出も是非ご覧ください。子供たちにとってさらに良い想い出になってくれてたらなと思います♪↓
鬼滅の刃】栗花落カナヲの光る刃の舞 in Piano recital
youtu.be

と、最後に、ダイソーノーマル刀では、見た目が寂しい。。。
ということで、ダイソーに売っているスプレーやタミヤの塗料で見た目もカナヲの刃に仕上げました ^^#
他には、炭治郎、善逸、まだ途中の伊之助 刀たちが出来上がってます。

このまましばらく 鬼滅の刃 人気であってほしいなぁ ^^*
もっとどっかに出かけて見せびらかせたい♪

最後までお付き合い下さりありがとうございました ^^#

はじめての F (⋈◍>◡<◍)。✧♡ ~ Pythonプログラム編② の弐~

はじめての F (⋈◍>◡<◍)。✧♡ ~ RasPi編②の弐 ~

さてっ.
RasPi編②の壱 では サンプルプログラムを実行して、FRAMメモリの読み書きができてそうか?ってのを波形をみて確認しました。
そう
波形は信号の『素顔💛』です ^^#

せっかくなので、データシートのすべてのコマンドを実行してみようと思います。
ここは、FRAM波形ワールドなページ♪

引き続き、波形を見るにはおうちにあった LabTool を使います。

Random Readコマンド

FRAMサンプルプログラム!
【fram_main2.py】

import os
import time
import sys
import time
import random 

from i2c_fram2 import *

if __name__ == '__main__':

    print(" HELLO FRAM ")
    print("----------------- ")
    fram = SDL_I2CFRAM(addr = 0x50)

    print("- WRITE - ")
    fram.write8(7,34)
    print("WRITE FINISH")

    print("- READ - ")
    fram.read8(7)
    print("READ FINISH")

    print("---framEND---")

【i2c_fram2.py】

import time
import smbus2
import sys
from decimal import *

from datetime import datetime

class SDL_I2CFRAM():

    ###########################
    # SDL_I2CFRAM Code
    ###########################
    def __init__(self, twi=1, addr=0x50):
        self._bus = smbus2.SMBus(twi)
        self._addr = addr

    def write8(self, address, data):
        w = smbus2.i2c_msg.write(self._addr, [address>>8, address%256, data]) 
        self._bus.i2c_rdwr(w)

    def read8(self, address):
        w = smbus2.i2c_msg.write(self._addr, [address>>8, address%256])    # r1
        r = smbus2.i2c_msg.read(self._addr, 1)    # r2
        self._bus.i2c_rdwr(w,r)    # r3
        print(list(r)[0])

では、プログラムを実行しておきましょう!

(env) pi@Donkey-Miho:~/miho/blog $ python fram_main2.py
 HELLO FRAM
-----------------
- WRITE -
WRITE FINISH
- READ -
34
READ FINISH
---framEND---

波形はこれ ↓↓

f:id:MihoN:20210209200651p:plain

つぎ!
■ Page Writeコマンド

FRAMサンプルプログラム!
【fram_main3.py】

import os
import time
import sys
import time
import random 

from i2c_fram3 import *

if __name__ == '__main__':
    fram = SDL_I2CFRAM(addr = 0x50)

    print(" HELLO FRAM ")
    print("----------------- ")

    print("- WRITE - ")
    address =0x00
    data = [1, 2, 3, 4, 5, 6, 7, 8]
    fram.write_block(address, data)
    print("WRITE FINISH")

# With LabTool
    print("- MemDump - ")
    fram.mem_dump()

    print("---framEND---")

【i2c_fram3.py】

import time
import smbus2
import sys
from decimal import *
from datetime import datetime

class SDL_I2CFRAM():

    ###########################
    # SDL_I2CFRAM Code
    ###########################
    def __init__(self, twi=1, addr=0x50):
        self._bus = smbus2.SMBus(twi)
        self._addr = addr

    def write_block(self, address, data):
        cnt_len = len(data)
        for y in range(0, cnt_len):
            print("data[%d] = %d" %(y, data[y]))
        print("---")
        new_data = [address%256] + data
        cnt_len = len(new_data)
        for y in range(0, cnt_len):
            print("new_data[%d] = %d" %(y, new_data[y]))
        self._bus.write_i2c_block_data(self._addr,address>>8, new_data)  # r1

    def mem_dump(self):
        w = smbus2.i2c_msg.write(self._addr, [0x00>>8, 0x00%256]) 
        self._bus.i2c_rdwr(w)
        for x in range(0,10):
            r = smbus2.i2c_msg.read(self._addr, 1)
            self._bus.i2c_rdwr(r)
            print("data = 0x%x " % (list(r)[0]))

では、プログラムを実行しておきましょう!

(env) pi@Donkey-Miho:~/miho/blog $ python fram_main3.py
 HELLO FRAM
-----------------
- WRITE -
WRITE FINISH
- MemDump -
data = 0x1
data = 0x2
data = 0x3
data = 0x4
data = 0x5
data = 0x6
data = 0x7
data = 0x8
data = 0x6c
data = 0x6d
---framEND---

※ 出力結果 0x6c や 0x6d の部分は、FRAMに書かれているデータが違えば変わってきます

波形はこれ ↓↓
f:id:MihoN:20210209195624p:plain

つぎ!
■ Sequential Readコマンド

FRAMサンプルプログラム!
【fram_main4.py】

import os
import time
import sys
import time
import random 

from i2c_fram4 import *

if __name__ == '__main__':
    fram = SDL_I2CFRAM(addr = 0x50)

    print(" HELLO FRAM ")
    print("----------------- ")

    print("- WRITE - ")
    address =0x00
    data = [1, 2, 3, 4, 5, 6, 7, 8]
    fram.write_block(address, data)
    print("WRITE FINISH")

    print("- READ - ")
    fram.read_block(0x00, 3)
    print("READ FINISH")

# With LabTool
    print("- MemDump - ")
    fram.mem_dump()

    print("---framEND---")

【i2c_fram4.py】

import time
import smbus2
import sys
from decimal import *
from datetime import datetime

class SDL_I2CFRAM():

    ###########################
    # SDL_I2CFRAM Code
    ###########################
    def __init__(self, twi=1, addr=0x50):
        self._bus = smbus2.SMBus(twi)
        self._addr = addr

    def write_block(self, address, data):
        cnt_len = len(data)
        for y in range(0, cnt_len):
            print("data[%d] = %d" %(y, data[y]))
        print("---")
        new_data = [address%256] + data
        cnt_len = len(new_data)
        for y in range(0, cnt_len):
            print("new_data[%d] = %d" %(y, new_data[y]))
        self._bus.write_i2c_block_data(self._addr,address>>8, new_data)

    def read_block(self, address, sequence):
        w = smbus2.i2c_msg.write(self._addr, [address>>8, address%256])   # r1
        r = smbus2.i2c_msg.read(self._addr, sequence)   # r2
        self._bus.i2c_rdwr(w,r)   # r3
        for x in range(0, sequence):
            print("data = 0x%x" % (list(r)[x]))

    def mem_dump(self):
        w = smbus2.i2c_msg.write(self._addr, [0x00>>8, 0x00%256]) 
        self._bus.i2c_rdwr(w)
        for x in range(0,10):
            r = smbus2.i2c_msg.read(self._addr, 1)
            self._bus.i2c_rdwr(r)
            print("data = 0x%x " % (list(r)[0]))

では、プログラムを実行しておきましょう!

(env) pi@Donkey-Miho:~/miho/blog $ python fram_main4.py
 HELLO FRAM
-----------------
- WRITE -
WRITE FINISH
- READ -
data = 0x1
data = 0x2
data = 0x3
READ FINISH
- MemDump -
data = 0x1
data = 0x2
data = 0x3
data = 0x4
data = 0x5
data = 0x6
data = 0x7
data = 0x8
data = 0x6c
data = 0x6d
---framEND---

※ 出力結果 0x6c や 0x6d の部分は、FRAMに書かれているデータが違えば変わってきます

波形はこれ ↓↓
f:id:MihoN:20210212110620p:plain

さいご!
■ Device IDコマンド

FRAMサンプルプログラム!
【fram_main5.py】

import os
import time
import sys
import time

from i2c_fram5 import *

if __name__ == '__main__':

    print(" HELLO FRAM ")
    print("----------------- ")
    fram = SDL_I2CFRAM(addr = 0x50)

    print("- DeviceID - ")
    fram.read_device_id()
    print("DeviceID FINISH")

    print("---framEND---")

【I2C_fram5.py】

import time
import smbus2
import sys

from decimal import *
from datetime import datetime

class SDL_I2CFRAM():

    ###########################
    # SDL_I2CFRAM Code
    ###########################
    def __init__(self, twi=1, addr=0x50):
        self._bus = smbus2.SMBus(twi)
        self._addr = addr

    def read_device_id(self):
        w = smbus2.i2c_msg.write(0xf8//2, [0xa0])   # D1
        r = smbus2.i2c_msg.read(0xf9//2, 3)   # D2
        self._bus.i2c_rdwr(w, r)   # D3
        print(list(r)[0],list(r)[1],list(r)[2])

では、プログラムを実行しておきましょう!

(env) pi@Donkey-Miho:~/miho/blog $ python fram_main_DeviceID.py
 HELLO FRAM
-----------------
- DeviceID -
0 165 16
DeviceID FINISH
---framEND---

波形はこれ ↓↓
f:id:MihoN:20210209202822p:plain
f:id:MihoN:20210209202834p:plain:w500

smbus2 を使った FRAM MB85RC256V の データシートのコマンドを全部実行できました!
API の仕様がうまく分ってなくても ^^; 波形を見るとこうなってるから、こう設定しよう!とか、いったい何がどうなって、どうなってるのかわかります ^^#
お手軽ロジアナで十分波形を見れました!
次は、SPI の FRAM の 波形を見てみたいなと思います ^^#

はじめての F (⋈◍>◡<◍)。✧♡ ~ Pythonプログラム編② の壱~

はじめての F (⋈◍>◡<◍)。✧♡ ~ RasPi編②の壱 ~

さてっ.
RasPi編① では サンプルプログラムを実行して、FRAMメモリの読み書きができてそう、ってところまで確認しました。

でも、なんとなく不安です。。。本当にコマンドはちゃんと実行されているのだろうか。。。
不安なら安心しましょう!そう!波形を見ればいいんです!!

波形を見るにはおうちにあった LabTool を使います。

ではさっそく ^^# っと、その前に
I2C について一緒に簡単に勉強しておきましょう♪

今回LobToolにつながれるFRAMはI2Cインターフェースを持つFRAMデバイスです。


■ なになに? I2C

I2C は Philips社(現在のNXP社)によって開発されたシンプルなシリアルバスです。
I2C は FRAMとMCU 間をシンプルにつなぎ、シリアル通信を提供します。
I2C は マスターがスレーブデバイスとの通信を開始する同期式プロトコルです。
その、I2Cプロトコルはデータ転送速度(クロック周波数)であるクロックをマスターが出す、マスター/スレーブ通信です。

Master                       Slave
MCU      ←   Data  → FRAM
            -- Clock →

双方向バスなので、マスターはスレーブへの書き込みと、スレーブからの読み取りが可能です。
また、その双方向のシリアルバスは、シリアルクロック(SCL)とシリアルデータ(SDA)の2つです。

I2Cバス:
・必要なバスラインは2本だけ!シリアル・データライン(SDA)とシリアル・クロックライン(SCL)
・バスに接続されている各デバイスを固有のアドレスで指定できる!
・通信は常にシンプルな、マスタ/スレーブ!
・複数のマスタが同時にデータ転送を開始した場合のデータの破損を防止する、衝突検出と調停機能を備える!
・ I2CではSCLの立ち上がりエッジ時にデータが読み込まれる!また、SDAの出力が遷移するのはSCLの立ち下がりエッジ時!

 
■ MB85RC256V I2C FRAM で確認してみよう!

以下は、同じI2Cバスに3つのFRAMを接続した例(マスタ1個、スレーブ(FRAM)3個)です。
f:id:MihoN:20200801224715p:plain
f:id:MihoN:20201112150159p:plain
プルアップ抵抗は I2C FRAM が正しく通信するために必要です。これは、I2Cプロトコルが、SCLおよびSDAバスラインがオープンドレインまたはオープンコレクタであることを前提としているためです。


■ I2C通信の波形からI2C通信を理解する

LabTool を使って波形を見てみます。
f:id:MihoN:20201127185227j:plain:w300

まず、LabTool を パソコンに接続し、LabToolの画面を立ち上げます。
立ち上がったら
” Sample Rate を 50MHz ” にし、” Add Signal ” を行います。設定は以下の図を参考に。
f:id:MihoN:20201127192656p:plain:w400

OK押下で以下の画面が出てきます。
SCL が D0 ってのと、 SDA が D1 ってのを覚えてOK押下。
f:id:MihoN:20201127192919p:plain:w200

最後に、D0 と D1 の トリガは立下りにします。
団子みたいな絵の Continuous capture を有効にします。
なお、D0 D1 I2C ってやつの順番は上下入れ替えできます。
掴んで動かしてみて ^^
f:id:MihoN:20201127193752p:plain:w200

次は、LabTool と FRAM を接続します。
前回の『はじめての F (⋈◍>◡<◍)。✧♡ ~ RasPi編① ~』を参考に、SCL、SDA、GNDの足を確認してね。
こんな感じ。
f:id:MihoN:20201127194428p:plain:w400
f:id:MihoN:20201127194444j:plain:w300

前回の『はじめての F (⋈◍>◡<◍)。✧♡ ~ RasPi編① ~』のプログラムを確認します!
分かりやすくするために、

RasPi編① で紹介したFRAMサンプルプログラム の fram_main.py の一部を少し変えてみます。
value = x +100 ※100を足しておきます 特に意味はないです ^^;
繰り返し文は 2回繰り返しにします。
あと、プログラムをシンプルに、print文も削除します。

FRAMサンプルプログラム!
【fram_main1.py】

import sys
from i2c_fram1 import *

if __name__ == '__main__':

    print(" HELLO FRAM ")
    print("----------------- ")
    fram = SDL_I2CFRAM(addr = 0x50)
    for x in range(0,2):
        value = x + 100
        fram.write8(x,value)
    print("---------")
    for x in range(0,2):
        fram.read8(x)  
    print("---framEND---")

【i2c_fram1.py】

import smbus2
import sys
from decimal import *

class SDL_I2CFRAM():

    def __init__(self, twi=1, addr=0x50):
        self._bus = smbus2.SMBus(twi)
        self._addr = addr

    def write8(self, address, data):
        print("addr =0x%x address = 0x%x data = 0x%x  " % (self._addr, address, data))
        self._bus.write_i2c_block_data(self._addr,address>>8,[address%256, data])     # w1

    def read8(self, address):
        self._bus.write_i2c_block_data(self._addr,address>>8,[address%256])              # r1
        returndata = self._bus.read_byte(self._addr)                                                      # r2
        print("addr = 0x%x address = 0x%x %i returndata = 0x%x " 
                 % (self._addr, address, address, returndata))
        return returndata

では、プログラムを実行しておきましょう!

(env) pi@Donkey-Miho:~/miho/blog $ python3 fram_main1.py
 HELLO FRAM
-----------------
addr =0x50 address = 0x0 data = 0x64
addr =0x50 address = 0x1 data = 0x65
---------
addr = 0x50 address = 0x0 0 returndata = 0x64
addr = 0x50 address = 0x1 1 returndata = 0x65
---framEND---

そして、そう!LabTool をみて!
波形がみえます。右にスクロールすれば5つ分の波形が見えてきます。
FRAMメモリへのデータ書き込みの様子が波形で確認できました!

f:id:MihoN:20210115205402p:plain

最初の波形を取り上げて

f:id:MihoN:20210115205504p:plain

波形について少し見てみましょう!
波形のアタマは...

f:id:MihoN:20210221214103p:plain

続きからオシリは...

f:id:MihoN:20210221214122p:plain

データシートの説明とも重ねてみましょう。

f:id:MihoN:20210213165645p:plain

データシートの Byte Write コマンドだ!

Byte Writeコマンドは、I2Cfram1.py の #w1 の1文が実行されたときの波形になります。
実行結果を載せときます これ ↓↓
■ Byte Writeコマンド
f:id:MihoN:20210209174931p:plain

つづけて # r1 , # r2 が実行されたときの波形をみてみましょう。
実行結果を載せときます これ ↓↓
Random Readコマンド
f:id:MihoN:20210209194704p:plain

調子にのってきたので、smbus2 を使って、データシートの コマンドを実行させてみよう!(次回 RasPi編②の弐 に続く)

とりあえず、これをやって分かったこと!
「ちゃんとコマンド実行されてるのかなぁ...」と思う時には、こうやって波形を見たらいいんですね!
My オシロを持ってたり、「波形!波形!」と言って、なにかあるとすぐに波形を見る方たちの気持ちが、ちょっとわかった瞬間でした(笑)

波形は信号の『素顔』💛

はじめての F (⋈◍>◡<◍)。✧♡ ~ Pythonプログラム編① ~

はじめての F (⋈◍>◡<◍)。✧♡ ~ RasPi編① ~

さ.
今回は 2019年の Donkey Car / AI Car に FRAM を載せたいと思います ^^#
ただ...使い道はこれから ^^; でも ゆくゆく Donkey Car / AI Car の中で使っていきたいので、Python3 で動くこと!
そして、今回はちゃんとコマンドが送れてるのかなど、LabTool を使って波形を見ようと思います。

ではさっそく
2017年 の はじめての F (⋈◍>◡<◍)。✧♡ ~ ハードウェア編 ~
http://miho-diary.hatenablog.com/entry/2017/05/08/120918
を参考に、SOP8 FRAM Device(今回は I2C FRAM) をユニバーサル基板(RasPi Zero ユニバーサル基板)に載せましょう♪

準備!

■ 用意するものっ

(A)
・SOP8 DIP 変換基板 金フラッシュ(9枚入り)

http://akizukidenshi.com/catalog/g/gP-05154/

・連結ソケット(両端オスピン)8P

http://akizukidenshi.com/catalog/g/gP-00264/

・FRAM(今回は MB85RC256V)

https://www.chip1stop.com/view/searchResult/SearchResultTop?keyword=MB85RC256V&partSameFlg=false


(B)
・丸ピンICソケット(8P)

http://akizukidenshi.com/catalog/g/gP-00035/

・RaspberryPi Zero 用ユニバーサル基板

http://akizukidenshi.com/catalog/g/gP-14031/


(C)
※ 次回②で使うことになりそうです
・LabTool

https://www.embeddedartists.com/products/labtool/

・LabTool専用エンクロージャ:なくてもいいよ

https://shop.emergeplus.jp/labtool/



(A) は
『はじめての F (⋈◍>◡<◍)。✧♡ ~ ハードウェア編 ~』を参考に、FRAMをユニバーサル基板で使えるようにしよう!

f:id:MihoN:20200726150136p:plain

【完成図:変換基板に搭載されたFRAM】

(B) では、
(A) でできたFRAMを RaspberryPi Zero用ユニバーサル基板に載せていきます。そのまま、Zero基板にハンダしてもいいんですが、せっかくなので、抜き差しでFRAMを取替っこ出来るようにしましょう!
ということで、丸ピンソケットIC を Zero基板にハンダづけすることにします!

f:id:MihoN:20200726151423p:plain

【完成図:Zero基板にFRAM搭載】


完成図は RasPi に Zero基板を搭載してしまってますが、搭載する前に、FRAMの配線を行わなければいけません。今回は I2C のFRAMです。
接続するピンは4つ。ピンの足に色付きの丸印がついているピンが対象です。

f:id:MihoN:20200726153820p:plain

【図:FRAMだと、どのピンが対象なの?】


でも、今回FRAMは変換基板に載せているので、変換基板のピン/足が対象です。

f:id:MihoN:20200726160044p:plain

【図:変換基板だと、どのピンが対象なの?】


変換基板の ピン/足 につけた色付きの丸印の色と、RasPiピン配 につけた色付きの丸印の色をつなぐように配線しよう!
配線が終わったら、Zero基板はRasPiの40ピンにぶすっと挿しておきます。

補足:
端子 A0~A2 について、今回は GND につないでも、つながなくても大丈夫だよ。

以下、データシートの一部抜粋。

f:id:MihoN:20200801224715p:plain

【図:端子機能説明 データシートの一部抜粋】


FRAMは認識されるかな?RasPiに電源を入れましょう!
ターミナルソフトで接続し、i2cdetectコマンドで I2Cバス一覧 および それらのアドレスを確認します。

FRAMがいないとき

(env) pi@Donkey-Miho:~ $ sudo i2cdetect -y 1

0 1 2 3 4 5 6 7 8 9 a b c d e f

00: -- -- -- -- -- -- -- -- -- -- -- -- --

10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

70: 70 -- -- -- -- -- -- --

FRAMがいるとき

(env) pi@Donkey-Miho:~ $ sudo i2cdetect -y 1

0 1 2 3 4 5 6 7 8 9 a b c d e f

00: -- -- -- -- -- -- -- -- -- -- -- -- --

10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

70: 70 -- -- -- -- -- -- --

FRAMは 0x50 に違いない!
じゃFRAMメモリへのデータ書き込み、読み出しを試してみよう!
今回は smbus2 を使ってみます。
https://pypi.org/project/smbus2/

別途インストールが必要です。インストールしましょう!

$ pip install smbus2


サンプルプログラムはここのサイトのソースを参考にさせていただきます。
https://www.raspberrypi.org/forums/viewtopic.php?t=209937

https://github.com/switchdoclabs/SDL_Pi_FRAM

FRAMサンプルプログラム!
【fram_main.py】

#!/usr/bin/env python3

import sys
from I2Cfram import *


if __name__ == '__main__':

    print(" HELLO FRAM ")
    print("----------------- ")
    fram = SDL_I2CFRAM(addr = 0x50)
    for x in range(0,5):
        value = x
        print("address = %i writing value = %i" %(x,value))
        fram.write8(x,value)
    print("---------")
    print("reading first 10 address")
    for x in range(0,5):
        print("address = %i value = %i" %(x,fram.read8(x)))
    print("---framEND---")

【I2Cfram.py】

#!/usr/bin/env python3

import smbus2
import sys
from decimal import *

class SDL_I2CFRAM():

    def __init__(self, twi=1, addr=0x50):
        self._bus = smbus2.SMBus(twi)
        self._addr = addr

    def write8(self, address, data):
        print("addr =0x%x address = 0x%x data = 0x%x  " % (self._addr, address, data))
        self._bus.write_i2c_block_data(self._addr,address>>8,[address%256, data])

    def read8(self, address):
        self._bus.write_i2c_block_data(self._addr,address>>8,[address%256])
        returndata = self._bus.read_byte(self._addr)
        print("addr = 0x%x address = 0x%x %i returndata = 0x%x " % (self._addr, address, address, returndata))
        return returndata

    def readB(self, adr):
        b = self._bus.read_byte_data(self._addr) 
        return b

【実行結果】
f:id:MihoN:20200728190316p:plain

今回書けなかったので、次回はちゃんとコマンドが送れてるのかなど、LabTool を使って波形を見ようと思います。