Chaîne caractères par liaison série

Bonjour à tous,

Etant élève en terminale S SI, j'ai un projet à mener tout au long de l'année.

Dans la réalisation de ce dernier, je dois parvenir à retranscrire la parole (de l'oral) sous forme de texte et à l'afficher sur un écran. J'ai donc opté pour l'utilisation d'un Raspbery PI model 3B+ car je pourrais installer un assistant vocal dessus.

Cependant, chaque chose dans son temps. Je suis en train de travailler simplement dans un premier temps sur l'envoi de textes du Rasperry vers l'arduino pour ensuite l'afficher sur un écran. La communication entre le Raspberry et l'arduino se fait par liaison série. Dans le programme python, je dois convertir ma chaîne de caractère en bytes (je crois que c'est parce que seul le binaire se communique par liaison série). Seulement, je dois dans le programma arduino convertir à nouveau les bytes en chaîne de caractères.

Pour reprendre de manière concrète, j'envoie la chaîne de caractère du Raspberry à l'arduino avec : ser.write(b'cequejeveuxenvoyer'). Pour récupérer la chaîne de caractère, j'ai entendu parler de l'ASCII, de tableau de char ou je ne sais pas trop quoi.
Si j'ai bien compris, en python, la fonction b'n'importe quoi' transforme mon message en tableau d'octet : je ne vois pas en quoi il s'agit d'un tableau. De plus, lorsque j'affiche sur un écran LCD I2C le message que j'envoie depuis le Raspberry, converti en tableau d'octet, j'obient par exemple pour A : -35 ; pour B : -43 et pour C : -39. Cependant, cela ne correspond pas aux caractères en code ASCII ; je crois que je mélange un peu tout :slight_smile:

Voici mon programme de reception arduino :

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

String message="";

void setup()
{
 Serial.begin(9600);
 lcd.init(); // Démarer l'écran                      
 lcd.backlight(); // Activer l'éclairage
 lcd.setCursor(0,0); // Placer le curseur en x 0 et y 0
}

void loop()
{
 if (Serial.available())
   {
    message = Serial.read() - '0';
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(message);
    delay(2000);
   }
}

Et pour le code python :

import serial
ser = serial.Serial('/dev/ttyACM0',9600)
while True :
    ser.write(b'cequejeveuxenvoyer')

Voilà, je tiens à préciser que je suis un novice d'arduino et qu'avant de demander de l'aide, j'ai fait tout mon possible pour essayer de comprendre ces conversions car, pour que tout soit clair, ce que je souhaiterais faire est de récupérer la chaîne de caractères associée aux bytes que je reçois en raison de la conversion indispensable de ma chaîne de caractère pour la communiquer par liaison série.

Merci beaucoup par avance,

CoLMa

je crois que je mélange un peu tout

Oui.

Dans le programme python, je dois convertir ma chaîne de caractère en bytes (je crois que c'est parce que seul le binaire se communique par liaison série). Seulement, je dois dans le programma arduino convertir à nouveau les bytes en chaîne de caractères.

Je ne vois pas pourquoi. Une chaîne de caractères se transmet telle quelle, et se reçoit telle quelle.

Transmettre le caractère 'A' côté PC, cela revient à transmettre un caractère ayant le code ASCII 65 ou 0x41. Aucun besoin de conversion.
Du côté ARDUINO, je te conseille de ne pas utiliser la classe String.

Vois ici : RitonDuino: ARDUINO : la fragmentation mémoire

Surtout 6.3. readBytesUntil()

Si j'ai bien compris, en python, la fonction b'n'importe quoi' transforme mon message en tableau d'octet

Non, b'string' indique une chaîne de bytes, un blob.

De quel PYTHON s'agit-il. PYTHON 2.7 ou PYTHON3. A préciser.

Ensuite il faut avoir une idée des données à transmettre. Est-ce que ce sont des caractères imprimables ou non ?
Une chaîne de caractère imprimable pourra se terminer par un caractère de terminaison simple : retour chariot par exemple. Avec des données binaires ce ne sera pas le cas.

colma:
je crois que je mélange un peu tout :slight_smile:

si ça peut aider :

En informatique, il y a un conteneur universel, c’est l’octet.
Un octet c’est 8 bits d’information. On utilise ça car c’est ce que le microprocesseur aime bien.

Ces octets, on met ce qu’on veut dedans. Des fois c’est par exemple un pixel d’une image, d’autres fois c’est un caractère faisant partie d’un texte.
Comme avec 8 bits on peut compter de 0 à 255, un octet contient donc à la base un nombre.
C’est l’humain qui donne un sens à ce nombre. Il peut les appeler char, byte ou uint8_t, ça désigne la même chose.

Pour les caractères, les américains ont créé une table de conversion : la caractère A correspond à la valeur 65, le B à 66, etc.
C’est ce qu’on apelle le code ASCII.
Puisque chaque octet contient un caractère, on peut dire qu’un texte, c’est un tableau (à 1 dimension) d’octets.

Bien.
Dans tes programmes (RPI, Arduino), les textes peuvent être contenus de diverses façons : C-string, String… peu importe.
Transmettre un texte du RPI à l’Arduino par liaison série, c’est donc : côté émetteur, prendre les caractères du texte 1 par 1, dans l’ordre, et les envoyer 1 par 1 sur la ligne série. Pour le récepteur : recevoir les caractères 1 par 1 et les ranger, soit dans un tableau d’octets (C-string), soit en utilisant un objet String…

Quand tu écris ser.write ( "hello") , l'objet ser fait le boulot : il prends les caractères de "hello" 1 par 1 et les envoie sur la ligne série.
Après ce n'est qu'un histoire de syntaxe du langage (je connais pas python), en C par exemple on doit passer en argument l'adresse du texte (ce qui n'est pas le texte lui-même).
Les caractères eux-mêmes ne subissent aucun transcodage. On ne fait que manipuler la représentation de l'information, pas l'information elle-même.

faudra aussi gérer le souci du UTF8 et des accents...

Bonsoir,

Merci à tous pour vos réponses, j'ai un petit peu avancé.

J'ai plusieurs questions :

  • Quelle est la différence entre le code ASCII 65 (pour le 'A') et le 0x41 ?

  • Comment fonctionne la fonction readBytesUntil() ? J'ai cru comprendre qu'elle renvoyait le nombre de caractères dans le port série, est-ce cela ?

  • Pour la classe String, elle me facilite les choses ; est-ce vraiment important de passer par autre chose ? Et quelle serait l'alternative ? Les char [] ? PS : Je ne les ai jamais compris :confused:

Concernant la version python, il s'agit de celle déjà installée sur la carte SD du Raspberry : c'est Thonny Python IDE, une version pour débutant si j'ai bien compris.

Concernant la réponse de hbachetti

Ensuite il faut avoir une idée des données à transmettre. Est-ce que ce sont des caractères imprimables ou non ?
Une chaîne de caractère imprimable pourra se terminer par un caractère de terminaison simple : retour chariot par exemple. Avec des données binaires ce ne sera pas le cas.

Je n'ai pas compris, que sont des caractères imprimables ? Qu'est ce qu'un caractère de terminaison simple ? Retour chariot ? L'idée est simplement d'envoyer des mots depuis le Raspberry et qu'ils s'affichent sur un écran LCD I2C relié à l'arduino.

Concernant le projet, comme je vous l'ai dit, j'ai un peu avancé. Ce n'est pas la première fois qu'on me dit qu'il suffit de transmettre ma chaîne de caractère sans avoir à la convertir

Je ne vois pas pourquoi. Une chaîne de caractères se transmet telle quelle, et se reçoit telle quelle.

.
Le problème, c'est que je ne connais pas l'existence d'une telle fonction python qui me permettrait de l'envoyer directement : ser.write("variable") ou ser.write(variable) ou ser.write('a') conduisent à une erreur alors que j'ai bien importé la librairie serial.

Par le biais de la fonction python ser.write(b'ABCDE'), j'obtiens bien maintenant sur mon écran les transcriptions avec la table ASCII de chacun des caractères de la chaîne envoyée, à savoir ici 65,66,67,68,69 et ces derniers défilent à une vitesse de 2 secondes que j'ai paramétrées alors qu'avant, j'obtenais des valeurs surprenantes ; j'ai simplement ajouté après avoir préciser le prot série dans lequel envoyé les données un délai "time.sleep(2)".

Voilà, merci encore de votre aide, j'attends vos réponses avec impatience !

Merci et bon week-end à tous ! :slight_smile:

Colma.

  • Quelle est la différence entre le code ASCII 65 (pour le 'A') et le 0x41 ?

Aucune. C'est le caractère 'A'. Tu peux aussi ajouter B01000001.

Puisque tu veux parler PYTHON :

'A' == chr(65) == chr(0x41) == chr(0b01000001)
True

Pour la classe String, elle me facilite les choses

Lis l'article en #1. C'est toi qui prends les risques, pas moi.

Je n'ai pas compris, que sont des caractères imprimables ?

chr(0x41)
'A'
chr(0x06)
'\x06'

'\x41' est un caractère imprimable. Python a la gentillesse de te le représenter par un 'A'.
0x06 n'en est pas un.

Qu'est ce qu'un caractère de terminaison simple ?

Un caractère qui termine la commande : retour chariot, line feed, ou un autre caractère de ton choix.

Par exemple si tu transmets :

"blabla\r" le caractère terminateur est "retour chariot". Comme il n'apparaît jamais dans la grammaire si cette grammaire est constituée uniquement de caractères imprimable, on ne risque pas de le confondre avec un autre.

Le problème, c'est que je ne connais pas l'existence d'une telle fonction python qui me permettrait de l'envoyer directement : ser.write("variable") ou ser.write(variable) ou ser.write('a') conduisent à une erreur alors que j'ai bien importé la librairie serial.

Si tu ne donnes ni ton code ni l'erreur en question, que dire ? ? ?

Par le biais de la fonction python ser.write(b'ABCDE'), j'obtiens bien maintenant sur mon écran les transcriptions avec la table ASCII de chacun des caractères de la chaîne envoyée, à savoir ici 65,66,67,68,69

Je suppose que tu reçois comme ceci :
int c = Serial.read();
Serial.print(c);

Et si tu les affiche avec Serial.print((char)c) ?

Merci de ta réponse :slight_smile:

Puisque tu veux parler PYTHON :

'A' == chr(65) == chr(0x41) == chr(0b01000001)
True

Pour savoir si j'ai bien compris, ce que tu as fait, c'est demandé à la console python si le caractère 'A' était pareil que sa représentation en ASCII, en 0X41 (de quelle représentation s'agit-il ?) et en binaire car le nombre binaire que tu as rentré vaut 65 en décimal ? Et tout ceci avec la fonction chr qui te permet d'afficher le caractère peut importe "son apparence" ?

Je te met le code à la fin du message mais au lieu de mettre un string, j'ai voulu mettre char message[] = "je ne sais pas ce que je devais mettre" sauf que le type char engendrait une erreur avec le Serial.read().
Comment fonctionnent les chars ?
Et ma version de python est-elle bonne ? (Thonny Python IDE)

Puisque tu veux parler PYTHON :

'A' == chr(65) == chr(0x41) == chr(0b01000001)
True

Du coup, un caractère imprimable est un caractère que l'IDE python peut retranscrire en "caractère compréhensible" ? Et pourquoi l'IDE t'as renvoyé '\x06' et pas '0x06', ce que tu lui avais rentré puisqu'il n'est pas imprimable ? Question bête mais c'est pour comprendre le rôle de chaque caractère dans les différentes instructions.

Mon code Arduino

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

String message = "";

void setup()
{
  Serial.begin(9600);
  lcd.init(); // Démarer l'écran                      
  lcd.backlight(); // Activer l'éclairage
  lcd.setCursor(0,0); // Placer le curseur en x 0 et y 0
  lcd.clear();
}

void loop()
{
 while(Serial.available () > 0) 
 {
  message = Serial.read()-'0';
  lcd.print(message);
  delay(1500);
 }
}

Code Python

import serial, time

ser = serial.Serial('/dev/ttyACM1',9600)
time.sleep(2)

ser.write(b'ABC')
ser.close()

Voilà, merci en tout cas de la réactivité de tes réponses et désolé si je pose beaucoup de questions ou si j'ai du mal :confused:

Bon week-end,

Colma.

J'ai envoyé le mauvais code arduino car avec le -'0' à la fin du Serial.read(), je n'obtiens pas la retranscription en ASCII ; d'ailleurs je ne sais pas pourquoi.

En tout cas, voici le vrai code arduino actuel que j'ai, je viens de le tester de nouveau et il fonctionne, enfin pour simplement me donner les nombre ASCII des caractères que je lui envoie hein :slight_smile:

VRAI CODE ARDUINO

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

String message = "";

void setup()
{
  Serial.begin(9600);
  lcd.init(); // Démarer l'écran                      
  lcd.backlight(); // Activer l'éclairage
  lcd.setCursor(0,0); // Placer le curseur en x 0 et y 0
  lcd.clear();
}

void loop()
{
 while(Serial.available () > 0) 
 {
  message = Serial.read();
  lcd.print(message);
  lcd.print(",");
  delay(1500);
 }
}

Pour savoir si j'ai bien compris, ce que tu as fait, c'est demandé à la console python si le caractère 'A' était pareil que sa représentation en ASCII, en 0X41 (de quelle représentation s'agit-il ?) et en binaire car le nombre binaire que tu as rentré vaut 65 en décimal ? Et tout ceci avec la fonction chr qui te permet d'afficher le caractère peut importe "son apparence" ?

Oui. PYTHON fait la distinction entre caractère 'A' et sa valeur décimale 65 ou hexadécimale 0x41.
En C cette distinction n'existe pas. 'A' est égal à 65 ou 0x41.

Et ma version de python est-elle bonne ? (Thonny Python IDE)

Si tu as la dernière version, c'est du PYTHON 3.7.

Du coup, un caractère imprimable est un caractère que l'IDE python peut retranscrire en "caractère compréhensible" ? Et pourquoi l'IDE t'as renvoyé 'x06' et pas '0x06', ce que tu lui avais rentré puisqu'il n'est pas imprimable ? Question bête mais c'est pour comprendre le rôle de chaque caractère dans les différentes instructions.

'x06' est un caractère, 0x06 est un entier.
chr(0x06) renvoie le caractère correspondant au code ASCII 6.
Se le caractère est imprimable, il l'affiche sous une forme imprimable, sinon sous une forme binaire.

Dans mon article arduino-la-fragmentation-memoire je déconseille l'utilisation de la class String.

Au paragraphe 6.3. readBytesUntil() tu trouveras un bout de code utile.

A moins que tu ne disposes d'une plateforme disposant de beaucoup de mémoire bien sûr.
Mais sur une UNO ou une NANO, tu as 2Kbytes à ta disposition, et c'est très peu.

J-M-L:
faudra aussi gérer le souci du UTF8 et des accents...

Visiblement notre ami fait une sortie de route à chaque nouveau détail qu'on lui donne :slight_smile:
Etre complet n'est pas la priorité...

ColMa, je te suggère de trouver sur le Web divers tutos sur l'informatique (la notation hexadécimale, la représentation des caractères, les tableaux, différence entre 0 et '0' et '\0' ...) et la programmation,
afin de ne pas buter sur chaque nouveau concept que tu découvres ici.

Visiblement notre ami fait une sortie de route à chaque nouveau détail qu'on lui donne

Oui, en effet Biggil, c'est qu'il s'agit du premier projet sérieur dans lequel je m'implique et jusqu'ici, je n'ai que fait tourner des moteurs et allumer des LEDS ou jouer avec des écrans et des petits modules RFID etc. rien avoir avec le Raspberry, que j'ai découvert pour l'occasion.

faudra aussi gérer le souci du UTF8 et des accents...

J'ai essayé d'envoyé des caractères avec accents mais en vain, cela plante dans le programme python car ils ne font pas partis de la table ASCII il me semble. Il faudra que j'y remédie car l'idée ensuite est que des variables se crées toutes seules pour stocker les mots retranscrits à l'écrit (à la base ils seront prononcés avec la parole et capté par un micro pour être retranscrit à l'aide d'un assistant vocal qui écrira lui les accents je pense :confused:

Mon point est que vous pouvez faire de l’exploration sur ces transferts vers un Arduino et apprendre des tas de choses et c’est très bien mais en pratique ensuite vous ne saurez sans doute pas afficher un vrai texte reçu correctement sur Arduino en français.

Je suppose que vous passerez par un service en ligne genre Google Voice qui permet de soumettre un flux audio et récupérer sa transcription

Cette transcription sera en Unicode ou UTF8 pour le français. La principale caractéristique d’UTF-8 est qu’elle est rétro-compatible avec le standard ASCII, c’est-à-dire que tout caractère ASCII se code en UTF-8 sous forme d’un unique octet, identique au code ASCII.

Par exemple « A » (A majuscule) a pour code ASCII 65 (0x41) et se code en UTF-8 par l'octet 65. Chaque caractère dont le point de code est supérieur à 127 (0x7F) (caractère non ASCII) se code sur 2 à 4 octets. Le caractère « € » (euro) se code par exemple sur 3 octets : 226, 130, et 172 (0xE2, 0x82 et 0xAC).

=> va se poser le problème donc qu’un octet reçu par serial ne représente plus un caractère et un autre souci c’est que les écrans classiques ne savent pas afficher de l’UTF8...

Pour tester votre code prenez par exemple côté RPi la phrase ‘Ça sent très bon la bûche de Noël mais elle coûte 50€‘ plutôt que ‘Hello World’.

Bonjour,

MERCI BEAUCOUP, les caractères s'affichent sur l'écran (ceux sans accents) grâce au bout de code de hbachetti.

Je peux désormais envoyer une chaîne de caractère du Raspberry à l'arduino. Voici les codes :

Code Arduino

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

void setup()
{
  Serial.begin(9600);
  lcd.init(); // Démarer l'écran                      
  lcd.backlight(); // Activer l'éclairage
  lcd.clear();
  lcd.setCursor(0,0);
}

void loop()
{
 char buf[256];
 while(Serial.available () > 0) 
 {
  int n = Serial.readBytesUntil('\r', buf, 255);
  buf[n] = '\0';
  if (n == 1 && buf[0] == '\n') 
    {
     return;
    }
  lcd.print(buf);
  delay(200);
 }
}

Code Python

import serial, time

ser = serial.Serial('/dev/ttyACM0',9600)
time.sleep(2)

ser.write(b'le contenu de la variable')
ser.close()

Seulement, pour plus d'interaction avec le programme python, j'aimerais que le programme me demande à chaque fois le message que je veux envoyer et pas qu'il soit pré-écrit dans le programme. Seulement, j'ai peur que quand j'écrive ser.write(b'message'), il envoie le mot message et pas le contenu de la variable. De plus, j'ai déja essayé et cela conduisait à une erreur avec comme message que le message en int ne ocnvenait pas en base 10 (quelque chose de la sorte).

Code Python 2.0

import serial, time

ser = serial.Serial('/dev/ttyACM0',9600)
time.sleep(2)

message = int(input("Votre message !"))
ser.write(b'message')
ser.close()

Voilà, si vous avez des solutions, je suis preneur :slight_smile:

=> va se poser le problème donc qu'un octet reçu par serial ne représente plus un caractère et un autre souci c'est que les écrans classiques ne savent pas afficher de l'UTF8...

Comment faire donc pour que le programme comprenne quand il s'agit d'un octet simple pour un caractère ou que le caractère est une suite de 3 octets et ne pas qu'il m'affiche les 3 caractères correspondant à chacun des 3 octets ?

Concernant l'écran que j'utilise, il s'agit simplement d'un écran LCD I2C 16x2 mais pour notre projet, nous aurons un meilleur écran :
https://www.gotronic.fr/art-shield-ecran-tft-tactile-ada1651-21306.htm

Merci encore de l'aide que vous m'avez importé :slight_smile:

Bon week-end :slight_smile:

message = int(input("Votre message !"))

Mais pourquoi int() ? Un message ne se transforme pas en integer !

Au sujet des caractère accentués le jeu de caractères de la table Latin-1 pourra amplement suffire pour du français.

Ensuite se posera le problème des polices de caractères de la librairie adoptée pour le TFT ILI9341.

Qu'il s'agisse de la librairie Adafruit_GFX ou UTFT les polices comptent en général 127 caractères.
Afficher des caractères accentués supposera de convertir une police TTF existante.

On se demande d'ailleurs dans ce projet quel est l'intérêt d'afficher le message sur un écran déporté sur un ARDUINO alors qu'il aurait été si simple d'afficher directement sur un écran connecté à RASPBERRY PI (HDMI ou DSI), avec toutes les facilités liées aux polices de l'OS.

colma:
j'ai peur que quand j'écrive ser.write(b'message'), il envoie le mot message et pas le contenu de la variable.

C'est parce que tu ne maitrises pas la syntaxe python. Je vois que tu n'as pas suivi mon conseil :grin:

Comment faire donc pour que le programme comprenne quand il s'agit d'un octet simple pour un caractère ou que le caractère est une suite de 3 octets et ne pas qu'il m'affiche les 3 caractères correspondant à chacun des 3 octets

C'est pas le programme qui doit comprendre ça, c'est l'afficheur.

  • Soit l'afficheur est intelligent et il comprend l'UTF8. Ca m'étonnerait.
  • Soit l'afficheur est sympa et permet d'afficher des caractères accentués, mais avec sa méthode à lui. Là c'est à ton prog Arduino de faire le boulot (repérer les caractères accentués dans le flux, et commander l'afficheur en conséquence). Ca m'étonnerait aussi.
  • Soit l'afficheur est bête (c'est le + probable) et ne sait pas afficher de caractères non-ASCII. Dans ce cas une de tes programmes (Arduino ou python) devra se charger de remplacer les caractères non-affichables par ... quelque chose d'affichable.

EDIT: le cas ou l'afficheur utilise une police "ASCII-étendue" comme Latin1 (c-a-d avec 255 caractères, dont nos accentués, au lieu de 127) correspond au second item. Quelque part, il faudra effectuer une traduction UTF8->ASCII étendu.

hbachetti:
On se demande d'ailleurs dans ce projet quel est l'intérêt d'afficher le message sur un écran déporté sur un ARDUINO alors qu'il aurait été si simple d'afficher directement sur un écran connecté à RASPBERRY PI (HDMI ou DSI), avec toutes les facilités liées aux polices de l'OS.

oui c'est la question que je me pose aussi, à quoi sert l'arduino dans tout cela puisque le RPi peut très bien afficher l'information (en mieux puisqu'on aura de vraies polices de caractères et que Python gère l'UTF8 ou l'unicode...

Bonjour à tous,

Merci de vos réponses, j'ai avancé dans le projet et j'arrive donc maintenant à afficher des contenus de variable.

Programme python

import serial, time

ser = serial.Serial('/dev/ttyACM0',9600)
time.sleep(1)

while True:
   message = str(input("Veuillez entrer un message !"))
   message_utf = message.encode()
   ser.write(message_utf)
   ser.write(b' ')

Biggil, je note tes remarques concernant l'affichage de caractères accentués, merci :slight_smile:

Concernant le code arduino, j'ai du mal à comprendre comment fonctionne la lecture et la concaténation (si c'est le bon mot) des chaînes de caractères :

Programme Arduino

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);

void setup()
{
  Serial.begin(9600);
  lcd.init(); // Démarer l'écran                      
  lcd.backlight(); // Activer l'éclairage
  lcd.clear();
  lcd.setCursor(0,0);
}

void loop()
{
 char buf[256];
 if(Serial.available () > 0) 
 {
  int n = Serial.readBytesUntil('\r', buf, 255);
  buf[n] = '\0';
  if (n == 1 && buf[0] == '\n') 
    {
     return;
    }
  lcd.print(buf);
  delay(200);
 }
}
  • Je créé la variable char buf[256]
  • Si il y a des caractères dans le buffer (la mémoire de la communication série ?), alors :
  • là je ne comprend pas jusqu'à "return", je crois que la variable n prend la valeur ASCII de chaque caractère mais je ne comprend pas le sens des arguements de la fonction Serial.ReadBytesUntil(), le rôle des '\0' ou avec un n ou un r au lieu du 0 et le rôle du dernier if avec les 2 esperluettes.

On se demande d'ailleurs dans ce projet quel est l'intérêt d'afficher le message sur un écran déporté sur un ARDUINO alors qu'il aurait été si simple d'afficher directement sur un écran connecté à RASPBERRY PI (HDMI ou DSI), avec toutes les facilités liées aux polices de l'OS.

Et bien en fait, au début de l'année, nous ignorions l'existence et le fonctionnement des Raspberry et ne connaissions en programmation que les arduino, par soucis de simplicité et par manque de connaissances, nous avions donc choisi d'utiliser arduino. Ce choix peut paraître surprenant, je suis d'accord mais peut-être que cela le sera moins pour vous si je vous explique les autres fonctions de notre projet :

Nous souhaitons créé un casque pour les personnes atteintes de surdité totale au partielle afin que ces personnes puissent interagir, échanger et comprendre ce que des tiers lui communiquent, voilà l'idée générale du projet.

Seulement, la retranscription vocale n'est pas la seul fonction : pour que notre projet qui est un casque puisse d'adapter à chaque utilisateur, une autre personne de notre groupe travaille sur la création d'une application (MIT) qui permettra, par Bluetooth, à l'utilisateur de personnaliser la police ainsi que sa taille mais également le nombre de mots que l'écran peut afficher avant de les effacer (c'est lié à la police : plus il y a de mots, plus la police est petite).

L'autre fonction de personnalisation essentielle et qui pourrait justifier le choix de l'arduino comme organe de programmation central (puisque le Raspberry ne sert qu'à la partie vocale), c'est la possibilité de contrôler la distance yeux-écran à l'aide de petits moteurs et d'un système vis écrou, tout cela à partir de l'application.

Voilà, nous avons sans doute fait des erreurs dans les choix pratiques et techniques mais nous sommes encore des novices en grand manque de connaissances concernant les possibilités de réalisation technique. Cependant, si vous avez des remarques ou des commentaires à nous faire parvenir concernant le projet, ils seront les bienvenus :slight_smile:

Reprenons la partie programmation, la suite de la partie retranscription vocale serait la suivante : installer un assistant vocal de chez Google ou chez Amazon (qui est gratuit pour les prototypes il me semble) ou encore l'assistant Jarvis sur le Raspberry. L'idée est qu'il soit toujours activé mais pas pour faire de la gestion par commande vocale ; j'ai vu dans une vidéo que chaque échange vocal était écrit sur programme python. L'idée est donc de créer une variable chaîne de caractères à intervalle de temps régulier, qui prendra en mémoire ce qui à été dit à l'oral et de l'envoyer sur l'écran arduino qui se trouvera devant ses yeux (je précise que nous étions partis à la base sur un écran transparent mais que notre professeur à refuser en raison du prix et que ce n'était pas grave si on le précisait le jour de l'oral).

Voilà, se pose le problème d'afficher ou non ce que le porteur du casque dit aussi, comment gérer cela, avec la fréquence des voix... On ne sait pas encore ce qu'on va faire là-dessus.

Si vous avez encore une fois des remarques sur le projet globale, pour nous le faciliter, en nous indiquant des options que nous ne connaissons pas ou plus précisément concernant la partie retranscription de la parole avec le procédé ci-dessus, de l'assistant vocal et de la création de la variable et de son envoi, nous sommes preneurs :slight_smile: Ou bien plus largement sur votre avis concernant le projet :slight_smile:

Merci beaucoup encore une fois et excusez moi pour le pavé que vous venez de lire :slight_smile:

Bonne semaine à tous !

  • là je ne comprend pas jusqu'à "return", je crois que la variable n prend la valeur ASCII de chaque caractère mais je ne comprend pas le sens des arguements de la fonction Serial.ReadBytesUntil(), le rôle des '\0' ou avec un n ou un r au lieu du 0 et le rôle du dernier if avec les 2 esperluettes.

le code est:

  int n = Serial.readBytesUntil('\r', buf, 255);
  buf[n] = '\0';

ça dit je mets dans n le nombre d'octets que j'ai lu. ces octets auront été stockés dans buf par la fonction readBytesUntil() et au maximum je vais en lire 255 et je m'arrête dès que j'ai reçu '\r'.

le premier octet est rangé dans buf[0], le deuxième dans buf[1], le troisième dans buf[2] etc....

la ligne suivante s'assure qu'on termine bien une cString (un tableau de caractère terminé par nul). Puisque n est le nombre de caractères lus et qu'un tableau commence à 0, on a les n caractères aux indices de 0 à (n-1) et on met le caractère null à la fin, en position n.

ce code là dit

if (n == 1 && buf[0] == '\n') 
    {
     return;
    }

si j'avais lu qu'un seul caractère et que c'était le retour chariot, j'ai reçu une ligne vide, ça ne m'intéresse pas, j'imprime rien, sinon j'imprime ce que j'ai reçu

Voilà, nous avons sans doute fait des erreurs dans les choix pratiques et techniques mais nous sommes encore des novices en grand manque de connaissances concernant les possibilités de réalisation technique. Cependant, si vous avez des remarques ou des commentaires à nous faire parvenir concernant le projet, ils seront les bienvenus :slight_smile:


vous devriez laisser l'arduino gérer tout ce qui est moteurs, actionneurs, LEds éventuellement mais tout ce qui est affichage avancé, polices, gestion audio etc faites ça sur le RPi...

Votre projet me semble bien trop ambitieux au vu de vos compétences actuelles. Vous devriez commencer avec un objectif plus raisonnable et améliorer vos compétences avant de rajouter de la complexité.