liaison série Arduino - Python (suite)
Bonjour
Ce sujet fait suite à une discussion que j'avais entamée dans un autre fil (https://www.developpez.net/forums/d2...nnees-arduino/) mais les échanges entre certains contributeurs ont dévié vers un autre débat ce qui a conduit à sa fermeture.
Je reviens donc à la suite du dernier post de ce précédent fil.
Pour éviter d'avoir à tout relire le post, ma question initiale portait sur la récupération des données issues du moniteur série d'Arduino via Python pour ensuite traiter ces données : à l'aide d'un tutoriel trouvé de-ci de-là, j'avais opté pour une méthode assez "brute" qui engendrait des caractères vides dans mes listes de mesures.
J'ai donc mis en oeuvre la solution proposée par Beginner : j'obtiens bien effectivement une liste (rapidement !!) des données envoyées via Arduino sans caractère vide donc cool !
En termes de réglages, d'habitude, sur les 3 paramètres d'acquisition possibles (fréquence échantillonnage, durée, nombre de points) qui ne sont indépendants que 2 à 2 (la 3ème se calculant à partir des 2 autres), on choisit plus souvent la fréquence d'échantillonnage et la durée plutôt que le nombre de points : c'est d'ailleurs vers cette solution que j'avais orientée mon code
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| # Importation des modules utilisés
import serial
# Initialisation des variables
arduino = None
rawdata = []
nbrPoints = 0
def acuisition(nbrPoints):
# Ouverture de la liaison série
try:
arduino = serial.Serial("COM3", baudrate=115200, timeout=3)
except Exception as e:
print("Vérifier le port série:", e)
return
periode=input("Saisir la période d'échantillonnage (en ms) : ")
arduino.write(periode.encode("ascii"))
duree=input("Saisir la durée totale (en ms) : ")
arduino.write(duree.encode("ascii"))
acquisition=input("Saisir S pour lancer l'acquisition")
arduino.write(acquisition.encode("ascii"))
nbrPoints=int(duree)//int(periode)
# Réception et stockage des données
print("Début de l'acquisition...")
compt = 0
while compt < nbrPoints:
data_read = arduino.readline().decode()[:-2]
rawdata.append(data_read)
print(compt, rawdata[compt], sep=" - ")
compt += 1
print("Fin de l'acquisition.")
acuisition(nbrPoints)
# print("\nrawdata:", rawdata, "\ntaille:", len(rawdata)) |
qui faisait face, côté Arduino, au code suivant :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
// Déclaration des variables du programme
unsigned long baud = 115000; // flux de la liaison série
int delai = 1000; // délai d'attente pour être sûr de décharger le condensateur
// Variables d'acquisition
int timeRes; // période d'échantillonnage en ms
int dureeAcquisition ; // durée totale de l'acquisition en ms, saisi dans Python
int nbrPoints; // sera calculé à partir des données précédentes
unsigned long cpt = 1;
int topDepart = 0; //variable pour lancer l'acquisition
String envoi;
unsigned long tempsZero;
unsigned long tempsCourant;
unsigned long tempsPrec;
// Broches de branchement au circuit
byte mesureTension = 2; //broche analogique de mesure de la tension aux bornes de C
byte chargeCondo = 3; //broche pour décharger initialement le condensateur
void setup()
{
Serial.begin(baud);
//configure la broche commandePin en tant que sortie
pinMode(chargeCondo, OUTPUT);
//on décharge le condensateur en le mettant à 0V
digitalWrite(chargeCondo, LOW);
//on attend delai ms pour être sur de l'avoir déchargé
delay(delai);
tempsPrec = 0;
tempsZero = millis();
reglages();
nbrPoints=dureeAcquisition/timeRes;
}
// Boucle principale
void loop()
{
tempsCourant = millis() - tempsZero;
if (tempsCourant >= tempsPrec && cpt <= nbrPoints)
{
lecture();
cpt++;
}
}
void reglages()
{
while (topDepart == 0) {
envoi = Serial.readString();
while (Serial.available() == 0 );
if (Serial.available() != 0)
{
timeRes = Serial.parseInt(); //on enregistre la valeur saisie dans timeRes
delay(100); //délai de temporisation
}
while (Serial.available() == 0 );
if (Serial.available() != 0)
{
dureeAcquisition = Serial.parseInt(); //on enregistre la valeur saisie dans dureeAcquisition
delay(100); //délai de temporisation
}
while (Serial.available() == 0 );
if (Serial.available() != 0)
{
topDepart = 1;
tempsPrec = 0;
tempsZero = millis();
}
}
}
void lecture()
{
//on met à 5V le générateur pour voir la charge
digitalWrite(chargeCondo, HIGH);
float tension;
// Lecture et conversion des données
tension = analogRead(mesureTension) * 5.0 / 1024; // mesure analogique et conversion en tension
// Envoie les données
Serial.print(tempsCourant / 1000.0, 3); // temps en seconde
Serial.print(';');
Serial.println(tension, 2); // donne la valeur recalculée de tension aux bornes de C
tempsPrec += timeRes;
//Serial.flush();
} |
Les mesures obtenues sont bien mieux échantillonnées et la période d'échantillonnage est plutôt très bien respecté (à partir pour une période de 1 ms où quelques sauts apparaissent) mais cela ne me dérange pas car c'est ensuite l'allure de la courbe qui m'intérèsse.
J'ai essayé en augmentant le baudrate : pas de soucis.
Pour obtenir les listes de tension et de temps, j'ai essayé une nouvelle approche sans avoir à passer par un document texte (j'ai cru comprendre que c'était faisable) : j'ai donc essayé la syntaxe suivante à la fin de la fonction acuisition:
Code:
1 2 3
| for val in rawdata:
temps.append(val[:5])
tension.append(val[6:]) |
Est-ce que c'est une bonne technique pour obtenir mes 2 listes ou est-ce un peu barbare ? Je précise qu'elle fonctionne mais en guide d'amélioration de mon code, je me renseigne.https://www.developpez.net/forums/d2.../#post11496668