スマートインソール自作で足圧分布を精密モニタリング
必要な部品と材料
| Arduino MKR1000 | ×1 | Wi-Fi内蔵の3.3V/5Vボードなら大抵動作。ただしESP系は本プロジェクトで測定値が不安定だったため非推奨 |
| 圧力感知抵抗器 (FSR) | ×3 | Interlink 402 (100N) を使用。より高価な406も試したが402で十分。精度向上には更多FSR推奨 |
| OpenBuilds ワイヤーケーブル (メートル売り) | ×1 | |
| 抵抗 10kΩ | ×3 | 測定レンジ調整用。抵抗値大→刻み幅大。詳細はAdafruit解説参照 |
| モバイルバッテリー | ×1 | |
| SparkFun ADXL345 3軸加速度センサー ブレークアウト | ×1 |
必要な工具と機材
- はんだごて(汎用)
- ハンダ、熱収縮チューブ等の付属資材
使用するアプリとオンラインサービス
- Thinger.io プラットフォーム(IoTデータ可視化)
- Arduino IDE
プロジェクト概要
圧力測定は歩行力学の解析に広く用いられ、臨床・スポーツ等で応用されています。本プロジェクトではFSRセンサーで荷重分布を把握し、リアルタイム圧力マップ可視化でデータ理解を容易にします。
必要ハードウェア
- Arduino MKR1000 - Wi-Fi内蔵ボードなら大抵可。ESP系は測定不安定のため避ける
- FSR (Force Sensitive Resistor) ×3 - Interlink 402 (100N) 推奨。より多くのFSRで精度向上
- 10kΩ抵抗 ×3 - 測定レンジ調整用
- 加速度センサー ADXL345 (16G) - 足の加速度・動作測定用。圧力測定のみなら不要だが、歩行サイクル解析に有用
- はんだごて - ワニ口クリップは靴内で不安定なため必須
配線

FSRのはんだ付けについて - 必読: FSRへのリード線はんだ付けは極めて慎重に。自信がない場合は挑戦しないでください。プラスチックが溶けるため極短時間で完了させる必要があります。私は苦い経験をしました…
FSRに極性はありません。抵抗値変更で測定レンジ調整可能。全センサーを5VとGNDの共通ラインに接続。加速度センサーは省略可能(圧力測定のみなら不要)。
インソールへのハードウェア取り付け
コード動作確認後に取り付けを推奨。はんだミスがあればこの段階で判明し、再取り付けの手間を省けます。
FSRをインソール3点に配置:左上(回外)、右上(回内)、かかと(踵圧)。最適位置は歩行時にアナログ値変化が最大になる場所を試行で決定。配線はテープで固定(動くとノイズ発生)。ベルクロテープでインソールと靴内側を固定。加速度センサーは靴のかかと背面に両面テープで貼り付け。

力の測定
Thinger.ioライブラリ前提で説明(詳細は「Thinger.ioでデータ送信」節参照)。
プログラム冒頭にWi-Fi接続情報等の変数定義、グローバル配列(FSR3個分)を宣言。配列を多用し、各FSR要素を個別管理しています。グローバル変数多用は副作用リスクありますが、Thinger.io送信には必要です。
セットアップと圧力読み取り
#define _DEBUG_ // シリアルモニタ有効化(最上部に記述必須)
#include <WiFi101.h>
#include <ThingerWifi101.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
#include <Adafruit_NeoPixel.h>
#define USERNAME "yourUsername"
#define DEVICE_ID "yourDeviceID"
#define DEVICE_CREDENTIAL "yourDeviceCredential"
#define SSID "yourSSID"
#define SSID_PASSWORD "yourSSIDPassword"
// FSR設定
#define noFSRs 3
#define FSR1 A1
#define FSR2 A2
#define FSR3 A3
float fsrVoltageArray[3];
float fsrForceArray[3];
float fsrWeightInGramsArray[3];
int pinArray[3] = {FSR1, FSR2, FSR3};
float forceMaxArray[3] = {100.0, 100.0, 100.0};
float million = 1000000.0;
float conversionToKgrams = 1.0/9.80665;
long K = 1000;
long R = 10*K; // 10kΩ
long Vcc = 5000; // 5V=5000mV (3.3Vなら3300)
float voltageMax = 0.98 * Vcc; // Vccの95%を上限とし、それ以上は最大荷重とみなす
ThingerWifi101 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
void setup(void) {
Serial.begin(115200);
thing.add_wifi(SSID, SSID_PASSWORD);
// 生アナログ値出力
thing["pressure"] >> [](pson & out) {
out["FSR1"] = analogRead(FSR1);
out["FSR2"] = analogRead(FSR2);
out["FSR3"] = analogRead(FSR3);
};
// 電圧値変換・出力
thing["voltage"] >> [](pson & out) {
for (int FSR = 0; FSR < noFSRs; FSR++) {
fsrVoltageArray[FSR] = 0.0;
fsrForceArray[FSR] = 0.0;
int fsrPin = pinArray[FSR];
int fsrReading = analogRead(fsrPin);
fsrVoltageArray[FSR] = (float) map(fsrReading, 0, 1023, 0, 5000); // 3.3Vデバイスなら5000→3300
}
out["FSR1voltage"] = fsrVoltageArray[0];
out["FSR2voltage"] = fsrVoltageArray[1];
out["FSR3voltage"] = fsrVoltageArray[2];
};
// ニュートン(力)変換・出力
thing["newton"] >> [](pson & out) {
for (int FSR = 0; FSR < noFSRs; FSR++) {
float force_value = (forceMaxArray[FSR]/voltageMax) * fsrVoltageArray[FSR];
// 3ケース分岐:
// 1. 電圧がvoltageMax近傍 → 無限大回避で最大値にキャップ
// 2. 計算力が微小 → ノイズ除去でゼロ
// 3. それ以外 → 対数スケールで傾斜緩和し微小変化を識別
if (fsrVoltageArray[FSR] < voltageMax) {
if (force_value <= 1.00) {
fsrForceArray[FSR] = 0.0;
} else {
fsrForceArray[FSR] = log10(force_value);
}
} else {
fsrForceArray[FSR] = log10(forceMaxArray[FSR]);
Serial.print("Cut off activated for FSR = "); Serial.println(FSR);
}
}
out["FSR1newton"] = fsrForceArray[0];
out["FSR2newton"] = fsrForceArray[1];
out["FSR3newton"] = fsrForceArray[2];
};
// 重量(グラム)変換・出力
thing["weight"] >> [](pson & out) {
for (int FSR = 0; FSR < noFSRs; FSR++) {
fsrWeightInGramsArray[FSR] = fsrForceArray[FSR] * conversionToKgrams * 1000.0;
}
out["FSR1weight"] = fsrWeightInGramsArray[0];
out["FSR2weight"] = fsrWeightInGramsArray[1];
out["FSR3weight"] = fsrWeightInGramsArray[2];
};
}
void loop(void) {
thing.handle(); // Thinger.io処理のみ。loop内に他コード記述不可
}
Thinger.ioダッシュボード設定もお忘れなく。正常動作時は以下のような表示になります。

加速度測定
圧力測定より簡単。ヘッダーにWire.h、Adafruit_Sensor.h、Adafruit_ADXL345_U.hを追加し、x/y/z軸加速度用グローバル変数を定義。
setup()内でセンサー初期化、レンジ設定(16G)、"accelerometer" thingでX/Y/Z加速度を出力。
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);
int x = 0, y = 0, z = 0;
void setup(void) {
Serial.begin(115200);
if(!accel.begin()) {
Serial.println("No ADXL345 detected");
} else {
accel.setRange(ADXL345_RANGE_16_G);
thing["accelerometer"] >> [](pson& out) {
sensors_event_t event;
accel.getEvent(&event);
out["x"] = event.acceleration.x;
out["y"] = event.acceleration.y;
out["z"] = event.acceleration.z;
Serial.print("X: "); Serial.print(event.acceleration.x);
Serial.print(" Y: "); Serial.print(event.acceleration.y);
Serial.print(" Z: "); Serial.print(event.acceleration.z);
Serial.println(" m/s^2");
};
}
}
実行後、以下のような出力が得られます。

全コード統合
完全なコードはページ末尾の「Code」セクションに掲載。
Thinger.ioでデータ送信
このライブラリは公式ドキュメントが充実していますが、重要ポイントを抜粋:
構造(末尾のセミコロン必須):
thing["識別子文字列"] >> [](pson& out) {
// あなたのコード
};
これはC++のラムダ関数。「thing」で始まり、一意の名前を持つ。「>>」は出力専用(入力なら「<<」、双方向なら「=」)。引数「pson &out」で柔軟なデータ構造(JSON対応)を出力チャネルへ送信。コード内では out["一意キー"] = 値 形式で送信。
loop()には thing.handle() のみ記述。計算処理は「thing」内に書くことで継続的更新が可能。
FAQ
- 動作しない! → 配線確認。_DEBUG_定義確認。TLS干渉の可能性。Thinger.io接続確認。
- 出力が期待と異なる → 更新コードが「thing」内にあるか確認。外部にあると更新されない。ESPデバイスはFSRと相性悪い模様。
- 出力が定期更新されない → delay()を入れていないか確認。削除のこと。更新頻度はThinger.io側で設定可能。
- 全出力を1グラフにまとめたい → 単一の「thing」に全コード統合。
お疲れ様でした!
FSRセンサー、加速度センサー、Thinger.ioの基礎理解に役立てば幸いです。改善提案や作品共有をお待ちしています!
コード
Smart-Insole-Tutorial Arduino
本チュートリアルの完全版コード
#define _DEBUG_ // 他のインクルードより前に記述必須
#include <WiFi101.h>
#include <ThingerWifi101.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
#define USERNAME "yourUsername"
#define DEVICE_ID "yourDevice"
#define DEVICE_CREDENTIAL "yourCredential"
#define SSID "yourSSID"
#define SSID_PASSWORD "yourSSIDPassword"
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);
int x = 0, y = 0, z = 0;
#define noFSRs 3
#define FSR1 A1
#define FSR2 A2
#define FSR3 A3
float fsrVoltageArray[3];
float fsrForceArray[3];
float fsrWeightInGramsArray[3];
int pinArray[3] = {FSR1, FSR2, FSR3};
float forceMaxArray[3] = {100.0, 100.0, 100.0};
float million = 1000000.0;
float conversionToKgrams = 1.0/9.80665;
long K = 1000;
long R = 10*K;
long Vcc = 5000;
float voltageMax = 0.98 * Vcc;
ThingerWifi101 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
void setup(void) {
Serial.begin(115200);
thing.add_wifi(SSID, SSID_PASSWORD);
if(!accel.begin()) {
Serial.println("No ADXL345 detected.");
} else {
accel.setRange(ADXL345_RANGE_16_G);
thing["accelerometer"] >> [](pson& out) {
sensors_event_t event;
accel.getEvent(&event);
out["x"] = event.acceleration.x;
out["y"] = event.acceleration.y;
out["z"] = event.acceleration.z;
};
}
thing["pressure"] >> [](pson & out) {
out["FSR1"] = analogRead(FSR1);
out["FSR2"] = analogRead(FSR2);
out["FSR3"] = analogRead(FSR3);
};
thing["voltage"] >> [](pson & out) {
for (int FSR = 0; FSR < noFSRs; FSR++) {
fsrVoltageArray[FSR] = 0.0;
fsrForceArray[FSR] = 0.0;
int fsrPin = pinArray[FSR];
int fsrReading = analogRead(fsrPin);
fsrVoltageArray[FSR] = (float) map(fsrReading, 0, 1023, 0, 5000);
}
out["FSR1voltage"] = fsrVoltageArray[0];
out["FSR2voltage"] = fsrVoltageArray[1];
out["FSR3voltage"] = fsrVoltageArray[2];
};
thing["newton"] >> [](pson & out) {
for (int FSR = 0; FSR < noFSRs; FSR++) {
float force_value = (forceMaxArray[FSR]/voltageMax) * fsrVoltageArray[FSR];
if (fsrVoltageArray[FSR] < voltageMax) {
if (force_value <= 1.00) {
fsrForceArray[FSR] = 0.0;
} else {
fsrForceArray[FSR] = log10(force_value);
}
} else {
fsrForceArray[FSR] = log10(forceMaxArray[FSR]);
Serial.print("Cut off activated for FSR = "); Serial.println(FSR);
}
}
out["FSR1newton"] = fsrForceArray[0];
out["FSR2newton"] = fsrForceArray[1];
out["FSR3newton"] = fsrForceArray[2];
};
thing["weight"] >> [](pson & out) {
for (int FSR = 0; FSR < noFSRs; FSR++) {
fsrWeightInGramsArray[FSR] = fsrForceArray[FSR] * conversionToKgrams * 1000.0;
}
out["FSR1weight"] = fsrWeightInGramsArray[0];
out["FSR2weight"] = fsrWeightInGramsArray[1];
out["FSR3weight"] = fsrWeightInGramsArray[2];
};
}
void loop(void) {
thing.handle();
}
回路図
3個のFSR(分圧回路付き)と加速度センサー

製造プロセス
- スマートバーテンダー:Raspberry Pi駆動の自作カクテルステーション
- Arduino Nanoで20kHzオシロスコープを自作:Nokia 5110 LCD搭載・簡易DIYガイド
- Arduino UNOで作る精密反応速度テスター
- 家庭用水ポンプが苦戦している理由:一般的な原因と対策
- 四半期ごとのサプライチェーン健康診断:スムーズな運営を確保する
- 圧縮空気システムの圧力損失を最小化する方法
- ABB、ベアリング健全性監視スマートセンサーを発表しダウンタイム削減へ
- スマートホームの進化:コネクテッドリビングの未来を展望する
- IoT投資のROIを最大化する:実践ガイド
- ビル管理システム(BMS):IoTでスマートシティを支える
- Pythonでsys.getsizeof()を使ってオブジェクトのメモリ使用量を効率的に測定する方法