Ciao,
come da buona educazione, dopo essermi presentato sono schizzato qui a postare le mie domande/dubbi/ignoranze!
Ho in corso la realizzazione di un piccolo rover casalingo (o più in generale indoor) che avevo motorizzato con una scheda MD49 +motori EMG49 (presi da robotitaly). Il tutto controllato da seriale del pc (vecchio ieeepc asus con windows).
Ultimamente ho voluto provare ad aggiungere arduino come driver della scheda MD49 per 'scaricare' il pc da un po' di lavoro. Ho fatto un po' di prove e devo dire che sono rimasto felicemente colpito dalla sua facilità d'uso e dalla mole di informazioni che si possono trovare in rete.
La configurazione hw con cui sto facendo le prove è fatta da:
- arduino uno + ethernet shield
- MD49
Arduino comunica col pc via ethernet-udp e accetta dei comandi di movimentazione (per ora avanti/indietro, ruota); quindi provvede, via SoftwareSerial, a inviare i comandi appropriati alla MD49 e a leggerne lo stato (encoders, condizioni di errore) in modo da chiudere un loop di posizione; la MD49 si pilota in velocità . Ho misurato le latenze di comunicazione arduino/MD49 e in media ho quasi 10ms fra 1)invio comando, 2)richiesta/ricezione encoders e 3)richiesta/ricezione errori.
Per gestire questi ritardi e mantenere una buona reattività alla comunicazione udp avevo provato a 'pollare' la presenza di pacchetti udp con un timer (libreria TimerOne). La routine del timer verifica la presenza di un nuovo pacchetto, invia l'ACK, lo decodifica e lo mette in un buffer (coda dei comandi) che viene successivamente letto dal loop(). Purtroppo col timer1 in funzione non solo la comunicazione udp andava in stallo ma anche la lettura degli encoders (ricevuta su pin7) era errata, quindi ho dovuto rinunciarci (almeno per ora) anche se resto dell'avviso che una gestione asincrona (interrupt) dell'udp sarebbe la cosa migliore.
La soluzione corrente quindi è consistita nel fare tutto nel loop(). Di seguito posto il codice (che contiene qualche reminiscenza del precedente approccio).
void loop(){
byte command = NO_CMD;
boolean mustRead;
float data[2];//La seguente riga era gestita come ISR del timer.
udpCheckAndManage();
//Se ho nuovi comandi ...
//noInterrupts();
if(packready) {
command = _command;
data[0] = _data[0];
data[1] = _data[1];mustRead = packready;
packready = false;
_command = NO_CMD;
}
//interrupts();if(mustRead) {
Serial.print("command: ");
Serial.print(command,HEX);
Serial.println();
}switch(command) {
case NO_CMD: break;case MOVE_FWD:
case MOVE_BWD:
Serial.println("setspeeds :");
Serial.println(_data[0]);
Serial.println(_data[1]);
board.set_speeds(_data[0], _data[1]);
break;
case ROTATE:
Serial.println("setspeeds :");
Serial.println(_data[0]);
Serial.println(_data[1]);
board.set_speeds(_data[0], _data[1]);
break;
case INIT_CMD:
board.disable_timeout();
delay(10);
board.set_mode(MODE_SIGNED_SPEED_WHEELS);
delay(10);
board.reset_encoders();
delay(10);
inited = true;Serial.println("Inited...\tSending URM to");
Serial.print(Udp.remoteIP());
Serial.print(" : ");
Serial.println(UDP_O_PORT);
break;
case STOP:
board.set_speeds(0.0, 0.0);
Serial.println("Stopped...");
break;
}//MD49 state reading
//1. read encoders and speeds
//2. get error state
if(inited) {
byte encs[8];
long _encs[2];
boolean res = board.get_encoders(encs);
if(!res){
Serial.println("Fail read encoders");
return;
}Serial.print("Encs ");
for(int i=0;i<4;++i){ Serial.print(encs_, HEX); Serial.print("-");}_
_ Serial.print(" ");_
for(int i=4;i<8;++i){ Serial.print(encs_, HEX); Serial.print("-");}
Serial.println("");
* encs[0] = board.decode_encoder(&encs[0]);
encs[1] = board.decode_encoder(&encs[4]);
_ //*
Serial.print("Encoders ");
Serial.print(encs[0]);
Serial.print(" ");_
Serial.println(_encs[1]);
* //*
* //noInterrupts();*
* sendURM(&Udp, _encs[0], encs[1]);
_ //interrupts();*
* }*
}
[/quote]
E finalmente le domande!!!
Qualcuno ha già avuto a che fare con problemi simili? Cioè vi siete trovati a dover gestire contemporaneamente comunicazioni (o dispositivi) con velocità molto diverse fra loro? Che tipo di soluzioni si possono utilizzare ? E, infine, è possibile che la TimerOne incasini l'udp o la comunicazione seriale sw sui pint 7 e 8?