Syntaxe

Python est le langage de prédilection du Raspberry Pi

Modérateurs : Francois, Manfraid

Répondre
Avatar du membre
vague nerd
Modérateur
Messages : 1473
Enregistré le : mar. 14 oct. 2014 11:42
Localisation : France !

Syntaxe

Message par vague nerd » ven. 10 juil. 2015 14:52

Bonjour.

Je travaille sur un petit véhicule "wifi-commandé" (ya pas de radio, ya du wifi ! ;)).
Le proto physique est quasi terminé, je cherche a améliorer un peu le proto logiciel.

Un pi contrôle un nunchuck de wii en i2c.

Il lit la valeur des différents capteurs du nunchuck,
les transforment en quelque chose d'humainement compéhensible,
et enfin envoie par socket ces valeurs à un second pi.

Le second pi contrôle un chassis type chenille au travers d'un sn754410NE

Au travers du soket, il recoit les valeurs lues sur le unchuck par le premier pi,
les convertit en sens de rotation et vitesse pour chaque moteur,
envoie les bon signaux aux gpio.

Etat des lieux !

Actuellement, les calculs côté client sont minimalistes (juste conversion pour rendre humainement compréhensible), plus ou moins tout le reste se fait côté serveur.
Je verrais comment arbitrer ça plus tard, pour le moment, c'est plus simple de tout mettre au point côté serveur (un seul code source, assez court).
Les conversions se font selon des seuils codés en dur, et des valeurs cibles (le résultat de la conversion) sont dans des tableaux 2d dans des variables locales.

Questions

Je voudrais rendre paramétrables les seuils codés en dur, ainsi que les valeurs cibles.

1ere question : quel est le "meilleur" moyen de paramétrer la structure de données suivante ?

Code : Tout sélectionner

vitesseGauche = [
	[100, 100, 20],
	[60, 60, 30],
	[0, 30, 30],
	[100, 0, 100],
	[0, 30, 30],
	[60, 60, 30],
	[100, 100, 20]
]
Dans un fichier texte plat ? Y-a-t-il des utilitaires prévus à cet effet ?

2eme question : je suis clair ?

Cdt.
Cordialement,

Vague Nerd

domi
Administrateur
Messages : 3230
Enregistré le : mer. 17 sept. 2014 18:12
Localisation : Seine et Marne

Re: Syntaxe

Message par domi » ven. 10 juil. 2015 16:25

Salut Vague Nerd,

Et bien si tu veux coder un tableau en chaîne de texte, pourquoi ne pas le faire avec JSON ?

A+
Domi
Passionné de Raspberry, Arduino, ESP8266, ESP32, et objets connectés :
Spécial débutant, concevez vous-même votre domotique DIY : https://www.youtube.com/c/DomoticDIY
Conception d'une station météo DIY, et envoi des infos à votre Domotique.

Avatar du membre
vague nerd
Modérateur
Messages : 1473
Enregistré le : mar. 14 oct. 2014 11:42
Localisation : France !

Re: Syntaxe

Message par vague nerd » ven. 10 juil. 2015 17:32

pourquoi ne pas le faire avec JSON ?
Pas pensé ! Tu aurais une url sous la main (avec un load et un save json en python)?

Pour inclure un script python dans un autre, comment faire ?
J'ai bien vu import et from, mais là, je ne veux inclure que des définition de variables...

Dit autrement, je définit des variables dans un script. Comme ces variables peuvent elles être visibles d'un autre script ?
EDIT : faut-il définir des fonctions qui retournent mes tableaux, puis simplement utiliser import ?
Cordialement,

Vague Nerd

Avatar du membre
vague nerd
Modérateur
Messages : 1473
Enregistré le : mar. 14 oct. 2014 11:42
Localisation : France !

Re: Syntaxe

Message par vague nerd » ven. 10 juil. 2015 17:56

Je galère vraiement sur la syntaxe python (déjà je suis pas fan des blocks définis par indentation)... :(

Question 3 :
Avec ce bout de code :

Code : Tout sélectionner

	if y>140:
		if y>160:
			if y>180:
				y=0
			else:
				y=1
		else:
			y=2
	else:
		if y<100:
			if y<80:
				if y<60:
					y=6
				else:
					y=5
			else:
				y=4
		else:
			y=3
, je convertis en dur une ordonnée (allant de disons de -210 à 210) à un indice de tableau (allant de disons 0 à 6), selon des seuils (if y>140 ...).
Je souhaite rendre ces seuils paramétrables, par exemple avec :

Code : Tout sélectionner

seuilsY = [ 140, 160, 180, 100, 80, 60 ]
.
Facile de transformer le code en dur pour qu'il utilise le tableau de seuils.

La ou je bloque (plus à cause de la syntaxe qu'autre chose), c'est que je veux que la taille de la matrice cible ne soit pas figée. C'est à dire que la taille de seuilsY peut varier de 2 à l'infini, mais doit être pair.
Une idée ? (Pas d'inconvénient à modifier la structure de seuilY).
Cordialement,

Vague Nerd

Avatar du membre
Manfraid
Modérateur
Messages : 1402
Enregistré le : ven. 3 oct. 2014 14:50
Contact :

Re: Syntaxe

Message par Manfraid » ven. 10 juil. 2015 19:38

Salut,

pourrait tu expliquer ce que tu veux faire exactement, car j'ai un peu de mal a comprendre.

sinon le json est l'idéal pour stocker les donner

ça doit être comme ça de mémoire

Code : Tout sélectionner

import json

with open('tonfichier','r') as f:
    #por charger
    data = json.load(f)

with open('tonfichier','w') as f:
    #por charger
    json.load(data,f)
NAS : DIY OS Debian: DD250Go + 3x2To + 6To
Raspberry pi : 2B OS : Raspbian
Se tromper est humain, Vraiment foutre la merde nécessite le mot de passe de root.

Avatar du membre
vague nerd
Modérateur
Messages : 1473
Enregistré le : mar. 14 oct. 2014 11:42
Localisation : France !

Re: Syntaxe

Message par vague nerd » ven. 10 juil. 2015 19:47

Question 3 : J'en suis là :

Code : Tout sélectionner

seuilsY = [ 60, 80, 100, 140, 160, 180 ]

Code : Tout sélectionner

	#conversion ordonnee
	found=False
	index=0
	while index < len(seuilsY) and not(found):
		if y<seuilsY[index]:
			y=index;
			found=True
		else:
			index=index+1
	if not(found):
		y=len(seuilsY)
Ca marche, mais je trouve vraiment ça très moche...
Cordialement,

Vague Nerd

Avatar du membre
vague nerd
Modérateur
Messages : 1473
Enregistré le : mar. 14 oct. 2014 11:42
Localisation : France !

Re: Syntaxe

Message par vague nerd » ven. 10 juil. 2015 19:49

pourrait tu expliquer ce que tu veux faire exactement, car j'ai un peu de mal a comprendre.
Question 1 : je veux séparer des tableaux de paramétrage du code source. json est une solution, un import de fonctions qui retourne le tableux aussi à priori, mais je sais pas si c'est bien propre.
A priori, je ferai du json dans un second temps.
Question 2 : suis-je clair? Je crois que j'ai la réponse :lol: !
Question 3 : pour simplifier, je veux convertir une valeur allant de -210 à +210 par exemple, à une valeur allant de 0 à 6 par exemple, en rendant le tout paramétrable (les plages de valeurs, les seuil, et même le nombre de plages et seuils). Ci-dessus le bout de code concerné par la question 3... là ou il en est. Encore au dessus, le code source en dur.

Sinon, dans la pratique, la plage -210/210 sont des valeurs retournées par un nunchuk de wii, 0 à 6 des indices dans un tableau disant comment configurer les moteurs en réponse au nunchuk ! Et ces tableaux sont ceux de la question 1 !
Dsl d'avoir mélangé les questions dans un même thread, mais ça évite d'avoir à redonner le contexte.
ça doit être comme ça de mémoire
Merci, ça suffit pour demander a google !

Code : Tout sélectionner

vitesseGauche = [
	[100, 100, 20],
	[60, 60, 30],
	[0, 30, 30],
	[100, 0, 100],
	[0, 30, 30],
	[60, 60, 30],
	[100, 100, 20]
]
with open('data.txt', 'w') as outfile:
    json.dump(vitesseGauche, outfile)
donne :

Code : Tout sélectionner

[[100, 100, 20], [60, 60, 30], [0, 30, 30], [100, 0, 100], [0, 30, 30], [60, 60, 30], [100, 100, 20]]
Je cherche maintenant le contraire de dump !

Code : Tout sélectionner

with open('vitesseGauche.json', 'r') as infile:
    vitesseGauche=json.load(infile)
(J'ai l'axe des y inversé, mais comme maintenant, j'ai des bô tableaux de paramétrage...)
Cdt.
Cordialement,

Vague Nerd

Avatar du membre
Manfraid
Modérateur
Messages : 1402
Enregistré le : ven. 3 oct. 2014 14:50
Contact :

Re: Syntaxe

Message par Manfraid » ven. 10 juil. 2015 20:17

je te l'ai mis, c'est un json.load(fd)
NAS : DIY OS Debian: DD250Go + 3x2To + 6To
Raspberry pi : 2B OS : Raspbian
Se tromper est humain, Vraiment foutre la merde nécessite le mot de passe de root.

Avatar du membre
vague nerd
Modérateur
Messages : 1473
Enregistré le : mar. 14 oct. 2014 11:42
Localisation : France !

Re: Syntaxe

Message par vague nerd » ven. 10 juil. 2015 21:05

Oui, merci, mais il y a eu un copier/coller malheureux dans ton code (read/write, load et load...). C'est bon, ça marche.

Question 4 : j'ai ce code dans une boucle, avec oldConvertedValues déclarré à "" avant la boucle.

Code : Tout sélectionner

	convertedValues = 'x:%d y:%d' % (x, y)
	if convertedValues!=oldConvertedValues:
		print 'x:%d y:%d' % (x, y)
		oldConvertedValues=convertedValues
Il y a print systématique...[/strike]
Cordialement,

Vague Nerd

Avatar du membre
vague nerd
Modérateur
Messages : 1473
Enregistré le : mar. 14 oct. 2014 11:42
Localisation : France !

Re: Syntaxe

Message par vague nerd » ven. 10 juil. 2015 23:43

Pour des paramètres nommés, il semble qu'il faille utiliser des dictionnaires... EDIT : prettyprint !
Je regarde ce que ca donne passé en json...
Je suis arrivé à faire ce que je voulais. Tout est paramétrable.
Voici le code source.

Code : Tout sélectionner

import socket
import os
import json

#Chargement du fichier de propriete
with open('nunchukServer.properties', 'r') as infile:
    properties=json.load(infile)
print ''
print '****** Properties ******'
print json.dumps(properties, indent=4, sort_keys=True)
print '******'

#init des gpio : tous en sortie, sens moteur en avant, vitesse a 0
os.system('gpio -g mode %d out' % (properties['motor1PinPwm'],))
os.system('gpio -g mode %d out' % (properties['motor1Pin1'],))
os.system('gpio -g mode %d out' % (properties['motor1Pin2'],))
os.system('gpio -g mode %d out' % (properties['motor2PinPwm'],))
os.system('gpio -g mode %d out' % (properties['motor2Pin1'],))
os.system('gpio -g mode %d out' % (properties['motor2Pin1'],))

os.system('gpio -g write %d 0' % (properties['motor1PinPwm'],))
os.system('gpio -g write %d 0' % (properties['motor1Pin1'],))
os.system('gpio -g write %d 1' % (properties['motor1Pin2'],))

os.system('gpio -g write %d 0' % (properties['motor2PinPwm'],))
os.system('gpio -g write %d 0' % (properties['motor2Pin1'],))
os.system('gpio -g write %d 1' % (properties['motor2Pin2'],))

#chargement des fichiers de configuration vitesse/sens des moteurs
with open('vitesseGauche.json', 'r') as infile:
    vitesseGauche=json.load(infile)

with open('vitesseDroite.json', 'r') as infile:
    vitesseDroite=json.load(infile)

with open('sensGauche.json', 'r') as infile:
    sensGauche=json.load(infile)

with open('sensDroite.json', 'r') as infile:
    sensDroite=json.load(infile)

print ''
print '****** Directions and speeds ******'
print vitesseGauche
print "\n".join(["\t".join(map(str, r)) for r in vitesseGauche])
print vitesseDroite
print "\n".join(["\t".join(map(str, r)) for r in vitesseDroite])
print sensGauche
print "\n".join(["\t".join(map(str, r)) for r in sensGauche])
print sensDroite
print "\n".join(["\t".join(map(str, r)) for r in sensDroite])
print '******'

#chargement des fichiers de seuil pour conversion vers index dans fichiers de vitesse/sens des moteurs
with open('seuilsY.json', 'r') as infile:
    seuilsY=json.load(infile)

with open('seuilsX.json', 'r') as infile:
    seuilsX=json.load(infile)
print ''
print '****** Thresholds ******'
print seuilsX
print seuilsY
print '******'

#init servoblaster
print ''
print '****** Launching Servod... ******'
os.system('sudo killall servod')
os.system('sudo %sservod  --p1pins="%s" --min=0us --max=20000us' % (properties['ServodPath'], properties['servodp1pins']))
print '******'
	
#init socket
connexion_principale = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connexion_principale.bind(('', properties['Port']))
connexion_principale.listen(5)
connexion_avec_client, infos_connexion = connexion_principale.accept()
print ''
print '****** Connected client : ******'
print(infos_connexion)
print '******'
print ''

#Boucle en attente du client.
#Pas de temporisation : recv est bloquant
#Temporisation de 0.1s sur le client
msg_recu = b""
oldConvertedValues = ""
while msg_recu.decode() != "fin":
	msg_recu = connexion_avec_client.recv(1024)
	#print(msg_recu.decode())
	msg_recu = msg_recu.decode()
	vals = msg_recu.split(';')
	x=int(vals[0])
	y=int(vals[1])
	#supression de points aberants
	if y>230:
		y=0

	#conversion ordonnee nunchuk en index dans fichiers de vitesses/sens, selon fichier de seuil
	found=False
	index=0
	while index < len(seuilsY) and not(found):
		if y<seuilsY[index]:
			y=index;
			found=True
		else:
			index=index+1
	if not(found):
		y=len(seuilsY)
	
	#conversion abscisse
	found=False
	index=0
	while index < len(seuilsX) and not(found):
		if x<seuilsX[index]:
			x=index;
			found=True
		else:
			index=index+1
	if not(found):
		x=len(seuilsX)

	#impression de controle uniquement si x ou y a change
	convertedValues = 'x:%d y:%d' % (x, y)
	if convertedValues!=oldConvertedValues:
		print 'x:%d y:%d' % (x, y)
		oldConvertedValues=convertedValues
			
	#Application du sens de rotation
	if sensGauche[y][x]==0:
		os.system('gpio -g write %d 0' % (properties['motor1Pin1'],))
		os.system('gpio -g write %d 1' % (properties['motor1Pin2'],))
	else:
		os.system('gpio -g write %d 1' % (properties['motor1Pin1'],))
		os.system('gpio -g write %d 0' % (properties['motor1Pin2'],))
	
	if sensDroite[y][x]==0:
		os.system('gpio -g write %d 0' % (properties['motor2Pin1'],))
		os.system('gpio -g write %d 1' % (properties['motor2Pin2'],))
	else:
		os.system('gpio -g write %d 1' % (properties['motor2Pin1'],))
		os.system('gpio -g write %d 0' % (properties['motor2Pin2'],))
	
	#Application de la vitesse de rotation
	os.system('echo 0=%d%% > /dev/servoblaster' % (vitesseGauche[y][x], ))
	os.system('echo 1=%d%% > /dev/servoblaster' % (vitesseDroite[y][x], ))

	connexion_avec_client.send(b"done.")

print("Fermeture de la connexion")
connexion_avec_client.close()
connexion_principale.close()
Voici l'impression écran au lancement (ça évite de mettre tous les fichiers de conf) :

Code : Tout sélectionner

****** Properties ******
{
    "Port": 12800,
    "ServodPath": "/home/pi/PiBits/ServoBlaster/user/",
    "motor1Pin1": 17,
    "motor1Pin2": 18,
    "motor1PinPwm": 4,
    "motor2Pin1": 22,
    "motor2Pin2": 23,
    "motor2PinPwm": 27,
    "servodp1pins": "7,13"
}
******

****** Directions and speeds ******
[[100, 100, 20], [60, 60, 30], [0, 30, 30], [100, 0, 100], [0, 30, 30], [60, 60, 30], [100, 100, 20]]
100     100     20
60      60      30
0       30      30
100     0       100
0       30      30
60      60      30
100     100     20
[[20, 100, 100], [30, 60, 60], [30, 30, 0], [100, 0, 100], [30, 30, 0], [30, 60, 60], [20, 100, 100]]
[[1, 1, 1], [1, 1, 1], [1, 1, 1], [0, 0, 1], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
******

****** Thresholds ******
[80, 140]
[60, 80, 100, 140, 160, 180]
******

****** Launching Servod... ******

Board revision:                  2
Using hardware:                PWM
Using DMA channel:              14
Idle timeout:             Disabled
Number of servos:                2
Servo cycle time:            20000us
Pulse increment step size:      10us
Minimum width value:             0 (0us)
Maximum width value:          2000 (20000us)
Output levels:              Normal

Using P1 pins:               7,13
Using P5 pins:

Servo mapping:
     0 on P1-7           GPIO-4
     1 on P1-13          GPIO-27

******

****** Connected client : ******
('192.168.0.15', 35475)
******

x:1 y:3
Je trouve cette partie de code un peu moche :

Code : Tout sélectionner

	while index < len(seuilsY) and not(found):
		if y<seuilsY[index]:
			y=index;
			found=True
		else:
			index=index+1
	if not(found):
		y=len(seuilsY)
Une recherche par dichotomie, ça aurait été mieux...
Q6 : Il y a quelque chose pour faire ça ?
EDIT : voici un bout de code à modifier, pour que dans le second exemple d'appel, la fonction retourne 1 au lieu de None :

Code : Tout sélectionner

def recherche_dans_tableau_trie(x,t):
    if len(t) == 0: return(None)
    a = 0
    b = len(t)-1
    while a <= b:
        c = int((a+b)/2)
        if x == t[c]: return(c)
        elif x < t[c]: b = c - 1
        else: a = c + 1
    return None

print recherche_dans_tableau_trie(2,[0,1,2,3,4])
print recherche_dans_tableau_trie(2,[0,1,3,4])
print recherche_dans_tableau_trie(2,[])
Q7 : j'imprime les valeurs converties dès qu'elles changent à l'aide de ce bout de code :

Code : Tout sélectionner

	#impression de controle uniquement si x ou y a change
	convertedValues = 'x:%d y:%d' % (x, y)
	if convertedValues!=oldConvertedValues:
		print 'x:%d y:%d' % (x, y)
		oldConvertedValues=convertedValues
Plutôt que d'imprimer ça de ligne en ligne, je voudrai remplacer la dernière ligne de console. C'est possible ?
EDIT : il suffit de ne faire qu'un chr(13) et pas de chr(10). Plutôt qu'un loing discourt, démo :

Code : Tout sélectionner

import sys, time

for i in range(1, 6):
    sys.stdout.write (str(i) + chr(13))
    sys.stdout.flush()
    time.sleep (1)
Cordialement,

Vague Nerd

Répondre

Retourner vers « Python »