2026年4月23日木曜日

Note

あなた
ブログはいま、bloggerを使用してるんですが、動画や写真って簡単に貼れるの?
ChatGPT
Bloggerでも写真も動画も貼れますが、動画はYouTube経由が前提で少し面倒です。写真は簡単にアップできます。
あなた
動画はそんなことなってるのは面倒だね
ChatGPT
その感覚は正しいです。Bloggerは動画まわりが古く、YouTube前提の設計になっています。
一番ラクなのは、YouTubeにアップしてURLを貼る方法です。
あなた
そうだね、他のサービスで、ワンステップでできるブログサイトはあるの?
ChatGPT
noteやはてなブログ、Tumblrなどがありますが、特にnoteがシンプルでおすすめです。
動画も画像もそのまま貼れて、スマホだけで完結します。
あなた
Noteを使用してみるか。
ChatGPT
いい選択です。noteはとてもシンプルで、写真や動画も直感的に投稿できます。
iPhoneだけで簡単にブログが書けます。

チャッピーとblogger

いま、ChatGPTをiPhone用のアプリで使用しているのは、わかりますか?
あなた
ChatGPT
かなり高い精度で推測はできます。 今回のようにiOSの情報が見えている場合は、 iPhoneアプリ利用と判断できます。 ただし、画面内容や個人情報までは見えません。
いや、このやり取りの全てをブログに貼りたいんだけど、どう操作してコピーすればいいの?
あなた
ChatGPT
iPhoneアプリでは全文コピーは弱いので、 ・長押しコピー(1つずつ) ・範囲選択(やや不安定) ・共有リンク(おすすめ) が現実的です。
なんか選択だと、このやりとりの全てを選択できないんだけど。
あなた
ChatGPT
仕様的に難しいです。 iPhoneアプリ単体では全文コピーはほぼ不可です。 共有リンクかPC利用が確実です。
いや、今後何度もするので、iPhone内で完結できるのがいいね。
あなた
ChatGPT
その場合は、 共有リンク → Safariで開く → コピー がベスト運用です。
Safariでコピーして、bloggerに貼り付けてみたのですが、自分の入力部分がうまく表現できてないね。
あなた
ChatGPT
原因は、コピー時に発言者情報が消えるためです。 → ChatGPTに「ブログ用に整形して」と頼むのが一番ラクです。
そうなんだね、じゃあ今までのやりとりをblogger用に吹き出しっぽく整形して。
あなた

2024年10月17日木曜日

MacBook Air M1 で tensorflow (metal) の環境作成

 概要

Metalに対応した tensor flow 環境を構築した時の備忘録です。

python 3.11 でしか metal に対応した環境がないとのこと。

使用したツールと環境
  1. homebrew
  2. pyenv 
  3. venv
  4. pip

homebrew: pyenvのインストールと設定

python の使用するバージョンを管理するためのツールとして、pyenv をインストールします。

brew install pyenv  

.zshrc に以下を追加する

alias python=python3

alias pip=pip3


export PYENV_ROOT="$HOME/.pyenv"

export PATH="$PYENV_ROOT/bin:$PATH"

eval "$(pyenv init -)" 

pyenv: python のバージョン選択

インストール可能な一覧を表示する
pyenv install --list

python 3.11.10 をインストールする
pyenv install 3.11.10

インストールしたpython を表示する
pyenv versions

  system

  3.11.10


標準で使用する、バージョンを変更する

pyenv global 3.11.10

pyenv versions      

  system

* 3.11.10 (set by /Users/da2/.pyenv/version)


venv: (python 作業環境の設定)

python 用の作業ディレクトリで venvで個々のパッケージをインストールする
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip

pip: パッケージのインストール

pip install tensorflow-macos
pip install tensorflow-metal
pip install keras
pip install torch torchvision torchaudio
pip install opencv-python
pip install scikit-image

 

Apple Silicon 用に ffmpeg をビルド

カスタマイズした x265 を使用するのに ffmpeg をビルドしてみた。

git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg

./configure --enable-libx265 --enable-gpl

make

sudo make install


2024年8月30日金曜日

Apple Silicon 用に x265 をビルド

x265 のビット深度16で使用してみたかったので、Macでビルドを行ってみた

リポジトリの取得

git clone https://bitbucket.org/multicoreware/x265_git 


ビルド

ビルドディレクトリに移動

ビルド用のディレクトリに移動(linuxとあるけどここでいいらしい)

cd x265_git/build/linux 

スクリプト実行

スクリプトを叩く(コンパイルオプションの選択を行う画面が出る)

./make-Makefiles.bash 

cmake実行

make を実行して Makefile の作成

 cmake ../../source

make 実行

make -j4

install

sudo make install

補足

ffmpeg ビルド時に pkgconfig を追加

sudo brew install pkgconfig

.zproifle に環境変数を追加
export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/lib
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/usr/local/lib

2019年7月15日月曜日

esp32 と9軸センサーとサーボ

esp32 と 9軸センサー と サーボモータ

esp32 は手軽にIOT用のデバイスが作成できます。9軸センサーとサーボモータによるテスト用のプログラムを記述したので、ハードウェアとソフトウェアについて解説を記述します。

ハードウェア構成

以下の、パーツを購入することで手軽に動作させることができると思います。

ESP-WROOM-32D開発ボード

WifiやBLEもできる、最近流行っているボードです。結構いろいろできるみたいなので、持っているのも悪くないと思います。

9軸センサー

加速度・ジャイロ・磁気の9軸センサーです。esp32 のI/O は3.3v みたいなので、JP7をショートさせて使用します。

サーボモータ

ホビー用によく使用される、サーボモータです。ソフトウェアでは、4個使用していますが、予算の都合で個数を購入するのがよいと思います。

ブレッドボード

ESP32 用には 一列が 6ピンないと、結線できないのでこちらを使用します。

ブレッドボード用ジャンパーワイヤー

結線用のワイヤーです。

USBケーブル

ESP32とPCを接続するケーブルです。持っていれば別に必要ではないです。

配線

以下、配線になります。モータ用電源に別途、電池ボックスとブレッドボードを使用しています。

電源ライン
3.3 V と GNDを ブレッドボードの+-に接続します。
サーボモータ
GPIO32, 33, 25, 26 をサーボモータの信号用に使用します。
ここでは、電池ボックスから4.8v の電圧を生成して結線しています。
サーボモータが1・2個なら esp32 の 5Vを使用します。
9軸センサー
電源は上記の電源ラインから配線します。
信号用にはGPIO22, 21 は 加速度センサーとの接続用に使用します。

ソフトウェア

Arduino IDE を使用して開発しています。導入方法等は他のページを参照してください。


ソースコード

以下、全ソースコードです。加速度センサーから読み取った値から roll, pitch を計算しています。roll, pitch に連動してサーボモータを動作させています。
細かい解説は後ほど、追記します。

#include <Wire.h>
#include <MadgwickAHRS.h>
#include <ESP32Servo.h>
#include "esp_system.h"
#define LED_PIN 32
#define SERVO_COUNT 4
int SERVO_PINS[SERVO_COUNT] = { 33, 25, 26, 27 };
Servo myServo[SERVO_COUNT];
Madgwick MadgwickFilter;
#define BMX055_ACCL_ADDR 0x19
#define BMX055_GYRO_ADDR 0x69
#define BMX055_MAG_ADDR  0x13

void setup()
{
  Serial.begin(115200);
  while (!Serial);
  Serial.println("BMX055 Test setup start");
  myServo[0].attach(SERVO_PINS[0]);
  myServo[1].attach(SERVO_PINS[1]);
  myServo[2].attach(SERVO_PINS[2]);
  myServo[3].attach(SERVO_PINS[3]);
  // ic2
  Wire.begin();
  InitAcclBMX055();
  InitGyroBMX055();
  InitMagBMX055();
  MadgwickFilter.begin(50); //50Hz
  Serial.println("BMX055 Test setup end");
}

void loop()
{
  //Serial.println("Read...");
  float ax, ay, az;
  ReadAcclBMX055(ax, ay, az);
  float gx, gy, gz;
  RaddGyroBMX055(gx, gy, gz);
  float mx, my, mz;
  ReadMagBMX055(mx, my, mz);
  // calculate roll/pitch/yaw
  //MadgwickFilter.updateIMU(gx, gy, gz, ax, ay, az);
  MadgwickFilter.update(gx, gy, gz, ax, ay, az, mx, my, mz);

  float pitch = MadgwickFilter.getPitch();
  float roll    = MadgwickFilter.getRoll();
  float yaw   = MadgwickFilter.getYaw();
  //Serial.print(pitch); Serial.print(",");
  //Serial.print(roll); Serial.println("");
  if( pitch > -90 && pitch < 90) {
    float angle = pitch + 90;
    myServo[0].write(angle);
    myServo[1].write(angle);
  } else {
    myServo[0].write(90);
    myServo[1].write(90);
  }
  if( roll > -90 && roll < 90) {
    float angle = roll + 90;
    myServo[2].write(angle);
    myServo[3].write(angle);
  } else {
    myServo[2].write(90);
    myServo[3].write(90);
  }

  delay(20);         
}
void  InitAcclBMX055()
{
  // 加速度
  Wire.beginTransmission(BMX055_ACCL_ADDR);
  Wire.write(0x0F); // Select PMU_Range register
  Wire.write(0x03);   // Range = +/- 2g
  Wire.endTransmission();
  delay(100);
 //------------------------------------------------------------//
  Wire.beginTransmission(BMX055_ACCL_ADDR);
  Wire.write(0x10);  // Select PMU_BW register
  Wire.write(0x08);  // Bandwidth = 7.81 Hz
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(BMX055_ACCL_ADDR);
  Wire.write(0x11);  // Select PMU_LPW register
  Wire.write(0x00);  // Normal mode, Sleep duration = 0.5ms
  Wire.endTransmission();
  delay(10);
}
void  InitGyroBMX055()
{
 //------------------------------------------------------------//
  Wire.beginTransmission(BMX055_GYRO_ADDR);
  Wire.write(0x0F);  // Select Range register
  Wire.write(0x04);  // Full scale = +/- 125 degree/s
  Wire.endTransmission();
  delay(100);
 //------------------------------------------------------------//
  Wire.beginTransmission(BMX055_GYRO_ADDR);
  Wire.write(0x10);  // Select Bandwidth register
  Wire.write(0x07);  // ODR = 100 Hz
  Wire.endTransmission();
  delay(100);
 //------------------------------------------------------------//
  Wire.beginTransmission(BMX055_GYRO_ADDR);
  Wire.write(0x11);  // Select LPM1 register
  Wire.write(0x00);  // Normal mode, Sleep duration = 2ms
  Wire.endTransmission();
  delay(100);
}
void  InitMagBMX055()
{
  Wire.beginTransmission(BMX055_MAG_ADDR);
  Wire.write(0x4B);  // Select Mag register
  Wire.write(0x83);  // Soft reset
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(BMX055_MAG_ADDR);
  Wire.write(0x4B);  // Select Mag register
  Wire.write(0x01);  // Soft reset
  Wire.endTransmission();
  delay(100);
  //------------------------------------------------------------//
  Wire.beginTransmission(BMX055_MAG_ADDR);
  Wire.write(0x4C);  // Select Mag register
  Wire.write(0x00);  // Normal Mode, ODR = 10 Hz
  Wire.endTransmission();
 //------------------------------------------------------------//
  Wire.beginTransmission(BMX055_MAG_ADDR);
  Wire.write(0x4E);  // Select Mag register
  Wire.write(0x84);  // X, Y, Z-Axis enabled
  Wire.endTransmission();
 //------------------------------------------------------------//
  Wire.beginTransmission(BMX055_MAG_ADDR);
  Wire.write(0x51);  // Select Mag register
  Wire.write(0x04);  // No. of Repetitions for X-Y Axis = 9
  Wire.endTransmission();
 //------------------------------------------------------------//
  Wire.beginTransmission(BMX055_MAG_ADDR);
  Wire.write(0x52);  // Select Mag register
  Wire.write(0x16);  // No. of Repetitions for Z-Axis = 15
  Wire.endTransmission();
}
void ReadAcclBMX055(float &xAccl, float& yAccl, float& zAccl)
{
  int data[6];
  for (int i = 0; i < 6; i++)
  {
    Wire.beginTransmission(BMX055_ACCL_ADDR);
    Wire.write((2 + i));// Select data register
    Wire.endTransmission();
    Wire.requestFrom(BMX055_ACCL_ADDR, 1);// Request 1 byte of data
    // Read 6 bytes of data
    // xAccl lsb, xAccl msb, yAccl lsb, yAccl msb, zAccl lsb, zAccl msb
    if (Wire.available() == 1)
      data[i] = Wire.read();
  }
  // Convert the data to 12-bits
  xAccl = ((data[1] * 256) + (data[0] & 0xF0)) / 16;
  if (xAccl > 2047)  xAccl -= 4096;
  yAccl = ((data[3] * 256) + (data[2] & 0xF0)) / 16;
  if (yAccl > 2047)  yAccl -= 4096;
  zAccl = ((data[5] * 256) + (data[4] & 0xF0)) / 16;
  if (zAccl > 2047)  zAccl -= 4096;
  xAccl = xAccl * 0.0098; // renge +-2g
  yAccl = yAccl * 0.0098; // renge +-2g
  zAccl = zAccl * 0.0098; // renge +-2g
}
void RaddGyroBMX055(float& xGyro, float& yGyro, float& zGyro)
{
  int data[6];
  for (int i = 0; i < 6; i++)
  {
    Wire.beginTransmission(BMX055_GYRO_ADDR);
    Wire.write((2 + i));    // Select data register
    Wire.endTransmission();
    Wire.requestFrom(BMX055_GYRO_ADDR, 1);    // Request 1 byte of data
    // Read 6 bytes of data
    // xGyro lsb, xGyro msb, yGyro lsb, yGyro msb, zGyro lsb, zGyro msb
    if (Wire.available() == 1)
      data[i] = Wire.read();
  }
  // Convert the data
  xGyro = (data[1] * 256) + data[0];
  if (xGyro > 32767)  xGyro -= 65536;
  yGyro = (data[3] * 256) + data[2];
  if (yGyro > 32767)  yGyro -= 65536;
  zGyro = (data[5] * 256) + data[4];
  if (zGyro > 32767)  zGyro -= 65536;
  xGyro = xGyro * 0.0038; //  Full scale = +/- 125 degree/s
  yGyro = yGyro * 0.0038; //  Full scale = +/- 125 degree/s
  zGyro = zGyro * 0.0038; //  Full scale = +/- 125 degree/s
}
void ReadMagBMX055(float& xMag, float& yMag, float& zMag)
{
  int data[8];
  for (int i = 0; i < 8; i++)
  {
    Wire.beginTransmission(BMX055_MAG_ADDR);
    Wire.write((0x42 + i));    // Select data register
    Wire.endTransmission();
    Wire.requestFrom(BMX055_MAG_ADDR, 1);    // Request 1 byte of data
    // Read 6 bytes of data
    // xMag lsb, xMag msb, yMag lsb, yMag msb, zMag lsb, zMag msb
    if (Wire.available() == 1)
      data[i] = Wire.read();
  }
  // Convert the data
  xMag = ((data[1] <<8) | (data[0]>>3));
  if (xMag > 4095)  xMag -= 8192;
  yMag = ((data[3] <<8) | (data[2]>>3));
  if (yMag > 4095)  yMag -= 8192;
  zMag = ((data[5] <<8) | (data[4]>>3));
  if (zMag > 16383)  zMag -= 32768;
}


2019年7月8日月曜日

Jetson Nano と コマンドでLチカ

LEDのチカチカは、GPIO を操作して行いますが。デフォルトでは root でしか操作できないようです。

配線

回路図とか描けないので、文章で・・
LEDと抵抗を直列につないで、Jestson の GND と GPIO16(Pin番号19)を接続します。

コマンドでLチカ

以下、シェルによるGPIOの操作になります。各行で何をしているか解説してみます。
$ sudo su
# echo 16 > /sys/class/gpio/export
# echo out > /sys/class/gpio/gpio16/direction
# echo 1 > /sys/class/gpio/gpio16/value
# echo 0 > /sys/class/gpio/gpio16/value
# echo 1 > /sys/class/gpio/gpio16/value
# echo 16 > /sys/class/gpio/unexport

1行目:root になります。/sys/class/gpio/export 等にアクセス権がないためです。
2行目:GPIO16を使用するため、/sys/class/gpio/export に "16" を書き込んでいます。
3行目:GPIO16を出力用にするために、/sys/class/gpio/gpio16/direction に "out" を書き込んでいます。
4行目:GPIO16の値に 1を設定しています。
5行目:GPIO16の値に 0を設定しています。
6行目:GPIO16の値に 1を設定しています。
7行目:GPIO16の使用をやめます。

GPIOの権限変更

root でしか使用できないのは、不便なのでデバイスの権限を変更します。

$ wget https://github.com/NVIDIA/jetson-gpio/archive/master.zip
$ unzip master.zip
$ cd jetson-gpio-master/
$ sudo cp etc/99-gpio.rules /etc/udev/rules.d/ 
$ sudo groupadd -f -r gpio
$ sudo usermod -a -G gpio ユーザ

1行目:NVIDIA さんから、gpio のファイル関係を取得
2行目:アーカイブファイルの展開
3行目:ディレクトリ移動
4行目:udev 用のファイルを配置
5行目:グループに gpio を追加
6行目:グループ gpio にユーザ(任意)を追加

再起動後、以下のパスの group がgpio になっていれば成功です。上記のシェルも gpio へ追加したユーザで実行できます。
ls -l /sys/class/gpio/export