2021年11月26日金曜日

RaspberryPi4 で PWM 入門 (Lフワ)

RaspberryPi4 で PWM 入門 (Lフワ)

概要

LED を PWM というアナログ信号を使ってゆっくり点滅させてみます
サンプルコードと回路を紹介します

環境

  • RaspberryPi4 8GRAM
  • RaspberryPiOS 5.10.17 armv7l
  • Python 2.7.16
    • pigpio 1.78

サンプルコード

後述でポイントを紹介しています
処理の概要はコメントにて記載しています

  • vim test_pwm.py
# -*- coding: utf-8 -*-
"""PWMのテストをするモジュール."""
import time
import RPi.GPIO as GPIO
import logging

from logging import getLogger


class TestPWM():
    """PWMのテストをするクラス."""

    def __init__(self):
        """GPIOやピン初期化を行います."""
        GPIO.setmode(GPIO.BOARD)
        GPIO.setup(12, GPIO.OUT)
        # channel=12 frequency=50Hz
        self.pin = GPIO.PWM(12, 50)
        logging.basicConfig(level=logging.INFO)
        self.logger = getLogger(__name__)

    def start(self):
        """pinをスタートさせます."""
        self.pin.start(0)
        self.logger.info('Started a pin for pwm.')

    def blink(self):
        """LEDをPWMで点滅させます."""
        self.logger.info('Started led blinking loop.')
        try:
            while True:
                # 5 刻みでデューティー比を変更します 0 -> 100
                for dc in range(0, 101, 5):
                    self.pin.ChangeDutyCycle(dc)
                    time.sleep(0.1)
                # 5 刻みでデューティー比を変更します 100 -> 0
                for dc in range(100, -1, -5):
                    self.pin.ChangeDutyCycle(dc)
                    time.sleep(0.1)
        except KeyboardInterrupt:
            pass
        finally:
            self.cleanup()

    def cleanup(self):
        """クリーンアップ処理をします."""
        self.pin.stop()
        GPIO.cleanup()
        self.logger.info('The pin cleanup process was completed.')


if __name__ == "__main__":
    pwm = TestPWM()
    pwm.start()
    pwm.blink()

ポイント

ピンを PWM 用として使う場合に GPIO.setup したあとに GPIO.PWM を呼び出します

周波数は高いほどより電力を必要とするアクチュエータなどを動かすことができます
今回は LED なので 50Hz ほどで十分です

ChangeDutyCycle で明るさを調整します
0 から 100 までで指定することができ 0 が暗くなり 100 が明るくなります
モーターなどの場合だと 0 が遅く、100 が速く回ります

処理が終了した際に必ずピンをもとに戻す必要があるので finally でクリーンアップしましょう

回路とサンプル動画

RaspberryPi の 6 ピンが GND になっています
12 ピンを LED のアノード側に 220 オームの抵抗を挟んで接続しています

実際にスクリプトを動作させると以下のように点滅するのが確認できると思います

最後に

RaspberryPi の場合ソフトウェア PWM という仕組みで PWM を出力しています
オシロスコープがある場合は波形を確認するとちゃんとした矩形波が出ていることが確認できると思います

自分は試していませんが RaspberryPi の周波数の上限は 8,000Hz ほどのようです
DC モーターなどは何とかなりそうですがステッピングモーターなど大きなモーターの場合にはモータドライバなどを使ったほうが良いでしょう

参考サイト

2021年11月25日木曜日

Gitlab CI でジョブが失敗したときに別のジョブを呼び出す方法

Gitlab CI でジョブが失敗したときに別のジョブを呼び出す方法

概要

when: on_failure を使います
ジョブごとに失敗した場合の挙動を指定したい場合は needs と組み合わせます

環境

  • RaspberryPi4 8GRAM
  • RaspberryPiOS 5.10.17 armv7l
  • Gitlab Runner 14.5.0

サンプル .gitlab-ci.yml

cleanup_build_job が何かしらのジョブが失敗した場合にコールされるジョブになります
when: on_failure が指定されていることがわかります

stages:
  - stage1
  - cleanup

.echo1_script: &echo1_script
  - "export MSG=hello"
  - "echo ${MSG} >> msg.txt"
  - "export MSG=HELLO"

.echo2_script: &echo2_script
  - "hoge"
  - "echo ${MSG} >> msg.txt"

cleanup_build_job:
  stage: cleanup
  script:
    - "echo 'Succeed cleanup.' >> msg.txt"
  when: on_failure
  artifacts:
    paths:
      - msg.txt

echo:
  stage: stage1
  script:
    - *echo1_script
    - *echo2_script
  artifacts:
    paths:
      - msg.txt

ジョブごとに失敗した場合の挙動を設定する場合

needs と組み合わせます
これを失敗した場合に実行するジョブごとに指定してあげることでそれぞれで失敗した場合の挙動を変えることができます

stages:
  - stage1
  - stage2
  - cleanup

.echo1_script: &echo1_script
  - "export MSG=hello"
  - "echo ${MSG} >> msg.txt"
  - "export MSG=HELLO"

.echo2_script: &echo2_script
  - "hoge"
  - "echo ${MSG} >> msg.txt"

cleanup_build_job_for_echo1:
  stage: cleanup
  script:
    - "echo 'Succeed cleanup by echo1.' >> msg.txt"
  when: on_failure
  needs: ["echo1"]
  artifacts:
    paths:
      - msg.txt

cleanup_build_job_for_echo2:
  stage: cleanup
  script:
    - "echo 'Succeed cleanup by echo2.' >> msg.txt"
  when: on_failure
  needs: ["echo2"]
  artifacts:
    paths:
      - msg.txt

echo1:
  stage: stage1
  script:
    - *echo1_script
  artifacts:
    paths:
      - msg.txt

echo2:
  stage: stage2
  script:
    - *echo2_script
  artifacts:
    paths:
      - msg.txt

ジョブの流れは以下のようになります
echo2 が失敗した場合には cleanup_build_job_for_echo2 だけが実行されています

echo2 も常に実行したい場合には

ただこの場合だと以下のように echo2 は実行されないので echo2 も常に実行したほしい場合には when: always を指定します

stages:
  - stage1
  - stage2
  - cleanup

.echo1_script: &echo1_script
  - "hoge"
  - "export MSG=hello"
  - "echo ${MSG} >> msg.txt"
  - "export MSG=HELLO"

.echo2_script: &echo2_script
  - "echo ${MSG} >> msg.txt"

cleanup_build_job_for_echo1:
  stage: cleanup
  script:
    - "echo 'Succeed cleanup by echo1.' >> msg.txt"
  when: on_failure
  needs: ["echo1"]
  artifacts:
    paths:
      - msg.txt

cleanup_build_job_for_echo2:
  stage: cleanup
  script:
    - "echo 'Succeed cleanup by echo2.' >> msg.txt"
  when: on_failure
  needs: ["echo2"]
  artifacts:
    paths:
      - msg.txt

echo1:
  stage: stage1
  script:
    - *echo1_script
  artifacts:
    paths:
      - msg.txt

echo2:
  stage: stage2
  script:
    - *echo2_script
  when: always
  artifacts:
    paths:
      - msg.txt

こんな感じで echo1 が失敗しても echo2 が実行されていることがわかります

最後に

これで失敗した場合にも特定のスクリプトを実行することができるようになりました

また調べてみると expected_stage_fail や on_failure_script と言った書き方もでてきたのですが expected_stage_fail や on_failure_script はどうやら使えないようです
https://gitlab.com/gitlab-org/gitlab/-/issues/19400

参考サイト

2021年11月24日水曜日

RaspberryPi4 に gitlab-runner をインストールする方法

RaspberryPi4 に gitlab-runner をインストールする方法

概要

今回は shell-executor として登録します
基本は ds64 モードで勧めていますが aarch64 でもインストールできます

環境

  • RaspberryPi4 8GRAM
  • RaspberryPiOS 5.10.17 armv7l

ds64-shell の起動

作業は 64bit 環境で行います

  • ds64-shell

curl, wget のインストール

  • sudo apt -y install curl wget

証明書系のツールインストール

libgnutls30 もインストールします
これがないと git clone 時にエラーになります

  • sudo apt -y install apt-transport-https ca-certificates libgnutls30

gitlab-runner のインストール

Gitlab の公式のリポジトリからインストールします
ds64 環境ではない 64bit 環境 (aarch64) ではこの手順から実行します

  • curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
  • sudo apt-get install gitlab-runner
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Suggested packages:
  docker-engine
The following NEW packages will be installed:
  gitlab-runner
0 upgraded, 1 newly installed, 0 to remove and 90 not upgraded.
Need to get 437 MB of archives.
After this operation, 476 MB of additional disk space will be used.
Get:1 https://packages.gitlab.com/runner/gitlab-runner/debian buster/main arm64 gitlab-runner arm64 14.5.0 [437 MB]
Fetched 437 MB in 2min 10s (3,375 kB/s)                                                                                                     
Selecting previously unselected package gitlab-runner.
(Reading database ... 38144 files and directories currently installed.)
Preparing to unpack .../gitlab-runner_14.5.0_arm64.deb ...
Unpacking gitlab-runner (14.5.0) ...
Setting up gitlab-runner (14.5.0) ...
GitLab Runner: creating gitlab-runner...
Home directory skeleton not used
Runtime platform                                    arch=arm64 os=linux pid=2632 revision=f0a95a76 version=14.5.0
gitlab-runner: the service is not installed
Runtime platform                                    arch=arm64 os=linux pid=2643 revision=f0a95a76 version=14.5.0
gitlab-ci-multi-runner: the service is not installed
Runtime platform                                    arch=arm64 os=linux pid=2673 revision=f0a95a76 version=14.5.0
Runtime platform                                    arch=arm64 os=linux pid=2721 revision=f0a95a76 version=14.5.0
INFO: Docker installation not found, skipping clear-docker-cache

runner の登録

Gitlab の URL とトークンを入力して登録します
executor は「shell」を入力しましょう

  • sudo gitlab-runner register

また gitlab-runner ユーザに gpio 関連を操作できるように権限を与えます

  • sudo usermod -aG gpio gitlab-runner

動作確認

プロジェクトに以下のような .gitlab-ci.yml を登録して成功するか確認しましょう

stages:
  - stage1
  - stage2

.echo1_script: &echo1_script
  - "export MSG=hello"
  - "echo ${MSG}"
  - "export MSG=HELLO"

.echo2_script: &echo2_script
  - "echo ${MSG}"

echo:
  image:
    name: alpine:latest
  stage: stage1
  script:
    - *echo1_script
    - *echo2_script

停止する場合は ds64-shell で

  • sudo systemctl stop gitlab-runner

再度起動する場合は ds64-shell で

  • sudo systemctl start gitlab-runner

します

トラブルシュート

server certificate verification failed. CAfile: 
/home/gitlab-runner/builds/QopMjzNB/0/root/project1.tmp/CI_SERVER_TLS_CA_FILE CRLfile: none

が出る場合は libgnutls30 がちゃんとインストールされているか確認しましょう
エラー文でググると証明書を自分で作成したりする記事が出てきますがそれだとダメなので気をつけましょう

Gitlab と通信できるようにファイアウォールなどの設定も確認しましょう

最後に

少しハマるポイントがありましたがインストールして動作しました

ds64 モードで紹介しましたが普通に armv7 でも動くかもしれません

参考サイト

2021年11月22日月曜日

波ダッシュと全角チルダの扱いに注意

波ダッシュと全角チルダの扱いに注意

概要

単純に違う文字になるので比較するときに注意しましょう

環境

  • Ruby 3.0.2p107

文字の比較と確認

irb で16進数の文字コードを確認してみます

irb(main):021:0> "〜".bytes.map {|b| b.to_s(16)}
=> ["e3", "80", "9c"]
irb(main):022:0> "~".bytes.map {|b| b.to_s(16)}
=> ["ef", "bd", "9e"]

上が波ダッシュで下が全角チルダです
見た目は一緒ですが Unicode は違うので当然比較すると false になります

irb(main):023:0> "~" == "〜"
=> false

自分が遭遇したケース

特定のサイトから取得した文字は全角チルダだったのですがそれを別のサービスの API を使ってサーバに保存し再度 GET API で取得すると波ダッシュになっていました

おそらく保存しているサーバ側では全角チルダを扱わずにすべて波ダッシュに変換して保存しているせいだと思われます

他の文字でも変換して保存している可能性がありサービス的に保存されたくない文字は変換やエスケープされている可能性があるので取り出すときに注意しましょう

2021年11月19日金曜日

AppScript「Logging output too large. Truncating output.」対策

AppScript「Logging output too large. Truncating output.」対策

概要

console.log だと出力の長さに制限があります
一番てっとり早いのは適当なセルに結果を出力してあげることです

環境

  • macOS 11.6
  • Chrome 91.0.4472.106
  • Google SpreadSheet
  • Apps Script

サンプルスクリプト

一部抜粋ですが console.log の箇所をセルに setValue するように変更するだけです

// console.log("var labels = ['" + labels.reverse().join("','") + "']");
// console.log("var amountData = [" + data.reverse().join(",") + "]");
// console.log("var calData = " + JSON.stringify(calData));
var labelResult = sheet.getRange("G12");
labelResult.setValue("var labels = ['" + labels.reverse().join("','") + "']");
var amountDataResult = sheet.getRange("G13");
amountDataResult.setValue("var amountData = [" + data.reverse().join(",") + "]");
var calDataResult = sheet.getRange("G14");
calDataResult.setValue("var calData = " + JSON.stringify(calData));

参考サイト

2021年11月18日木曜日

Gitlab の MergeRequest Approval Rule を試す

Gitlab の MergeRequest Approval Rule を試す

概要

Approval ルールはレビューが approval ボタンを押さないとマージボタンが有効にならない機能です
Gitlab のマージリクエストを間違ってマージしないようにするのに役に立ちます

環境

  • Gitlab EE 14.3.3

設定方法

まずは MergeRequest を作成します
そしてレビューの欄に「Approval rules」があるのでクリックします

すると「Add approval rule」というボタンが出てくるのでクリックします

Approval の名前と Approval の必要数そして Approval するレビュアーを選択します
ここで選択した人が approve しない限り MergeRequest をマージすることはできません

Approval Rule が作成されると以下のように Merge ボタンが disable になりマージできません
Draft がない状態でもマージボタンが押せないことが確認できると思います

最後に

approval 自体はフリープランでも使えますが approval settings と approval rule はプレミアプランしか使えないので注意しましょう

今回は MergeRequest ごとに作成する方法を紹介しましたがプロジェクトごとにルールの雛形を作成したりすることもできます
詳しくは参考サイトにある URL から確認してください

参考サイト

2021年11月17日水曜日

RaspberryPi4 (8GB RAM) で一ヶ月間 Monero をマイニングした結果

RaspberryPi4 (8GB RAM) で一ヶ月間 Monero をマイニングした結果

概要

タイトルの通りです
参考データとして紹介します

環境

  • RaspberryPi4 ModelB 8GB
  • RaspberryPiOS 5.10.17 armv7l
  • xmrig 6.15.2

結果

0.00049521 XMR

一日平均

0.00001597 XMR

稼働時間

ほぼ24時間
金曜日の一部 (約 7 時間ほど) だけ停止

稼働オプション

donate-level は 1 です
xmrig は直接 RaspberryPi 上で動作させています (docker 上ではないです)

arm7v アーキテクチャでは xmrig は動作しないので ds64 化して動かしています (参考)

平均ハッシュレート

120 hash/sec

下が 90 で上が 300 くらいブレがありそれを平均すると 100 - 130 ほどで推移していることになりました

交換可能になるまで

交換可能 XMR は執筆時点で 0.01 XMR です
これになるには一ヶ月 0.0005 XMR だとすると

  • 0.01 / 0.0005 = 20 ヶ月

になります
約 2 年ほどフル稼働させればようやく交換可能な値になります

最後に

電気代は計算していませんが1ヶ月100円ほどだとすると 20 ヶ月する稼働でも 2,000円ほどなので 0.01 XMR = 300円で余裕で赤字という結果になりました

将来的に Monero が跳ねれば話は別ですが、、