dimanche 15 décembre 2013

Communication entre le cerveau et le cervelet de tirobot

Il y a un ordinateur embarqué dans tirobot et un microcontrôleur pour l'interface des senseurs et le contrôle des moteurs. Ici, on pourrait dire que le cerveau est le Raspberry Pi et le cervelet c'est le Arduino. Ce qui est bien, les deux peuvent se parler via USB, ce qui fourni aussi le courant au Arduino. Cependant, le Raspberry Pi sera programmé en Python et c'est du code C qui est compilé pour le Arduino. Il faut donc écrire un mini protocole de communication entre le deux. Tant qu'à ce définir un protocole, vaut mieux le développer tout de suite en introduisant les contraintes auxquels ont risque de faire face durant le développement et pourquoi pas penser au future avec des ajout possible.

Premièrement, il y a peu de mémoire sur le Arduino et ce n'est pas très puissant. Il font donc oublier le transfert via du texte. Il faut penser que le buffer de communication série du arduino ne fait que 64 octets et que sur le Uno Rev 3, il n'y a que 2 KBytes de RAM. Plus la taille des commandes sera petite, plus se sera rapide de les transférer sans oublier que convertir du texte en chiffre, c'est demandant pour le Arduino. Donc, se sera des commande binaire qui seront utilisées.

Le format est que j'ai implémenté est assez simple:
  • 2 octets pour le numéro de la commande
  • 1 octet pour la taille complète de la commande incluant sont numéro et l'octet de la taille ( valeur minimum de 3 finalement).
  • Liste de paramètre étant soit un octet signé ou non, 2 octet signé, 4 octets signé ou un virgule flottant sur 4 octet ( float). 
Comme le format int du arduino Uno est un 2 octets signé, se sera le type le plus utilisé, mais si c'est possible de n'utiliser qu'un octet pour le transfert, pourquoi pas.

Pour ne pas avoir à trop coder pour chaque commande, je me suis défini un format bien simple pour décrire les commandes. J'utilise un classeur sous Google Drive que j'exporte en .CSV et j'ai du code Python qui transforme le fichier .CSV en code python et arduino capable de décoder et encoder en binaire la commande en plus de générer le squelettes des méthodes de traitement des commandes. Par exemple:


1AvanceAvance le robot de x unites2aUnitei16Vitesseu8

La commande numéro 1, dont le nom est "Avance" ayant comme description "Avance le robot de x unites" a deux paramètres. Cette commande est envoyée vers le arduino ( "a" signifie arduino et "p" pour le code python et il est possible d'inscrire les deux). Le premier paramètre se nomme "Unite" et est un entier signé sur 2 octet ( int 16 bit ) et le deuxième paramètre se nomme "Vitesse" et est un entier non signé d'un octet ( unsigned byte ). 

Le générateur de code a comme sortie deux fichier, un étant le code arduino et l'autre le code python. 

Le fichier .CSV suivant:

1,Avance,Avance le robot de x unite,2,a,Unite,i16,Vitesse,u8,,
2,Tourne,Fait tourné le robot sur x degree,2,a,Degree,i16,Vitesse,u8,,

Permet d'avoir le code suivant en python:

## Avance le robot de x unite
class AvanceCommand( BaseCommand ):
""" Avance le robot de x unite """
def __init__(self):
CommID = 1
nbrParam = 2
Unite = 0 #BaseInitType
Vitesse = 0 #BaseInitType

def decode(self, bytearray ):
Unite = bytearray[0] #BaseInitType
Vitesse = bytearray[1] #BaseInitType


def encode(self, bytearray ):
Unite = 0 #BaseInitType
Vitesse = 0 #BaseInitType


## Fait tourné le robot sur x degree
class TourneCommand( BaseCommand ):
""" Fait tourné le robot sur x degree """
def __init__(self):
CommID = 2
nbrParam = 2
Degree = 0 #BaseInitType
Vitesse = 0 #BaseInitType

def decode(self, bytearray ):
Degree = bytearray[0] #BaseInitType
Vitesse = bytearray[1] #BaseInitType


def encode(self, bytearray ):
Degree = 0 #BaseInitType
Vitesse = 0 #BaseInitType


def HandleDecodeCommand( bytearray, commID ):
retcomm = None
if commID = 1:
retcomm = AvanceCommand()
retcomm.decode(byteArray)
elif commID = 2:
retcomm = TourneCommand()
retcomm.decode(byteArray)
return retcomm

Et celui-ci pour le arduino:

int DecodeAndHandleCommand(commID, char* databuffer)
 {
 switch (commID){
 1: // Decode commande Avance
  {
  // Unite int
  // Vitesse int
  Avance(*(int*)&databuff[0], (int)databuff[2]);
  }
  break;
 2: // Decode commande Tourne
  {
  // Degree int
  // Vitesse int
  Tourne(*(int*)&databuff[0], (int)databuff[2]);
  }
  break;
  }
 }

int Avance(int Unite, int Vitesse)
{
 // Avance le robot de x unite
}

int Tourne(int Degree, int Vitesse)
{
 // Fait tourné le robot sur x degree
}

Il ne reste que le code de gestion des ports séries et l'implémentation interne des commandes à écrire, le reste se génère seul. Possiblement que j'augmenterai le générateur avec d'autres fonctions tel la gestion d'enum ou encore de constante. Mais pour le moment c'est déjà un minimum intéressant, et pas débogué ni terminé en passant! Le code python n'est pas encore fonctionnel.

1 commentaire:

  1. Casino Player Rewards Program - Dr. Maryland
    If 안산 출장안마 you are having issues with 상주 출장마사지 the Casino Player Rewards Program, 경기도 출장샵 please 경산 출장샵 contact the Customer Support Team (“Support”) at 1.866.770.7712. 울산광역 출장안마

    RépondreSupprimer