Construa uma Palmilha Inteligente para Monitorar Precisamente a Distribuição de Pressão Plantar
Componentes e Materiais
- Arduino MKR1000 × 1 — placas 3.3V/5V com Wi-Fi funcionam, mas evite ESP (leituras imprecisas observadas).
- Resistores Sensíveis à Força (FSR) × 3 — modelo Interlink 402 (100N). Interlink 406 mais caro também funciona, mas 402 basta. Mais FSRs = melhor precisão.
- Cabo OpenBuilds (por metro) × 1
- Resistor 10k Ω × 3 — ajuste para escalar leituras. Maior resistência = maiores incrementos. Mais info aqui.
- Power Bank × 1
- Acelerômetro Triple Axis ADXL345 (SparkFun) × 1
Ferramentas Necessárias
- Ferro de solda — não esqueça solda, heat-shrink e acessórios.
Aplicativos e Serviços Online
- Plataforma Thinger.io
- Arduino IDE
Sobre o Projeto
Medição de pressão plantar já é usada em diversas situações: informa mecânica da marcha, aplicações clínicas e esportivas. Este projeto usa sensores para entender distribuição de peso. Visualização em tempo real do mapeamento de pressão facilita compreensão dos dados.
Hardware Necessário
- Arduino MKR1000 — a maioria das placas 3.3V/5V com Wi-Fi serve, mas não recomendo ESP; várias placas ESP retornaram medições imprecisas.
- FSRs (3) — Interlink 402 (100N). Também testei Interlink 406, mas 402 seria suficiente. Use mais FSRs para maior precisão.
- Resistores 10K — altere para escalar leituras ao intervalo desejado. Resistores maiores = incrementos maiores.
- Acelerômetro ADXL345 16G — mede aceleração e movimento do pé. Opcional se só quer pressão, mas útil para análise do ciclo de marcha.
- Ferro de solda — essencial. Clips jacaré não funcionam bem dentro do sapato.
Ligação do Circuito
Notas rápidas sobre o circuito:
FSRs — Leia antes de soldar: Seja extremamente cauteloso ao soldar fios nos FSRs. Não tente se não tem certeza da habilidade. Solda muito rápido ou o plástico derrete. Aprendi da pior forma...
FSR não tem polaridade (lado positivo/negativo).
Resistores podem ser alterados para escalar leituras.
Terra/5V: Todos sensores soldados na linha 5V e comum.
Acelerômetro: Pode omitir se não precisar. Não é estritamente necessário para medir pressão, mas ajuda na análise de aceleração/ciclo de marcha.
Fixando Hardware na Palmilha
Recomendo fazer isso após rodar o código primeiro, pois erros de solda serão detectados então, evitando refazer a fixação.
FSRs fixados em três pontos da palmilha: superior esquerdo (eversão), superior direito (inversão), calcanhar (pressão no calcanhar). Encontrar o melhor ponto é tentativa e erro: onde o valor analógico mais varia ao caminhar.
Fita adesiva prende os fios; movimento causa interferência nas leituras. Usei velcro na sola e dentro do sapato para fixar a palmilha.
Acelerômetro colado com fita dupla-face na parte traseira do calcanhar do sapato.
Medindo as Forças
Agora pronto para medir forças. (Assumo familiaridade com biblioteca Thinger.io; veja seção "Enviar dados via Thinger.io").
Programa tem cabeçalho longo com variáveis de configuração (WiFi, credenciais Thinger.io) e arrays globais. Optei por arrays para cada sensor FSR (tamanho 3). Evite muitas variáveis globais por efeitos colaterais, mas necessárias para Thinger.io.
Código explicado nos comentários. Download do código completo ao final.
#define _DEBUG_ // habilita Serial Monitor
#include <WiFi101.h>
#include <ThingerWifi101.h>
#include <Wire.h> // Acelerômetro
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
#include <Adafruit_NeoPixel.h>
#define USERNAME "seuUsuario"
#define DEVICE_ID "seuDeviceID"
#define DEVICE_CREDENTIAL "suaCredencial"
#define SSID "seuSSID"
#define SSID_PASSWORD "suaSenha"
// FSR sensors
#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 em kOhm
long Vcc = 5000; // 5V=5000mV, 3.3V=3300mV
float voltageMax = 0.98 * Vcc; // 95% de Vcc
ThingerWifi101 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
Conexão Thinger.io configurada via:
ThingerWifi101 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
Credenciais obtidas na sua conta Thinger.io.
No setup(), inicia serial e WiFi:
void setup(void) {
Serial.begin(115200);
thing.add_wifi(SSID, SSID_PASSWORD);
}
void loop(void) {
thing.handle();
}
Definimos "things" (conceito chave Thinger.io) para enviar dados à nuvem. Cada "thing" é como uma função com estrutura especial.
Thing "pressure" lê valores brutos dos 3 FSRs e imprime no Serial; também envia ao canal "out".
thing["pressure"] >> [](pson & out) {
out["FSR1"] = analogRead(FSR1);
Serial.print("FSR1:"); Serial.println(analogRead(FSR1));
out["FSR2"] = analogRead(FSR2);
Serial.print("FSR2:"); Serial.println(analogRead(FSR2));
out["FSR3"] = analogRead(FSR3);
Serial.print("FSR3:"); Serial.println(analogRead(FSR3));
};
Thing "voltage" lê e escala tensão (0-5000mV) via map, armazena em fsrVoltageArray.
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); // ajuste 5000 se não 5V
}
out["FSR1voltage"] = fsrVoltageArray[0];
out["FSR2voltage"] = fsrVoltageArray[1];
out["FSR3voltage"] = fsrVoltageArray[2];
};
Thing "newton" — mais complexo: converte tensão para força em Newtons. Distingue casos limite: tensão muito alta (saturação), força muito pequena (ruído), caso normal (logaritmo para reduzir inclinação). Fórmulas aproximadas; cada sensor tem curva ligeiramente diferente, mas simplificamos.
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" — converte Newton para gramas.
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];
};
Configure dashboard no Thinger.io. Se tudo certo, parecerá com:
Medindo Aceleração
Mais simples que pressão. Adicione bibliotecas Wire.h, Adafruit_Sensor.h, Adafruit_ADXL345_U.h e variáveis globais x,y,z.
No setup(), verifica sensor, define range 16G e cria thing "accelerometer" que envia aceleração x,y,z (m/s²) ao canal "out".
#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(" ");
Serial.print("Y: "); Serial.print(event.acceleration.y); Serial.print(" ");
Serial.print("Z: "); Serial.print(event.acceleration.z); Serial.println(" m/s^2");
};
}
}
Saída esperada similar a:
Juntando Tudo
Código completo no final da página.
Enviar Dados via Thinger.io
Biblioteca bem documentada aqui. Pontos-chave:
Estrutura (note ponto-e-vírgula após chave de fechamento):
thing["identificador"] >> [](pson& out) {
// seu código
};
Chamada lambda function em C++. "thing" é palavra obrigatória. Identificador único por thing.
>> indica só saída. Entrada usa <<, bidirecional usa =. Nosso caso: só saída.
Argumento pson &out: estrutura de dados flexível (suporta JSON). Enviamos valores com out["chave_unica"] = valor.
Loop geralmente só chama thing.handle(). Cálculos ficam dentro dos "things" para atualização contínua.
Perguntas Frequentes
- Nada acontece!
- Verifique fiação. Se nada no Serial Monitor, confira se
#define _DEBUG_está na primeira linha. TLS pode interferir (desative com cuidado). Verifique conexão Thinger.io. - Saída diferente do esperado
- Todo código que precisa atualizar está dentro de um "thing"? Fora não atualiza. Placas ESP não funcionam bem com FSRs por razão desconhecida.
- Saída não atualiza regularmente
- Removeu
delay()? Taxa de atualização configurável no Thinger.io. - Quero tudo num gráfico só
- Coloque todo código num único "thing".
Parabéns!
Espero que este tutorial ajude a entender FSRs, acelerômetros e Thinger.io. Adorarei sugestões de melhoria e ver suas criações!
Código
Smart-Insole-Tutorial (Arduino)
Código completo do tutorial
#define _DEBUG_ // Deve vir antes de qualquer include
/* Tutorial: https://www.hackster.io/projects/a5ceae */
#include <WiFi101.h>
#include <ThingerWifi101.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
#define USERNAME "seuUsuario"
#define DEVICE_ID "seuDevice"
#define DEVICE_CREDENTIAL "suaCredencial"
#define SSID "seuSSID"
#define SSID_PASSWORD "suaSenha"
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();
}
Esquemáticos
Três FSRs (com divisores de tensão) e um acelerômetro.
Processo de manufatura
- Bartender Inteligente: Construa sua Própria Estação de Coquetéis com Raspberry Pi
- ABB Lança Sensor Inteligente para Monitorar Saúde de Rolamentos e Reduzir Downtime
- Evolução Casa Inteligente: O Que o Futuro Reserva para Vida Conectada
- Maximize o ROI em Seus Investimentos em IoT: Um Guia Prático
- Sistemas de Gestão de Edifícios: Impulsionando Cidades Inteligentes com IoT
- Medir Eficientemente o Uso de Memória de Objetos Python com sys.getsizeof()
- Check-up Trimestral de Saúde da Cadeia de Suprimentos: Garanta Operações Suaves
- Teste de Tempo de Reação Preciso com Arduino UNO
- Por Que a Bomba de Água da Sua Casa Está com Dificuldades: Causas Comuns e Soluções
- Minimize Perdas de Pressão no Seu Sistema de Ar Comprimido