あらきけいすけのメモ帳

あらきけいすけの雑記帳2

Raspberry Pi Zero W(RPi4BもOK)をUSBガジェットにしてUSBケーブル1本でWindows 10マシンから操作する

自分用の書きかけの覚書。Raspberry Pi Zero WとWindows 10 ノートPCをUSBケーブル1本(A-micro B*1)で繋いで(給電も兼ねる)、Win10PCからRPi0wにリモートログインできるようにする(RPi0w側でsshが起動していればWin側はTeraTerm*2などで、RPi0w側でVNCが起動していればWin側はVNC Viewer*3などで、RPi0w側でxrdp*4が起動していればWin側はリモートデスクトップ接続でつなぐ)。要点はどうも次の2点に集約できそう:

  • ラズパイ側
    • linux USB gadget 機能を有効にする。*5Raspbian OSの/bootディレクトリのconfig.txt, cmdline.txtを書き換える。
      1. /boot/config.txt の最後尾に "dtoverlay=dwc2" と書かれた行を追加する。
      2. /boot/cmdline.txt の "rootwait" と "quiet" の間に " modules-load=dwc2,g_ether" を書き加える。
      詳細は参考にしたサイトを参照。
    • sshVNCを有効にするとか、xrdpをインストールするとかのネットワーク接続によるリモートログイン可能な状況を作る)
  • Windows

首尾よく接続出来たら、RPi0wにUSB経由でリモートログインして、Wi-Fi接続の設定をするとさらに世界が広がるwwww
参考にしたサイト:
qiita.com
gist.github.com
blog.gbaman.info

OpenCV+Pythonで動画を録画/再生する(音声はなし, Windows 10/Raspberry Pi 共通)

自分用の覚書。OpenCV*1で動画を録画するためのPythonミニマル・コード*2
サンプル1:PC/ラズパイに接続されたUSBカメラ*3の動画像を表示する。終了はCtrl+C. VideoCapture()の引数の0はビデオデバイスの番号。

import cv2
cap = cv2.VideoCapture(0)
try:
    while True:
        ret, frame = cap.read()
        if ret == True:
            cv2.imshow('a',frame)
        cv2.waitKey(1)

except KeyboardInterrupt:
    cap.release()
    cv2.destroyAllWindows()

サンプル2:PCに接続されたカメラの動画像をディスプレイに表示し、ファイル'test.m4v'に録画する。終了はCtrl+C.([2019.6.24追記]手元のRPiではデスクトップ環境上の Python3(IDLE)を使って実行すると、出力した動画ファイルが常に壊れていた。LXTerminal上で実行すると、再生可能な動画ファイルを出力した。)低速度撮影(time lapse)は2, 12, 20行頭の#を取る

import cv2
#import time

cap = cv2.VideoCapture(0)
fps    = cap.get(cv2.CAP_PROP_FPS)
width  = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

fname  = 'test.m4v'
fmt    = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
size   = (width,height)
writer = cv2.VideoWriter(fname, fmt, fps, size)
#intrvl = 1 #[sec] set time interval of time-lapse recording

try:
    while True:
        ret, frame = cap.read()
        if ret == True:
            cv2.imshow('a',frame)
            writer.write(frame)
            #time.sleep(intrvl) # waiting (for time-lapse)
        cv2.waitKey(1)

except KeyboardInterrupt:
    cap.release()
    cv2.destroyAllWindows()

サンプル3:サンプル2で録画したファイル'test.m4v'を再生する。終了はCtrl+C.

import cv2
import time

vFile  = 'test.m4v'
cap    = cv2.VideoCapture(vFile)
fps    = cap.get(cv2.CAP_PROP_FPS)

try:
    while cap.isOpened():
        ret, frame = cap.read()
        if ret == True:
            cv2.imshow('a',frame)
            time.sleep(1/fps)
        cv2.waitKey(1)

except KeyboardInterrupt:
    cap.release()
    cv2.destroyAllWindows()

Microsoft Excel について

業務用の覚書。書きかけ。

Excelの利点

  • (多分、職場の)誰もが Excel を持っている。Excel ファイルとちょっとましなマシン(Core i7 + 8GB RAM とか)があればどこでも作業できる。(業務遂行に関して自由度が上がる)
  • (多分、実用的には、項目数が50以下、レコード数が10,000以下程度なら) WYSIWYG のデータベースとして使える。つまりクエリを投げずに直に検索, 置換, 編集ができる。とくに「フィルター*1」と「ウィンドウ枠の固定*2」は操作が直感的でいい。
  • オンプレミス*3で運用できる。(これはGoogleドライブにはできない)
  • プログラム(VBAマクロ)を書いてデータ操作ができる。(ただし Visual Basic for Application は動作がもっさりとしている。特にスレッディングができない*4。)
  • (たしかに PythonPHPExcel ファイルを操作できるライブラリはあり、そっちの方が高速ではあるのだけれど、Excel とは別のプログラミング環境を導入する必要がある…というのは、可搬性に関わる敷居が高いことを意味していると思う)
  • Excel ファイルにデータを書き出せる(データファイルとアプリケーション実行環境の「閉じた(複数にまたがらない)」エコシステムである。)
  • VBA には「連想配列( Scripting.Dictionary オブジェクト)」*5があるので Key-Value 的なコードが書けなくもない。これは重複検出に便利。
  • VBA は変数名にマルチバイト文字*6が使えるので、テーブルの項目名を変数名に使うとかできちゃったりする
  • Excel VBA 使いがいれば、外注するよりコミュニケーションの時間コストを下げることができる

コーディングの注意点

Excel VBA による Excel ワークブック/ワークシート, CSVファイル, XMLファイル等のデータ処理の進行は、HTMLベースのWebアプリケーションに似ていてイベント(Excel内のボタン操作など)によってコードが駆動される。

ラグランジュ補間(2点を通る直線の公式)、単位の換算、そのプログラミングについての覚え

授業のための覚書

2点(x_0,y_0), (x_1,y_1)を通る直線の公式:\displaystyle y=\frac{x-x_1}{x_0-x_1}y_0+\frac{x-x_0}{x_1-x_0}y_1
これは Lagrange 補間(Lagrangian interpolation*1)と呼ばれる計算技法である。この式は次のようにも書ける:
2点(x_0,y_0), (x_1,y_1)を通る直線の公式:\displaystyle y=\frac{x-x_0}{x_1-x_0}(y_1-y_0)+y_0
「直線の式」だからって、この計算式の応用範囲が「直線を描画する」といったグラフィックスだけに限られるわけではない。例えば、摂氏温度*2から華氏温度*3への換算にも使える。水の氷点が(0度C,32度F), 沸点が(100度C,212度F)なので摂氏温度がc度のときの華氏温度の値は\displaystyle f=\frac{c-100}{0-100}32+\frac{c-0}{100-0}212になる。
ここで受験数学の答案のような「筆算にしばられた発想」だと、係数を整理してf=1.8c+32とまとめるところだが、プログラミングの世界では整理すべきでない。この換算をC言語コードで書くときは、次のように書くのがベター;

// マクロ, 関数形式マクロ
#define Cfleeze   (0.0)
#define Cboil   (100.0)
#define Ffleeze  (32.0)
#define Fboil   (212.0)
#define tempC2tempF(tempC) (tempC - Cfleeze)/(Cboil - Cfleeze)*(Fboil - Ffleeze) + Ffleeze
// 定数, 関数
float tempC2tempF (float tempC) {
  const float Cfleeze =  0.0, Cboil = 100.0;
  const float Ffleeze = 32.0, Fboil = 212.0;
  tempF = (tempC - Cfleeze)/(Cboil - Cfleeze)*(Fboil - Ffleeze)
          + Ffleeze;
  return tempF;
}

このコードならば「tempC=CfleezeのときにFfleeze」「tempC=CboilのときにFboil」の値を返す tempC の1次関数を計算していると分かる。ややこしい計算はコンピュータにやらせればよい。むしろ「何の計算をコンピュータにやらせているのかはっきり分かる」コードの方がベターである*4

演算数から考えると const を使って計算の定数を予め作っておいて*5、define で「インラインで計算」するのが早いかも:

// マクロ, 関数形式マクロ
// tempC2tempF(tempC) = (tempC - Cfleeze)/(Cboil - Cfleeze)
//                      *(Fboil - Ffleeze) + Ffleeze
#define Cfleeze   (0.0)
#define Cboil   (100.0)
#define Ffleeze  (32.0)
#define Fboil   (212.0)
const float
  tempC2tempFCoeff  = (Fboil - Ffleeze)/(Cboil - Cfleeze),
  tempC2tempFOffset = -(Cfleeze)*(Fboil - Ffleeze)/(Cboil - Cfleeze)
                      + Ffleeze;
#define tempC2tempF(tempC) ((tempC)*tempC2tempFCoeff + tempC2tempFOffset)

*1:ラグランジュ補間 - Wikipedia

*2:セルシウス度 - Wikipedia

*3:華氏 - Wikipedia

*4:プログラミングの世界では、いきなり数値をソースコードに書くことは「マジックナンバー」と呼ばれ、プログラムの可読性が悪くなるので避けるべきとされている。;マジックナンバー (プログラム) - Wikipedia可読性 - Wikipedia

*5:変数名は長くなってもよいから、計算で使うデータの内容を表示した方がよい。変数名の長さは、実際のCPU上で動くマシン語には影響しない。

python のリスト/辞書/タプルに特定の値を持つ要素が存在するかどうかの確認方法

で、躓いたのでメモをする。

if 〔探索値〕 in 〔リスト名/辞書名/タプル名〕:
        〔探索値がリスト/辞書のキー/タプル中にあったときの処理〕

ここで 〔探索値〕の添字を返すメソッド

〔リスト名〕.index(探索値)

を用いると存在しない場合に ValueError を返して、例外処理を書かないとコードの進行が止まる。辞書の〔キー〕・〔値〕のペアの〔値〕の中から探索するには

if 〔探索値〕 in 〔辞書名〕.values():
        〔探索値が辞書の値の中にあったときの処理〕

pigpio ライブラリの spi_xfer() 関数を用いて Raspberry Pi 3B から SPI 接続のA/Dコンバータ MCP3208 を利用する

自分用の覚書。ようやく pigpio の spi_open() と spi_xfer() のパラメータの与え方が分かったので、Python と C のミニマルコードをメモしておく。

Python

参考にしたサイト
tomosoft.jp

#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# Raspberry Pi 3B から MCP3208 を利用するコード (終了は Ctrl-C)
#
# ピンの接続
#   Raspberry Pi 3B           MCP3208
#   [19] GPIO_10 SPI_MOSI  -> [11] D_IN
#   [21] GPIO_09 SPI_MISO  <- [12] D_OUT
#   [23] GPIO_11 SPI_CLK   -> [13] CLK
#   [24] GPIO_08 SPI_CE0_N -> [10] ~CS/SHDN
#
# MCP3208 の [1]CH0 のA/D変換値(0~4095)を表示する
#
# 参考にしたサイト (2018年10月27日アクセス)
#   http://abyz.me.uk/rpi/pigpio/python.html
#     pigpio library: Python Interface
#   https://tomosoft.jp/design/?p=10477
#     TomoSoft: pigpioによるI2CとSPIインタフェースの実装
#     注: MCP3208 は12bitのA/Dコンバータだが testspi.py では
#         そのうちの上位10bitのデータ(0~1023)を利用していた。
#

import time
import pigpio

slct = 0 # +1 +1 # SPI接続機器の番号 chip select
baud = 50000     # 通信速度
flag = 0 # +256  # bin(256) = 0b100000000 は Aux SPI の利用フラグ
adch = 0         # MCP3208のCH0の番号

pi = pigpio.pi()
hndl = pi.spi_open(slct, baud, flag) # デバイスオープン

try:
  while True:
    cmnd = ( 0b00011000 + adch ) << 2
    c, raw = pi.spi_xfer(hndl,[cmnd,0,0]) # 最初の要素が命令の入力
    #
    #    [0][1][1][D2][D1][D0][0][0]
    #        |  |   |   |   |
    #        |  |  読み出しチャネルの指定
    #        | 1: シングルエンド
    #       [スタートビット]
    #
    data = ((raw[1] & 0b11111111) <<  4) + \
           ((raw[2] & 0b11110000) >>  4)
    print(c,raw,bin(data),data)
    time.sleep(1)

except KeyboardInterrupt:
    pi.spi_close(hndl)
    pi.stop()

C言語

参考にしたサイト
Raspberry Pi 3とADS7843を使ってタッチスクリーンの情報を受け取る(Cでpigpioを使ってSPI通信→Nodejs) - Qiita
gpio - pigpio spiXfer in C++ - Raspberry Pi Stack Exchange

/*
  pigpio の spiOpen(), spiXfer() を利用する最小限コード
  Raspberry Pi 3B と MCP3208 の接続は上の Python コードと同じ
  動作: A/Dコンバータを1秒間隔で10回読んで、表示する(終了は自動)

  参考にしたサイト
    https://qiita.com/yuji_miyano/items/e86150759818c3c12fa4
    https://raspberrypi.stackexchange.com/questions/79127/pigpio-spixfer-in-c/79128#79128
*/
#include <stdio.h>
#include <unistd.h>
#include <pigpio.h>

int main (void) {
  if ( gpioInitialise() < 0 ) {
    printf("gpioInitialise() failed\n");
  }
  else {
    printf("gpioInitialise() succeeded\n");
    int slct = 0;//+2   // SPI接続機器の番号 chip select
    int baud = 50000;   // 通信速度
    int flag = 0;//+256 // 256: Aux SPI の利用フラグ
    int hndl = spiOpen(slct, baud, flag);
    if ( hndl < 0 ) {
      printf("spiOpen() failed\n");
    }
    else {
      printf("spiOpen() succeeded\n");
      int count = 0;
      while ( count < 10 ) {
        int adch = 0;  // MCP3208のCHの番号(0-7)
        char txBuf[3]; // 読み出し命令, AD変換データの入れ物
        txBuf[0]= ( 0x18 + adch ) << 2;
        txBuf[1]= txBuf[2]= 0;
        spiXfer(hndl,txBuf,txBuf,3); // pigpio: SPI読み出し
        int data =  // 読み出したバッファからの移し替え
          ( txBuf[1] & 0xff ) << 4 |
          ( txBuf[2] & 0xf0 ) >> 4;
        printf("%d %d\n",count,data);
        count++;
        sleep(1);
      }
      spiClose(hndl);
    }
    gpioTerminate();
  }
}

2018年台風12号 Jongdari の動きと天気図

あまりにもへんてこな動きをした台風だったので*1、2018年7月28日21時の天気図と衛星画像を簡単にまとめてみた。低気圧は反時計回りの渦なのだが、今回は上空10,000m位の高さにかなり強くて大きな低気圧があって、衛星画像を見ても日本の南におおきな渦が回っているのが見える。*2f:id:arakik10:20180729083954j:plain

見たところ台風12号はこの上空の低気圧の流れに流されて西へと向かう奇天烈な軌道を取ったようにみえる。藤原の効果*3というときは主に同じ高度の2個の渦の相互作用を考える(例えば英語版Wikipediaにあるように2個の台風の融合)ようだが、今回は「上下2層」の相互作用なので、「融合」は無くて「吹送(みたいな何か)」が起きたのか。

*1:2018年7月28日3時JSTのJTWCの進路予想f:id:arakik10:20180729152042g:plain

*2:この季節にこのような場所と高度にこのような低気圧ができるのが珍しいことかどうかは知らない。

*3:Fujiwhara effect - Wikipedia, 藤原の効果 - Wikipedia