Ho un problema con i servo e con i led fade

Ciao a tutti mi sono iscritto a questo forum perché ho bisogno del vostro aiuto.
Ho sempre trovato risposte e tanti codici da prendere come spunto, non sono un programmatore esperto, Arduino è un dispositivo che mi e servito e mi serve per i miei piccoli progetti, veniamo al dunque ho realizzato un piccolo busto di Terminator T800 siccome non mi piacciono le cose statiche mi sono divertito ad animarlo con
5 servo comandi per il movimento della testa e degli occhi
2 micromotori STEPPER per simulare effetto zoom pupilla
2 led rossi effetto dissolvenza
e qui che subentra ARDUINO.
Con un Joystick tipo quelli della PS1 ho inserito dentro un Arduino Pro Mini caricato su la libreria PS2X (da me modificata a mio piacimento vi allego il codice)

//Master
#include <PS2X_lib.h>

#include <SoftwareSerial.h>
#define Rxpin 0  // Tx per Bluetooth Rx per Arduino
#define Txpin 1  // Rx per Bluetooth Tx per Arduino
SoftwareSerial Bluetooth(Rxpin, Txpin);

PS2X ps2x;

int error = 0;
byte type = 0;
byte vibrate = 0;
int valLY = 0;
int valLX = 0;
int valRY = 0;
int valRX = 0;


void setup() {

  //Serial.begin(115200);
  Bluetooth.begin(115200);
  //Impostazione dei pin:  GamePad(clock, command, attention, data, Pressures?, Rumble?) controllo errore.
  error = ps2x.config_gamepad(5, 3, 2, 4, true, true);


  if (error == 0) {
   // Serial.println("Controller trovato, configurato correttamente");

  }

  else if (error == 1) {
   // Serial.println("Nessun controller trovato, controlla il cablaggio.");
  } else if (error == 2) {
   // Serial.println("Controller trovato ma non accetta comandi.");
  } else if (error == 3) {
   // Serial.println("Il controller rifiuta di accedere alla modalità Pressione, potrebbe non supportarla.");
  }

  type = ps2x.readType();
  switch (type) {
    case 0:
   //   Serial.println("Nessun Controller Rilevato");
      break;
    case 1:
   //   Serial.println("Controller DualShock Rilevato");
      break;
    case 2:
    //  Serial.println("Controller non compatibile con la libreria");
      break;
  }
}

void loop() {

  if (error == 1)
    return;

  if (type == 2) {
    return;
  }

  else {  //DualShock Controller

    ps2x.read_gamepad(false, vibrate);

    if (ps2x.ButtonPressed(PSB_START)) {
    //  Serial.println("Start");
      Bluetooth.write('i');
    }
    if (ps2x.ButtonPressed(PSB_SELECT)) {
     // Serial.println("Select");
      Bluetooth.write('I');
    }

    //vibrate = ps2x.Analog(PSAB_BLUE);

    if (ps2x.Button(PSB_GREEN)) {

    //  Serial.println("Triangolo");
      Bluetooth.write('G');
    }
    if (ps2x.Button(PSB_RED)) {
    //  Serial.println("Cerchio");
      Bluetooth.write('h');
    }
    if (ps2x.Button(PSB_PINK)) {
    //  Serial.println("Quadrato");
      Bluetooth.write('H');
    }
    if (ps2x.Button(PSB_BLUE)) {
    //  Serial.println("X");
      Bluetooth.write('g');
    }
    //***************************************

    if (ps2x.Button(PSB_PAD_UP)) {
    //  Serial.println("Sopra");
      Bluetooth.write('E');
    }
    if (ps2x.Button(PSB_PAD_RIGHT)) {
    //  Serial.println("Destra");
      Bluetooth.write('f');
    }
    if (ps2x.Button(PSB_PAD_LEFT)) {
    //  Serial.println("Sinistra");
      Bluetooth.write('F');
    }
    if (ps2x.Button(PSB_PAD_DOWN)) {
    //  Serial.println("Sotto");
      Bluetooth.write('e');
    }

    //***************************************

    if (ps2x.NewButtonState()) {

      if (ps2x.Button(PSB_L3)) {
     //   Serial.println("L3");
        Bluetooth.write('M');
      }
      if (ps2x.Button(PSB_R3)) {
     //   Serial.println("R3");
        Bluetooth.write('m');
      }
      if (ps2x.Button(PSB_L2)) {
     //   Serial.println("L2");
        Bluetooth.write('L');
      }
      if (ps2x.Button(PSB_R2)) {
     //   Serial.println("R2");
        Bluetooth.write('l');
      }
    }

    //***************************************

    if (ps2x.Button(PSB_L1) || ps2x.Button(PSB_R1)) {

      valLY = ps2x.Analog(PSS_LY);

     

      if (valLY < 125) {
        Bluetooth.write('A');
      //  Serial.println(valLY);
      }
      if (valLY > 135) {
        Bluetooth.write('a');
     //   Serial.println(valLY);
      }
    
      //***************************************

      valLX = ps2x.Analog(PSS_LX);

         
      if (valLX < 125) {
        Bluetooth.write('B');
      //  Serial.println(valLX);
      }
      if (valLX > 135) {
        Bluetooth.write('b');
      //  Serial.println(valLX);
      }
    
      //***************************************
      valRY = ps2x.Analog(PSS_RY);

      if (valRY < 125) {
        Bluetooth.write('C');
      //  Serial.println(valRY);
      }
      if (valRY > 135) {
        Bluetooth.write('c');
    //    Serial.println(valRY);
      }

      //***************************************
      valRX = ps2x.Analog(PSS_RX);

      if (valRX < 125) {
        Bluetooth.write('D');
      //  Serial.println(valRX);
      }
      if (valRX > 135) {
        Bluetooth.write('d');
     //   Serial.println(valRX);
      }
    }
    //***************************************
  }
  delay(10);
}

tramite un Bluetooth HC05(Master) invio ad un Arduino Nano dei comandi semplici tipo lettere A-a-B-b-C- ecc. ecc. a sua volta via Bluetooth HC05(Slave) li riceve e con un switch case esegue le varie funzioni, (vi allego codice).

//Slave

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


#define Rxpin 2  // pin Tx su Bluetooth Rx su Arduino
#define Txpin 3  // pin Rx su Bluetooth Tx su Arduino
SoftwareSerial Bluetooth(Rxpin, Txpin);

const int stepsPerRevolution = 200;  
Stepper myStepper(stepsPerRevolution, 10, 11, 12, 13);


#define LED_PIN 9  // pin di output dove sono collegati i Led degli occhi


#define BUTTON A0  // pin di input dove è collegato il pulsante

int Val_Pulsante = 0;   // serve per conservare lo stato del pin di input
int val = 0;
byte Ultimo_val = "";

Servo Servo_A; //Collo orizzontale
Servo Servo_B; //Collo verticale
Servo Servo_C; //Occhi orizzontale
Servo Servo_D; //Occhi verticale 
Servo Servo_E; //Mascella

int Gr_Servo_A, Gr_Servo_B, Gr_Servo_C, Gr_Servo_D, Gr_Servo_E;

void setup() {
  
  Serial.begin(115200);
  Bluetooth.begin(115200);
  
  myStepper.setSpeed(60);
  pinMode(BUTTON, INPUT);
  pinMode(LED_PIN, OUTPUT);
 
 
  Servo_A.attach(4);
  Servo_B.attach(5);
  Servo_C.attach(6);
  Servo_D.attach(7);
  Servo_E.attach(8);

  Gr_Servo_A = 90;
  Gr_Servo_B = 90;
  Gr_Servo_C = 90;
  Gr_Servo_D = 90;
  Gr_Servo_E = 90;

}

void loop() {

  //Val_Pulsante = digitalRead(BUTTON);  // legge il valore dell'input sul pin e lo conserva
  // controlla che l'input pulsante premuto vuol dire che il Chip e Inserito
  
  //if (Val_Pulsante == LOW) {  //Chip Inserito
  
  if (Bluetooth.available()) 
  {
    char Dati_BT = Bluetooth.read();

    switch (Dati_BT) {
       
      case 'A':

        if (Gr_Servo_A > 0) {
          Gr_Servo_A -= 1;
          Servo_A.write(Gr_Servo_A);
          Serial.println("ricevuto A");
        }
        break;

      case 'a':

        if (Gr_Servo_A < 180) {
          Gr_Servo_A += 1;
          Servo_A.write(Gr_Servo_A);
          Serial.println("ricevuto a");
        }
        break;

      case 'B':

        if (Gr_Servo_B > 0) {
          Gr_Servo_B -= 1;
          Servo_B.write(Gr_Servo_B);
          Serial.println("ricevuto B");
        }
        break;

      case 'b':

        if (Gr_Servo_B < 180) {
          Gr_Servo_B += 1;
          Servo_B.write(Gr_Servo_B);
          Serial.println("ricevuto b");
        }
        break;

      case 'C':

        if (Gr_Servo_C > 0) {
          Gr_Servo_C -= 1;
          Servo_C.write(Gr_Servo_C);
          Serial.println("ricevuto C");
        }
        break;

      case 'c':

        if (Gr_Servo_C < 180) {
          Gr_Servo_C += 1;
          Servo_C.write(Gr_Servo_C);
          Serial.println("ricevuto c");
        }
        break;

      case 'D':

        if (Gr_Servo_D > 0) {
          Gr_Servo_D -= 1;
          Servo_D.write(Gr_Servo_D);
          Serial.println("ricevuto D");
        }
        break;

      case 'd':

        if (Gr_Servo_D < 180) {
          Gr_Servo_D += 1;
          Servo_D.write(Gr_Servo_D);
          Serial.println("ricevuto d");
        }
        break;

      case 'E':
  if (Gr_Servo_E > 0) {
          Gr_Servo_E -= 1;
          Servo_E.write(Gr_Servo_E);
          Serial.println("ricevuto E");
  }

        break;

      case 'e':
if (Gr_Servo_E < 180) {
          Gr_Servo_E += 1;
          Servo_E.write(Gr_Servo_E);
        
        Serial.println("ricevuto e");
}
        break;

      case 'F':

        if (Ultimo_val != 'F') {

          Mot_Led_Avanti();
          Serial.println("ricevuto F");
        }
        Ultimo_val = 'F';

        break;

      case 'f':

        if (Ultimo_val != 'f') {

          Mot_Led_Indietro();
          Serial.println("ricevuto f");
        }
        Ultimo_val = 'f';

        break;

    }
    delay(10);
  }

  //else {
  //se il Chip viene estratto
  //}

  //}
}

void Mot_Led_Avanti() {

  for (int i = 0; i < 255; i = i + 5) {
    digitalWrite(LED_PIN, i);
    myStepper.step(5);
    if (i == 255) break;
    //delay(20);
  }
}

void Mot_Led_Indietro() {

  for (int i = 255; i >= 0; i = i - 5) {
    digitalWrite(LED_PIN, i);
    myStepper.step(-5);
    if (i == 0) break;
    //delay(20);
  }
}

Nella realizzazione del codice(che io ci ho messo mesi) le varie parti del codice singolarmente funzionano bene.
Quando ho messo tutto insieme mi sono accorto che il led degli occhi non funzionavano più in dissolvenza, dopo settimane di prove e contro prove ho scoperto che se disattivo le funzioni Servo_A.attach(4) i led funzionano e logicamente i servo no.

Adesso mi trovo in una situazione che veramente non capisco se ce un errore oppure e tutto concettualmente sbagliato e quindi non funzionerà mai.
Grazie spero qualcuno possa aiutarmi almeno a capire se quello che voglio realizzare e una cosa che può funzionare.
Forse dovevo chiederlo prima di iniziare sarebbe stato più logico, ma ho iniziato con i led poi ho aggiunto i motori e poi mi sono fatto prendere dal codice e non mi sono fermato più.

Grazie

... quindi una scheda basata su ATmega328P ... su tale MCU la libreria Servo utilizza Timer1 che va in conflitto con il PWM sui pin 9 e 10 (che usa lo stesso Timer1) ... ora, vedo che tu usi delle digitalWrite() e non delle analogWrite(), ma non vorrei che ci fosse comunque qualche conflitto. :roll_eyes:

Ho idea che devi trovare un altro pin per i LED ... dato che non vedo uso dei pin analogici, puoi usare uno di essi; ti ricordo infatti che, su ATmega328P, i pin Analogici (A0 .. A5, NON A6 ed A7) li puoi usare anche come pin digitali :wink:

Guglielmo

Grazie Guglielmo della tua risposta,
ti confermo che ho sempre usato analogWrite() avevo modificato il codice poco prima di postarlo nel FORUM per un ultimo tentativo di capire se funzionasse con il digitalWrite() e mi sono dimenticato di rimetterlo apposto quindi ti confermo che ho usato sempre analogWrite(), anche perché se non erro con il digitalWrite() non e possibile fare effetto dissolvenza.

Confermo a parte il pin A0 i pin A1 ad A5 sono liberi proverò a usare quelli,
come ho fatto a non pensarci prima grazie

Ho provato su tutti i pin spostando servo e motori ma nulla da fare, alla fine ho ricreato un codice pulito semplice con un servo e un led da accendere in dissolvenza non ci sono riuscito quindi penso ci sia un conflitto nella libreria del servo, se qualcuno sa come aiutarmi io non capisco mi mancano le conoscenze. grazie

Vediamo questo codice minimale che riproduce il malfunzionamento...

Allora, i pin A0 .. A5 sono digitali ma NON PWM, e te li avevo suggeriti per le digitalWrite() che usavi, NON per le analogWrite().

Se devi usare analogWrite() DEVI usare dei pin PWM e quindi sei soggetto alle limitazioni imposte dai Timers che usi ... se usi la libreria servo NON puoi usare il PWM sui pin 9 e 10 (Timer1), usa altri pin PWM.

Questa una tabella riepilogativa su ATmega328P:

Timer0
Usato da millis() e delay() e per il PWM sui pin 5 e 6
fast hardware pwm
(default 976.5625 Hz)
Pin 5 è anche usato per il “pulse counting”
Pin 8 è usato per il “input capture”

Timer1
Usato dalla libreria Servo e per il PWM sui pin 9 e 10. Libreria e PWM mutuamente esclusivi.
8-bit phase correct pwm mode
(default 488.28125 Hz)

Timer2
Usato per il PWM sui pin 3 e 11
8-bit phase correct pwm mode
(default 488.28125 Hz)

Guglielmo

Lo completerei con:

Timer2
Usato dalla funzione tone e per il PWM sui pin 3 e 11. Tone e PWM mutuamente esclusivi.
8-bit phase correct pwm mode
(default 488.28125 Hz)

1 Like

... grazie per la segnalazione, integro :grin:

Guglielmo

Allora grazie al consiglio di Guglielmo mi sono messo di impegno e ho capito che il problema era proprio sul pin 9 come mi suggerisce di evitare di usare.

quindi ho spostando i servo sui pin A1>A5 e usando il pin 5 o 6 per i led (gli unici liberi che funzionano con l'effetto dissolvenza) . Ho fatto varie prove sembra andare tutto bene.

Continuerò a testarlo per un po di tempo prima di impiantarlo nella testa di TERMINATOR

Grazie a tutti

Bene, tanto 5 e 6 sono gestiti da Timer0 che ... non va modificato/usato per altri scopi (è quello che gestisce millis(), micros(), ecc.) :wink:

Guglielmo

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