SpresenseでELTRESアドオンボードを利用して、
歩数とGPS座標をサーバへ送信します。
歩数は、加速度センサを利用して計測します。
計測方法は、Arduino Spresenseのサンプルコードである
「Step Counterサンプルスケッチ」を参考にしています。
部品
- SPRESENSEメインボード
- SPRESENSE用Qwiic接続基板
- Qwiicケーブル(Qwiic -Qwiic)50 mm
- Qwiic - LSM6DSO搭載 6DoFモジュール
- ELTRESアドオンボード
- SPRESENSE用ELTRESアドオンボード対応 LPWAアンテナ
- uFL接続 15mm GPS用アンテナ
設計図
ソースコード
歩数計付きGPSトラッカ
#include <EltresAddonBoard.h>
#include <SparkFunLSM6DSO.h>
#include <MemoryUtil.h>
#include <SensorManager.h>
#include <AccelSensor.h>
#include <Aesm.h>
#include <ApplicationSensor.h>
const int walking_stride = 60; /* 60cm */
const int running_stride = 80; /* 80cm */
const int accel_range = 2; /* 2G */
const int accel_rate = 52; /* 52 Hz */
// const int accel_rate = 50; /* 50 Hz */
const int accel_sample_num = 50; /* 50 sample */
const int accel_sample_size = sizeof(float) * 3;
/* 最新)GGS情報 */
static eltres_board_gga_info last_gga_info;
/* (最新)緯度:dmm形式の度 */
static uint8_t last_lat_deg;
/* (最新)緯度:dmm形式の分 */
static double last_lat_min;
/* (最新)経度:dmm形式の度 */
static uint8_t last_lon_deg;
/* (最新)経度:dmm形式の分 */
static double last_lon_min;
/* GNSS情報更新時間 */
static uint32_t last_gnss_update_time;
/* ペイロード格納領域 */
static uint8_t payload_data[16];
/* 歩数の最新値 */
uint32_t latest_step = 0;
/* 加速度センサ */
static LSM6DSO myIMU;
/**
* ペイロードの作成と設定
*/
void set_eltres_payload(void)
{
String temp;
const uint8_t lat_deg = last_lat_deg;
const uint8_t lon_deg = last_lon_deg;
const double lat_min = last_lat_min;
const double lon_min = last_lon_min;
memset(payload_data, 0, sizeof(payload_data));
payload_data[0] = 0x81;
// 緯度
temp = String(lat_deg);
payload_data[1] = ((temp.charAt(0) - '0') << 4) + (temp.charAt(1) - '0');
temp = String(lat_min / 100, 6).substring(2);
payload_data[2] = ((temp.charAt(0) - '0') << 4) + (temp.charAt(1) - '0');
payload_data[3] = ((temp.charAt(2) - '0') << 4) + (temp.charAt(3) - '0');
payload_data[4] = ((temp.charAt(4) - '0') << 4) + (temp.charAt(5) - '0');
// 経度
temp = String(lon_deg);
payload_data[5] = (temp.charAt(0) - '0');
payload_data[6] = ((temp.charAt(1) - '0') << 4) + (temp.charAt(2) - '0');
temp = String(lon_min / 100, 6).substring(2);
payload_data[7] = ((temp.charAt(0) - '0') << 4) + (temp.charAt(1) - '0');
payload_data[8] = ((temp.charAt(2) - '0') << 4) + (temp.charAt(3) - '0');
payload_data[9] = ((temp.charAt(4) - '0') << 4) + (temp.charAt(5) - '0');
// epoch秒のところに歩数を入れる
payload_data[10] = (uint8_t)((latest_step >> 24) & 0xff);
payload_data[11] = (uint8_t)((latest_step >> 16) & 0xff);
payload_data[12] = (uint8_t)((latest_step >> 8) & 0xff);
payload_data[13] = (uint8_t)((latest_step >> 0) & 0xff);
EltresAddonBoard.set_payload(payload_data);
}
void eltres_event_cb(eltres_board_event event)
{
switch (event) {
case ELTRES_BOARD_EVT_SEND_READY:
// 送信前通知時
set_eltres_payload();
break;
}
}
void gga_event_cb(const eltres_board_gga_info *gga_info)
{
last_gga_info = *gga_info;
if (last_gga_info.m_pos_status) {
last_gnss_update_time = (uint32_t) (millis() / 1000);
int dot_index;
String lat_str = String((char*)gga_info->m_lat);
double lat = lat_str.toDouble(); // ddmm.mmmm
last_lat_deg = (uint8_t) (floor(lat / 100.0));
last_lat_min = lat - ((double)last_lat_deg) * 100.0;
String lon_str = String((char*)gga_info->m_lon);
double lon = lon_str.toDouble(); // ddmm.mmmm
last_lon_deg = (uint8_t) (floor(lon / 100.0));
last_lon_min = lon - ((double)last_lon_deg) * 100.0;
}
}
bool step_counter_result(sensor_command_data_mh_t &data)
{
StepCounterStepInfo* steps =
reinterpret_cast<StepCounterStepInfo*>
(StepCountReader.subscribe(data));
if (steps == NULL)
{
return 0;
}
latest_step = steps->step;
return 0;
}
void setup()
{
Serial.begin(115200);
eltres_board_result e_ret;
e_ret = EltresAddonBoard.begin(ELTRES_BOARD_SEND_MODE_1MIN,
eltres_event_cb, gga_event_cb);
if (e_ret != ELTRES_BOARD_RESULT_OK) {
exit(1);
}
delay(500);
Wire.begin();
delay(10);
myIMU.begin();
// myIMU.initialize(BASIC_SETTINGS);
myIMU.setIncrement();
myIMU.setAccelRange(accel_range);
myIMU.setAccelDataRate(accel_rate);
myIMU.setBlockDataUpdate(true);
/* Initialize sensor class */
SensorManager.begin();
AccelSensor.begin(SEN_accelID,
accel_rate,
accel_sample_num,
accel_sample_size);
Aesm.begin(SEN_stepcounterID,
SUBSCRIPTION(SEN_accelID),
accel_rate,
accel_sample_num,
accel_sample_size);
StepCountReader.begin(SEN_app0ID,
SUBSCRIPTION(SEN_stepcounterID),
step_counter_result);
Aesm.set(walking_stride, running_stride);
}
void loop()
{
float x;
float y;
float z;
x = myIMU.readFloatAccelX();
y = myIMU.readFloatAccelY();
z = myIMU.readFloatAccelZ();
AccelSensor.write_data(x, y, z);
}
今後の課題
実際にデータを送信してみて、歩数が多いところがありました。
Spresenseのサンプルソースコードの処理に従っているため、
一部補正値などの指定が間違っている可能性がありますが、
加速度センサに合わせた調整も必要かもしれません。
-
melodie
さんが
2022/09/25
に
編集
をしました。
(メッセージ: 初版)
-
melodie
さんが
2022/09/25
に
編集
をしました。
ログインしてコメントを投稿する