Variômetro Acústico Ultra-Sensível: Barômetro de Precisão para Pilotos
Componentes e Materiais
| Arduino Pro Mini 328 - 3.3V/8MHz | × | 1 |
| Sensor Barométrico GY-63 (MS5611) 3.3V | × | 1 |
| Chave DIP 8 posições | × | 1 |
| Buzzer ativo (com oscilador interno) | × | 1 |
| Multiplexador 8x1 4051 3.3V | × | 1 |
| Bateria LiPo 1s 3.7V 350mAh + fios e conectores | × | 1 |
| Módulo step-up + carregador USB LiPo TP5400 | × | 1 |
| Resistores (rede 8×4.7k, 220Ω, 2×10k) e capacitores (47µF, 470µF) | × | 1 |
| Fusível rearmável 0.5A | × | 1 |
| Caixa plástica ABS preta 78×39×22 mm | × | 1 |
| Chave deslizante liga/desliga | × | 1 |
| Conector fêmea 6 pinos (para FTDI) | × | 1 |
| Headers macho (vários tamanhos) | × | 1 |
| Fio rígido 30 cm para jumpers | × | 1 |
| Corda verde para fixação | × | 1 |
Sobre o Projeto
Introdução
Este instrumento é utilizado por pilotos durante voos (asa delta, parapente, planador, balão, etc.) para ajudar a localizar o núcleo das térmicas e subir de forma mais eficiente.
Descrição Geral
Trata-se de um barômetro extremamente sensível que emite sinais sonoros durante a subida e também durante a descida. Os sons são bipes simples: um por segundo, dois por segundo ou mais durante a subida (maior taxa de subida = maior frequência de bipes). A sensibilidade é tal que começa a bipar com apenas alguns centímetros por segundo de velocidade vertical — experimente levantar lentamente o braço segurando o variômetro para ouvir o som. Em caso de taxa de descida, emite bipes longos e contínuos a partir de -1 m/s.
Lista de Componentes
- Arduino Pro Mini 3.3V 8 MHz como MCU
- Sensor barométrico GY-63 (MS5611) 3.3V
- Chave DIP 8
- Buzzer ativo com oscilador interno
- Multiplexador 8x1 4051 3.3V
- Bateria LiPo 1s 3.7V 350mAh + fios 10cm vermelho/preto e conectores M+F
- Módulo step-up + carregador USB LiPo TP5400 da AZDelivery
- Alguns resistores: rede 8×4.7k, 220Ω, 2×10k, e capacitores 47µF, 470µF
- Fusível rearmável 0.5A
- Caixa plástica ABS preta, 78×39×22 mm
- Chave deslizante liga/desliga
- Conector fêmea 6 pinos (para FTDI)
- Headers macho 17 pinos (diversas configurações)
- Header macho 4 pinos 90° para circuito do sensor P
- 30 cm de fio rígido encapado para jumpers e conexões
- Corda verde
O esquemático Fritzing acima mostra tudo o que você precisa para construir o circuito. Atenção: o capacitor cerâmico marrom logo abaixo da chave preta é, na verdade, um fusível rearmável (não encontrei o símbolo correto no Fritzing). No lugar dos 8 resistores, utilizei um único componente: uma rede de resistores contendo 8 × 4.7kΩ internamente; observe na próxima foto — é o componente preto no topo da chave DIP azul, com nove pinos (um comum e oito para os resistores). O arquivo Fritzing para download está disponível abaixo.
Significado da Chave DIP
Optei pela chave DIP azul, com 8 micro-chaves on/off em um único invólucro colorido, para selecionar e alterar os parâmetros de funcionamento do variômetro. A tabela a seguir explica cada configuração:
- Pino 1: não utilizado (qualquer posição não altera nada)
- Pino 2: volume baixo ou alto — atua eletricamente: quando ligado, curto-circuita o resistor em série com o buzzer, permitindo maior corrente e volume mais alto
- Pinos 3 e 4: alarme de descida (m/s): -999 (sem limite), -1, -2, -3 — funcionam como código binário de 2 bits (00=0, 01=1, 10=2, 11=3)
- Pinos 5 e 6: frequência dos bipes (Hz): +1, +1.5, +2, +3 — também em binário; em mesma velocidade de subida, +2 Hz bipa mais rápido que +1 Hz
- Pinos 7 e 8: sensibilidade (m/s): +0.0 (máxima), +0.1, +0.2, +0.5 — +0.0 detecta subidas <10 cm/s; até fechar uma porta na sala pode disparar bipes por mudança de pressão. Na posição +0.5, requer velocidade significativamente maior para bipar
Do ponto de vista eletrônico, os pinos 1 e 3–8 são lidos analógicamente via multiplexador 4051; o software decide se está ligado ou desligado (valores > 512 ou não). O MCU (Arduino) seleciona qual das 8 portas ler através de 3 bits de saída (000 a 111). Veja a função readDIPswitch() no código.
Cuidados com a Bateria
Os dois resistores de 10kΩ junto com o capacitor de 47µF formam um divisor de tensão para monitorar a bateria. Baterias LiPo são críticas se descarregadas abaixo de 3.3V — a cada 10 segundos (BATTinterval) a função checkBATT() é chamada e, em caso de baixa tensão, o buzzer avisa com 6 bipes curtos por segundo. Não demore para desligar e recarregue logo!
MUITO IMPORTANTE: faça pelo menos um FURO na caixa para permitir a passagem de ar para o sensor de pressão. Fiz dois furos: um para ouvir o buzzer e outro para ver o LED de status de carga quando conectado ao cabo micro USB. Com furos, o variômetro não é mais à prova d'água.
O PCB
Utiliza-se PCB de face única, por isso precisei incluir alguns jumpers de fio (linhas pontilhadas) para resolver o roteamento completo. Seguem os arquivos das faces de componentes e solda (espelhados) para download e impressão em folhas "amarelas" ou "azuis" (as azuis dizem ser melhores, mas são mais caras). Ao imprimir, desative economia de toner e use resolução 1200 dpi para preto profundo. A transferência de toner para o PCB é feita com ferro de passar. Imprimir ambas as faces torna o projeto "profissional".
São usados cerca de uma dúzia de pinos do Arduino. Soldar os pinos não utilizados é desnecessário: deixe-os livres. Coloque o header fêmea de 6 pinos na face superior do Pro Mini para permitir futura conexão FTDI para atualizações de firmware.
O circuito step-up USB de alimentação fica montado de cabeça para baixo. Para fixá-lo, use dois pinos machos fortes (sem o suporte plástico) ao lado do conector USB onde está escrito "Power USB": solde tudo junto (dois pinos + conector USB). Três fios conectam GND-, BAT+ e OUT+ a este circuito.
O Sensor Barométrico
O sensor GY-63 (MS5611), marcado como P-Sensor no PCB, vem em uma pequena placa e comunica-se via barramento I2C. O uso é simples; inclui também sensor de temperatura que não utilizei.
O programa chama a função readPSensor(), que é o núcleo do software. O que precisamos é a variação relativa de altitude: a função lê várias vezes por segundo e acumula em PrexTotal; a cada meio segundo (PrexInterval) calcula a variação média de altitude e prossegue com bipes ou bipe longo considerando as configurações da chave DIP. Este método simples de filtragem é suficiente; testei filtragem Kalman e também os complexos algoritmos Madgwick e Mahony sem benefícios significativos para este propósito.
Atualizações e Dicas
É isso. Gostei muito deste projeto! Faça você também! :-)
Marco Zonca
Código
Código do Variômetro Acústico Arduino
/* Este sketch atua como Variômetro para parapente, por Marco Zonca, 2020
Arduino MiniPro 3.3 como CPU, GY-63 (MS5611) sensor barométrico,
8 x chave DIP, buzzer, Mux 4051, lipo 1s 3.7v 350mA,
3.7v -> 5v step-up + carregador USB LiPo;
Chave DIP: 1= não usado 2= hw volume buzzer baixo/alto
3= \ alarme descida: OFF -1.0 -2.0 -3.0 m/s 4= /
5= \ frequência bipes: +1.0 +1.5 +2.0 +3.0 Hz 6= /
7= \ sensibilidade: +0.0 +0.1 +0.2 +0.5 m/s 8= / */
#include <MS5611.h>
#include <NewTone.h>
const int muxIOpin = 15;
const int vbattPin = 14;
const int muxbit0 = 4;
const int muxbit1 = 5;
const int muxbit2 = 6;
const int buzzerPin = 7;
const int DIPSWinterval = 5000;
const int BATTinterval = 10000;
const int PrexInterval = 500;
const boolean isDebug = false;
float sensibility[5];
float frequency[5];
float sinkalarm[5];
long n=0;
boolean dipswitch[9];
String dips;
unsigned long prevDIPSWmillis = 0;
unsigned long prevBATTmillis = 0;
float n1=0;
float n2=0;
float SensorVBatt=0;
double referencePressure = 0;
unsigned long prevPrexMillis = 0;
unsigned long currPrexMillis = 0;
double realPressure = 0;
float absoluteAltitude = 0;
float relativeAltitude = 0;
float avgAltitude = 0;
float avgPrevAltitude = 0;
long PrexCounter = 0;
float PrexTotal = 0;
float PrexVario = 0;
boolean isFirstCalc = true;
MS5611 psensor; // sensor de pressão
void setup() {
Serial.begin(9600);
pinMode(muxbit0, OUTPUT);
pinMode(muxbit1, OUTPUT);
pinMode(muxbit2, OUTPUT);
pinMode(buzzerPin, OUTPUT);
sensibility[4]=0; sensibility[3]=0.5; sensibility[2]=0.2; sensibility[1]=0.1; sensibility[0]=0.0;
frequency[4]=0; frequency[3]=3.0; frequency[2]=2.0; frequency[1]=1.5; frequency[0]=1.0;
sinkalarm[4]=0; sinkalarm[3]=-3.0; sinkalarm[2]=-2.0; sinkalarm[1]=-1.0; sinkalarm[0]=-999.9;
readDIPswitch();
psensor.begin();
referencePressure = psensor.readPressure();
if (isDebug == true) Serial.println("Vario is on");
NewTone(buzzerPin, 4);
delay(750);
noNewTone();
}
void loop() {
readPSensor();
if ((prevDIPSWmillis + DIPSWinterval) < millis()) {
readDIPswitch();
prevDIPSWmillis = millis();
}
if ((prevBATTmillis + BATTinterval) < millis()) {
checkBATT();
prevBATTmillis = millis();
}
}
void readPSensor() {
realPressure = psensor.readPressure();
absoluteAltitude = psensor.getAltitude(realPressure);
relativeAltitude = psensor.getAltitude(realPressure, referencePressure);
PrexCounter++;
PrexTotal += relativeAltitude;
currPrexMillis = millis();
if (currPrexMillis - prevPrexMillis >= PrexInterval) {
avgAltitude = PrexTotal / PrexCounter; // média
if (isFirstCalc == true) {
avgPrevAltitude = avgAltitude;
isFirstCalc = false;
}
PrexVario = (avgAltitude - avgPrevAltitude) * (1000.0 / PrexInterval); // vario m/s
if ((PrexVario <= sensibility[4]) && (PrexVario >= sinkalarm[4])) {
noNewTone();
}
if (PrexVario > sensibility[4]) {
// subida: bipe-bipe
NewTone(buzzerPin, (int)(PrexVario + frequency[4]));
}
if (PrexVario < sinkalarm[4]) {
// descida: bipe longo
NewTone(buzzerPin, 0.1);
}
avgPrevAltitude = avgAltitude;
prevPrexMillis = currPrexMillis;
PrexTotal = 0;
PrexCounter = 0;
if (isDebug == true) {
Serial.print("Vario=");
Serial.println(PrexVario);
}
}
}
void readDIPswitch() {
int s = 0;
for (n = 1; n < 9; n++) {
dips = "0000" + String(n - 1, BIN);
dips = dips.substring(dips.length() - 3, dips.length());
digitalWrite(muxbit0, dips.substring(2, 3) == "0" ? LOW : HIGH);
digitalWrite(muxbit1, dips.substring(1, 2) == "0" ? LOW : HIGH);
digitalWrite(muxbit2, dips.substring(0, 1) == "0" ? LOW : HIGH);
dipswitch[n] = (analogRead(muxIOpin) <= 512);
if (isDebug) Serial.print(dipswitch[n] ? "1" : "0");
}
if (isDebug) Serial.println();
// Sensibilidade (pinos 7 e 8)
s = 0;
if (dipswitch[7]) s += 2;
if (dipswitch[8]) s += 1;
sensibility[4] = sensibility[s];
if (isDebug) { Serial.print("Sensibility="); Serial.println(sensibility[4]); }
// Frequência (pinos 5 e 6)
s = 0;
if (dipswitch[5]) s += 2;
if (dipswitch[6]) s += 1;
frequency[4] = frequency[s];
if (isDebug) { Serial.print("Frequency="); Serial.println(frequency[4]); }
// Alarme descida (pinos 3 e 4)
s = 0;
if (dipswitch[3]) s += 2;
if (dipswitch[4]) s += 1;
sinkalarm[4] = sinkalarm[s];
if (isDebug) { Serial.print("SinkAlarm="); Serial.println(sinkalarm[4]); }
}
void checkBATT() {
n1 = analogRead(vbattPin);
n2 = ((6.60 * n1) / 1023.00);
SensorVBatt = n2 + ((n2 * 0.0) / 100); // correção arbitrária (inativa = 0.0%)
if (SensorVBatt <= 3.4) {
NewTone(buzzerPin, 6, 1000); // 6 bipes curtos
}
if (isDebug) {
Serial.print("VBatt=");
Serial.println(SensorVBatt);
}
}
Peças Personalizadas e Gabinetes
Esquemáticos
vario_R1XzPifiX4.fzz (arquivo Fritzing para download)
Processo de manufatura
- Armazene e Gerencie Dados Sensíveis com Segurança usando Google Cloud Secret Manager
- Barômetro Aneroide: Design, História e Futuro da Medição de Pressão
- Técnica Avançada de Detecção Identifica Defeitos em Transistores com Sensibilidade Sem Precedentes
- Sensores de Deformação Ultra-Finos MXene Revolucionários Aprimoram Precisão e Segurança de Braços Robóticos
- Receptores Ópticos Avançados para Comunicações Espaciais
- Amstrong® Ultra 650MC – Aço de Alta Resistência e Baixo Carbono para Soldabilidade Superior
- Amstrong® Ultra 650MCT – Aço de Alta Resistência e Baixo Carbono para Soldabilidade Superior
- Amstrong® Ultra 700MC – Aço de Alta Resistência, Grão Fino, para Soldabilidade Superior
- Amstrong® Ultra 700MCT – Aço de Ultra-Alto Limite de Escoamento com Baixo Carbono e Grão Fino para Soldabilidade Superior
- Cromo de Ultra-Alta Pureza (UHP Cr) – 99,95%+ para Aplicações Críticas