Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão

Componentes e Materiais

Sobre o Projeto

Prefácio

Adoro velejar sozinho: no mar, com seu barco, você tem tudo para evoluir. Tempo ruim é duro, mas dias de sol e vento bom são o máximo. Felicidade: horizontes infinitos, técnica perfeita, escolhas ótimas... e um bom drink com sanduíche! Exatamente aí entra o Autopiloto: trabalha por você enquanto você toma seu chá das 5 no mar. :-)

O que o Autopiloto faz por você

Barco à vela não tem motor e não segue rota programada sozinho. Todo trabalho é do velejador: ajustar velas, monitorar vento/clima, manusear cabos, vigiar tráfego, decidir rumo e timonear. Quando o velejador quer pausa (10 seg a alguns min – o famoso "hora do chá"), liga o autopiloto. Em segundos, GPS adquire posição, velocidade e rumo, mantendo a direção. O sistema de direção (pau de leme conectado ao leme), antes movido pelas mãos do velejador, passa a ser controlado pelo autopiloto via motor de passo com polias e cabos.

Controlar o leme é trabalho contínuo de ajuste fino ou grosso. Barcos menores/leves sofrem mais influências: ondas, vento, deslocamento de peso a bordo, correntes. Mas o velejador fica atento, ajustando rota via controle remoto: 4 botões (+1, -1, +10, -10 graus). Esses botões também estão no autopiloto (verde/direita, vermelho/esquerda). Botão azul (central) = ativar/pausar. Botão preto = configurar parâmetros na memória.

Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão

O Circuito

Processamento principal: Arduino Uno. Arduino Nano = watchdog externo (sei que Uno tem watchdog interno, mas quis microcontrolador independente – sonho realizado!). Uno alimenta Nano via pino 3 → A0 (HIGH/LOW, 5V/0V) pelo menos 1 vez a cada 2.5s (feedingInterval); se não, Uno "travou" → Nano reseta Uno. Nunca aconteceu ainda!

Display LCD1602 + conversor I2C (4 fios, economiza pinos). Botões e controle remoto via divisores de tensão resistivos (menos portas do MCU). Usei resistores 1% precisão; valores analógicos no código. Se botões não reconhecidos por resistores diferentes, ajuste constantes em checkRfRC() e checkHWButtons().

RF 433MHz funciona bem; adicionei antena de bobina (fio de cobre) → testado 10m, acho que chega a 20m+ (barco teste: 4.20m).

GPS: Comecei com EM406A, mas sofria Week-Rollover-Bug (muito antigo). Troquei por Beitian BN-220T. Configure via software para saída 2Hz apenas sentença $GNRMC. GPS TX → pino 0 (RX) do Uno. Desconecte GPS temporariamente durante upload de sketch!

EEPROM 24C04 (512 bytes I2C) para gravar parâmetros do motor de passo (explicados em Software).

Lista de Componentes Detalhada

(Ver lista completa na seção Componentes acima)

Sensores no multiplexador 4051:

LEDs: Amarelo pisca 1Hz = watchdog ok; Azul = autopiloto ativo (apagado = pausa); Vermelho pisca = botão RC pressionado.

Tudo a 5.0V via LiPo 2S 7.4V 2600mAh + 7805. Corrente < 800mA (típico 100-450mA). Dissipador no 7805 obrigatório! Termistor no dissipador → buzzer apita se > 50°C.

Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão
Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão
Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão
Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão
Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão
Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão
Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão
Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão

PCBs e Montagem

PCBs face única → alguns jumpers (linhas pontilhadas) para resolver rotas. Mostradas faces de componentes; arquivos para download: faces componentes, solda, espelhadas – impressão laser em folhas "amarelas" ou "azuis" (azuis dizem ser melhores, mas mais caras). Usei amarelas. Desative economia de toner, use 1200 dpi para preto profundo. Transferência de toner com ferro quente. Impressão nas duas faces facilita posicionamento e dá ar profissional.

Ambas PCBs dimensionadas para empilhar sobre o Arduino Uno: Power Shield embaixo, Autopilot Shield por cima.

Optei por não soldar tudo junto: usei headers e jumpers Dupont (~200 conexões não soldadas). Permite reuso, mas pode causar mau contato. Sugestão: soldar tudo para circuito estável!

Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão
Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão

Configuração de Parâmetros e Valores dos Sensores

Botão preto entra no Modo Setup (pode durante navegação ativa, sem pausar). Pressionar repetidamente navega pelas páginas:

  1. Sensores: Tensão bateria (V=7.83), Consumo (mA=177), Temp. dissipador (38°C)
  2. Interval: ex. 2000 ms – tempo entre tentativas do motor de passo para restaurar rumo
  3. Minimum: ex. 2° – desvio mínimo para autopiloto intervir (até isso, leme centralizado)
  4. Max: ex. 40° – máximo giro do motor por vez (se cálculo der 50°, move só 40°)
  5. Coeffic.: ex. 1.50x – coeficiente de giro (cálculo 40° → motor move 40×1.50=60°)
  6. Página 6: "Updating..." se algo mudou → salva na EEPROM

Parâmetros essenciais para ajuste fino no barco: responsividade, suavidade dependem de diâmetro das polias, qtd. polias, sensibilidade do leme, comprimento do pau de leme, etc. Instale, teste em dia bonito com vento fraco!

Funcionamento "Ao Vivo"

Navegando no mar/lago/porto. Hora do chá: ligue autopiloto, aguarde fix GPS. Display mostra velocidade (nós), relógio, rumo atual H270° (R=rota alvo, H=rumo real). Lembre: 180°=S, 270°=W, 360/0°=N, 90°=E. R e H iguais em Pausa (mostra STOP). Conecte cabo do motor ao pau de leme, pressione azul → autopiloto assume direção; mantém R e corrige H (-10°, +5°, etc. até H=R). Ajuste rota com botões vermelho/verde na unidade ou controle remoto. Para reassumir: pausa (botão azul), desconecte cabo, timoneie manual. Pronto.

Lado do Software

Código longo, mas claro. Usa ~65% programa, ~45% memória. Mesmo com classe String (manipulação NMEA), fluxo estável. Usa serialEvent() para receber GPS 2x/seg, chama nmeaExtractData(), valida com nmea0183_checksum(). Se GPS diferente, verifique estrutura da sentença (ex: EM406A usa $GPRMC, BN-220 usa $GNRMC – só mudar nome). Link útil checksum: nmeachecksum.eqth.net.

Exemplo sentença NMEA completa:
$GPRMC,095836.000,A,4551.9676,N,01328.7118,E,2.09,341.84,280519,,*08

No Setup(): EEPROM verificada – se nova/desconhecida, inicializada (formatada). Parâmetros lidos/escritos como bytes: endereços 0=0x29, 1=0x00, 2-3=interval, 4-5=min, 6-7=max, 8-11=coefficient (byte, byte, int, int, float). Operações EEPROM defensivas. Sensores checados a cada 10s via readMuxSensors() (multiplexador) → alarme se bateria baixa ou temp. alta. Resolução consumo ~40mA. Botões HW/RC checados continuamente; comportamento depende de IsSetup e RefreshDisplay(). Núcleo: seção STEERING CONTROL chama gomotor() para mover motor out/back (leme 10° direita, após interval volta a zero, novo cálculo). Direção funciona até no Setup. Watchdog feeding simples: toggle pino ASAP.

Instalação no Barco à Vela

Conforme foto: autopiloto e motor de passo na popa, bem fixos com parafusos. Cabo 6mm da polia principal passa por duas polias laterais fixadas ao barco com anéis de elástico (mantém tensão leve). Decida como conectar cabo ao pau de leme (conexão temporária; fácil conectar/desconectar). Mantenha sistema longe da água! :-)

Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão

Novidades e Atualizações

Aviso Legal e Alertas

Isto é um jogo, nada sério! Anos atrás fiz viagem de 16 meses ao redor do mundo em barco à vela. Navegamos extensivamente com autopiloto REAL (NÃO ESTE!) em todas condições, até mau tempo. Autopiloto real é hardware/software MUITO ROBUSTO no qual se confia muito. Este autopiloto Arduino é um jogo fantástico para brincar e passar tempo divertido.

Divirta-se!

Marco Zonca

Código

Sketch Autopiloto (para Uno)
/* This sketch act as Autopilot for small sailing boats, by Marco Zonca, 2019
   Arduino UNO as CPU, Arduino Nano as watchdog, GPS BT-220 nmea, stepper motor + controller,
   rf433Mhz RC, 6 buttons, buzzer, i2c display, 2 leds, i2c 24c04 eeprom, Mux 4051 for sensors,
   lipo 2s 7.4v 2600mA, 7805 voltage regulator, Thermistor; */
#include <LiquidCrystal_I2C.h>
#include <NewTone.h>
#include <Stepper.h>
#include <Wire.h>
String inputString = "";
String nm_time = "00:00:00";
String nm_validity = "V";
String nm_latitude = "ddmm.mmmm'N";
String nm_longitude = "dddmm.mmmm'E";
String nm_knots = "0.0kn";
float nmf_knots = 0.0;
String nm_truecourse = "360";
float nmf_truecourse = 360;
String nm_date = "dd/mm/yyyy";
String nm_routetofollow = "000";
float nmf_routetofollow = 0;
unsigned long previousStearingMillis = 0;
unsigned long currentStearingMillis = 0;
unsigned long prevCheckSensorsMillis = 0;
unsigned long currCheckSensorsMillis = 0;
int CheckSensorsInterval = 10000;
bool stringComplete = false;
bool isfirstfix = true;
bool ispause = true;
bool isStearing = false;
bool isSetup = false;
int s=0, y=0, z=0, d=0;
int rfRemoteControlValue = 0;
int HWButtonValue = 0;
int SetupParameter = 0;
float calcmove = 0, cm = 0, Stearing = 0, prevStearing = 0, t = 0;
int EEdisk = 0x50, EEid1 = 0x29, EEid2 = 0x00;
unsigned int EEaddress = 0, EEbytes = 12;
byte EEdata[12], EEbytedata;
int EEerr = 0;
float SensorVBatt=0, SensorVRes=0, SensorTemp=0, SensormAmp=0;
// Parâmetros default (lidos/gravados na EEPROM)
// endereço len tipo notas
// 0-255 bytes em 0x50 EEdisk, 256-512 em 0x51 (não usado)
// 0 1B byte 01001001 (0x29 id1)
// 1 1B byte 00000000 (0x00 id2)
int StearingInterval = 2000;    // ms entre tentativas 2-3B int 1000-5000 step 100
int StearingMinToMove = 2;      // graus 4-5B int 0-20 step 1
int StearingMaxMove = 40;       // graus 6-7B int 10-45 step 1
float StearingCoeffMove = 1.5;  // (graus * coeff) 8-11B float 0.1-4 step 0.1
// 12 livre
byte bStearingInterval[sizeof(int)];
byte bStearingMinToMove[sizeof(int)];
byte bStearingMaxMove[sizeof(int)];
byte bStearingCoeffMove[sizeof(float)];
int prev_StearingInterval=0, prev_StearingMinToMove=0, prev_StearingMaxMove=0;
float prev_StearingCoeffMove=0;
const int ledpausePin = 2;
const int watchDogPin = 3;
const int MuxSelBit0Pin = 7; // 00=Vin 01=Vbatt 10=Temp
const int MuxSelBit1Pin = 6;
const int motorsABenablePin = 13;
const int MuxIOPin = 14;
const int ButtonsPin = 15;
const int rfRemoteControlPin = 16;
const int speakerPin = 17;
const int RCleftbutton = 201, RCrightbutton = 202, RCleft10button = 203, RCright10button = 204;
const int HWleftbutton = 101, HWrightbutton = 102, HWpausebutton = 103, HWsetupbutton = 104;
const int HWleft10button = 105, HWright10button = 106;
const int motorStepsPerRevolution = 200; // 200 para modelo 23LM
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
Stepper motor(motorStepsPerRevolution, 9, 10, 11, 12);

void setup() {
  Serial.begin(4800);
  lcd.begin(16,2);
  Wire.begin();
  motor.setSpeed(60);
  inputString.reserve(200);
  pinMode(motorsABenablePin, OUTPUT);
  pinMode(MuxSelBit0Pin, OUTPUT);
  pinMode(MuxSelBit1Pin, OUTPUT);
  digitalWrite(motorsABenablePin, LOW);
  digitalWrite(MuxSelBit0Pin, LOW);
  digitalWrite(MuxSelBit1Pin, LOW);
  pinMode(ledpausePin, OUTPUT);
  pinMode(watchDogPin, OUTPUT);
  digitalWrite(ledpausePin, LOW);
  digitalWrite(watchDogPin, LOW);
  // read+check EEPROM (formatting if new)
  lcd.clear(); lcd.setCursor(0,0); lcd.print("Memory check...");
  lcd.setCursor(0,1);
  for (s = 0; s < EEbytes; s++) {
    EEaddress = s; EEbytedata = readEEPROM(EEdisk, EEaddress); EEdata[s] = EEbytedata;
  }
  if (EEerr) { lcd.print("E="); lcd.print(EEerr); delay(1000); }
  if ((EEdata[0] != EEid1) || (EEdata[1] != EEid2)) {
    lcd.print(" init!"); goupdateEEPROM();
    if (EEerr) { lcd.print("E="); lcd.print(EEerr); delay(1000); }
  }
  memcpy(bStearingInterval, EEdata+2, sizeof(int));
  memcpy(bStearingMinToMove, EEdata+4, sizeof(int));
  memcpy(bStearingMaxMove, EEdata+6, sizeof(int));
  memcpy(bStearingCoeffMove, EEdata+8, sizeof(float));
  StearingInterval = *((int*)bStearingInterval);
  StearingMinToMove = *((int*)bStearingMinToMove);
  StearingMaxMove = *((int*)bStearingMaxMove);
  StearingCoeffMove = *((float*)bStearingCoeffMove);
  prev_StearingInterval = StearingInterval;
  prev_StearingMinToMove = StearingMinToMove;
  prev_StearingMaxMove = StearingMaxMove;
  prev_StearingCoeffMove = StearingCoeffMove;
  lcd.print(" OK"); delay(1000);
  lcd.clear(); lcd.print("GPS reading..."); delay(1000);
}

void loop() {
  // CHECK SENSORS
  currCheckSensorsMillis = millis();
  if (currCheckSensorsMillis - prevCheckSensorsMillis >= CheckSensorsInterval) {
    readMuxSensors();
    if ((SensorVBatt <= 7.0) || (SensorTemp >= 50)) {
      lcd.clear(); lcd.setCursor(0,0); lcd.print("Alarm sensors! ");
      lcd.setCursor(1,1); lcd.print("V="); lcd.print(SensorVBatt); lcd.print(" ");
      lcd.print(int(SensorTemp)); lcd.write(0xDF); lcd.print("C");
      NewTone(speakerPin,10); delay(1000); noNewTone();
    }
    prevCheckSensorsMillis = currCheckSensorsMillis;
  }
  // STEERING CONTROL
  currentStearingMillis = millis();
  if (currentStearingMillis - previousStearingMillis >= StearingInterval) {
    if (isStearing == false && ispause == false) {
      calcmove = nmf_routetofollow - nmf_truecourse;
      if (calcmove < -180) calcmove += 360;
      else if (calcmove > 180) calcmove -= 360;
      if (abs(calcmove) >= StearingMinToMove) {
        if (abs(calcmove) >= StearingMaxMove) {
          cm = (calcmove < 0) ? -StearingMaxMove : StearingMaxMove;
          calcmove = cm;
        }
        Stearing = calcmove * StearingCoeffMove;
        gomotor(int((Stearing * 216) / 360)); // 54 passos = 1/4 volta
        prevStearing = Stearing; isStearing = true;
      }
    } else {
      if (isStearing == true) {
        Stearing = -prevStearing;
        gomotor(int((Stearing * 216) / 360));
        Stearing = 0; prevStearing = 0; isStearing = false;
      }
    }
    previousStearingMillis = currentStearingMillis;
  }
  // RC RF BUTTONS
  rfRemoteControlValue = checkRfRC();
  if (rfRemoteControlValue) {
    switch (rfRemoteControlValue) {
      case RCleftbutton: goleft(); break;
      case RCrightbutton: goright(); break;
      case RCleft10button: goleft10(); break;
      case RCright10button: goright10(); break;
    }
  }
  // HW BUTTONS
  HWButtonValue = checkHWButtons();
  if (HWButtonValue) {
    switch (HWButtonValue) {
      case HWleftbutton: if (!isSetup) goleft(); else setupMinus(); break;
      case HWrightbutton: if (!isSetup) goright(); else setupPlus(); break;
      case HWpausebutton: gopause(); break;
      case HWsetupbutton: gosetup(); break;
      case HWleft10button: goleft10(); break;
      case HWright10button: goright10(); break;
    }
  }
  // GPS NMEA
  if (stringComplete) {
    bool ret = nmeaExtractData();
    inputString = ""; stringComplete = false;
    if (ret) RefreshDisplay();
  }
  // WATCHDOG FEEDING
  if (digitalRead(watchDogPin) == LOW) digitalWrite(watchDogPin, HIGH);
  else digitalWrite(watchDogPin, LOW);
}

// ... (demais funções: readMuxSensors, nmeaExtractData, setupPlus, setupMinus, gomotor,
// RefreshDisplay, serialEvent, nmea0183_checksum, checkRfRC, checkHWButtons, gosetup,
// goupdateEEPROM, goleft, goleft10, goright, goright10, gopause, readEEPROM, writeEEPROM,
// roundZeroDec, roundOneDec, roundTwoDec – código completo no GitHub)
Sketch Watchdog (para Nano)
/* Watchdog para manter CLIENTE (Uno) sob controle, Arduino NANO 3.0 by Marco Zonca
   CLIENTE deve alimentar Watchdog antes de feedingInterval senão força restart */
const int feedingPin = 14;
const int ledPin = 15;
const int restartPin = 16;
const int buzzerPin = 17;
const long ledInterval = 1000;
const long feedingInterval = 2500;
const long timeForClientStart = 16000;
int ledState = LOW, previousFeedingState = LOW, feedingState = LOW;
unsigned long previousLedMillis = 0, previousFeedingMillis = 0;

void setup() {
  digitalWrite(restartPin, HIGH); // LOW força restart do CLIENTE
  pinMode(ledPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  pinMode(restartPin, OUTPUT);
  pinMode(feedingPin, INPUT);
  delay(timeForClientStart); // tempo para CLIENTE iniciar
}

void loop() {
  unsigned long currentMillis = millis();
  // BLINK LED
  if (currentMillis - previousLedMillis >= ledInterval) {
    previousLedMillis = currentMillis;
    ledState = (ledState == LOW) ? HIGH : LOW;
    digitalWrite(ledPin, ledState);
  }
  // CHECK FEEDING
  feedingState = digitalRead(feedingPin);
  if (feedingState == HIGH) {
    if (previousFeedingState == LOW) previousFeedingMillis = currentMillis;
    previousFeedingState = HIGH;
  } else previousFeedingState = LOW;
  if (currentMillis - previousFeedingMillis > feedingInterval) {
    // CLIENTE dormindo
    ledState = HIGH; digitalWrite(ledPin, ledState);
    tone(buzzerPin,1500); delay(500);
    digitalWrite(restartPin, LOW); // restart CLIENTE
    tone(buzzerPin,1500); delay(500);
    digitalWrite(restartPin, HIGH);
    tone(buzzerPin,1500); delay(timeForClientStart);
    noTone(buzzerPin);
    currentMillis = millis();
    previousFeedingState = LOW;
    previousFeedingMillis = currentMillis;
    previousLedMillis = currentMillis;
  }
}

Peças Personalizadas e Caixas

Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão

23lm-stepper-plate-v2_PlvJaff9Hl.step
23lm-stepper-pulley-56_UhsbaWbiBt.step

Esquemáticos

Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão Sistema Autopiloto Avançado para Barcos à Vela – Direção Automática de Precisão

Processo de manufatura

  1. Construa um Sensor de Movimento Infravermelho DIY para Raspberry Pi – Guia Passo a Passo
  2. Projetando um Sistema de Recuperação por Paraquedas Balístico para UAVs
  3. Monitoramento Contínuo é a Escolha Certa para Suas Operações?
  4. ATI Industrial Automation: Líder em Trocadores Automáticos de Ferramentas para Robôs Industriais
  5. Sua Fábrica Está Pronta para IoT? Um Guia Prático
  6. Cortadores Poligonais de Precisão para Tornos Automáticos – Soluções de Corte Ajustáveis e Alto Desempenho
  7. Torno CNC R07 Cincom – Usinagem de Precisão de 7 mm para Peças Pequenas
  8. Sistema de Propulsão Hipersônica Revolucionário Permite Viagens Transcontinentais em Menos de 30 Minutos
  9. Como Transmissões Manual e Automática Transferem Potência: Visão Clara
  10. Guia Abrangente de Sistemas de Transmissão Automática