2024年2月24日土曜日

µStreamerをラズパイZero Wで動かしてみた。

 ラズパイZero WにUSBカメラを繋いでリアルタイムストリーミングをやってみた。前回BBBlueで試したときかなり低遅延でCPU負荷も軽かったし、mjpg-streamerは更新されていないっぽいのでuStreamerを使ってみる。

久しぶりにRaspberry Pi Zero Wを引っ張り出してきたらOSのアップデートが大変そうだったので新規インストールすることに。

Raspberry Pi Imagerを使ってRaspberry Pi OS Lite(32bit)のBookwormをインストール。あらかじめWiFi設定やSSHの有効化ができるので最近は便利だなぁ。

dtoverlay=sdtweak,overclock_50=100

とりあえずsudo nano /boot/firmware/config.txtでSDカードオーバクロックだけ追加した。

ustreamerはapt-getからもインストールできたりするんだけど、バージョンが古いらしくフォーラムとかを見ていてもビルドを推奨されてるようだったのでビルドしてみた。GPUアクセラレーションのM2Mとかを使う場合もビルドしたバージョンじゃないと対応してないみたいだし。

sudo apt-get install libevent-dev libjpeg62-turbo-dev libbsd-dev git
git clone --depth=1 https://github.com/pikvm/ustreamer
cd ustreamer
make
sudo make install

とりあえずこんな感じで5分ぐらいでビルドできた。

インストールが終わったらカメラを接続してテスト。このuStreamerだとカメラ側のハードウェアエンコーダーをそのまま使えたりするので、カメラの情報を確認する。

v4l2-ctl --list-formats-ext

このコマンドで今接続してるカメラの対応してるフォーマットと解像度が一覧で見れる。

Logicool C270を接続してみたんだけど、このカメラの場合はYUYVとMotion-JPEGに対応していた。ということでuStreamerでMotion-JPEGを使って配信してみる。

ustreamer -m MJPEG -f 30 -s 0.0.0.0 -p 8080

これで640x480の30fpsでストリーミングを開始できる。ブラウザからhttp://ラズパイのIP:8080にアクセスして/streamをクリックするとストリーミングを確認することができる。

画面にストップウォッチとストリーミング映像を並べて表示してカメラでストップウォッチを撮影してスクリーンショットするという手法で遅延を測ってみた。

WiFiルータにラズパイZero Wの内蔵無線LAN経由で接続して廊下を挟んで隣の部屋のルータにつながっているけど遅延0.16秒ぐらいでサクサク動く。

ラズパイZero WでもustreamerのCPU使用率は5%ぐらいでほぼ負担がかかっていない。UVCのkworkerも3%ぐらいだし。カメラのハードウェアエンコーダに頼っているのでラズパイZero W側ので処理はHTMLでデータを流すだけだし。

ちなみにHD解像度でも試してみた。

ustreamer -m MJPEG -f 30 -s 0.0.0.0 -p 8080 -r 1280x720

これで1280x720のワイドな解像度で配信できる。

遅延も相変わらず約0.16秒。ワイドだとより視野角が増えてロボットに乗せるのには良さそう。ちなみにこの遅延、前回試したところによるとカメラ側の性能にも左右されるのでもっと速いカメラもあるかも?手持ちの中ではLogicoolのC270とC310が一番良かった。(C310のほうが0.01~0.02秒ぐらい速いことも)

このぐらいの低遅延で映像が送れてCPU側の負担も少ないので動く系のロボットとかで使えそう。他の処理にCPUとメモリを割り当てられるし。帯域は解像度によるけど、あんまり多くない。音声が送れないのが少し残念な点かもしれない。

FPVみたいな使い方をする場合はもう少し広角レンズがほしいかもしれない。BuffaloのBSW505MBKとかは120°な広角レンズを搭載しているっぽいけども、まずはC270のレンズ交換を試してみないとな…


2024年2月4日日曜日

パルワールドの鯖をLinuxで立てて落ちたら自動で再起動。

 最近友人とパルワールドをプレイしてるんだけど、Linux鯖で鯖を立てていても地味に落ちていて自分がいないときにみんながプレイできなくなるパターンがあったので自動で再起動するようにしてみた。
ダンジョンに入った瞬間に落ちたりすることが多いかも。

パルワールドの鯖の建て方は公式に載っているので割愛するけど、SteamCMDをHomeディレクトリに入れておいて、Homeディレクトリ内のpalworldディレクトリから起動するようにしている。

./steamcmd.sh +force_install_dir palworld +login anonymous +app_update 2394010 validate +quit

鯖のインストールもアップグレードもとりあえずはこの1行で行っている。

設定ファイルはこの場合で言う、palworld直下のDefaultPalWorldSettings.iniにデフォルトの設定が保存されるので、このファイルの中身をコピーして、./Pal/Saved/Config/LinuxServer/PalWorldSettings.iniの中身に貼り付けて必要な設定を変更する。とりあえずServerNameとServerPasswordだけ変更した。

そんでもってPalServer.shを起動すれば鯖が立ち上がるんだけど、4人ぐらいでプレイしていても2時間置きぐらいにセグったりして落ちているので、自分が先に寝たりすると友人が入れなかったりで(地味に夜通しでやってるやつも居るし)ということで対策してみた。

まえにどこかで見た手法何だけど、とりあえずいちばん簡単なシェルスクリプトでwhileを使って実装してみた。

#!/bin/bash
cd palworld
count=0
start_time=$(date +%s)
while :
do
  ./PalServer.sh
  echo "Server Down"
  end_time=$(date +%s)
  run_time=$(((end_time - start_time) / 60))
  count=$(expr $count + 1)
  echo $count
  echo $run_time
  sleep 10s
done

とりあえずこんな感じでhomeディレクトリにpal.shとかで保存して実行権限を与えれてScreenで実行してる。落ちた回数と稼働時間もコメントするようにしてあるけど、実際はwhileの中でPalServer.shを呼んでいるだけ。落ちると10秒待って何度でも実行される。

一応こんな感じで簡単に実装したんだけど今のところちゃんと動いてる。1日に5回ぐらい落ちてるけど…。

アップグレードが来たら自動で更新できるようにしたいなぁ

2024年2月3日土曜日

candleLightファームウェアをWindowsでビルドしてみた。

 candleLightはSTM32F0シリーズのUSB2CANとかで使えるファームウェアなんだけど、STM32G431とかでも使えるように改良してる人がいたのでWindowsでビルドしてみた。
というのもCANFDが使えるというからといって購入したCANable 2.0のデフォルトファームウェアでCANFDがうまく使えなかったので…

Windows側で必要なのはcmakeとmingw64(makeに使用)とgcc-arm-none-eabi-8-2019-q3-update-win32-sha2.exeだった。

とりあえずこれらをインストールして、gcc-arm-none-eabi-8-2019-q3-update-win32-sha2.exe以外は環境変数に入れて呼び出せるようにしておく。

pgreenlandさんのcandleLightブランチをとりあえずZipでダウンロードして展開。

cmakeフォルダの中のgcc-arm-none-eabi-8-2019-q3-update.cmakeをWindows用に少し変更

set(TOOLCHAIN gcc-arm-none-eabi-8-2019-q3-update)
set(CMAKE_MAKE_PROGRAM "C:/mingw64/bin/mingw32-make.exe")

set(TOOLCHAIN_BIN_DIR "C:/Program Files (x86)/GNU Tools ARM Embedded/8 2019-q3-update/bin")

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CMAKE_C_COMPILER "${TOOLCHAIN_BIN_DIR}/arm-none-eabi-gcc.exe" CACHE INTERNAL "")
set(CMAKE_CXX_COMPILER "${TOOLCHAIN_BIN_DIR}/arm-none-eabi-g++.exe" CACHE INTERNAL "")

set(CMAKE_EXE_LINKER_FLAGS "" CACHE INTERNAL "")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

SET (CMAKE_C_COMPILER_WORKS 1)
SET (CMAKE_CXX_COMPILER_WORKS 1)

コマンドプロンプトでCMakeLists.txtがあるディレクトリに移動して

mkdir build
cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/gcc-arm-none-eabi-8-2019-q3-update.cmake -G "MinGW Makefiles"
make

こんな感じでビルドできた。WindowsでのポイントはcmakeがnmakeでVisualStudioの環境を作ってしまうようなデフォルト設定になっているので、-G "MinGW Makefiles"をつけるところ。一旦このオプションをつけないで実行してしまうとエラーが出てしまうのでbuildフォルダを削除してやり直し。一番ココでハマった…

というわけでCANable2_MKS_fw.binってのがSTM32G431用のバイナリファイル。しかもこれ、CANable2の公式ファームウェアではCAN FD対応していないらしいけどこっちは対応してるっぽい。

Windows上だとCangarooで使う場合はデフォルトでインストールされるWINUSBドライバでいいけども、Python-CANとかでgs_usbを使う場合はZadigとかでlibusbKに変更する必要がある。その時は(Interface0)が付いてる方だけど変更すること。(OptionのList All Deviceを有効にしないと出ないかも)

ファームウェアを書き込むときは前はdfu-utilでやっていたけど、ブラウザから書き込みができるWebUSB DFUを使うと便利かも。Vender IDは0x0483。




2024年1月26日金曜日

ブラーバ380jのバッテリの中身を入れ替えてみた。

 以前ブラーバのバッテリをEneloopに交換したんだけど、またエラーが出るようになってきたのでバッテリを交換してみた。今回も赤点滅7回のバッテリエラー。

前回はEneloopを使ったんだけど、Ni-MHバッテリが昔より高くなってる?8本パックって1900円ぐらいだったのに…
ということで代替を探してみると富士通のニッケル水素電池って実はEneloopとおなじくFDKで作られているということで実質おなじもの?スペックも同じだし。ということで富士通にしてみた。

6本必要なので2本パックと4本パックにしてみた。これで1500円ぐらいだったので当時購入したEneloopと同じぐらいのお値段。
以前Eneloopに詰め替えたバッテリ、下に切り目をいれて抜き出したのでテープで貼っていたんだった。
バラバラにする前にヒューズとかジャンパの位置を確認しておく。写真を取っておいた。
6本まとめてテープで仮止めするのが意外と大変。形が崩れると入らなくなるし…
良い子は真似してはいけないダイレクトハンダ。一瞬で決めてる。今回は削らずにも結構ハンダが乗りやすかった。本当はスポット溶接しないとだめなんだけどね。
赤いケーブルは外から回すんだけど、間違って中に通してしまった…
やり変えるのも面倒なのでそのまま行くことに。
バッテリパックに戻して完成。

とりあえずこれでブラーバでもエラー7が出なくなったので正常に充電できてそう。純正バッテリと特性が違ったりするのでおすすめはしないけどEneloopで3年ちょい使えてたので今回も大丈夫だと信じたい。
純正じゃないのでやってみたい人は自己責任ですな。

2024年1月7日日曜日

ダウンライトをLED化してみた。

 壁紙を変えるときにやろうと思っていたダウンライトのLED化、電気工事士持ってる人は居るんだけども忘れていて、ふとメルカリを見ていたらいいのが出ていたのでポチってみた。

パナソニックの電球色LEDタイプの一体型が3つで1500円という。LSEB9502LE1 3つって書いてあったのに実際届いたら60W相当(LSEB9502 LE1)が2つに100W相当(LSEB9505 LE1)が1つだったんだけど、安かったので良しとした。


60W相当品が定価で3300円、100W相当品が定価で6600円だったのに、60W相当品が3つという表記で出品されていたので結果的にだいぶお安い。消費電力は明るさおなじで1/10以下。

今回LED化するキッチンのダウンライトの構成が対面キッチンで流し台の上に付いてるのが60Wの白熱球(DDL-2895YW)が2つ。壁紙張り替えのときに外さないでやったようで微妙に汚いんだよなぁ…
DAIKOからPanasonicにするとカバーの直径が1ミリぐらい大きくなるらしいので隠れることに期待。

冷蔵庫の上に付いてるのがおなじやつが1つという感じ。
このままLED電球つけてるけどE17タイプは斜めに電球が刺さるので変な方向照らしてるやつ。
ということでたまたま100Wが一つと60Wが一つで届いてしまったので冷蔵庫の上のダウンライトをアップグレードできる感じに。結果オーライってところ。

E26のダウンライトの方はLED電球でLED化済み。E17のタイプはやっぱりユニットごと交換したほうがかっこいいかなと。

ちなみに取り付けには電気工事士の資格が必要なところが一体型の難点らしい。つかなくなったら電気工事が必要。まぁうちには電気工事士が居るので安いこっちの方にした。(GX53ソケットタイプだと電気工事が不要で球を交換できるっぽいけど)


交換してもらったのがこちら。もともとついてたDAIKOのやつは爪が3つだったので外しにくかったっぽい。隙間とかもないのですごくスッキリ。フラットな感じが良い。

そしておそらく元々ついてたバルブが劣化していたのかめちゃめちゃ明るくなってる。特にシングルのところは60Wから100W相当にアップグレードされてるし。
今回はE17のダウンライト(Φ100穴タイプ)を交換したけど、Φ125のやつも将来的には交換しておきたいな。見た目が思った以上に良くなって満足。

2024年1月5日金曜日

MX Anywhere 2Sのスイッチを交換してみた。

 友人のLogicool MX Anyware 2Sがチャタり始めたということでスイッチを交換してみた。今回はRazerのオムロン設計協力の独自スイッチであるD2FC-F-K(50M)-RZに交換することに。

2個で500円ぐらいだった。
DeathAdder Eliteで使われている5倍耐久性がたかいスイッチ。
Anywhere 2Sはソールの下にねじがあるのでソールを剥がしていく。デザインナイフなどできっかけを作ったら小さいマイナスドライバーを滑り込ませていくときれいに剥がれる。(引っ張って剥がしたりすると伸びてしまうため)
ソールがはがせたらプラスネジなのでプラスドライバーで外せる。
マウス上面には重りもついていたので今回は軽量化のためにおもりを取り外すことに。こちらもプラスネジ2本で固定されているので簡単に取り外せる。(約15g軽量化)
基板を取り外すしてスイッチを取り外す。ハンダを少し盛ってから3つの端子を順番に繰り返し温めていくと10週目ぐらいで外れた。

スイッチが外れたらハンダ吸い取り器を使ってハンダを取り除く。
あとは新しいスイッチをはんだ付けしてフラックスのクリーニング。
緑色のRAZER OMRONスイッチはなんか強そう。
結構ネジの数やホイールの周りが細かい部品なので少し大変だった。
もとに戻して完成。
基板を固定するとき、電源スイッチの位置に注意。基板もケースもスイッチをオフの状態で入れておかないとスイッチが入れられなくなる。

2Sは4年ぐらい使っててチャタり始めたらしいので5倍耐久スイッチならほかが壊れるまで使えるかなぁ?

2023年12月31日日曜日

MT6701のI2C基板をSSIで使ってみた。

 先日MT6701のI2C版基板をArduinoで動作確認が取れたのでSPIライクなSSI接続でも使えるように改造してみた。I2C接続だと双方向通信だけども、SSIだと受信のみしかできないのでパラメータの書き換えとかはできないけど高速に通信できるらしい。

MT6701

まずはMT6701を剥がしてみた。どうやら8番ピンがVCCに直結になっているのでこれをCSとして出さないといけない。PWM/Analog出力は使う予定がないので、ICの下のパターンをカットしてPWM/AnalogのところにCSを出してみた。
画像でいうと赤い線を2箇所カットしてMT6701を実装したところで8番Pinを真ん中の端子にジャンパした感じ。

MT6701

これでI2CとSSIが使える基板となった。CS(改造後の真ん中のPin)をVCCに接続して、SCLとSDAをプルアップすればI2Cとして使えるし(Internal Pullupでもいいし)、SSIとして使う場合はCSとMISO(SDAのピン)とCLK(SCLのピン)の3本をマイコンに接続すれば良い。

#include <SPI.h>

#define CS_PIN PA15

SPIClass SPI_1(PB5, PB4, PB3);  //MOSI=PB5, MISO=PB4, SCK=PB3

void setup() {
  Serial.begin(115200);
  SPI_1.begin();

  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);
  Serial.println("MT6701 SSI Angle Reader Start");
}

void loop() {
  digitalWrite(CS_PIN, LOW);
  SPI_1.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE1));
  delayMicroseconds(1);
  uint16_t raw = SPI_1.transfer16(0xFFFF);//ダミーデータ送信
  SPI_1.endTransaction();
  digitalWrite(CS_PIN, HIGH);

  uint16_t angle = raw >> 2;
  float degrees = (angle * 360.0) / 16384.0;
  uint8_t mg = raw & 0b11;

  Serial.print("Raw: ");
  Serial.print(angle);
  Serial.print(", Degrees: ");
  Serial.print(degrees, 2);
  Serial.print(", Status: ");
  switch (mg) {
    case 0b00: Serial.println("OK"); break;
    case 0b01: Serial.println("Too Strong"); break;
    case 0b10: Serial.println("Too Weak"); break;
    case 0b11: Serial.println("Error"); break;
  }

  delay(200);
}

こんな感じでArduno上のBluepillのSPI1のAlternativeピンを使用して読み込んでみた。とりあえずI2C同様問題なく読み込めた。SimpleFOCとかでも使えるようなのでこれならモータ制御で問題なく使えるのかなぁ。

DOに10kのプルアップがあるとより安定するとかなんとか。

SSIだとMT6701には書き込みができないので同じピン配置でなにかデータを書き込んだり設定変更する場合はCSをHighにした状態でInternal Pullupを使ってソフトウェアI2Cを使えば書き込めるかも?