うちのこの自宅サーバーをUbuntu 19.10 から 20.04 LTSにしました。

今までのサーバー用PCはそのまま放置。20.04 LTS用のPCは別な物を用意して、クリーンインストールしています。もちろんIPv4、IPv6のIPアドレスが変わるので、宅内ルーターのポートマッピング設定は変えました。

それに、うちの(jm1lxs.com)ドメインはお名前ドットコムで取得したので、同サイト内のDNSレコード設定でIPv6のグローバルIPアドレス(240fで始まるアドレス)を紐付けしました。

 

この投稿はUbuntu 20.04 LTSになった後に行いました。

前回のGnuplotアニメーションに続いて、今回はX軸をプロットする毎に16秒分変化させて、以前より滑らかに動くようにしてみました。

動画にした方法は、MacのVNC上で画面録画しただけです。録画時間は約5時間35分、これを2分10秒まで縮めました。

 

↑ offset値が頻繁に上下していますが、これは生活ノイズ(ここでは電化製品のオンオフなど電気的ノイズを表現)で上下しています。多分、裸のGPSモジュールとラズパイの配線がワニ口クリップの長い配線のせいかも知れません。また、ラズパイのアップグレード中も30μs位変化した所を見たので、そんな要因も含まれます。

↓ 生活ノイズが無いと、このように落ち着いています。

 

↓ この動画の元になったGnuplotのスクリプト(C言語)です。なぜC言語なのかと言うと、Gnuplotのスクリプトだけで現時刻に応じてX軸の範囲を設定する方法が分からなかったからです。

/*
 * loopstats-plot.c
 *
 * gcc -Wall -o loopstats-plot loopstats-plot.c
 * 2020/02/10
 *
 * loopstatsのoffset値をGnuplotでグラフ化する。
 *
 * X軸は現時刻から-3600秒前の値を使用。
 * X軸は16秒毎に16秒分変化する。
 *
 */

#include <stdio.h>
#include <time.h>
#include <unistd.h>

#define YOHAKU 150

int main(void)
{
    FILE *gp;
    int s1, s2;
    
    gp = popen("gnuplot -persist", "w");
    
    fprintf(gp, "set encoding iso_8859_1\n");
    fprintf(gp, "set grid y2tics\n");
    fprintf(gp, "set y2range [-0.00004:0.00004]\n");
    fprintf(gp, "set y2tics ('40' 0.00004, '30' 0.00003, '20' 0.00002, '10' 0.00001, '5' 0.000005, '0' 0.00000, '-5' -0.000005, '-10' -0.00001, '-20' -0.00002, '-30' -0.00003, '-40' -0.00004)\n");
    fprintf(gp, "set xzeroaxis lt -1\n");
    fprintf(gp, "set timestamp\n");
    fprintf(gp, "unset ytics\n");
    fprintf(gp, "set title 'loopstats offset' font 'Helvetica,16'\n");
    fprintf(gp, "set xlabel '-3600 (s)' font 'Helvetica,14'\n");
    fprintf(gp, "set y2label 'offset ({\265}s)' font 'Helvetica,14'\n");
    fprintf(gp, "plot '< tail -225 /var/log/ntpstats/loopstats' using 2:3 with points axis x1y2\n");
    
    while (1) {
        time_t t = time(NULL);
        s1 = t % 86400 + YOHAKU;
        s2 = t % 86400 - 3600 - YOHAKU;
        
        // X軸設定 [現時刻−3600秒:現時刻]
        fprintf(gp, "set xrange [%d:%d]\n", s2,s1);
        fprintf(gp, "replot\n");
        fflush(gp); // ここで描画
        
        sleep(16); // 再描画まで16秒待つ
    }
    fprintf(gp, "unset output\n");
    fprintf(gp, "exit\n");
    pclose(gp);
    
    return 0;
}
$ gcc -Wall -o loopstats-plot loopstats-plot.c
$ ./loopstats-plot

今テスト中の1PPS利用Stratum 1 NTPサーバーのoffset値を、Gnuplotでほぼリアルタイムでグラフ化してみました。表示範囲は過去60分間です。

118倍速の動画にしたので見て下さい。全画面で見ないと、小さ過ぎて見れませんが。

 

↑ 動画にした方法は、ラズパイの画面をVNCでMacに表示させて、スクリーンショットの選択部分を収録で約1時間録画しました。Gnuplotの機能にあるGIF出力を利用した物ではありません。

 

Gnuplotの操作方法は以下の通りです。過去60分間の部分は、< tail -225 であり、ログの末尾から225行読み込む事を意味しています。そしてログの記録が16秒毎(衛星をロストしない限り)ですので、これを計算すると
225×16秒=3600秒(60分間)
となります。

↓ pause 16.0は、このスクリプトファイルの再読み込みまでの待機時間で、結果16秒毎にグラフを更新させています。

$ vi loopstats-plot.cmd

set yrange [-0.0001:0.0001]
set format y '%6.5f'
set size ratio 0.5
set grid
set xzeroaxis lt -1
set timestamp
set title 'loopstats offset' font 'Helvetica,16'
set xlabel '-3600 [s]' font 'Helvetica,14'
set ylabel 'offset [s]' font 'Helvetica,14'
plot '< tail -225 /var/log/ntpstats/loopstats' using 2:3 w l
pause 16.0
reread
$ gnuplot loopstats-plot.cmd

ラズパイでStratum 1 NTPサーバーを試してみました。その方法は全てネット上にある記事のつまみ食いです。

 

↓ そのつまみ食いの結果がこれです。精度もStratum 1と言って良いのでは?

↑ グラフ中央の跳ね上がり(下がり)の原因は、ntpとgpsbを再起動させた為です。

 

どんなつまみ食いだったかを備忘録として残して置きます。

秋月のGPSキット(K-13850)とラズパイ4で試しました。

始めに見落としがちな事を。
このGPSを使用する場合、1PPS出力がアクティブLowである事を意識して置かないと、私みたいにハマってしまいます。そのパルスは ↓


秋月の取説PDFからコピぺ

このような波形の時は、/boot/config.txt に assert_falling_edge=true が必要になります。これを記述して置かないと100msズレて参照リストから外れたサーバー “x”印になってしまいます。

 

GPSとラズパイの結線


カラー図は秋月からのコピぺ

 

インストール

$ sudo apt update
$ sudo apt install ntp
$ sudo apt install gpsd gpsd-clients pps-tools

 

設定

$ sudo vi /boot/cmdline.txt

console=serial0,115200の削除
$ sudo vi /boot/config.txt

末尾に追加
enable_uart=1
dtoverlay=pps-gpio
dtparam=gpioin=18
dtparam=assert_falling_edge=true
$ sudo vi /etc/modules

末尾に追加
pps-gpio
$ sudo vi /etc/default/gpsd

START_DAEMON="true"
USBAUTO="false"
DEVICES="/dev/ttyS0 /dev/pps0"
GPSD_OPTIONS="-n"
$ sudo vi /etc/ntp.conf

server 127.127.28.2 minpoll 4 maxpoll 4 prefer
fudge  127.127.28.2 refid GPS stratum 14
server 127.127.22.0 minpoll 4 maxpoll 4
fudge  127.127.22.0 refid PPS stratum 0

server ntp.nict.jp iburst

 

自動再起動設定

$ sudo systemctl enable gpsd.service
$ sudo reboot

 

上記の手順で作動確認出来たRaspbianは ↓

2019-09-26-raspbian-buster-lite
2019-09-26-raspbian-buster
2020-02-05-raspbian-buster-lite
2020-02-05-raspbian-buster

 

このフローチャートに従って、共有メモリに書き込むプログラムAのその部分 ↓

    while (1) { // 無限ループ
        if ((fp=popen("ntpq -c rv", "r"))==NULL) {
            string s = "N"; // ntpp -c rv 実行失敗時 N を共有メモリに書き込む
            sprintf(shared_memory, s.c_str());
        } else {
            fgets(str, 512, fp); // 一行読み込む
            ptr = strstr(str, "sync_ntp");
            if (ptr != NULL) {
                string s = "S"; // S を共有メモリに書き込む
                sprintf(shared_memory, s.c_str());
                sleep(16);
            } else {
                ptr = strstr(str, "sync_unspec");
                if (ptr != NULL) {
                    ptr = strstr(str, "no_sys_peer");
                    if (ptr != NULL) {
                        string s = "M"; // M を共有メモリに書き込む    
                        sprintf(shared_memory, s.c_str());
                    } else {
                        string s = "N"; // N を共有メモリに書き込む
                        sprintf(shared_memory, s.c_str());
                    }
                } else {
                    string s = "N"; // N を共有メモリに書き込む    
                    sprintf(shared_memory, s.c_str());
                }
            }
        }
        pclose(fp);
        sleep(1);
    }

 

プログラムAによって共有メモリに書き込まれた文字により、表示を変化させるラズパイ7桁時計のその部分 ↓

    static int segdata[22][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
        {H, H, H, H, H, H, L, H}, // 0. 小数点付き
        {L, H, H, L, L, L, L, H}, // 1. 小数点付き
        {H, H, L, H, H, L, H, H}, // 2. 小数点付き
        {H, H, H, H, L, L, H, H}, // 3. 小数点付き
        {L, H, H, L, L, H, H, H}, // 4. 小数点付き
        {H, L, H, H, L, H, H, H}, // 5. 小数点付き
        {H, L, H, H, H, H, H, H}, // 6. 小数点付き
        {H, H, H, L, L, L, L, H}, // 7. 小数点付き
        {H, H, H, H, H, H, H, H}, // 8. 小数点付き
        {H, H, H, H, L, H, H, H}, // 9. 小数点付き
	{L, L, L, L, L, L, L, L}, // Blank
	{L, L, L, L, L, L, L, H}, // dp
    };

    // 中略

    while (1) { // 無限ループ 1サイクル14.8ミリ秒 1秒間に約67回繰り返す

        // 共有メモリの文字により表示を変える
        switch (*shared_memory) {
            case 'S': // +++++ 時計表示 + 同期LED点灯 +++++
                disp = 2000;  // 2ミリ秒表示維持
                LEDstate = 1; // 同期LED点灯
                break;
            case 'M': // +++++ 時計表示 ++++++++++++++++++
                disp = 2000;  // 2ミリ秒表示維持
                LEDstate = 0; // 同期LED消灯
                break;
            case 'N': // +++++ チラツキ表示 ++++++++++++++
                disp = 10000; // 10ミリ秒表示維持
                LEDstate = 0; // 同期LED消灯
                break;
        }

        gpioWrite(SYNC_LED, LEDstate); // 共有メモリに応じて同期LED点灯・消灯

        // 時刻の取得
        clock_gettime(CLOCK_REALTIME, &ts);
        localtime_r(&ts.tv_sec, &lotm);  // ローカル時間に変換
        num[0] = ts.tv_nsec / 100000000; // 1/10秒の桁取得
        num[1] = lotm.tm_sec % 10 + 10;  //  1. 秒の桁取得(小数点付き)
        num[2] = lotm.tm_sec / 10;       // 10  秒の桁取得
        num[3] = lotm.tm_min % 10;       //  1  分の桁取得
        num[4] = lotm.tm_min / 10;       // 10  分の桁取得
        num[5] = lotm.tm_hour % 10;      //  1  時の桁取得
        num[6] = lotm.tm_hour / 10;      // 10  時の桁取得

        // 7桁ダイナミック表示ルーチン
        for (j = 0; j < 7; j++) {
            for (i = 0; i < 9; i++) { // 7セグメントデータセット
                gpioWrite(nanaseg[i], segdata[num[j]][i]);
            }
            gpioWrite(common[j], SEG_ON); // 7セグLED表示
            gpioDelay(disp);             // 共有メモリに応じて表示維持時間変化
            gpioWrite(common[j], SEG_OFF);// 7セグLED消灯
        }

    }

 

↓ 7セグLEDのコモンをオシロで観測した画像。