Quellcode durchsuchen

Ajout d'un menu, ajout des attributs d'ajout et suppression des capturs, modification du programme principal par une machine d'états. TODO ajouter des commentaires

tags/PoDoCor-v0.1
lilian vor 3 Jahren
Ursprung
Commit
26b6936563
4 geänderte Dateien mit 201 neuen und 83 gelöschten Zeilen
  1. +8
    -2
      README.md
  2. +122
    -10
      bin/data.py
  3. +7
    -7
      bin/functions.py
  4. +64
    -64
      main.py

+ 8
- 2
README.md Datei anzeigen

@@ -6,12 +6,18 @@ Poeles-Dragon-Calculator (PoDoCor) est un logiciel d'expérimentation développ

Pour l'instant il n'existe pas d'interface graphique, de plus il n'existe qu'en français. Cela sera développé plus tard.

Ce logiciel est développé pour Linux avec python3 et un arduino. Les autres plateformes viendront plus tard.
Ce logiciel est développé pour Linux avec python3 et Arduino. Les autres plateformes viendront plus tard.

## Utilisation et fonctionnement

Au démarrage, le logiciel crée un dossier "data" à la racine du dossier de PoDoCor, où se trouve le script principal; dans ce dossier se trouveront toutes les données au format CSV.

Le logiciel extraie les données brutes que renvoie l'Arduino: si l'Arduino extraie la valeur 342 à la suite d'une conversion analogique-numérique, ce sera cette valeur qui sera transmise. Le CSV ne contient donc que des données qu'il est nécessaire de traiter, en particulier si les capteurs utilisés nécessitent l'utilisation d'une table de conversion ou d'un étalonnage, ces opérations devront être effectuées avant de lancer PoDoCor. Il est prévu néanmoins, dans une future version, d'inclure la phase d'initialisation dans le processus.
Si aucun fichier n'est déjà créé, ou s'il ne contient aucune déclaration de capteur, le logiciel en demandera la création au démarrage.

Le menu principal propose de commencer l'enregistrement des données ou de gérer les capteurs; le sous-menu permet d'afficher les capteurs enregistrés, d'en ajouter ou supprimer, et de changer l'ordre des capteurs pour correspondre à l'ordre des données envoyées par l'Arduino

Pour que le logiciel fonctionne, il est nécessaire de déclarer les capteurs utilisés: leur nom, l'unité dans laquelle il mesure, et une variable (0 ou 1) pour savoir si l'Arduino envoie des données brutes de ce capteur (i.e. une simple conversion analogique-numérique, sans mapping des données acquises), ou si ce sont les données normalisées que renvoie l'Arduino (une température par exemple). Lors de cette création de capteurs, ne JAMAIS utiliser de virgule (","), sans quoi le logiciel s'arrêterait pour ses futures initialisations.

Concernant les données simplement converties en numérique (si l'Arduino extraie la valeur 342 à la suite d'une conversion analogique-numérique par exemple), ce sera cette valeur qui sera transmise. Le CSV contient donc à la fois des données brutes et normalisées; les données brutes nécessiteront donc un traitement, en particulier si les capteurs utilisés nécessitent l'utilisation d'une table de conversion ou d'un étalonnage, ces opérations devront être effectuées avant de lancer PoDoCor. Il est prévu néanmoins, dans une future version, d'inclure la phase d'initialisation dans le processus.

Une fois le logiciel démarré, le démarrage du processus d'enregistrement des données démarre en utilisant Shift+P; de même, ce processus s'arrête en utilisant Shift+P.

+ 122
- 10
bin/data.py Datei anzeigen

@@ -10,7 +10,7 @@ class Arduino_data():
self.nb_captor_signals = 0
self.data_file_path = ''
self.data_array = np.empty((1,1))
self.data_path_dir = os.path.abspath(os.path.dirname(__file__)) + "/data"
self.data_path_dir = os.path.abspath(os.path.dirname(__file__)) + "/../data"
if(not(os.path.isdir(self.data_path_dir))): #creer dossier si non existant
os.mkdir(self.data_path_dir, 0o777)
self.raw_data_temp = [[]]
@@ -27,28 +27,101 @@ class Arduino_data():
else:
lines = captors_file.readlines()
self.nb_captor_signals = len(lines)
if(self.nb_captor_signals == 0):
captors_file.close()
print("Ajoutez au moins 1 capteur avant de commencer:\n")
self.add_captor_manually(file)
captors_file = open(file, "r")
lines = captors_file.readlines()
self.nb_captor_signals = len(lines)
self.data_array = np.empty((1,self.nb_captor_signals))
for i in range(self.nb_captor_signals):
captor_line = lines[i]
capt = Captor_data();
capt.read_captor(captor_line)
captors_file.close()
self.raw_data_temp = np.empty((1,self.nb_captor_signals))

def add_captor_manually(self, file):
self.nb_captor_signals += 1
capt = Captor_data()

coma = ","
capt.captor_name = str(input("Nom du capteur : "))
while(capt.captor_name.find(coma) != -1):
capt.captor_name = str(input("Nom du capteur ("," non accepté): "))
capt.unit = str(input("Unité : "))
while(capt.unit.find(coma) != -1):
capt.unit = str(input("Unité (\",\" non accepté): "))
capt.data_type = -1
while(capt.data_type <= -1 or capt.data_type >= 2):
capt.data_type = int(input("Type de données : 0 (raw) ou 1 (real): "))

captors_file = open(file, "a")
captors_file.write(".\n")
captors_file.write(capt.captor_file_line())
captors_file.close()
self.raw_data_temp.append([])
np.append(self.raw_data_temp, [])
self.data_array = np.empty((1,self.nb_captor_signals))
print("Capteur ajouté")

def captors_print_list(self, file):
captors_file = open(file, "r")
print(" Nom Unit Type(raw/real)")
for i in range(self.nb_captor_signals):
print("Capteur n°" + str(i+1) + " : " + str(captors_file.readline()))
captors_file.close()

def extract_data_to_array(self, raw_data_txt):
def del_captor(self, file):
self.captors_print_list(file)
captor_to_del = int(input("\nNumero du capteur a supprimer : "))-1
captors_file = open(file, "r")
lines = captors_file.readlines();
captors_file.close()
captors_file = open(file, "w")
for i in range(self.nb_captor_signals):
carac_coma_nb = 1
while((raw_data_txt[carac_coma_nb] != ',') or (raw_data_txt[carac_coma_nb:carac_coma_nb+2] != "\n")): #fin de la donnee ou de la ligne
carac_coma_nb +=1
single_data = int(raw_data_txt[0:carac_coma_nb])
raw_data_txt = raw_data_txt[carac_coma_nb+1:]
self.raw_data_temp[0,i] = single_data
if(i != captor_to_del):
captor_line = lines[i]
captors_file.write(captor_line)
else:
break;
captors_file.close()
self.nb_captor_signals = self.nb_captor_signals-1

def change_captors_order(self, file):
self.captors_print_list(file)
captors_file = open(file, "r")
lines = captors_file.readlines();
captors_file.close()
captors_order = []
print("Assigner ligne par ligne les anciens numéros de capteur à leur nouvelle place:")
for i in range(self.nb_captor_signals):
captors_order.append(int(input("nouveau n°" + str(i+1) + " : ancien n° : ")))

captors_file = open(file, "w")
for i in range(self.nb_captor_signals):
captor_line = lines[captors_order[i]-1]
captors_file.write(captor_line)
captors_file.close()
print("\nNouvel ordre des capteurs")
self.captors_print_list(file)

def extract_data_to_array(self, raw_data_txt):
coma = ","
coma_places = raw_data_txt.find(coma)
if(coma_places == -1 and len(raw_data_txt) < 2):
print("Donnees non transmises par l'Arduino.")
elif(coma_places == -1 and len(raw_data_txt) > 2):
raw_data_temp[0,0] = int(raw_data_txt)
if(len(coma_places) != self.nb_captor_signals-1):
if(len(coma_places) < self.nb_captor_signals-1):
print("Il y a moins de donnees transmises que de capteurs. Vérifiez les donnees transmises.")
else:
print("Il y a plus de donnees transmises que de capteurs.\nLes " + str(len(coma_places)-self.nb_captor_signals-1) + " donnees de fin seront supprimees")
else:
coma_places.insert(0,0)
coma_places.append(len(raw_data_txt))
for i in range(min(len(coma_places)-1, self.nb_captor_signals)):
self.raw_data_temp[0,i] = int(raw_data_txt[coma_places[i]:coma_places[i+1]])
np.append(self.data_array, raw_data_temp, axis=1)

def create_data_file(self):
@@ -60,3 +133,42 @@ class Arduino_data():
file = open(self.data_file_path,"a") #mode append
file.write(data)
file.close()




class Captor_data():

def __init__(self):
self.captor_name = ""
self.unit = ""
self.data_type = 0 #type possibles : donnee brute raw a convertir (0), donnees reelles utilisables en l'etat (1)

def set_captor_name(self, name):
self.captor_name = name

def set_unit(self, unit):
self.unit = unit

def set_data_type(self, data_type):
self.data_type = data_type

def read_captor(self, line):
for j in range(3):
carac_coma_nb = 1
while((line[carac_coma_nb] != ',') and (line[carac_coma_nb:carac_coma_nb+2] != "\n")): #fin de la donnee ou de la ligne
carac_coma_nb +=1
if(j == 0):
self.captor_name = line[0:carac_coma_nb]
elif(j == 1):
self.unit = line[0:carac_coma_nb]
elif(j == 2):
self.data_type = int(line[0:carac_coma_nb])
line = line[carac_coma_nb+1:]

def captor_string(self):
type_txt = ["raw", "real"]
return self.captor_name + "(" + self.unit + " " + type_txt[self.data_type] + ")"

def captor_file_line(self):
return self.captor_name + "," + self.unit + "," + str(self.data_type) + "\n"

+ 7
- 7
bin/functions.py Datei anzeigen

@@ -4,13 +4,13 @@ if(os.name == "posix"):
else:
import msvcrt as gt

def press_key(caracter, actual_state, future_state):
""" Cette fonction sert à détecter si le caractère est pressé, pour passer
d'un état (ou boucle) à un autre."""
def press_key(caracters, numbers, actual):
""" Cette fonction sert à détecter si un caractère est pressé, pour passer d'un
état (numbers) à un autre."""

pressed_key = gt.getch() #detection de touche pressee (arret procedure acquisition)
if(pressed_key == caracter):
flag_data = future_state
place = caracters.find(pressed_key)
if(place == -1):
return actual
else:
flag_data = actual_state
return flag_data
return numbers[place]

+ 64
- 64
main.py Datei anzeigen

@@ -2,102 +2,102 @@ import serial
import numpy as np
import matplotlib.pyplot as plt
import os
if(os.name == "posix"):
import getch as gt #clavier
else:
import msvcrt as gts
import time
import bin.functions as fc
import bin.data as data

#Variables principales

serial_path = '/dev/ttyUSB0'
script_path = os.path.abspath(os.path.dirname(__file__))
data_path_dir = script_path + "/data"
data_nb = 10
captors_path = os.path.abspath(os.path.dirname(__file__)) + "/captors.txt"

#Variables cachees

flag_data = 0
flag_data = False
data_buff_max = 10
data_buff_nb = 0
data_buff = ""
pressed_key = ''
full_rec_data = np.empty((1,data_nb))
raw_data_temp = np.empty((1, data_nb))
flag_exception_serial = 0
flag_state = 1 # etat neutre


#Programme principal

#init

#creer dossier si non existant
if(not(os.path.isdir(data_path_dir))):
os.mkdir(data_path_dir, 0o777)

try:
arduino_ser = serial.Serial(serial_path, 9600) #communication avec Arduino
except serial.serialutil.SerialException:
print("SerialException : la carte Arduino n'est pas connectee ou est connectee sur au autre port.\nFermeture du programme.")
flag_exception_serial = 1

while(1 and flag_exception_serial == 0):
pressed_key = gt.getch() #detection de touche pressee (demarrage procedure acquisition)
if(pressed_key == 'P'):
flag_data = 1
print("SerialException : la carte Arduino n'est pas connectee ou est connectee sur au autre port.")
flag_state = -1
else:
arduino_data = data.Arduino_data()
arduino_data.add_captors_from_file(captors_path)
print("PoDoCor est pret a enregistrer les donnees")

while(flag_state > 0):
if(flag_state == 1):
print("_________________________________\n\nMAJ + P : Enregistrement des donnees\nMAJ + N : Gerer les capteurs\nMAJ + X : Arrêt du programme (ne fonctionne pas pendant l'enregistrement)\n_________________________________\n")
flag_state = fc.press_key('XPN', [0, 2, 3], flag_state) #detection de touche pressee (demarrage procedure acquisition)
elif(flag_state == 3):
print(" _________________________________\n MAJ + U : Lister les capteurs\n MAJ + A : Ajouter un capteur\n MAJ + E : Supprimer un capteur\n MAJ + T : Changer l'ordre des capteurs\n MAJ + Q : Menu principal\n _________________________________\n")
flag_state = fc.press_key('AETUQ', [31, 32, 33, 34, 1], flag_state) #detection de touche pressee (demarrage procedure acquisition)
if(flag_state == 31):
arduino_data.add_captor_manually(captors_path)
flag_state = 3
elif(flag_state == 32):
arduino_data.del_captor(captors_path)
flag_state = 3
elif(flag_state == 33):
arduino_data.change_captors_order(captors_path)
flag_state = 3
elif(flag_state == 34):
arduino_data.captors_print_list(captors_path)
flag_state = 3

elif(flag_state == 2):
data_buff_nb = 0
data_path_file = data_path_dir + "/" + time.asctime()+".csv"
file = open(data_path_file, "w")
file.close()
else:
flag_data = 0

while(flag_data == 1 and flag_exception_serial == 0): #boucle de reception des donnees
arduino_ser.write(1) #envoi de '1' a l'Arduino
raw_data_txt = arduino_ser.readline() #format des donnees: data1,data2,data3\n raw data
#print(raw_data_txt)
if(raw_data_txt == ''): # si aucune donnée reçue
print("Arduino n'envoie aucune donnee, veuillez verifier le code televerse.")
flag_data = 1
data_buff_nb = 0
else:
data_buff_nb +=1
data_buff = data_buff + str(raw_data_txt) + "\n" #add 1 data line in buffer
print("a\n"+data_buff)
arduino_data.create_data_file()
while(flag_state == 2): #boucle de reception des donnees
time_0 = time.time()
arduino_ser.write(1) #envoi de '1' a l'Arduino
time.sleep(time_0+0.5-time.time())
time_1 = time_0+0.5
raw_data_txt = arduino_ser.readline() #format des donnees: data1,data2,data3\n raw data
print(raw_data_txt)
if(raw_data_txt == ''): # si aucune donnée reçue
print("Arduino n'envoie aucune donnee, veuillez verifier le code televerse.")
flag_state = -1
data_buff_nb = 0
else:
data_buff_nb +=1
data_buff = data_buff + str(raw_data_txt) + "\n" #add 1 data line in buffer

#procedure extraction donnees pour affichage
for i in range(data_nb):
carac_coma_nb = 1
while((raw_data_txt[carac_coma_nb] != ',') or (raw_data[carac_coma_nb:carac_coma_nb+2] != "\n")): #fin de la donnee ou de la ligne
carac_coma_nb +=1
single_data = int(raw_data_txt[0:carac_coma_nb])
raw_data_txt = raw_data_txt[carac_coma_nb+1:]
raw_data_temp[0,i] = single_data
np.append(full_rec_data, raw_data, axis=1)
raw_data_temp = raw_data*0
arduino_data.extract_data_to_array(raw_data_txt)

# procedure d'ecriture fichier
if(data_buff_nb == data_buff_max):
file = open(data_path_file,"a") #mode append
file.write(data_buff)
file.close()
arduino_data.append_data_to_file(data_buff)
data_buff = "" #remise a zero
data_buff_nb = 0

pressed_key = gt.getch() #detection de touche pressee (arret procedure acquisition)
if(pressedKey == 'P'):
flag_data = 0
else:
flag_data = 1
flag_state = fc.press_key('P', [1], flag_state)
time.sleep(time_1+0.5-time.time())
print(time.time())

# while end
if(data_buff_nb > 0): #vidage du buffer
arduino_data.ppend_data_to_file(self, data_buff)
data_buff = ""
data_buff_nb = 0

assert pressed_key != 'P' "Sortie de la boucle de reception des donnees"
arduino_ser.close()
assert flag_data == True, "Sortie de la boucle de reception des donnees"

if(data_buff_nb > 0):
file = open(file_name,"a")
file.write(data_buff)
file.close()
data_buff = ""
data_buff_nb = 0

arduino_ser.close()
elif(flag_state == 0):
break

print("Fermeture du programme.")

Laden…
Abbrechen
Speichern