ハードウェア制御とファームウェア構成
以下では、低消費電力マイコンSTM8L052を用いた水メーターの主要な制御モジュールについて解説します。
流量パルスの検出
水流による磁気センサーの信号をキャプチャするため、タイマーリソースを活用します。
// タイマー設定例(TIM3利用)
void Timer_Configuration(void) {
CLK_PeripheralClockConfig(CLK_Peripheral_TIM3, ENABLE);
TIM3_TimeBaseInit(TIM3_Prescaler_128, TIM3_CounterMode_Up, 0xFFFF);
TIM3_ITConfig(TIM3_IT_Update, ENABLE);
TIM3_Cmd(ENABLE);
}
// 割り込み処理ルーチン
INTERRUPT_HANDLER(TIM3_UPD_OVF_TRG_BRK_IRQHandler, 21) {
if (TIM3_GetITStatus(TIM3_IT_Update) != RESET) {
pulse_accumulator++;
TIM3_ClearITPendingBit(TIM3_IT_Update);
}
}
低消費電力モードの制御
バッテリー寿命を延長するため、測定間隔以外はCPUを停止させます。
// システムスリープ状態への移行
void System_Sleep(void) {
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
}
// ウェイクアップ時の初期化処理
void Wakeup_Process(void) {
PWR_ClearFlag(PWR_FLAG_WU);
// クロック源を再設定
CLK_HSICmd(ENABLE);
while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == RESET);
}
LoRa無線通信モジュールの実装
SX1278チップを使用した遠距離データ送信の初期化および送信関数です。
// 無線モジュールの初期化シーケンス
void Radio_Init(void) {
SPI_Cmd(ENABLE);
WriteReg(REG_OP_MODE, MODE_SLEEP);
SetFrequency(433000000); // 433MHz帯
SetOutputPower(MAX_POWER);
}
// 使用量データの送信処理
void Transmit_Data(uint32_t usage_volume) {
uint8_t tx_packet[6];
tx_packet[0] = 0x55; // ヘッダー
// ビッグエンディアン形式でパッキング
tx_packet[1] = (usage_volume >> 24) & 0xFF;
tx_packet[2] = (usage_volume >> 16) & 0xFF;
tx_packet[3] = (usage_volume >> 8) & 0xFF;
tx_packet[4] = usage_volume & 0xFF;
// チェックサム付与
tx_packet[5] = CalcChecksum(tx_packet, 5);
SendPayload(tx_packet, sizeof(tx_packet));
}
データ処理アルゴリズム
瞬間流量の算出
#define SENSOR_PPL 400 // リットルあたりのパルス数
float Get_InstantFlow(void) {
static uint32_t prev_ticks = 0;
float flow_liters_per_min = 0.0f;
uint32_t current_ticks = pulse_accumulator;
uint32_t diff = current_ticks - prev_ticks;
// パルス差分をリットル単位に変換
flow_liters_per_min = (float)diff / SENSOR_PPL;
prev_ticks = current_ticks;
return flow_liters_per_min * 60.0f; // 分単位に換算
}
ゼロ点補正とオフセット処理
// ドリフト補正関数
void Perform_ZeroCalibration(void) {
delay_ms(3000); // 安定待機
base_offset = pulse_accumulator;
}
// 補正後の純流量取得
float Get_CorrectedVolume(void) {
return (pulse_accumulator - base_offset) * (1.0f / SENSOR_PPL);
}
システム動作フロー
MCU --> Sensor: タイマー割り込み開始
loop 各周期
Sensor -->> MCU: パルス信号入力
MCU ->> MCU: 使用量計算&バッファリング
MCU ->> LCD: 数値更新
MCU ->> Radio: ペイロード送信指示
end
プロジェクト構成
SmartMeter_Project/
├── Hardware/
│ ├── Design/ # 回路図およびレイアウト
│ └── BOM/ # 部品表
├── Source/
│ ├── driver/ # 周辺ドライバ(SPI, GPIO)
│ ├── app/
│ │ ├── main.c # メインループ
│ │ ├── meter_logic.c # 流量計算ロジック
│ │ └── wireless.c # 無線通信処理
│ └── startup_stm8l.s
├── Tests/
│ ├── power.log # 電流消費ログ
│ └── accuracy.txt # 計測精度データ
└── Documentation/
├── SysSpec.md # 仕様書
└── Interface.txt # 通信プロトコル
検証とパフォーマンス
システムの信頼性を保証するため、以下の検証を実施します。
信号品質の確認
- センサー出力の立上り・立下がり時間の測定
- 割り込みレイテンシの確認(目標: 15μs以内)
電力消費特性
| 動作モード | 消費電流 |
|---|---|
| アクティブ(センサー監視) | 4.2mA |
| RF送信中 | 120mA(ピーク) |
| ディープスリープ | 1.8μA |
データ整合性チェック
// XORベースのシンプルチェックサム
uint8_t CalcChecksum(uint8_t *data, uint8_t length) {
uint8_t checksum = 0xFF;
for (uint8_t i = 0; i < length; i++) {
checksum ^= data[i];
}
return checksum;
}
機能拡張
プリペイド機能の実装
EEPROMへのデータ書き込みにより残高管理を行います。
#define MEM_BALANCE 0x1000
void Update_Balance(float amount) {
uint16_t val = (uint16_t)(amount * 100);
FLASH_Unlock(FLASH_MemType_Data);
FLASH_ProgramByte(MEM_BALANCE, (val >> 8) & 0xFF);
FLASH_ProgramByte(MEM_BALANCE+1, val & 0xFF);
FLASH_Lock(FLASH_MemType_Data);
}
異常検知(漏水検知)
#define FLOW_LIMIT 3.5f // 検知閾値
void Monitor_Leakage(void) {
float current_flow = Get_InstantFlow();
if (current_flow > FLOW_LIMIT) {
Trigger_Buzzer();
Send_Alert("LEAK_DETECTED");
}
}
適用事例
- スマートシティ向け水道メーター: 遠隔検針による効率化と、階層別課金システムとの連携。
- 精密農業: 給水管の流量モニタリングによる、土壌水分量に応じた最適な灌漑制御。
- 設備管理: ビル空調の循環水流量を常時監視し、異常時のメンテナンス予知を行うシステム。