dimanche 15 décembre 2013

Insomnie, insonmie

Bon, je trouvais que de mettre du code python sans formatage, c'était un peu cheap. Malheureusement c'est rester coincé quelque part dans mon cerveau et impossible pour moi de dormir. Donc, après une petite séance de vidage de cerveau, voici le même code généré, toujours pas fonctionnel, mais cette fois formaté style IDLE:

## 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 

Comme il reste une fonctionnalité à implémenter, je ne mettrai pas le code ici tout de suite, mais en gros c'est un petit script python qui prend un fichier en entré et qui génère un fichier HTML. J'ai utilisé les même couleurs que IDLE pour les mots réservés, méthodes intégrées au langages, commentaires et strings. En passant, il y a pygments qui fait en bien mieux le travail, a une interface web et un service web pour l'appeler directement en plus d'être installable localement via easy_install. Dans mon cas, c'était pour faire taire mon cerveau que j'ai fais ça.

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.

mercredi 11 décembre 2013

Petit robot deviendra grand!

Bon sang que ça fait longtemps que je n'ai rien écrit ici! Pas que je suis resté tranquille c'est dernier mois. Je n'ai pas travailler sur ce que je pensais par contre. Je vais sûrement revenir au développement sur Android bientôt. Mais pour le moment, je suis tombé en amour avec Python! Ce qui m'a emmené à essayer plus sérieusement Python sont premièrement un projet au travail et une volonté d'utiliser mes raspberry pi sans avoir à me taper du C++ sous linux. Je voulais coder de quoi rapidement. J'avais déjà essayé Python il y a plusieurs années mais c'était trop lent pour ce que je voulais faire à l'époque et il n'y avait pas autant de librairies disponible. Maintenant, c'est tellement complet comme offre et tellement simple à programmer que je suis vendu Python. Je ne pense pas faire un jeux en Python, ça reste un langage interprété, mais pour bien d'autre utilisation où bien souvent la vitesse n'est pas un point important ou encore comme langage de haut-niveau qui permet d'interfacer plusieurs sous-système, c'en est merveilleux.

Tirobo-01 avec ses composants non fixés

Tout ça pour dire que mon projet en Python pour ne pas laisser mon 2e raspbery pi ramasser la poussière est un projet de petit robot. Petit, oui, mais combien impressionnant. J'ai fait mon shopping sur robotshop, shopping très instructif et je lève mon chapeau à un service après-ventre incroyable de leur part, et pour le prix de deux gros kit de lego ou megablock que monstre numéro 1 jouerait 2 ou 3 semaines avec et laisserait de côté, j'ai toutes les pièces pour fabriquer le jouet le plus techno qui soit. Voici en gros les pièces qui seront utilisées:

Évidemment, j'avais déjà certains composants ici dont le Raspberry pi, la clé wifi, DEL et bien des batteries rechargeables pour les moteurs. Mais pour environs 250$ et un peu de soudure, ça devient tout un petit robot. Mais pensez-y, le robot peu non seulement se brancher en HDMI et streamer des films en 1080p avec son surround, mais vous pouvez vous connecter réseau dessus, partir un session VNC avec desktop graphique qui inclus les environnements de développement pour le arduino mais aussi pour le code Python. Sincèrement, c'est vraiment impressionnant.