Создание умной стельки для точного мониторинга распределения давления под ногой
Компоненты и расходные материалы
| Arduino MKR1000 | × | 1 |
| Датчики силы (FSR) — модель Interlink 402 | × | 3 |
| Провод (по метру) | × | 1 |
| Резисторы 10 кОм | × | 3 |
| Power Bank | × | 1 |
| Акселерометр ADXL345 (SparkFun Breakout) | × | 1 |
Необходимые инструменты
- Паяльник (припой, термоусадка и аксессуары)
Приложения и онлайн-сервисы
- Платформа Thinger.io
- Arduino IDE
О проекте
Измерение давления применяется во многих областях: информация о биомеханике шага, клиника, спорт. В этом проекте датчики дают представление о распределении веса. Реализована визуализация давления в реальном времени — так данные понятнее.
Необходимое железо
- Arduino MKR1000 — подойдут большинство 3.3В/5В плат с Wi-Fi, но ESP не рекомендую: несколько плат давали неточные измерения.
- FSR (3 шт.) — Interlink 402 (100 Н). Также пробовал дороже Interlink 406, но 402 достаточно. Больше FSR — выше точность.
- Резисторы 10 кОм — меняйте для масштабирования диапазона измерений. Чем больше резистор, тем крупнее шаги. Подробнее здесь.
- Акселерометр ADXL345 (16G) — для измерения ускорения и движений стопы. Опционально, но полезно для анализа шаговой фазы.
- Паяльник — крокодилы в ботинке не работают.
Сборка схемы

Важные замечания:
FSR — читайте перед пайкой: будьте крайне осторожны при пайке проводов к FSR. Не пытайтесь, если не уверены в навыках. Пайте очень быстро — пластик плавится. Узнал на горьком опыте…
У FSR нет полярности — плюс/минус не важны.
Резисторы можно менять для масштабирования диапазона.
GND/5V: все датчики подключены к общей шине 5V и GND.
Акселерометр: можно не ставить, если не нужен. Для чистого измерения давления не обязателен, но помогает при анализе гаитовой фазы.
Монтаж железа на стельку
Рекомендую сделать это ПОСЛЕ запуска кода — если есть ошибки пайки, вы узнаете сразу и сэкономите время на перепайке.
Три FSR клеятся в точки стельки: левый верх — эверсия, правый верх — инверсия, пяточный — давление на пяту. Точное положение — методом проб: ищите точку, где аналоговое значение меняется сильнее всего при ходьбе.
Провода зафиксированы скотчом — движение вызывает помехи. Велкро на подошве и внутри ботинка держит стельку на месте.
Акселерометр (если есть) на заднюю часть пятки — двусторонний скотч.

Измерение сил
Готовы к измерениям. Далее предполагаю знакомство с библиотекой Thinger.io. Подробнее — в разделе «Отправка данных через Thinger.io».
Программа имеет длинный заголовок: переменные для Wi-Fi, глобальные массивы для каждого FSR (длина 3). Использую массивы максимально — каждый элемент под свой датчик. Глобальные переменные нужны для отправки через Thinger.io.
Код прокомментирован. Полный код внизу страницы.
#define _DEBUG_ // Включает Serial Monitor
#include
#include
#include // Акселерометр
#include
#include
#include
#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; // R в кОм
long Vcc = 5000; // 5В = 5000 мВ, 3.3В = 3300 мВ
float voltageMax = 0.98 * Vcc; // Макс. напряжение 95% от Vcc
ThingerWifi101 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
Соединение с Thinger.io настраивается строкой:
ThingerWifi101 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
Параметры берутся из вашего аккаунта на Thinger.io — настройте сначала.
В setup() устанавливается Serial и Wi-Fi:
void setup(void) {
Serial.begin(115200);
thing.add_wifi(SSID, SSID_PASSWORD);
}
void loop(void) {
thing.handle();
}
Определяем «thing» — ключевую концепцию Thinger.io. Это как функция, но со специальной структурой для отправки данных в облако.
thing["pressure"] — считывает сырые значения трёх FSR, выводит в Serial и в канал out.
thing["voltage"] — переводит АЦП в милливольты (map 0-1023 → 0-5000), сохраняет в fsrVoltageArray, отправляет в out.
thing["newton"] — самая сложная часть: перевод напряжения в силу (Ньютоны). Логарифмическая функция сглаживает кривую. Разбираются крайние случаи: слишком высокое напряжение (обрезаем до макс. силы), слишком низкое (нуль, шум), средние — логарифм.
thing["weight"] — простое преобразование Ньютонов в граммы.
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];
};
Настройте дашборд на Thinger.io. Ожидаемый вид:

Измерение ускорения
Проще, чем давление. Добавляем библиотеки Wire.h, Adafruit_Sensor.h, Adafruit_ADXL345_U.h и три глобальные переменные x, y, z.
В setup() проверяем датчик, задаём диапазон 16G, создаём thing["accelerometer"], который читает событие и отправляет x, y, z в out.
#include
#include
#include
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(" ");
Serial.print("Y: "); Serial.print(event.acceleration.y); Serial.print(" ");
Serial.print("Z: "); Serial.print(event.acceleration.z); Serial.println(" m/s^2");
};
}
}
Ожидаемый вывод в Serial:

Сборка всего вместе
Полный код в конце страницы.
Отправка данных через Thinger.io
Библиотека хорошо документирована, но ключевые моменты:
Структура «thing» (обратите внимание на точку с запятой после }):
thing["идентификатор"] >> [](pson& out) {
// ваш код
};
Это лямбда-функция C++. Обязательное первое слово — thing.
Строка в скобках — уникальное имя функции.
>> — только выходные значения. Для входа — <<, для входа+выхода — =. У нас только выход.
pson &out — гибкая структура данных (поддерживает JSON).
Отправка значений: out["уникальная-строка"] = значение.
В loop() только thing.handle(). Весь код обновления данных внутри «things» — они циклически выполняются сами. Важно: если данные обновляются регулярно, вычисления должны быть внутри «things».
FAQ
Ничего не работает! Проверьте провода. Если Serial молчит — убедитесь, что #define _DEBUG_ в первой строке. TLS может мешать — можно отключить (осторожно). Проверьте связь с Thinger.io.
Вывод не как ожидается. Весь обновляемый код внутри «thing»? Если снаружи — не обновляется. ESP-платы плохо работают с FSR.
Вывод не обновляется регулярно. Убрайте delay(). Частоту обновления задавайте на Thinger.io.
Хочу всё в одном графике. Положите весь код в один «thing».
Готово!
Надеюсь, туториал помог понять основы FSR, акселерометров и Thinger.io. Буду рад предложениям по улучшению кода — делитесь своими созданиями!
Код
Smart-Insole-Tutorial (Arduino)
Полный код туториала:
#define _DEBUG_
#include
#include
#include
#include
#include
#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();
}
Схемы
Три FSR (с делителями напряжения) и акселерометр.

Производственный процесс
- Умный бармен: создайте свою Raspberry Pi-станцию для коктейлей
- ABB запускает умный датчик для мониторинга здоровья подшипников и снижения простоев
- Эволюция умного дома: что будущее готовит для коннектед жилья
- Максимизация ROI от IoT-инвестиций: практическое руководство
- Системы управления зданиями: питание умных городов с IoT
- Эффективное измерение использования памяти объектами Python с помощью sys.getsizeof()
- Квартальная проверка здоровья цепочки поставок: обеспечьте бесперебойные операции
- Точный тест времени реакции на Arduino UNO
- Почему насос вашего дома работает плохо: частые причины и решения
- Минимизация потерь давления в системе сжатого воздуха