SPRESENSEはGPSを受信できるので、正確な時間を取得できます。それならその時間をRTCに設定してみて、時報アプリを作れないかなと思い作ってみました。




時報の音源は次のURLの「Sine波 予報音3回」のMP3ファイルを拝借させていただきました。

時報音の音源
https://ultra.zone/jihou.ja


スケッチは、メインループと "pthread" で構成されています。メインループはGPS時間を取得をしてRTCを更新し、"pthread" は RTCの時間を監視して1分毎に時報を鳴らすというものです。

もともとは、task_create でスレッドを生成していたのですが、なぜかPANICが起きるので pthread に置きかえました。^^;


#include &ltGNSS.h>
#include &ltRTC.h>
#include &ltSDHCI.h>
#include &ltAudio.h>
#include &ltpthread.h>

static SDClass theSD;
static SpGnss Gnss;
AudioClass *theAudio = AudioClass::getInstance();

#define JST_IN_SECONDS (9 * 60 * 60);

static File myFile;
static bool bTimeFixed = false;

static void time_signal_thread(void *arg) {

while(true) {
usleep(100000);
if (bTimeFixed == false) continue;

RtcTime now = RTC.getTime();
if (now.second() != 56) continue;

myFile = theSD.open("jihou.mp3");
if (!myFile) {
Serial.println("File open error");
while(1);
}

theAudio->writeFrames(AudioClass::Player0, myFile);
theAudio->setVolume(-60);
theAudio->startPlayer(AudioClass::Player0);
while (true) {
sleep(1); // To ensure not re-entering the audio routine.
int err = theAudio->writeFrames(AudioClass::Player0, myFile);
if (err == AUDIOLIB_ECODE_FILEEND) {
theAudio->stopPlayer(AudioClass::Player0);
myFile.close();
break;
}
}
}

return 0;
}

void setup() {
int result;

Serial.begin(115200);
theSD.begin();
sleep(3); /* Wait HW initialization done. */

theAudio->begin();
theAudio->setRenderingClockMode(AS_CLKMODE_NORMAL);
theAudio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, AS_SP_DRV_MODE_LINEOUT);
theAudio->initPlayer(AudioClass::Player0, AS_CODECTYPE_MP3, "/mnt/sd0/BIN"
, AS_SAMPLINGRATE_AUTO, AS_CHANNEL_MONO);
Serial.println("Audio initialized");

Gnss.begin();
Gnss.select(GPS);
Gnss.start(COLD_START);
Serial.println("Gnss start...");

int policy;
struct sched_param param;
pthread_t m_pid = pthread_self();
pthread_getschedparam(m_pid, &amppolicy, &ampparam);
Serial.println("Main Priority is : " + String(param.sched_priority));

pthread_t t_pid;
pthread_create(&ampt_pid, NULL, time_signal_thread, NULL);
param.sched_priority = 130;
pthread_setschedparam(t_pid, policy, &ampparam);
Serial.println("time_signal_thread start: " + String(param.sched_priority));
}


void loop() {

if (!Gnss.waitUpdate(-1)) return;

SpNavData NavData;
Gnss.getNavData(&ampNavData);

Serial.println("numSat: " + String(NavData.numSatellites));

if (NavData.time.year == 1980) return;
bTimeFixed = true;

/* Create RTC time */
RtcTime gtime(NavData.time.year, NavData.time.month, NavData.time.day
, NavData.time.hour, NavData.time.minute, NavData.time.sec
, NavData.time.usec * 1000 /* RtcTime requires nsec */);

gtime += JST_IN_SECONDS; /* convert UTC to JST */

printf("%04d/%02d/%02d %02d:%02d:%02d\n"
, gtime.year(), gtime.month(), gtime.day()
, gtime.hour(), gtime.minute(), gtime.second());

/* When time is different more than 1 sec, update RTC time */
if (abs(RTC.getTime() - gtime) >= 1) {
RTC.setTime(gtime);
Serial.println(" * Updated RTC time * ");
}
}




わざわざスレッドにしなくてもいいんじゃないかというコードではありますが、スレッドにすることでRTC の効用を少し分かりやすくしてみたつもりです。^^;

SPRESENSEはGPS時刻を取得できるので、複数のカメラ付きSPRESENSEを時刻同期で撮影すれば全球カメラができそうですね。ヘルメットにつけたりしたら面白いかも。
(^^)