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

2020年10月2日金曜日

meishi2 の QMK ファームウェアのビルドをラズパイのコマンドラインでやってみた

名刺サイズ自作キーボード meishi2 を組み立てた後そのままにしていたので、引っ張り出してきて QMK ファームウェアをビルドして書き込んでみました。ラズパイのコマンドラインでやっています。ほぼ「 meishi2 keyboard ビルドガイド」に記載されていることをそのままやっています。

環境

QMK ファームウェアをビルドする母艦はラズパイを使いました。

  • Raspberry Pi 4B Model B 4GB Memory
  • Raspberry Pi OS Version: August 2020 (Raspbian GNU/Linux 10 buster)

QMK ファームウェアのビルド環境を構築

QMK ソースコードをダウンロード

$ git clone https://github.com/qmk/qmk_firmware.git

QMK ビルドに必要な依存を解決

$ cd qmk_firmware/
util/qmk_install.sh
  • 主に QMK ビルドに必要な Raspberry Pi OS の deb パッケージがインストールされるようです。

meishi2 をラズパイに接続

ログを見ながら meishi2 をラズパイに接続してみるのでまずはシスログをリアルタイムで確認

$ tail -f /var/log/syslog

meishi2 とラズパイを USB ケーブルで接続すると LED が点灯し、ログには以下のメッセージやその他いろいろ出てきました。

Sep 25 12:25:43 raspi4 kernel: [  409.663764] usb 1-1.1: Product: meishi2

QMK をビルドして meishi2 に書き込み

とりあえずやってみたらエラーになりました。

$ make meishi2:default:avrdude
QMK Firmware 0.10.17
WARNING: Some git submodules are out of date or modified.
 Please consider running make git-submodule.

Making meishi2 with keymap default and target avrdude

tmk_core/protocol/lufa.mk:14: lib/lufa/LUFA/makefile: No such file or directory
make[1]: *** No rule to make target 'lib/lufa/LUFA/makefile'.  Stop.
Make finished with errors
make: *** [Makefile:584: meishi2:default:avrdude] Error 1

メッセージに従い以下実施

$ make git-submodule

再度以下実行したらうまくいきました。

$ make meishi2:default:avrdude

途中で以下のメッセージが出ました。

Detecting USB port, reset your controller now

meishi2 基板上の pro micro の横のタクトスイッチ (シルク印刷で SW5 と記載) を押すと meishi2 のリセットがかかり書き込みが完了しました。この時にラズパイ上で meishi2 と接続されている USB デバイスファイルが /dev/ttyACM0 であると自動認識したようです。

meishi2 の pro micro の LDE は緑 x 1、赤 x 2 が点灯している状態になったので USB ケーブルの切断/再接続をしたところ緑 x 1 のみの点灯状態となりました。

これで meishi2 が使えるようになったようです。

動作確認

meishi2 には 4つのキーがあり、今回の QMK の初期設定で左から順番に以下の内容が設定されていました。

  • 左 CTRL + Z (やり直し)
  • 左 CTRL + X (切り取り)
  • 左 CTRL + C (コピー)
  • 左 CTRL + V (貼り付け)

meishi2 を PC と USB ケーブルで接続するとうまくキーボードとして認識されたようで、エディタ上で上記 4ボタンが期待通りに動きました。

参考

2020年6月19日金曜日

ラズパイで PlatformIO でコマンドラインで M5StickC を Lチカ

ラズパイのコマンドラインで PlatformIO を使って M5StickC を Lチカしてみました。


環境

  • Raspberry Pi 4 model B
  • Raspbian GNU/Linux 10 (buster)
  • M5StickC

pipenv プロジェクト作成

pipenv プロジェクトのディレクトリを作成して移動

$ mkdir /some/where/m5stickc-lflash
$ cd /some/where/m5stickc-lflash/

pipenv プロジェクト作成

$ pipenv --python $(which python3)

pipenv shell 起動

$ pipenv shell

以下、全て pipenv シェルで実行


Platformio インストール

インストール

$ pipenv install platformio

バージョン確認

$ platformio --version
PlatformIO, version 4.3.4

M5StickC のボード ID を確認

PlatformIO での M5StickC のボード ID を確認しました。

$ platformio boards
--- 省略 ---
Platform: espressif32
================================================================================
ID                               MCU    Frequency    Flash    RAM     Name
-------------------------------  -----  -----------  -------  ------  --------------------------------
--- 省略 ---
m5stack-core-esp32               ESP32  240MHz       4MB      320KB   M5Stack Core ESP32
m5stack-fire                     ESP32  240MHz       16MB     6.25MB  M5Stack FIRE
m5stack-grey                     ESP32  240MHz       16MB     520KB   M5Stack GREY ESP32
m5stick-c                        ESP32  240MHz       4MB      320KB   M5Stick-C
--- 省略 ---

ボード ID は m5stick-c でよさそうです。


PlatformIO プロジェクト作成

プロジェクトのディレクトリを作成して移動

$ mkdir pio_project
$ cd pio_project/

プロジェクト初期化

$ platformio init --board=m5stick-c
  • 上で調べてた M5StickC のボード ID を指定しました。

シリアルポートデバイスを確認

M5StickC を USB 接続したラズパイのシリアルポートデバイスを確認しました。

M5StickC をラズパイの USB に接続する時の /var/log/messages で確認することもできますが、PlatformIO をインストールしたのでこれで確認してみました。

M5StickC をラズパイの USB に接続している状態で以下のコマンドを打ちました。

$ platformio device list
/dev/ttyUSB0
------------
Hardware ID: USB VID:PID=0403:6001 SER=7552CE3E93 LOCATION=1-1.3
Description: M5 Serial Converter

/dev/ttyAMA0
------------
Hardware ID: fe201000.serial
Description: ttyAMA0

/dev/ttyUSB0 で良いようです。


Lチカプログラムを用意

led-flash.ino ファイルを src/ に置きました。

$ cat src/led-flash.ino

#define LED_PIN 10

#define LED_ON  LOW
#define LED_OFF HIGH


void setup() {
    pinMode(LED_PIN, OUTPUT);
}

void loop() {
    digitalWrite(LED_PIN, LED_ON);
    delay(100);

    digitalWrite(LED_PIN, LED_OFF);
    delay(900);
}
  • M5StickC の LED は LOW が ON、HIGH が OFF とのことです。

プログラムをビルド

以下のコマンドでビルド

$ platformio run

エラー無くビルドできました。ターゲットに upload を指定していないのでビルドされただけで M5SticC には書き込まれていません。

.pio/ 配下にビルドされたファイルが出来ていました。

$ ls -la .pio/build/m5stick-c/
合計 28712
drwxr-xr-x 4 pi pi     4096  6月 19 21:38 .
drwxr-xr-x 3 pi pi     4096  6月 19 21:32 ..
-rw-r--r-- 1 pi pi   149000  6月 19 21:38 .sconsign37.db.dblite
drwxr-xr-x 3 pi pi     4096  6月 19 21:32 FrameworkArduino
-rw-r--r-- 1 pi pi   211040  6月 19 21:32 firmware.bin
-rwxr-xr-x 1 pi pi  4265992  6月 19 21:32 firmware.elf
-rw-r--r-- 1 pi pi 24743628  6月 19 21:32 libFrameworkArduino.a
-rw-r--r-- 1 pi pi        8  6月 19 21:32 libFrameworkArduinoVariant.a
-rw-r--r-- 1 pi pi     3072  6月 19 21:32 partitions.bin
drwxr-xr-x 2 pi pi     4096  6月 19 21:38 src

再度ビルドして M5StickC に書き込み

$ platformio run --upload-port /dev/ttyUSB0 --target upload
  • 上で確認したシリアルポートデバイスを指定しました。
  • --target upload によりビルド後 M5StickC に書き込まれました。

M5StickC で Lチカできました。


参考

ラズパイで esptool でコマンドラインで M5Stick のフラッシュをバックアップ&リストア

ラズパイのコマンドラインで esptool を使って M5StickC のフラッシュをバックアップ、リストアしてみました。

ほぼ https://lang-ship.com/blog/work/esp32-esptool-py/ に書かれていることをそのままやっています。

環境

  • Raspberry Pi 4 model B
  • Raspbian GNU/Linux 10 (buster)
  • M5StickC

M5StickC を接続したラズパイのシリアルポートデバイスを確認

ラズパイで $ tail -f /var/log/messages をしながら M5StickC に付属の USB ケーブルでラズパイの USB に接続すると以下のメッセージが出ました。

Jun 18 23:33:44 raspi4 kernel: [19742.992308] usb 1-1.2: FTDI USB Serial Device converter now attached to ttyUSB0

ttyUSB0 と出ているのでシリアルポートデバイスは /dev/ttyUSB0 であることがわかりました。

デバイスファイルも存在していました。

$ ls -l /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 0  6月 18 23:33 /dev/ttyUSB0

pipenv プロジェクト作成

pipenv インストール

$ sudo apt install pipenv

pipenv プロジェクト用のディレクトリを作成して移動

$ mkdir /some/where/m5stickc
$ cd /some/where/m5stickc/

pipenv プロジェクト作成

$ pipenv --python $(which python3)

pipenv shell 起動

$ pipenv shell

以下、全て pipenv シェルで実行

M5StcikC のフラッシュをバックアップ

esptool をインストール

$ pipenv install esptool

esptool.py --help で確認すると出てくる flash_id : Read SPI flash manufacturer and device ID を実行。シリアルポートは上で確認した /dev/ttyUSB0 を指定しました。

$ esptool.py --port /dev/ttyUSB0 flash_id
esptool.py v2.8
Serial port /dev/ttyUSB0
Connecting......
Detecting chip type... ESP32
Chip is ESP32-PICO-D4 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, Embedded Flash, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
--- 省略 ---
Manufacturer: c8
Device: 4016
Detected flash size: 4MB
Hard resetting via RTS pin...

いろいろ情報が表示され、フラッシュのサイズが 4MB であることがわかりました。

フラッシュをバックアップ

$ esptool.py --port /dev/ttyUSB0 read_flash 0x00000 0x400000 ./image-factory-default-4M.bin
  • 先頭アドレス 0x00000 から上で確認したフラッシュのサイズ 0x400000 (10進数で ‭4,194,304‬) バイトを読み出して指定したファイルに保存しました。

保存したファイルのサイズはフラッシュのサイズと同じ 4MB でした。

$ ls -lh image-factory-default-4M.bin
-rw-r--r-- 1 pi pi 4.0M  6月 17 23:18 image-factory-default-4M.bin

バックアップしたフラッシュをベリファイ

$ esptool.py --port /dev/ttyUSB0 verify_flash --diff yes 0x0000 ./image-factory-default-4M.bin
--- 省略 ---
Auto-detected Flash size: 4MB
Verifying 0x400000 (4194304) bytes @ 0x00000000 in flash against ./image-factory-default-4M.bin...
-- verify FAILED: 279 differences, first @ 0x0000b02b
   0000b02b 00 a8
   0000b02c 00 aa
   0000b02d a0 fa
   --- 省略 ---
   0000b81b 00 ff
   0000b81c 01 ff
   0000b81d 00 ff

A fatal error occurred: Verify failed.

ベリファイがエラーになりました。。。

「起動するたびにデータを書き換えているプログラムが存在しており、その場合にはベリファイチェックがNG」とのことで、工場出荷時のフラッシュだったのですがこれに該当しているのかもしれません。

フラッシュをリストア

ベリファイはエラーになりましたが、このバックアップからリストアしてみました。

まずはフラッシュを消去

$ esptool.py --port /dev/ttyUSB0 erase_flash

バックアップしたフラッシュをリストア

$ esptool.py --port /dev/ttyUSB0 write_flash 0x0000 ./image-factory-default-4M.bin
  • 先頭アドレス 0x0000 を指定すると良いようです

うまくリストアできていました。

2020年5月14日木曜日

Grafana で Raspberry Pi の CPU、GPU 温度をグラフ表示



前回のブログ [Grafana で Raspberry Pi のメモリ使用率などリソース状態を可視化してみた] で CPU 使用率やメモリ使用率等のリソースを Grafana のダッシュボードで確認できるようにしましたが、下のキャプチャ画面のように CPU と GPU 温度に関しては現在の状態 (温度) の確認はできますが、過去の状態をグラフで確認することはできないようです。

CPU、GPU の現在の温度

今回は Grafana にダッシュボードを追加して、Raspberry Pi の CPU、GPU 温度のグラフを表示してみました。

環境

InfluxDB に保存されている CPU、GPU の温度データを確認

InfluxDB に保存されている CPU 温度のデータは実際の温度を 1,000倍した値が保存されており、GPU 温度はそのままの値が保存されているので確認してみました。

InfluxDB shell 起動

$ influx

telegraf データベースを指定

> use telegraf

CPU 温度データを確認

> select * from cpu_temperature limit 3
name: cpu_temperature
time                host  value
----                ----  -----
1587525500000000000 raspi 50464
1587525510000000000 raspi 50464
1587525520000000000 raspi 50464

CPU 温度は 50464 という値になっていますが、これは Telegraf で CPU データを取得するときに /sys/class/thermal/thermal_zone0/temp を参照しているためと思われます。実際は値を 1000 で割った 50.464度ですね。

ちなみに手動だと以下のように現時点の値を確認できました。

$ cat /sys/class/thermal/thermal_zone0/temp
54230

GPU 温度は以下のように、実際の温度が値として保存されていました。

> select * from gpu_temperature limit 3
name: gpu_temperature
time                host  value
----                ----  -----
1587525501000000000 raspi 50.5
1587525510000000000 raspi 49.9
1587525520000000000 raspi 50.5

CUP 温度とは異なり GPU 温度は以下のコマンドで取得しているためだと思われます。

$ /opt/vc/bin/vcgencmd measure_temp
temp=53.7'C

ダッシュボード追加

ブラウザで Grafana の GUI を開いて以下実行しました。

  • [Create (+ アイコン)] - [Dashboard]

  • CPU 温度を追加するために [Add Query] をクリック

  • 以下、Query のフォームで

    • [From] の [select measurement] をクリックして [cpu_temperature] を選択
    • [Select] の [field (value)]、[mean ()] に続く [+] をクリックして [Math] - [math] を選択
      • [math (/100)] が追加されたので [(/100)] をクリックして [(/1000)] に変更 (上で確認した通り、IfluxDB 上では 1,000倍された値なので 1,000 で割りました)
  • 画面右側の方の [Query Inspector] をクリックしてクエリを確認すると select 文でも / 1000 されていることが確認できました。

    SELECT mean("value") / 1000 FROM "cpu_temperature" WHERE time >= now() - 6h GROUP BY time(20s) fill(null)
    
  • 次に GPU 温度を追加するために [Add Query] をクリック

  • 追加された Query のフォームで

    • [From] の [select measurement] をクリックして [cpu_temperature] を選択
    • CPU 温度とは異なり、GPU 温度は InfluxDB に実温度が保存されている (1,000倍されていない) ので 1,000 で割る必要はありません
  • 画面上部のフロッピーアイコンの [Save dashboard] をクリックし、適宜ダッシュボード名等を入れて保存

CPU、GPU 温度のグラフを表示できました。

2020年4月24日金曜日

Grafana で Raspberry Pi のメモリ使用率などリソース状態を可視化してみた



Grafana Labs でラズパイ用の Grafana ダッシュボード Raspberry Pi Monitoring が公開されているので試してみました。
CPU 使用率やメモリ使用率等だけでなく、CPU や GPU の温度も確認できるようです。

Raspbian の標準リポジトリから Grafana をインストールするとログイン画面が真っ白で何も表示されなかったので、Grafana サイトのリポジトリからインストールしました。
なお、Raspberry Pi Monitoring はデータソースに InfluxDB、メトリックスコレクタに Telegraf を使うことが前提のようなのでこれらもインストールしました。

環境

  • Raspberry Pi 3 Model B
  • Raspbian GNU/Linux 10 (buster)

Ansible インストール

Ansible の playBook で Grafana, InfluxDB, Telegraf をインストールしてみるので、まずは Ansible をインストールしました。

$ sudo apt install ansible

Ansible playbook ファイル作成

pbook-grafana.yaml を作成

- hosts: localhost
  vars:
    distrib_id: debian
    distrib_codename: buster
  connection: local
  gather_facts: no
  become: true
  handlers:
    - name: telegraf-restarted
      service:
        name: telegraf
        state: restarted
  tasks:
    # influxdb, telegraf 共通
    - name: influxdb, telegraf apt_key
      apt_key:
        url: https://repos.influxdata.com/influxdb.key
        state: present
    - name: influxdb, telegraf apt_repository
      apt_repository:
        repo: deb https://repos.influxdata.com/{{ distrib_id }} {{ distrib_codename }} stable
        state: present
        filename: influxdb
    - name: influxdb, telegraf apt update
      apt:
        update_cache: yes

    # influxdb
    - name: apt install influxdb
      apt:
        update_cache: no
        state: present
        pkg:
          - influxdb
    - name: service influxdb start
      service:
        name: influxdb
        state: started

    # telegraf
    - name: apt install telegraf
      apt:
        update_cache: no
        state: present
        pkg:
          - telegraf
    - name: service telegraf start
      service:
        name: telegraf
        state: started
    - name: telegraf user
      user:
        # GPU 温度取得 (vcgencmd measure_temp) のために必要
        name: telegraf
        groups: video
    - name: telegraf blockinfile
      blockinfile:
        dest: /etc/telegraf/telegraf.d/raspi.conf
        create: yes
        block: |
          [[inputs.net]]

          [[inputs.netstat]]

          [[inputs.file]]
            files = ["/sys/class/thermal/thermal_zone0/temp"]
            name_override = "cpu_temperature"
            data_format = "value"
            data_type = "integer"

          [[inputs.exec]]
            commands = ["/opt/vc/bin/vcgencmd measure_temp"]
            name_override = "gpu_temperature"
            data_format = "grok"
            grok_patterns = ["%{NUMBER:value:float}"]
      notify:
        telegraf-restarted

    # grafana
    - name: grafana apt_key
      apt_key:
        url: https://packages.grafana.com/gpg.key
        state: present
    - name: grafana apt_repository
      apt_repository:
        repo: deb https://packages.grafana.com/oss/deb stable main
        state: present
        filename: grafana
    - name: grafana apt update
      apt:
        update_cache: yes
    - name: apt install grafana
      apt:
        update_cache: no
        state: present
        pkg:
          - grafana
    - name: service grafana-server start
      service:
        name: grafana-server
        state: started
    - name: grafana systemd
      systemd:
        name: grafana-server.service
        state: started
        enabled: yes

Ansible でインストール

$ ansible-playbook -i localhost, pbook-grafana.yaml

インストール後の InfluxDB データベース確認

InfluxDB shell 起動

$ influx
Connected to http://localhost:8086 version 1.8.0
InfluxDB shell version: 1.8.0
>

データベース確認

> show databases
name: databases
name
----
_internal
telegraf
  • telegraf データベースが作成されていました。

telegraf データベースを選択

> use telegraf
Using database telegraf

telegraf データベースの measurements を確認

> show measurements
name: measurements
name
----
cpu
cpu_temperature
disk
diskio
gpu_temperature
kernel
mem
net
netstat
processes
swap
system

試しに gpu_temperature のデータを確認

> select * from gpu_temperature limit 3;
name: gpu_temperature
time                host  value
----                ----  -----
1587525501000000000 raspi 50.5
1587525510000000000 raspi 49.9
1587525520000000000 raspi 50.5
  • 取得した GPU の温度が格納されているようです。

InfluxDB shell 終了

> quit

ブラウザでアクセスできるようになるまで待つ

ansible を実行すると grafana-server の起動まで完了しますが、初めて起動する時はしばらく (5分程度) は 3000番ポートが開かれていないためブラウザでアクセスできません

3000番ポートが開かれている場合

$ netstat -na | grep 3000
tcp6       0      0 :::3000                 :::*                    LISTEN

3000番ポートが開かれていない場合

$ netstat -na | grep 3000
$

3000番ポートが開かれていない場合でもログが流れているので起動していることがわかります。

$ sudo tail -f /var/log/grafana/grafana.log

3000番ポートが開かれるのを待って次に進みます。

ブラウザで Grafana にログイン

  • URL: http://[grafana-server の IP]:3000/login
  • 初期ログイン情報
    • ID: admin
    • PW: admin
  • 案内に従いパスワード変更

データソースに InfluxDB を登録

  • [Confuguration (歯車アイコン)] - [Data Sources]
  • [Add data source]
  • influxDB を選択
  • Name: InfluxDB (任意)
  • Name の [Default] を ON
  • url: http://localhost:8086/
  • Access: Server (dfault)
  • Whitelisted Cookies: (空)
  • Auth は全てデフォルト通り無効
  • Database: telegraf
  • User, Password, HTTP Method は空白
  • Min time interval も空白
  • [Save & Test]
    • Data source is working と表示された

Raspberry Pi Monitoring ダッシュボートを Import

ダッシュボード ID (今回は 10578) を指定するとインポートできるようですが、今回の環境ではなぜかうまくいかなかったので、サイトから json ファイルをダウンロードしてインポートやってます。

ダッシュボードの JSON ファイル取得

ダッシュボードを登録

  • [Create (+ アイコン)] - [Import]
  • [Upload .json file] で上でダウンロードした raspberry-pi-monitoring_rev1.json をアップロード
  • 以下入力
    • Name: Raspberry Pi Monitoring (多分任意)
    • Folder: General
    • Unique identifier (uid): value set (初期値)
    • influxdb: InfluxDB
    • [Import]

ダッシュボードで Raspberry Pi のリソースを見ることができるようになりました。

grafana-dboard

参考

2019年7月8日月曜日

OctoPrint の API で Python で 3D プリンターの位置情報を取得

はじめに

OctoPrint の API を使って Python で 3D プリンターの現在位置を取得したいのですが、素直には取得できませんでした。

現在位置を取得する G-code M114 を OctoPrint の API から 3D プリンターの Marlin ファームウェアに送っても結果は API には返ってこず、OctoPrint の Terminal に以下のような位置情報が表示されるだけでした。

Recv: X:-10.00 Y:-15.00 Z:0.00 E:0.00 Count X:-1000 Y:-1500 Z:0

そこで、OctoPrint の PositionUpdate イベントを使って OctoPrint が M114 の結果を受け取った時に位置情報をファイルに書き出すようにしてみました。

環境

  • Raspberry Pi 3 model B
  • Raspbian GNU/Linux 9.4 (stretch)
  • Python 3.5.3
  • OctoPrint 1.3.9
  • 3D プリンター Alunar M508
  • Marlin 1.1.1

現在位置をファイルに書き出すスクリプト準備

以下の内容の /some/where/get-3dp-pos.py を設置しました。

#!/usr/bin/env python3

import argparse
import json

POS_FILE = '/tmp/3dp-pos'

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--now'  , type=str)
    parser.add_argument('--data' , type=str)
    parser.add_argument('-x'     , type=str)
    parser.add_argument('-y'     , type=str)
    parser.add_argument('-z'     , type=str)
    parser.add_argument('-e'     , type=str)
    parser.add_argument('-t'     , type=str)
    parser.add_argument('-f'     , type=str)
    args = parser.parse_args()

    with open(POS_FILE, 'w') as f:
        f.write('{}\n'.format(json.dumps(vars(args), sort_keys=True, indent=4)))

if __name__ == '__main__':
    main()

ファイルに実行権限を付けました。

$ sudo chmod +x /some/where/get-3dp-pos.py

OctPrint にイベントを登録

OctoPrint の設定ファイル config.yaml に PositionUpdate イベントを登録しました。

$ diff -U 0 config.yaml{.org,}
--- config.yaml.org     2019-07-08 17:33:42.532568347 +0900
+++ config.yaml 2019-07-08 17:33:42.512568302 +0900
@@ -58,0 +59,7 @@
+events:
+  enabled: true
+  subscriptions:
+  - event: PositionUpdate
+    command: /some/where/get-3dp-pos.py --now '{__now}' --data '{__data}' -x {x} -y {y} -z {z} -e {e} -t {t} -f {f}
+    type: system
+

動作確認

config.yaml を変更したので、まずは OctoPrint を再起動しました。

位置情報を取得する G-code M114 を 3D プリンターに送ると以下のようにファイルに位置情報が書き込まれました。

$ cat /tmp/3dp-pos
{
    "data": "{reason: None, e: 0.0, t: 0, f: 200.0, y: 45.0, x: 30.0, z: 0.0}",
    "e": "0.0",
    "f": "200.0",
    "now": "2019-07-08T19:26:16.670214",
    "t": "0",
    "x": "30.0",
    "y": "45.0",
    "z": "0.0"
}

なお、ヘッドが移動中に M114 を送った場合は OctoPrint のターミナルに

Recv: echo:busy: processing

と表示され、ヘッドの移動が完了した時に位置情報がファイルに書き込まれました。

2019年6月16日日曜日

Raspberry Pi の GPIO で 3DTouch を直接操作

3DTouch

3DTouch

はじめに

3D Touch は 3D プリンターのオートレベリング用タッチセンサーで、通常は 3D プリンターの制御基板に直接接続して使用します。

しかし、今回は Raspberry Pi の GPIO に 3D Touch を接続して Python スクリプトから PWM で 3D Touch を制御してみました。

環境

  • Raspberry Pi 3 model B
  • Raspbian GNU/Linux 9.4 (stretch)
  • Python 3.5.3

ケーブル配線の確認

3DTouch からはサーボ用と思われるケーブルが 3本とスイッチ用と思われるケーブルが 2本の合計 5本出ています。

それぞれのケーブルの配線は [ Geeetech 3DTouch auto bed leveling sensor for 3D printer ] を確認すると以下のようです。

サーボ用と思われるケーブル 3本

  • 茶色: GND
  • 赤色: +5V
  • 橙色: control signal

スイッチ用と思われるケーブル 2本

  • 黒色: GND
  • 白色: Z min

サーボを PWM で制御するための周期と周波数の確認

ググっても 3DTouch の PWM 周波数を見つけられませんでした。オープンソースの 3D プリンター制御基板は Arudino を使用している場合が多いので、まずは Arudino の Servo ライブラリを確認してみました。

https://forum.arduino.cc/index.php?topic=151645.0 を眺めてみると、Servo ライブラリソースコードの Servo.h で以下のように定義されており、

#define REFRESH_INTERVAL    20000     // minumim time to refresh servos in microseconds

周期は 20,000 μs でよさそうです。周波数は 1,000,000 μs / 20,000 μs = 50 Hz となります。

更に、オープンソースの 3D プリンター制御基板のファームウェア Marlin のソースコードを見てみても Marlin/servo.h に同じ定義がされているので 50 Hz であっているようです。

サーボを PWM で制御するための Duty 比の確認

3DTouch のプッシュピンを上げ下げするための Duty 比もググって見つけることができませんでした。しかし、3DTouch とほぼ同じ仕様と思われる BLTouch の仕様が https://reprap.org/forum/read.php?1,823443 に記載されていたのでこれを参考にしました。

3DTouch の動作 PWM オンと思われる時間 duty 比 ※
Push-pin Down 700μs 0.035
Push-pin Up 1,500us 0.075
Self-test 1,800μs 0.09
Alarm Release 2,200μs 0.11

※ (PWM オンと思われる時間 μs) / (周期 20,000 μs) で計算

Raspberry Pi の GPIO で 3DTouch を操作

周波数と duty 比がわかったので Raspberry Pi の Python で 3DTouch を操作してみました。

まずは、pigpiod を起動しました。

$ sudo pigpiod

python3 の対話モード インタープリターを起動しました。

$ python3

以降は Pytho3 の対話モード インタープリターで実行しました。

PWM に使用する GPIO を定義しました。

>>> GPIO_PWM = 18
  • 今回は GPIO 18 を 3DToch の control signal に接続しています。

周波数を設定しました

>>> PWM_FREQ = 50

3DTouch の各動作に対応する duty 比を設定しました。

>>> DUTY_PP_DOWN       =  35000
>>> DUTY_PP_UP         =  75000
>>> DUTY_TEST          =  90000
>>> DUTY_ALARM_RELEASE = 110000
  • pigpio は引数として duty 比に 1,000,000 を掛けた値を渡すようです。

pigpio モジュールのインポートやその他初期化をしました。

>>> import pigpio
>>> pi = pigpio.pi()
>>> pi.set_mode(GPIO_PWM, pigpio.OUTPUT)

試しにプッシュピンを下げてみました。

>>> pi.hardware_PWM(GPIO_PWM, PWM_FREQ, DUTY_PP_DOWN)

最後に pigpio リソースを開放して終了しました。

>>> pi.stop()

2018年12月5日水曜日

Raspberry Pi で OctoPrint で WebCam で 3D プリンタを遠隔チェック

はじめに

Raspi にインストールした OctoPrint に WebCam の設定をしてプリント中の 3D プリンタを遠隔から監視できるようにしてみました。

なお Raspi に OctoPrint はすでにインストールされ、カメラもすでに使える状態になっているところから始めています。

環境

  • Raspberry Pi 3 model B
  • Raspbian GNU/Linux 9.4 (stretch)
  • オフィシャル Raspi カメラ V2.1
  • OctoPrint Version 1.3.9

Raspi のカメラが使えることを確認

以下のコマンドを実行。

$ raspivid -o ./test.h264

Raspi カメラで 5秒間程度動画撮影し、カレントディレクトリに動画ファイル test.h264 ができました。

このままでは Windows で再生できなのでフォーマットを変換します。

まずは必要なパッケージをインストール。

$ sudo apt install gpac

フォーマットを変換。

$ MP4Box -add ./test.h264 ./test.mp4

カレントディレクトリにできた test.mp4 を Windows に移動して再生できることを確認しました。

MJPG-Streamer コンパイル

必要なパッケージインストール

$ sudo apt install \
subversion \
libjpeg62-turbo-dev \
imagemagick \
ffmpeg \
libv4l-dev \
cmake

MJPG-Streamer をダウンロードしてコンパイル

$ cd ~
$ git clone https://github.com/jacksonliam/mjpg-streamer.git
$ cd mjpg-streamer/mjpg-streamer-experimental
$ export LD_LIBRARY_PATH=.
$ make

試しに WebCam サーバー起動

MJPG-Streamer をコンパイルしたディレクトリに移動

$ cd ~/mjpg-streamer/mjpg-streamer-experimental

MJPG-Streamer を実行 - オフィシャル Raspi カメラでない場合はコマンドが異なるようです

$ ./mjpg_streamer \
-i './input_raspicam.so -fps 5' \
-o './output_http.so'

ブラウザで以下の URL にアクセスすると Raspi カメラで撮影されたストリーミング動画を見ることができました。 - http://<your Raspi's IP>:8080/?action=stream

Ctrl + C で MJPG-Streamer を停止

OctoPrint で WebCam サーバーを起動/停止できるようにスクリプト設置

以下のファイルを設置しました。

/home/pi/scripts/webcam

#!/bin/bash
# Start / stop streamer daemon

case "$1" in
    start)
        /home/pi/scripts/webcamDaemon >/dev/null 2>&1 &
        echo "$0: started"
        ;;
    stop)
        pkill -x webcamDaemon
        pkill -x mjpg_streamer
        echo "$0: stopped"
        ;;
    *)
        echo "Usage: $0 {start|stop}" >&2
        ;;
esac

/home/pi/scripts/webcamDaemon

#!/bin/bash

MJPGSTREAMER_HOME=/home/pi/mjpg-streamer/mjpg-streamer-experimental
MJPGSTREAMER_INPUT_USB="input_uvc.so"
MJPGSTREAMER_INPUT_RASPICAM="input_raspicam.so"

# init configuration
camera="auto"
camera_usb_options="-r 640x480 -f 10"
camera_raspi_options="-fps 10"

if [ -e "/boot/octopi.txt" ]; then
    source "/boot/octopi.txt"
fi

# runs MJPG Streamer, using the provided input plugin + configuration
function runMjpgStreamer {
    input=$1
    pushd $MJPGSTREAMER_HOME
    echo Running ./mjpg_streamer -o "output_http.so -w ./www" -i "$input"
    LD_LIBRARY_PATH=. ./mjpg_streamer -o "output_http.so -w ./www" -i "$input"
    popd
}

# starts up the RasPiCam
function startRaspi {
    logger "Starting Raspberry Pi camera"
    runMjpgStreamer "$MJPGSTREAMER_INPUT_RASPICAM $camera_raspi_options"
}

# starts up the USB webcam
function startUsb {
    logger "Starting USB webcam"
    runMjpgStreamer "$MJPGSTREAMER_INPUT_USB $camera_usb_options"
}

# we need this to prevent the later calls to vcgencmd from blocking
# I have no idea why, but that's how it is...
vcgencmd version

# echo configuration
echo camera: $camera
echo usb options: $camera_usb_options
echo raspi options: $camera_raspi_options

# keep mjpg streamer running if some camera is attached
while true; do
    if [ -e "/dev/video0" ] && { [ "$camera" = "auto" ] || [ "$camera" = "usb" ] ; }; then
        startUsb
    elif [ "`vcgencmd get_camera`" = "supported=1 detected=1" ] && { [ "$camera" = "auto" ] || [ "$camera" = "raspi" ] ; }; then
        startRaspi
    fi

    sleep 120
done

軽く webcamDaemon スクリプトを読んでみたところ、camera="auto" となっているので USB カメラか Raspi カメラ かを自動判定しているようです。camera="usb" とすると USB カメラ (接続されて使えるようになっていれば) を指定でき、camera="raspi" とすると Raspi カメラを指定できるようです。

また、/boot/octopi.txt が存在すれば source コマンドで読み込むので、webcamDaemon スクリプトを修正しなくてもこのファイルで camera 変数の値を変更することができそうです。

作成したスクリプトに実行権限付与

$ chmod +x /home/pi/scripts/webcam
$ chmod +x /home/pi/scripts/webcamDaemon

設置したスクリプトで WebCam サーバーの起動/停止ができることを確認

まずは起動していないことを確認

$ ps -efwww | grep mjpg_streamer | grep -v grep
$

なにも表示されないので起動していないことが確認できました。

WebCam サーバー起動

$ /home/pi/scripts/webcam start
/home/pi/scripts/webcam: started

$ ps -efwww | grep mjpg_streamer | grep -v grep
pi        4759  4751  2 00:10 pts/2    00:00:00 ./mjpg_streamer -o output_http.so -w ./www -i input_raspicam.so -fps 10

mjpg_streamer プロセスが起動しているのがわかります。

また、プロセスの引数が -i input_raspicam.so となっているのでカメラの自動認識で Raspi カメラを認識できていることがわかります。

ブラウザで以下の URL にアクセスすると Raspi カメラで撮影されたストリーミング動画を見ることができました。 - http://<your Raspi's IP>:8080/?action=stream

WebCam サーバー停止

$ /home/pi/scripts/webcam stop
/home/pi/scripts/webcam: stopped

$ ps -efwww | grep mjpg_streamer | grep -v grep
$

なにも表示されないので停止したことが確認できました。

OctoPrint システムメニューで WebCam サ ーバーを起動/停止できるように設定ファイル修正

/home/pi/.octoprint/config.yaml の最後に以下追加 - 今まで一度も OctoPrint を起動していない場合はこの .octoprint/ ディレクトリは まだ作成されていないかもしれません

system:
  actions:
    - action: streamon
      command: /home/pi/scripts/webcam start
      confirm: false
      name: Start video stream
    - action: streamoff
      command: /home/pi/scripts/webcam stop
      confirm: false
      name: Stop video stream

参考ページでは command: sudo /home/pi/scripts/webcam stop というように停止時は sudo により root 権限で stop させる ようになっています。これは別ユーザーが WebCam サーバーを起動した場合でも OctoPrint から WebCam サーバーを停止できるようにするためだと思われますが、パスワード無しで sudo できることが前提です。Raspbian のデフォルトでは確かパスワード無しで sudo できたはずですが、私の Raspi は sudo 時にパスワードが必要なように設定を変更しています。このため sudo をつけると OctoPrint から WebCam サーバーを停止で きないので command: /home/pi/scripts/webcam stop というように sudo を付けないように変更しています。別ユーザーが起動し た WebCam サーバーは OctoPrint で停止できませんが、私の使い方ではそのような状況にはならないかなと考えています。

OctoPrint で WebCam サーバー起動/停止

/home/pi/.octoprint/config.yaml を修正したので OctoPrint が起動している場合は念のため OctoPrint 再起動

ブラウザで OctoPrint にアクセスし、電源アイコン (System) のプルダウンから Start video stream を選択して WebCam サーバー起動

ブラウザで以下の URL にアクセスすると Raspi カメラで撮影されたストリーミング動画を見ることができました。 - http://<your Raspi's IP>:8080/?action=stream

電源アイコン (System) のプルダウンから stop video stream を選択して WebCam サーバー停止

OctoPrint の画面で WebCam のストリーミングを確認できるよ うにする

WebCam サーバーが起動していない場合は起動

スパナのアイコン (Settings) をクリック

WebCam & Timelapse をクリック

Stream URL に http://<your Raspi's IP>:8080/?action=stream を設定

参考ページには Stream URL に /webcam/?action=stream を設定するようにと書かれていましたが、私の環境ではこれではだめ でした。

Test をクリックして WebCam のストリーム動画が表示されることを確認

Save をクリック

OctoPrint を再起動し、ブラウザのキャッシュをクリアし、OctoPrint ページをリロード

WebCam サーバーを起動

Control タブに WebCam のストリーミング画像が表示されるようになりました。

参考

  • https://discourse.octoprint.org/t/setting-up-octoprint-on-a-raspberry-pi-running-raspbian/2337
  • https://www.raspberrypi.org/documentation/usage/camera/raspicam/raspivid.md

2018年11月16日金曜日

Raspberry Pi で Samba

Raspberry Pi に保存したファイルを Windows に移動させたかったので Raspberry Pi に Samba を入れま した。

環境

  • Raspberry Pi 3 Model B
  • Raspbian GNU/Linux 9.4 (stretch)

Samba インストール

$ sudo apt install samba

設定

設定ファイルを確認すると以下の様にすでにホームディレクトリの設定が有効になっていました。

$ cat /etc/samba/smb.conf
... snip ...
[homes]
   comment = Home Directories
   browseable = no

# By default, the home directories are exported read-only. Change the
# next parameter to 'no' if you want to be able to write to them.
   read only = yes

# File creation mask is set to 0700 for security reasons. If you want to
# create files with group=rw permissions, set next parameter to 0775.
   create mask = 0700

# Directory creation mask is set to 0700 for security reasons. If you want to
# create dirs. with group=rw permissions, set next parameter to 0775.
   directory mask = 0700

# By default, \\server\username shares can be connected to by anyone
# with access to the samba server.
# The following parameter makes sure that only "username" can connect
# to \\server\username
# This might need tweaking when using external authentication schemes
   valid users = %S

# Un-comment the following and create the netlogon directory for Domain Logons
# (you need to configure Samba to act as a domain controller too.)
;[netlogon]
... snip ...

pi ユーザーを smbpasswd に登録してパスワードを設定

$ sudo smbpasswd -a pi
New SMB password:
Retype new SMB password:
Added user pi.

接続

\\XX.XX.XX.XX\pi で Windows から接続できました。(XX.XX.XX.XX は Raspberry Pi の IP アドレスです)

2018年7月29日日曜日

ラズパイで PWM で Python3 でサーボモーターを制御

環境

  • Raspberry Pi 3 Model B
  • Raspbian GNU/Linux 9.4 (stretch)
  • サーボモーター: SG90

wiringpi2 インストール

$ sudo pip3 install wiringpi2

Python3 コード

SG90 の信号線は Raspberry Pi の GPIO18 に接続しています。

DUTY_MIN, DUTY_MAX の値は適当に。。。

あと、このスクリプトは root 権限で実行しないと、Raspberry Pi が固まります。

#!/usr/bin/env python3

import wiringpi
import time

PWM_PIN = 18

DUTY_MIN = 45
DUTY_MAX = 105

wiringpi.wiringPiSetupGpio()
wiringpi.pinMode(PWM_PIN, wiringpi.GPIO.PWM_OUTPUT)
wiringpi.pwmSetMode(wiringpi.GPIO.PWM_MODE_MS)
wiringpi.pwmSetClock(375)

while True:
    for duty in range(DUTY_MIN, DUTY_MAX):
        wiringpi.pwmWrite(PWM_PIN, duty)
        time.sleep(0.01)

    for duty in range(DUTY_MAX, DUTY_MIN, -1):
        wiringpi.pwmWrite(PWM_PIN, duty)
        time.sleep(0.01)