RaspberryPi[24] Raspberry PiリチウムUPS拡張ボード

ラズパイ用のUPSです。アマゾンで偶然見つけて購入しました。これで。スーパーキャパシタは出番ないかも。アマゾンによると下記の説明があります。

・放電中の充電をサポート:外部電源障害は、UPS電源の出力には影響しません。 注意:充電中にUPSを使用してRaspberry Pi3b / 3B +に電力を供給する場合,入力電力が2.5A以上であることを確認してください。推奨用途:3V 2.5A電源
・2 つの電源モード: 屋外ポータブル モデルと屋内 UPS 電源供給モード: 1) 屋外ポータブル電源として、マザーボードはリチウム電池で駆動されます。外部電源の最大容量は 5.1V です。 2.5A。 2)屋内UPS電源モードとして:UPS電源インターフェース用の外部5V電源、電源要件5V 2A-3A、最大出力電流は5V 3Aに達する可能性があります
・4+2LED は、バッテリー電源、充電または放電のステータスを表示するように設計されています。 1) 4 バッテリー電源 LED: 現在のバッテリー電圧と電源を表示するために使用されます。 2) 電源 LED:スイッチを「ON」にすると LED が点灯し、「OFF」にすると LED が消灯します。 (電源が外部から供給されているかどうかを確認するために使用されます)。 3) 充電インジケータ LED: UPS が MicroUSB インターフェースを介して外部から充電されると、充電 LED が作動し始めます
・保護機能: 外部出力ポートには自己回復ヒューズがあり、外部短絡による RPi の焼損を防ぎます。 1) 5V.3A 自己回復ヒューズ: 2 つの USB 出力電流の合計が 3A になると、自己回復ヒューズが切れます。無負荷の場合、5V出力は自動的に復元されます。 2) PMU 過放電保護: リチウム電池の電圧が 2.8V を下回ると、PMU は電池が過放電されたと判断し、リチウム電池を保護するために 5V 出力を遮断します
・バッテリー容量:最大3800mAH、出力電流:1.8A
・出力電圧:5.1V±0.1V、ダブルUSB出力

UPSの機能としては十分だと思います。価格は¥3,398で、4000mAh のリチューム電池が付いているのでコスパも結構いいです。マニュアルは付属していないですが、RPi UPSPack V3 Product User Guideに必要な情報があります。

ラズパイとの接続はこんな感じです。

Userガイドを見れば配線はわかると思いますが、UPS基板とラズパイの基板をシリアル通信線と電源線を接続します。リチュームイオン電池はコネクタをUPS基板に刺すだけです。リチュームイオン電池は付属していますが、一般に出回っている、3.7Vタイプであれば使用できると思います。少し調べたところ、プラスとマイナスは規格化されていないようなので、購入する場合はコネクタ形状と何方が+なのかをよく見て買わないと火を噴くかもしれません。これくらい標準化してくれよと思う。

ラズパイへ電源はUPSのUSB-AからラズパイのUSB-Cに接続します。AC/DCの5VはUPSのUSB-Cに刺します。この時、UPS上にあるSWでラズパイに電源を供給するかしないかを切り替えます。デフォルトは供給しないになっていました。UPS上には4つのLEDがあり、LED4まで点灯すると満充電、LED1が点滅しだすともうすぐで電池切れのようです。ここまでが、ハードウエアのお話でした。

ソフトは、ここからZIPファイルをダウンロードします。バイナリでラズパイにSCPでコピーします。コピーしたZIPファイルを解凍します。その時のフォルダの名称がUPSPACK_V3-masterとなっているので、UPSPACK_V3にrenameしておきます。解凍した後、.py ファイルは chmod +x で実行フラグ立てておきます。

次に、ラズパイのシリアルポートを有効にします。必要なシリアルポートはBTに使用されているので、まずはBTを無効にします。

/boot/config.txt の末尾に、dtoverlay=disable-btを追記します。

追記:シリアルコンソールを有効にしていると、何やらプロセスが動き、ラズパイが重くなりますので、Raspberry Piの設定でシリアルコンソールを無効にします。

sudo vi /boot/config.txt
dtoverlay=disable-bt

ここで一旦再起動を行ったあと、Raspbery Piの設定を開き、インターフェースのシリアルポートをオンにします。それでもう一度再起動し、下記のように出ればOKです。

pi@raspberrypi:/etc $ ls -al /dev | grep serial*
lrwxrwxrwx   1 root root           7  4月  7 15:25 serial0 -> ttyAMA0
lrwxrwxrwx   1 root root           5  4月  7 15:25 serial1 -> ttyS0

ラズパイとUPSはシリアル通信をしているので、確認するために、minicomをインストールして下記のように確認します。

sudo apt-get install minicom -y
sudo minicom -D /dev/ttyAMA0 -b 9600

下記プログラムは電源供給がされない場合、且、90%を割ったらシャットダウンコマンドを発呼します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <signal.h>
#include <stdlib.h>
#include <syslog.h>

#define BUFFER_SIZE 255
#define SHUTDOWN_P  95
#define TRUE 1
#define FALSE 0


int serial_port;

void sigint_handler(){
	printf("\n recieve CTL-C\n");
	close(serial_port); 
	exit(0);
}
    
int main(int argc, char *argv[])
{
	
	char *p;
	long index;
	int int_left;
	int i;
	int cnt;
	int disp;
	
	if(argc > 1) disp = TRUE;
	else FALSE;

	signal(SIGINT, sigint_handler);
   
	
    serial_port = open("/dev/ttyAMA0", O_RDWR);  // シリアルポートのパスを適切に指定してください
    if (serial_port < 0) {
        perror("シリアルポートを開くエラー");
        return 1;
    }

    struct termios tty;
    memset(&tty, 0, sizeof(tty));

    if (tcgetattr(serial_port, &tty) != 0) {
        perror("tcgetattr エラー");
        return 1;
    }

    // ボーレートの設定(例: 9600 bps)
    cfsetispeed(&tty, B9600);
    cfsetospeed(&tty, B9600);

    // フロー制御の設定
    tty.c_cflag &= ~PARENB;  // パリティなし
    tty.c_cflag &= ~CSTOPB;  // ストップビット1
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;      // データビット8

    // ローカルモードの設定
    tty.c_lflag = 0;

    // 非カノニカルモードの設定
    tty.c_iflag &= ~IGNBRK;
    tty.c_iflag &= ~(IXON | IXOFF | IXANY);

    // 非カノニカルモードでの読み取りを指定
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 0;

    // 設定の適用
    if (tcsetattr(serial_port, TCSANOW, &tty) != 0) {
        perror("tcsetattr エラー");
        return 1;
    }

    // データの読み取り
    char buffer[BUFFER_SIZE];
    char left[BUFFER_SIZE];  
    char data[BUFFER_SIZE];  
        
    memset(buffer, 0, sizeof(buffer));

    while (1) {
        int bytes_read = read(serial_port, buffer, sizeof(buffer));
        if (bytes_read < 0) {
            perror("データの読み取りエラー");
            return 1;
        }

        if (bytes_read > 0) {
			for(i=0;i<bytes_read;i++){
				data[cnt]=buffer[i];
				cnt++;
			}
			if(strchr(buffer,'\n') != NULL ){
				data[cnt] = '\0';
				cnt = 0;
			}
			if(disp == TRUE) printf("%s", data);
			
			if(strstr(data,"NG")!= NULL){          
				p = strstr(data,"Vout");
				if(p != NULL){
					index = p - data;
//					printf("index : %d\n",index);

					for(i=0;i<3;i++){
						left[i] = data[index-4+i];
					}
					left[3] = '\0';
					sscanf(left,"%d",&int_left);
					if(disp == TRUE) printf("%d\%\n",int_left);
					if(int_left< SHUTDOWN_P) {
					if(disp == TRUE) printf("shutdown \n");
					if(disp == FALSE)syslog(LOG_INFO,"shutdown by UPS");
					if(disp == FALSE)	system("sudo /usr/sbin/shutdown -h now");   
					}         
				}
			}
		}
		memset(buffer, 0, sizeof(buffer));
	}
    close(serial_port);
    return 0;
}

こんなのがずらずら出てくれば通信しています。 

$ SmartUPS V3.2P,Vin GOOD,BATCAP 96,Vout 5250 $
96%
$ SmartUPS V3.2P,Vin GOOD,BATCAP 96,Vout 5250 $
96%
$ SmartUPS V3.2P,Vin GOOD,BATCAP 96,Vout 5250 $
96%
$ SmartUPS V3.2P,Vin GOOD,BATCAP 96,Vout 5250 $
96%
$ SmartUPS V3.2P,Vin GOOD,BATCAP 96,Vout 5250 $
96%
$ SmartUPS V3.2P,Vin GOOD,BATCAP 96,Vout 5250 $
96%
$ SmartUPS V3.2P,Vin GOOD,BATCAP 96,Vout 5250 $
96%

電源供給を断ちラズパイが落ちるまでは約6時間でしょうか。LED1の点滅からしばらくしてラズパイが落ちました。この時のログを見てみると、即死でしたので、特にshutdown コマンドは吐かないようです。その後、再度電源を供給するもしばらくはラズパイは起動しません。ある程度、リチューム電池に蓄電されないと起動しないようです。

次にやることは、電源供給が止まったらshutdown コマンドを実行するようにすることと、再度、電源供給がなされたら起動できるようにすることかな。

電源供給時は  Vin NG

電源無響給仕は Vin GOOD

これを見れば、shutdown コマンドは出せそうだね。

最終的には、shutdown している間は電源供給し、shudownが終わったころにラズパイの電源をオフにするという回路は絶対に必要なんですが、これを実現するためには、時素リレーか、マイコンもしくはカウンターで時間保留する必要はあります。マイコンを使うと何でもできるので、ESP32にやらせようと思います。