Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] First design to abstract I2C comm behind a class #4

Merged
merged 7 commits into from
Feb 10, 2017

Conversation

azerupi
Copy link
Member

@azerupi azerupi commented Feb 1, 2017

Le but est de créer une abstraction autour de la communication I2C pour chaque module. Un module est (généralement) une partie spécifique du robot commandé par une arduino, e.g. les capteurs ultrasons.

@azerupi azerupi added the I2C label Feb 2, 2017
@JonathanPetit
Copy link
Member

Le dernier commit est l'ajout du code arduino pour les capteurs ultrasons. Il y a encore un ou deux bugs dans le résultat de communication arrivé à la raspberry. Cela provient surement du code arduino. Ce sera fixer dans le courant de la semaine prochaine!

Copy link
Member

@charlesvdv charlesvdv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Juste quelques détails à modifier pour que ce soit parfait !


const byte SLAVE_ADDRESS = 0x04;
const byte N_SENSORS = 2;
const byte N_MEASURES = 5;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Utilise #define au lieu de const pour des constantes définies au dessus de ton code.

Copy link
Member Author

@azerupi azerupi Feb 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personnellement je préfère les constantes qu'utiliser le préprocesseur. Il n'y à pas d'avantage à utiliser #define au lieu de const

http://arduino.stackexchange.com/a/510/8755

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je n'ai pas pensé que les bonnes pratiques du C sont différentes des bonnes pratiques du C++. C'est nickel alors!

self.n = self.get_number_of_sensors()

def get_range(self, sensor):
cmd = I2C.pack8(1, sensor)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mettre les int dans des constantes pourrait être plus clair pour le lecteur.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Le mieux serait probablement d'utiliser une énumération

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C'est vrai que ce serait plus propre avec des enums. Ca serait quand meme pas mal de faire juste pour avoir une vue d'ensemble sur les commandes qu'on peut faire et directement avoir l'id de la commande.

@@ -0,0 +1,11 @@
from range_sensors import RangeSensor
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pas sur que ce code devrait être merger vu qu'on utilisera d'office pas comme ça dans la version finale.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Le main.py?
Oui, la c'est majoritairement pour pouvoir tester, mais je pense que ça peut mal de le merger. Il changera quand on ajoutera plus de code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok pour le garder pour l'instant 😄 c'est vrai que ca ne fait pas de mal.


return sum / N_MEASURES;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useless lines.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tu parles des "blank lines"?

@charlesvdv charlesvdv mentioned this pull request Feb 7, 2017
8 tasks
@azerupi
Copy link
Member Author

azerupi commented Feb 8, 2017

J'ai résolu le problème qu'on avait !!

I2C

Monsieur Marchand m'a expliqué que dans le protocole I2C, le master demande à écrire et lire des données sur des registres spécifique d'un esclave. Pour lire plusieurs bytes d'affilées on doit indiquer un registre à partir duquel on va lire, tant que le maitre n'envoie pas de signal d’arrêt, l'esclave va envoyer les registres suivants.

Donc, pour résoudre le problème qu'on avait, j'ai ajouté une variable dans l'arduino qui mémorise l'état de la réponse à la commande. Quand on reçoit une commande de la Pi, on passe dans l'état command_processed = false et on ignore les autres messages que la Pi envoie, jusqu'au moment ou l'arduino à pu envoyé sa réponse.

Mais... je ne suis pas super content de cette approche, je pense que ce serait mieux de se mettre d'accord d'ignorer tous les bytes null 0x00. De cette façon, on ne dépends plus de l'ordre des messages. Tout byte non-null sera considéré une nouvelle commande, les bytes null seront ignorés ou considérés comme la fin d'une commande.

Qu'en pensez-vous?

Commandes

Après réflexion, je me dis que les commandes choisies ici ne sont pas toutes utiles.
Depuis qu'on a ajouté la commande get_number_of_sensors, la commande enumerate_sensors n'apporte plus rien de plus. Comme les capteurs sont numérotés de 1 à nombre de capteurs + 1, cette commande renverra juste une liste consécutive...

Je propose de la supprimer.

Abstraction arduino

J'ai quelques idées à explorer pour créer des abstractions pour le code Arduino, mais comme le code ici fonctionne déjà, je propose qu'on le merge déjà pour que tout le monde y ai accès facilement. Si je trouve un bon design je ferai un nouveau PR.

Donc je pense que ceci est prêt à être reviewed, @charlesvdv?

self.bus.write_byte(self.adress, data)

def receive(self, num_bytes=1):
if num_bytes == 1:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normalement on a plus besoin de ca vu que read_i2c_block_data devrait aussi gérer les receive d'un byte et ca permetterait aussi d'etre plus conforme avec la nouvelle facon de faire les choses c-à-d mettre 0x00 sur le bus quand on a fini la commande.


class I2C:

def __init__(self, adress):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C'est address et pas adress. Il y a plusieurs endroits ou il faut le changer (dans us_sensors.ino également).


const byte SLAVE_ADDRESS = 0x04;
const byte N_SENSORS = 2;
const byte N_MEASURES = 5;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je n'ai pas pensé que les bonnes pratiques du C sont différentes des bonnes pratiques du C++. C'est nickel alors!

@@ -0,0 +1,11 @@
from range_sensors import RangeSensor
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok pour le garder pour l'instant 😄 c'est vrai que ca ne fait pas de mal.

self.n = self.get_number_of_sensors()

def get_range(self, sensor):
cmd = I2C.pack8(1, sensor)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C'est vrai que ce serait plus propre avec des enums. Ca serait quand meme pas mal de faire juste pour avoir une vue d'ensemble sur les commandes qu'on peut faire et directement avoir l'id de la commande.

// Enumerate all the sensors
case 3:
for(byte i = 0; i < N_SENSORS; i++) {
Wire.write( i );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gros gros détail mais tant qu'on y ait autant avoir la meme convention de codage partout. J'écrirais plutot Wire.write(i);

break;

case 4:
Wire.write( N_SENSORS );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

La meme que juste au dessus.

@charlesvdv
Copy link
Member

Un autre truc que l'on devrait ajouter sont des logs dans le code de la raspberry. J'ai oublié de mettre ca dans la review.

@azerupi
Copy link
Member Author

azerupi commented Feb 9, 2017

Merci!
Je suis d'accord avec tout ce que tu as dis, je ferai les modifs tantôt.
Le logging est pas indispensable pour cette PR, il peut être ajouté par une PR ultérieurement :)

@azerupi
Copy link
Member Author

azerupi commented Feb 9, 2017

Ok, je pense que j'ai adressé tout ce qu'il restait. J'ai également rajouté des commentaires, surtout dans le code python et j'ai supprimé la commande qui permet d'énumérer les capteurs, vu qu'elle n'as pas vraiment d'utilité.

A priori, je n'ai pas changé grand chose, mais sachez que je n'ai pas testé ce dernier commit.

@JonathanPetit
Copy link
Member

Normalement vu ce que tu as changé cela ne doit pas poser trop de problèmes...
Mais je serais d'avis de le tester avant de le merge?

class RangeSensor(I2C):
"""
This class is an abstraction around the I2C communication with
the range-sensor mdoule.
Copy link
Member

@charlesvdv charlesvdv Feb 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo avec module. @azerupi


Details of the "protocol" used:

The Raspberry Pi sens a byte to the module containing a command
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ca serait plutot send non ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oui, bien vu!

@charlesvdv
Copy link
Member

@azerupi dès que le code est tester et que tu as corrigé les 2 petites typos on pourra merger tout ca 😄

@azerupi
Copy link
Member Author

azerupi commented Feb 10, 2017

J'ai testé, résolu quelques erreurs et ça fonctionne bien.

Il y à juste un truc qui peut être amélioré, c'est que l'arduino block pendant un petit moment quand le capteur pointe dans le vide et fini par renvoyer 0 comme distance. On pourrait essayer de résoudre le problème nous même, ou alors on pourrait regarder si en utilisant la librairie NewPing le problème disparaît de lui même.

En attendant, le code est bon pour merger. Je ferrai des tests avec NewPing quand je testerai mes idées d'abstractions pour l'I2C du code Arduino.

@charlesvdv
Copy link
Member

Je pense que si on mets un timeout plus faible pour pulseIn on diminuerait le problème.

@azerupi
Copy link
Member Author

azerupi commented Feb 10, 2017

J'ai essayé, mais ça n'avait pas l'air de changer quelque chose

@charlesvdv
Copy link
Member

Ok parfait ! Je vais merger alors ! Merci beaucoup @azerupi @JonathanPetit pour la PR!

@charlesvdv charlesvdv merged commit ae722e7 into Ecam-Eurobot:master Feb 10, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants