Controllo proporzionale servo via bluetooth

Salve a tutti.

Sto incontrando alcune difficoltà con un progetto riguardante il controllo di sterzo attuato dal servo SG90 della Tower Pro (quello fornito nello starter kit V5 di Arduino UNO) attraverso uno shield bluetooth che monta il modulo RN-42 di Roving; l'intero shield è di futura elettronica.

Link

Per il controllo uso la app Roboremo, la quale permette di configurare telecomandi virtuali personalizzati.

Ho seguito passo-passo questa guida, che a mio parere sembra quella piu adatta allo scopo.

Link

essa comprende anche questo sketch.

// Control servo motor over Bluetooth using RoboRemo app
// www.roboremo.com

// Hardware setup:
// BT module   Arduino
// GND ------- GND
// VCC ------- 5V
// TX-O ------ pin0
// RX-I ------ pin1

// Servo       Arduino
// GND ------- GND
// VCC ------- VCC
// signal ---- pin4

#define bluetooth Serial
#include <Servo.h>


Servo myServo;

char cmd[100];
int cmdIndex;


void exeCmd() {
  
  // "servo" is the servo motor id
  
  if(cmd[0]=='s' &&
     cmd[1]=='e' &&
     cmd[2]=='r' &&
     cmd[3]=='v' &&
     cmd[4]=='o' &&
     cmd[5]==' ') {
       
       int val = 0;
       for(int i=6; cmd[i]!=0; i++) {
         val = val*10 + (cmd[i]-'0');
       }
       // if cmd is "servo 1234", val will be 1234
          
       myServo.writeMicroseconds(val);      
     }   
}



void setup() {
  
  delay(500); // wait for bluetooth module to start

  bluetooth.begin(115200); // Bluetooth default baud is 115200
  
  myServo.attach(4, 1000, 2000);
  
  cmdIndex = 0;
}


void loop() {
  
  if(bluetooth.available()) {
    
    char c = (char)bluetooth.read();
    
    if(c=='\n') {
      cmd[cmdIndex] = 0;
      exeCmd();  // execute the command
      cmdIndex = 0; // reset the cmdIndex
    } else {      
      cmd[cmdIndex] = c;
      if(cmdIndex<99) cmdIndex++;
    }
   
    
  }
  
}

il problema che riscontro, è la mancata risposta dell' ATMEGA al segnale seriale in arrivo dal modulo.

il modulo dialoga verso il micro a 9600 baud fissi e la cosa che mi fa specie è che nello sketch manchi il comando Serial.begin (9600), cosa che se però aggiungo, mi porta al non potermi connettere attraverso il BT.

Posso confermare che i segnali arrivano chiaramente al modulo: lo noto dal led di trasmissione che risponde prontamente alla ricezione.

Tral'altro ho testato lo stesso modulo attraverso un semplice sketch per l'accensione di un led via BT.

Dallo sketch che vi ho mostrato, ho appurato che il sistema lavora discriminando tutti i segnali tranne quelli con un flag denominato "servo", che deve essere impostato come id sullo slider virtuale della app. Una volta rilevato il segnale servo, estrapola il valore in microsecondi e lo trasforma in impulso da mandare via pin 4 al servo. il tutto usando una sottoroutine che viene richiamata ad ogni ciclo di lettura della seriale.
Trovo la cosa utile ed intelligente, dato che in questo modo, creando altre routine che rilevano un flag diverso, potrei aggiungere controlli per altre funzioni.

secondo voi di cosa si tratta? Non ho una grande esperienza e non vorrei che ci sia qualche conflitto tra le librerie, un errore nello sketch o che semplicemente lo sketch stesso non si adatti bene al mio modulo, dato che nella guida usano un modulo BlueSmiRF.

Vorrei infine chiedervi una piccola delucidazione sul funzionamento in dettaglio di questa parte dello sketch, dato che ho solo intuito per logica la sua funzione, sopratutto nella parte del ciclo for:

if(cmd[0]=='s' &&
     cmd[1]=='e' &&
     cmd[2]=='r' &&
     cmd[3]=='v' &&
     cmd[4]=='o' &&
     cmd[5]==' ') {
       
       int val = 0;
       for(int i=6; cmd[i]!=0; i++) {
         val = val*10 + (cmd[i]-'0');
       }
       // if cmd is "servo 1234", val will be 1234
          
       myServo.writeMicroseconds(val);

Vi ringrazio in anticipo e spero di non essermi dilungato troppo in dettagli superflui. Se vi serve altro posso darvi anche un manuale d'uso della app.

Ti invitiamo a presentarti (dicci quali conoscenze hai di elettronica e di programmazione) qui: Presentazioni
e a leggere il regolamento: Regolamento

Presentazione effettuata, ora tornando al discorso qualcuno ha idee? :slight_smile:

Io suggerisco SEMPRE di non usare i pin 0 e 1, ovvero la vera Seriale dato che ogni volta ... si riscontrano delle incompatibilità !

Fai una prova, usa la SoftwareSerial su altri due pin e vedi se ti funzione (... attenzione alle limitazioni sui pin utilizzabili con la MEGA, come indicato nella pagina della SoftwareSerial)

Guglielmo

P.S: : Inoltre, il lasciare liberi i pin 0 ed 1 permette il debug via seriale ... :wink:
P.P.S. : In quel for estrae il valore dal codice ASCII dei caratteri che riceve ... in ASCII i numero da 0 a 9 sono rappresentati con i valori 0x30 .. 0x39 ... lui sottrae ogni volta 0x30 e si trova quindi un valore compreso tra 0 e 9.

Accidenti credo di aver capito tutto! Sto usando uno shield vero e proprio, non un modulo.
evidentemente devono aver previsto questa incompatibilità, e quindi i pin connessi stanno altrove.

Ed ora guardando il programma test funzionante, noto questa stringa:

SoftwareSerial bluetooth(2, 4)

immagino che quelli siano i pin Rx/Tx, e guarda un po, in questa configurazione il programma di test funzionava, ora provo nel programma dei servo e vi faccio sapere :smiley:

EDIT:

Qualcosa non va ancora

Dunque...

Il servo sta ronzando in posizione fissa, il che significa che arduino lo sta pilotando per rimanere nella sua posizione di partenza e questo dovrebbe essere ok.

Pare che non ci sia dialogo tra modulo e micro.

cosa che ho notato è che nel programma test (qui sotto) vengono attivati i pin 2 e 4 come rx e tx
mentre sul datasheet dello shield i pin sono segnalati come 3 e 4, però ho ricezione e trasmissione corretta attraverso quelli nativi dello sketch.

ho testato lo stesso sketch con entrambe le configurazioni e sembrano andare entrambe, non capisco...

#include <SoftwareSerial.h>

SoftwareSerial bluetooth(2, 4);
byte b;

void setup() {
 // put your setup code here, to run once:
 Serial.begin(9600);   // opens serial port, sets data rate to 9600 bps
 Serial.flush();
 bluetooth.begin(115200);
 //enter command mode
 //bluetooth.println("$$");
 Serial.println("setup complete.");
}

void loop() {
 // if theres data from the bluetooth module
 if (bluetooth.available()) {
   //echo it to the serial monitor
   Serial.print("bt module said:");
   Serial.println((char)bluetooth.read());
 }
 //if theres data from the serial monitor
 if (Serial.available()>0) {
   b=Serial.read();
   //echo it back to the serial monitor
   Serial.print("serial said:");

   Serial.println(b);
   //send it to the bluetooth module
   bluetooth.print(b);
 }
}

in ogni caso ho modificato lo sketch servo in questo modo: potrebbe esserci qualcosa di errato seconod voi?

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

SoftwareSerial bluetooth(2, 4);

Servo myServo;

char cmd[100];
int cmdIndex;


void exeCmd() {
  
  // "servo" is the servo motor id
  
  if(cmd[0]=='s' &&
     cmd[1]=='e' &&
     cmd[2]=='r' &&
     cmd[3]=='v' &&
     cmd[4]=='o' &&
     cmd[5]==' ') {
       
       int val = 0;
       for(int i=6; cmd[i]!=0; i++) {
         val = val*10 + (cmd[i]-'0');
       }
       // if cmd is "servo 1234", val will be 1234
          
       myServo.writeMicroseconds(val);      
     }   
}



void setup() {
  
  delay(500); // wait for bluetooth module to start

  Serial.begin(9600);
  Serial.flush();
  bluetooth.begin(115200); // Bluetooth default baud is 115200
  
  myServo.attach(7, 1000, 2000);
  
  cmdIndex = 0;
}


void loop() {
  
  if(bluetooth.available()) {
    
    char c = (char)bluetooth.read();
    
    if(c=='\n') {
      cmd[cmdIndex] = 0;
      exeCmd();  // execute the command
      cmdIndex = 0; // reset the cmdIndex
    } else {      
      cmd[cmdIndex] = c;
      if(cmdIndex<99) cmdIndex++;
    }
   
    
  }
  
}

a qusto punto vi link anche il data sheet dello shield... sono alla frutta

Link