Problemas com Servos usando 2 arduinos e bluetooth

O que acontece é que os servos ficam dando espasmos durante a transmissão de dados fica pior quando tento colocar eles em grau menor que 180, estando os 2 e 180 graus não tem espasmos ou seja eles ficam imóveis se desligo o transmissor também cessam os espasmos, parece que a cada ciclo depois do delay o servos tendem a ir a 180 graus por isso quando eu diminuo para um numero menor que 18;0 eles ficam tentando voltar a 180 e quando recebem os dados vão para a posição indicada. não sei o que pode estar errado. Estou usando dois arduinos nano no transmissor um hc05 e no receptor um hc06 estão configurados na mesma velocidade e estão se conectando e recebo os dados corretos mas mesmo assim os servos se movimentam quando em grau menor que 180 quanto menor o grau maior é o movimento. Espero que possam me ajudar. Este é o meu primeiro post no fórum então se cometi algum erro me desculpem.

Código do transmissor:

#include <SoftwareSerial.h>

SoftwareSerial btSerial(3, 2); // RX, TX
const int potPin = A0; // Pino do potenciômetro
const int buttonPin1 = 4; // Pino do botão 1
const int buttonPin2 = 5; // Pino do botão 2
const int buttonPin3 = 6; // Pino do botão 3
const int buttonPin4 = 7; // Pino do botão 4

void setup() {
  pinMode(buttonPin1, INPUT_PULLUP); // Configura o botão 1 como entrada com pull-up
  pinMode(buttonPin2, INPUT_PULLUP); // Configura o botão 2 como entrada com pull-up
  pinMode(buttonPin3, INPUT_PULLUP); // Configura o botão 3 como entrada com pull-up
  pinMode(buttonPin4, INPUT_PULLUP); // Configura o botão 4 como entrada com pull-up
  
  Serial.begin(9600); // Inicia a comunicação serial para depuração
  btSerial.begin(9600); // Inicia a comunicação com o módulo Bluetooth
}

void loop() {
  // Lê o valor do potenciômetro
  int potValue = analogRead(potPin);
   int servo1Pos = map(potValue, 0, 1023, 0, 180);

  
  // Lê o estado dos botões
  bool buttonState1 = digitalRead(buttonPin1);
  bool buttonState2 = digitalRead(buttonPin2);
  bool buttonState3 = digitalRead(buttonPin3);
  bool buttonState4 = digitalRead(buttonPin4);

  // Envia os dados para o Receptor via Bluetooth
  btSerial.print(servo1Pos);
  btSerial.print(",");
  btSerial.print(buttonState1);
  btSerial.print(",");
  btSerial.print(buttonState2);
  btSerial.print(",");
  btSerial.print(buttonState3);
  btSerial.print(",");
  btSerial.println(buttonState4);

  // Envia dados para serial monitor

  Serial.print(servo1Pos);
  Serial.print(",");
  Serial.print(buttonState1);
  Serial.print(",");
  Serial.print(buttonState2);
  Serial.print(",");
  Serial.print(buttonState3);
  Serial.print(",");
  Serial.println(buttonState4);

  delay(100); // Pequeno atraso para estabilidade
}

Codigo do receptor

#include <Servo.h>
#include <SoftwareSerial.h>

Servo servo1; // Declaração do servo 1
Servo servo2; // Declaração do servo 2
const int relay1Pin = 8; // Pino do relé 1
const int relay2Pin = 9; // Pino do relé 2

int servo1Pos; // Variável para armazenar a posição do servo 1
int servo2Pos = 90; // Posição inicial do servo 2
const int servo2Step = 1; // Incremento/decremento do servo 2

SoftwareSerial btSerial(3, 2); // RX, TX para o módulo Bluetooth

void setup() {
  Serial.begin(9600); // Inicia a comunicação serial para depuração
  btSerial.begin(9600); // Inicia a comunicação com o módulo Bluetooth
  servo1.attach(10); // Anexa o servo 1 ao pino 9
  servo2.attach(11); // Anexa o servo 2 ao pino 10
  pinMode(relay1Pin, OUTPUT); // Configura o pino do relé 1 como saída
  pinMode(relay2Pin, OUTPUT); // Configura o pino do relé 2 como saída
}

void loop() {
  if (btSerial.available()) {
    // Se houver dados disponíveis no módulo Bluetooth
    String data = btSerial.readStringUntil('\n');
    // Processa os dados recebidos
    int separatorIndex1 = data.indexOf(',');
    int separatorIndex2 = data.indexOf(',', separatorIndex1 + 1);
    int separatorIndex3 = data.indexOf(',', separatorIndex2 + 1);
    int separatorIndex4 = data.indexOf(',', separatorIndex3 + 1);
    
    // Extrai os valores do potenciômetro e dos botões
    int potValue = data.substring(0, separatorIndex1).toInt();
    int buttonState1 = data.substring(separatorIndex1 + 1, separatorIndex2).toInt();
    int buttonState2 = data.substring(separatorIndex2 + 1, separatorIndex3).toInt();
    int buttonState3 = data.substring(separatorIndex3 + 1, separatorIndex4).toInt();
    int buttonState4 = data.substring(separatorIndex4 + 1).toInt();

    // Atualiza a posição do servo 1 sem mapear novamente
    servo1Pos = potValue;
    servo1.write(servo1Pos);

    // Controla o servo 2 com base nos estados dos botões
    if (buttonState1 == 0) {
      servo2Pos = max(servo2Pos - servo2Step, 0); // Move para a posição 0
    } else if (buttonState2 == 0) {
      servo2Pos = min(servo2Pos + servo2Step, 180); // Move para a posição 180
    }

    servo2.write(servo2Pos); // Atualiza a posição do servo 2

    // Controla o relé 1 com base no estado do botão 3
    if (buttonState3 == 0) {
      digitalWrite(relay1Pin, HIGH); // Liga o relé 1
    } else {
      if (buttonState4 == 0) { // Verifica se o botão 4 está pressionado
        digitalWrite(relay1Pin, HIGH); // Mantém o relé 1 ligado
      } else {
        digitalWrite(relay1Pin, LOW); // Desliga o relé 1
      }
    }

    // Controla o relé 2 com base no estado do botão 4
    if (buttonState4 == 0) {
      digitalWrite(relay2Pin, HIGH); // Liga o relé 2
    } else {
      digitalWrite(relay2Pin, LOW); // Desliga o relé 2
    }
  }
}

Olá! Bem vindo ao Forum.

Essa tremedeira nos servos pode ter diferentes razões. Muitas vezes têm a ver com alimentação insuficiente (p. ex. alimentar o servo com o Arduino). Porém, pelo que você descreve, talvez não seja o caso.

Eu recomendaria dar uma olhada no pedaço abaixo do seu programa, para ter certeza de que ele faz o que você realmente quer:

Para mim o que está aí é:

  • se o botão 1 estiver solto, mova o servo para o maior dos ângulos entre (servo2Pos - servo2Step) e zero. Ou seja, ele vai levar o servo a zero somente se servo2Step for maior que servo2Pos;
  • já se o botão 2 estiver solto, esqueça o estado do botão 1 e mova o servo para o menor valor entre (servo2Pos + servo2Step) e 180.

Usando o else if, quem "manda" no movimento será sempre o botão 2. Só será considerado o teste/movimento do botão 1 se o botão 2 estiver apertado.

Era isso mesmo que você pretendia?

E o que acontece quando o botão 1 está apertado? E quando os botões 1 e 2 estão apertados?

Esses botões são chaves On-Off ou são botões (chaves táteis) mesmo?

A mesma questão lógica se aplica aos botões relacionados ao relé.

Obrigado por responder, era pra quando pressionado o botão 1 o servo moveria da posição inicial (90) em direção ao zero quando pressionado o botão 2 moveria o servo em direção a 180, quando nenhum botão estiver pressionado ele não se move, o mesmo vale para os reles quando o botão 3 é pressionado o rele 1 aciona e quando o botão 4 é pressionado o rele 1 e 2 acionam simultaneamente, os botões são interruptores do tipo normalmente aberto ou seja só fecham contato quando pressionado. A Alimentação dos servos e dos reles são fonte separadas do arduino, então não acho que sejam a causa do movimento dos servos. quando diminuo o delay no transmissor o movimento dos servos também alteram estou monitorando os dados transmitidos e os dados recebidos pelo monitor serial e os dados estão corretos. ainda não sei o que acontece. No lado do transmissor os dados enviados sem nenhum botão pressionado são respectivamente: 180,1,1,1,1. onde 180 é o valor mapeado do potenciometro e os outros quatro uns separado por virgula são os botões quando não pressionado em caso de eu pressionar qualquer botão o valor enviado muda pra zero ai sim dependendo de qual botão eu aciono tenho resposta no receptor e os dados estão corretos pois monitoro os dados no lado do receptor também e os valores do dois servos variam perfeitamente entre 0 e 180 no monitor serial do receptor.

Ok, por hora então eu sugiro que você troque os else if por if:

// Controla o servo 2 com base nos estados dos botões
    if (buttonState1 == 0) {
      servo2Pos = max(servo2Pos - servo2Step, 0); // Move para a posição 0
    } 
    if (buttonState2 == 0) {
      servo2Pos = min(servo2Pos + servo2Step, 180); // Move para a posição 180
    }

Removi o else mas ainda continua os espasmos. a unica coisa que muda é quando eu aumento o tempo de delay pra 200 ou até 350 os espasmos diminuem e ficam apenas tremendo ou seja a variação de angulo é menor mas ainda continua.

Os servos têm espasmos mesmo se você não apertar botão nenhum?

Minha segunda hipótese (mas ela só vale para o servo 1) é que flutuações no valor do potenciômetro (jitter) estão fazendo o servo vibrar.

No código do transmissor, troque o trecho:

por

int potValue = analogRead(potPin);
for (int i=0; i < 4; i++) {                       //Coleta mais 4 leituras do potenciômetro
   potValue += analogRead(potPin);
   delay(50);
  }
potValue = potValue/5;               //Extrai a média das 5 leituras
int servo1Pos = map(potValue, 0, 1023, 0, 180);

Veja se isso ajuda com o servo 1.

Sim os servos tem espasmos mesmo sem apertar qualquer botão, mas quando o transmissor esta desligado e não existe nenhum dado no receptor eles ficam estáticos ou quando os dois estão na posição máxima de 180 graus também ficam estáticos, os dados monitorados tanto do lado do transmissor quanto do receptor estão perfeitos sem números ou caracteres estranhos. no lado do receptor adicionei umas linhas para monitorar os dados e estão perfeitos ou seja estou monitorando o servo 1 o servo 2 e ambos informam a posição correta sem variação e mesmo assim os servos agem dando esses espasmos que aumentam quando o valor se aproxima de zero, mesmo não tendo nenhum outro valor interferindo ou seja variando. Um exemplo se eu tivesse valores variando eu entenderia, mas nesse caso os valores tem uma variação minima de 1 grau ou seja esta em 180 e vai para 179 mas acho que isso não causaria os espasmos. É como se ele estivesse recebendo 180, depois 90 depois 180 depois 90, mas nao é isso que acontece, os dados estão bem estáveis dos dois lados tanto no transmissor quanto no receptor. Adicionei as linhas que sugeriu e não mudou exatamente em nada os espasmos continuam. segue a novela...

Vamos ver se alguém mais experiente aparece para dar alguma sugestão. Eu não consigo enxergar o que mais pode estar causando esse comportamento nos servos, até porque você está imprimindo os valores e vendo que estão corretos.

Como você acredita que o problema está acontecendo na transmissão/recepção dos dados, de repente pode valer a pena programar o transmissor para só mandar alguma informação se um dos botões for apertado; e o receptor para só alterar a posição dos servos se receber alguma coisa.

Resolvi fazer um teste programei o receptor para reenviar os dados recebidos de volta ao transmissor e fiquei monitorando os dois lados quando coloco um delay menor que 200 os dados enviados são cheio de caracteres estranhos, junto com os dado, mas quando o delay fica acima de 200 os dados são consistentes e sem variações. Acho que o programa esta enviando certo o bluetooth que deve estar zoando os dados. Vou fazer mais testes e posto os resultados aqui caso alguém mais tiver problemas iguais. Obrigado pelo tempo e pela ajuda.

O problema dos espasmos quase sempre é a fonte de alimentação. Os servos puxam muita corrente. Então precisa ter uma fonte potente e separada para eles. Veja se com só 1 servo conectado tambem ocorre. Com 2 deve piorar se for fonte.

acjacques obrigado por tentar ajudar, mas a alimentação dos servos é separada do arduino, então creio que não seja esse o problema, ainda estou tentando entender o que ocorre e continuo fazendo testes inclusive montei outro jogo com dois arduinos uno e dois hc05 um configurado como master e outro como slave mas o problema persiste.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.