ブレッドボード上ですが、7セグLED6桁ダイナミック表示成功です。
私は初体験なので嬉しいですね。自作プログラムも表示に関しては上手く出来たと自画自賛。
調子に乗って1/10秒表示の7桁にしてみました。
今、ラズパイでNTP時計を自作しようと奮闘中なんですが、プログラムの自作に目処が付いたので、その自作プログラムをデーモン化して自動起動するようにしてみました。
この情報は、無知の私がネットで知り得た事なので、全てが誤りかも知れません。また、OSの再起動コマンドsudo reboot時、自作プログラムの終了が遅い時があります。でもsudo shutdown -r nowには直ぐに反応しますが。
これらを理解した上で参考にして下さい。
自作プログラム(test11)やユニットファイルの置き場所は
自作プログラム
/usr/local/sbin/test11
ユニットファイル
/etc/systemd/system/test11.service
自作プログラムのmain()にデーモン関数を使用。
これにはヘッダファイル unistd.h が必要です。
#include <unistd.h>
int main(void)
{
if(daemon(0, 0) == 0) { // デーモン関数
mainLoop(); // ここに自作プログラム(無限ループ)を書く
} else {
cout << "error" << endl; // この1行は自信無し
}
return 0;
}
ユニットファイル作成。ntp.serviceの後に起動、GUIログイン環境。
$ sudo vi /etc/systemd/system/test11.service
[Unit] Description = test11 daemon After = ntp.service ConditionPathExists = /usr/local/sbin [Service] ExecStart = /usr/local/sbin/test11 Restart = no Type = forking [Install] WantedBy = graphical.target
パーミッションを644に変更。
$ sudo chmod 644 /etc/systemd/system/test11.service
systemctlコマンドでデーモンとする。
$ sudo systemctl daemon-reload $ sudo systemctl start test11.service $ sudo systemctl enable test11.service
ハードは出来ていないけどソフトはおおかた完成?
↓ この大型7セグLED6個とラズパイでNTP時計を作るのが目標なんです。丁度、今発売中のハム関係の雑誌で同じような記事があったから、そのソースコードが気になるんですが。
時刻取得及び7セグLED6桁ダイナミック表示ルーチン(無限ループ)は
このフローチャートはLucidchartのフリー版で作成。
一桁当たりの表示時間を3ミリ秒とすると、時刻の取得は1秒間に約55回になります。この時、Pi4でのCPU使用率は約8%でした。実際にはZeroにする予定なので、どの位のCPU使用率なるのか心配です。Zeroでも少ないCPU使用率なら時刻の取得サイクルは、このまま変えずに行きたいです。
/*
* test12.cpp
*
* daemon化
*
* 6桁ダイナミック表示対応
* 時刻 08:34:27 の場合
* 表示順序は 7 -> 2 -> 4 -> 3 -> 8 -> 0
*
*/
#include <iostream>
#include <pigpio.h>
#include <unistd.h>
#define H 0x1
#define L 0x0
#define SEG_ON 0x1
#define SEG_OFF 0x0
using namespace std;
void mainLoop(void);
int main(void)
{
if(daemon(0, 0) == 0) { // デーモン関数
mainLoop();
} else {
cout << "error" << endl;
}
return 0;
}
void mainLoop(void)
{
int i, j;
int num[6];
struct timespec ts;
struct tm lotm;
// 1秒 10秒 1分 10分 1時 10時
// Common 1 2 3 4 5 6
static int common[6] = {18, 23, 24, 17, 25, 5};
// GPIO 18 23 24 17 25 5
// 7seg a b c d e f g dp
static int nanaseg[8] = {21, 20, 16, 26, 19, 6, 13, 12};
// GPIO 21 20 16 26 19 6 13 12
static int segdata[12][8] = { // 7セグメントデータ
// a b c d e f g dp
{H, H, H, H, H, H, L, L}, // 0
{L, H, H, L, L, L, L, L}, // 1
{H, H, L, H, H, L, H, L}, // 2
{H, H, H, H, L, L, H, L}, // 3
{L, H, H, L, L, H, H, L}, // 4
{H, L, H, H, L, H, H, L}, // 5
{H, L, H, H, H, H, H, L}, // 6
{H, H, H, L, L, L, L, L}, // 7
{H, H, H, H, H, H, H, L}, // 8
{H, H, H, H, L, H, H, L}, // 9
{L, L, L, L, L, L, L, L}, // Blank
{L, L, L, L, L, L, L, H}, // dp
};
// pigpioライブラリ初期化
if (gpioInitialise() < 0) exit(1);
// コモン用GPIOピンをアウトプット設定
for (i = 0; i < 6; i++) {
gpioSetMode(common[i], PI_OUTPUT);
}
// セグメント用GPIOピンをアウトプット設定
for (i = 0; i < 8; i++) {
gpioSetMode(nanaseg[i], PI_OUTPUT);
}
/*
*
* 時刻取得及びダイナミック表示ルーチン(無限ループ)
*
* 時刻取得、1桁3ミリ秒表示×6、時刻取得、1桁3ミリ秒表示×6の繰り返し
*
*/
while (1) {
clock_gettime(CLOCK_REALTIME, &ts); // 時刻の取得
localtime_r(&ts.tv_sec, &lotm); // ローカル時間に変換
num[0] = lotm.tm_sec % 10; // 1秒の桁取得
num[1] = lotm.tm_sec / 10; // 10秒の桁取得
num[2] = lotm.tm_min % 10; // 1分の桁取得
num[3] = lotm.tm_min / 10; // 10分の桁取得
num[4] = lotm.tm_hour % 10; // 1時の桁取得
num[5] = lotm.tm_hour / 10; // 10時の桁取得
for (j = 0; j < 6; j++) { // 6桁ダイナミック表示ルーチン
for (i = 0; i < 8; i++) { // 7セグメントデータセット
gpioWrite(nanaseg[i], segdata[num[j]][i]);
}
gpioWrite(common[j], SEG_ON); // 7セグLED点灯
gpioDelay(3000); // 3ミリ秒点灯維持
gpioWrite(common[j], SEG_OFF); // 7セグLED消灯
}
}
// pigpioライブラリ終了処理
gpioTerminate(); // これは無限ループに含まれないので不要?
}
先日、Raspberry Pi 4でLチカを経験してから、毎晩これに夢中です。
あれから物凄く努力して、7セグLEDを1つ繋げて現時刻の0秒から9秒を表示出来るようになりました。
↑ 1桁ですが、疑似ダイナミック表示させています。点灯は0.25ミリ秒、消灯は1.25ミリ秒を繰り返して、6桁のダイナミック表示1桁目のつもりなんですが。
私の開発環境は、このブログ内にある「ラズパイで初めてのLチカ」を見て下さい。
↓ 点灯消灯時間を変えてありますが、そのソースコードです。
/*
* test7.cpp
* clock_gettime()に変更
*/
#include <iostream>
#include <pigpio.h>
#include <time.h>
using namespace std;
int main(void)
{
int i, j;
struct timespec ts;
struct tm lotm;
// 7seg a b c d e f g dp
int gpio_pin[8] = {21, 20, 16, 26, 19, 06, 13, 12};
// GPIO 21 20 16 26 19 06 13 12
int segdata[12][8] = { // 7segment 2次元配列
// a b c d e f g dp
{0, 0, 0, 0, 0, 0, 1, 1}, // 0
{1, 0, 0, 1, 1, 1, 1, 1}, // 1
{0, 0, 1, 0, 0, 1, 0, 1}, // 2
{0, 0, 0, 0, 1, 1, 0, 1}, // 3
{1, 0, 0, 1, 1, 0, 0, 1}, // 4
{0, 1, 0, 0, 1, 0, 0, 1}, // 5
{0, 1, 0, 0, 0, 0, 0, 1}, // 6
{0, 0, 0, 1, 1, 1, 1, 1}, // 7
{0, 0, 0, 0, 0, 0, 0, 1}, // 8
{0, 0, 0, 0, 1, 0, 0, 1}, // 9
{1, 1, 1, 1, 1, 1, 1, 1}, // Blank
{1, 1, 1, 1, 1, 1, 1, 0} // dp
};
// pigpioライブラリ初期化
if (gpioInitialise() < 0) exit(1);
// GPIO使用ピンをアウトプット設定
for (i = 0; i < 8; i++) {
gpioSetMode(gpio_pin[i], PI_OUTPUT);
}
// 表示消灯を100回繰り返して終了
for (i = 0; i < 100; i++) {
clock_gettime(CLOCK_REALTIME, &ts); // 時刻の取得
localtime_r(&ts.tv_sec, &lotm); // ローカル時間に変換
// int num = lotm.tm_hour / 10; // 時、十の位取得
// int num = lotm.tm_hour % 10; // 時、一の位取得
// int num = lotm.tm_min / 10; // 分、十の位取得
// int num = lotm.tm_min % 10; // 分、一の位取得
// int num = lotm.tm_sec / 10; // 秒、十の位取得
int num = lotm.tm_sec % 10; // 秒、一の桁取得
cout << num << flush;
for (j = 0; j < 8; j++) { // 7セグLED表示(秒一の位)
gpioWrite(gpio_pin[j], segdata[num][j]);
}
gpioDelay(4000); // 4ミリ秒
for (j = 0; j < 8; j++) { // 消灯(10 -> Blank)
gpioWrite(gpio_pin[j], segdata[10][j]);
}
gpioDelay(20000); // 20ミリ秒
}
cout << endl;
// pigpioライブラリ終了処理
gpioTerminate();
return 0;
}
$ sudo ./test7
6666666666677777777777777777777777777777777777777777888888888888888888888888888888888888888889999999
このソースコードの点灯4ミリ秒、消灯20ミリ秒、約41Hzの疑似ダイナミック表示なら、私の目に7セグLEDのちらつきは感じません。
でもVNCで遠隔操作している時は、そのサイクルを早くしても、ちらつきます。
Raspberry Pi 4を使用して、私にとって初めてのLチカを試しました。正確には、オシロの波形を見てLチカを頭の中でイメージしました。
用意した物(ソフトウェアはフリー)
Raspberry Pi 4
Raspbian Buster with desktop 2019-09-26
Geany(Raspbianに入っている総合開発環境)
g++(Raspbianに入っているC++コンパイラ)
pigpio(Raspbianに入っているGPIO制御ライブラリ)
Geanyの設定は、テンプレートから新規作成のmain.cxxを選択。その後、ビルドコマンドを設定画面(Set Build Commands)のC++コマンドのラベルとコマンドを変更しました。これはこちらのサイトを参考にさせて頂きました。
Label: GPIO-Build Command: g++ -Wall -pthread -o "%e" "%f" -lpigpio -lrt
↓ コンパイルをコマンドラインでやりたい場合は
$ g++ -Wall -pthread -o test2 test2.cpp -lpigpio -lrt
↓ Lチカ用のソースコードはこれ。これを走らせると500μ秒点灯、500μ秒消灯を繰り返すみたい。このソースコードはどこかの英語で書かれたサイトからコピペしました。
/*
* test2.cpp
*/
/* Libraries */
#include <iostream>
#include <pigpio.h>
/* Variables and Constants */
using namespace std;
#define LED 17
#define HIGH 0x1
#define LOW 0x0
/* Main function */
int main(void)
{
cout << "Raspberry Pi initialized!" << endl;
if (gpioInitialise() < 0) exit(1);
gpioSetMode(LED, PI_OUTPUT); // 3.3V PIN
for (;;)
{
gpioWrite(LED, HIGH);
gpioDelay(500);
gpioWrite(LED, LOW);
gpioDelay(500);
}
gpioTerminate();
}
上記ソースコードをGeanyにコピペして、自分で設定したGPIO-Buildを選択してコンパイル完了(Compilation finished successfully) ↓
プログラムの実行はコマンドラインで
$ sudo ./test2
↓ プログラム実行中の波形。まだLEDを繋げて無いので確認して無いけど、1秒間に約900回点滅する事になるので、多分私の目ではチカチカと点滅するようには見えないかも。
↓ LEDを繋げてみました。赤丸のLEDなんですが、点滅では無く点灯ですね。スマホのカメラで240fps撮影して、ようやく点滅しているように見えます。