そろそろ中堅エンジニアのIT雑記

プログラミングを仕事にして若干、まだまだ新米エンジニアの雑記です。

Raspi天体カメラ

品不足が解消されたみたいなので、RaspberryPi 4とHQカメラを入手しました。
天体撮影用のカメラを作ってみました。

レンズ

天体撮影するに当たって、大事なのはレンズです。
ラズパイHQカメラはC-CSマウントレンズが使えます。
しかし、C-CSマウントは監視カメラなどによく使われるため、あまり日常使用されません。
手持ちのEFマウントレンズが使えるよう、K&F Conceptのマウントアダプタを利用しました。
焦点距離が55mm-200mmのレンズを装着しました。

ラズパイHQカメラのセンササイズをフルサイズ換算すると約5.6倍になります。
従って望遠端の200mmを利用すると1120mm相当の焦点距離を得られます。
これは天体撮影ではかなりメリットです。

筐体

ともかく、撮影をトライしてみたかったので、簡単な3Dプリントで筐体を出力しました。

RaspberryPi

持ち運びを考えて、本体はRaspberryPi Zeroなどでも良かったのですが、撮影後の処理速度を考えてRaspberryPi 4にしました。
RaspberryPi 5が入手できたら、置き換えも検討しています。
SDカードではなく、USB SSDにブートイメージを焼き、起動していいます。

システム構成

プログラム言語はPythonを採用しましたが、撮影コマンドはlibcamera-stillを利用したいため、subprocess.run()を利用しました。
また、フォーカス合わせのためのプレビュー表示はRaspberryPiにVNC接続してlibcamera-helloコマンドを叩くことにしました。
撮影はPythonスクリプトを組み、撮影したJpeg画像をLINEで通知できるようにしています。
Pythonスクリプトの実行はIPhoneからRaspberryPiにSSH接続して実行します。IPhoneのショートカット機能を使って、アイコンをタップするだけで実行できるようにしました。
以上の構成で、IPhoneからアイコンをタップし、LINEでjpeg画像を受け取れるシステムを作成しました。

スクリプト

以下が作成したスクリプトです。

import os           # for base directry
import sys          # for command line argument
import datetime     # for date time string
import time         # for time evaluation
import requests     # for LINE API
import subprocess   # for unix command execution

basedir = os.path.dirname(__file__)

url = "https://notify-api.line.me/api/notify" 
token = "LINE notifyトークン"

start_time = time.time()

t_delta = datetime.timedelta(hours=9)
JST = datetime.timezone(t_delta, 'JST')
now = datetime.datetime.now(JST)
date_str = now.strftime("%Y%m%d")
time_str = now.strftime("%H%M%S")

output_dir = basedir + "/capture/" + date_str
if not os.path.isdir(output_dir):
    os.mkdir(output_dir)

filename = sys.argv[1]  # output file name

exposure_time = float(sys.argv[2])  # exposure time in seconds
exposure_time_micro = exposure_time * 1000000

output_file = output_dir + "/" + filename + "_" + time_str + ".jpg"

subprocess.run(["libcamera-still", \
                            "-o", output_file, \
                            "--shutter", str(exposure_time_micro), \
                            "--gain", "16", \
                            "--immediate"])

headers = {"Authorization" : "Bearer "+ token} 
message =  filename + "_" + time_str + ".jpg was captured.\n" \
           + "exposure time:" + str(exposure_time) + "sec." 
payload = {"message" :  message} 
image = output_file
files = {'imageFile': open(image, 'rb')}
r = requests.post(url, headers = headers, params=payload, files=files)

end_time = time.time()
diff_time = end_time - start_time
print(diff_time)

試し撮り

試し撮りしたオリオン大星雲