9. ANNEXES▲
9-1. Arduino RGB▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
/* Broches */
const
int
LED_R =
8
;
const
int
LED_G =
9
;
const
int
LED_B =
10
;
void
setup() {
// Initialise les broches
pinMode
(LED_R, OUTPUT
);
pinMode
(LED_G, OUTPUT
);
pinMode
(LED_B, OUTPUT
);
}
void
loop() {
// 1 seconde par couleur
digitalWrite
(LED_R, HIGH
);
delay
(1000
);
digitalWrite
(LED_R, LOW
);
digitalWrite
(LED_G, HIGH
);
delay
(1000
);
digitalWrite
(LED_G, LOW
);
digitalWrite
(LED_B, HIGH
);
delay
(1000
);
digitalWrite
(LED_B, LOW
);
}
9-2. Arduino JCMB▲
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.
/* Broches */
const
int
LED_R =
8
;
const
int
LED_G =
9
;
const
int
LED_B =
10
;
void
setup() {
// Initialise les broches
pinMode
(LED_R, OUTPUT
);
pinMode
(LED_G, OUTPUT
);
pinMode
(LED_B, OUTPUT
);
}
void
loop() {
digitalWrite
(LED_R, HIGH
);
digitalWrite
(LED_G, HIGH
);
delay
(1000
);
digitalWrite
(LED_R, LOW
);
digitalWrite
(LED_B, HIGH
);
delay
(1000
);
digitalWrite
(LED_G, LOW
);
digitalWrite
(LED_R, HIGH
);
delay
(1000
);
digitalWrite
(LED_G, HIGH
);
delay
(1000
);
digitalWrite
(LED_R, LOW
);
digitalWrite
(LED_G, LOW
);
digitalWrite
(LED_B, LOW
);
}
9-3. Arduino intensité d'un canal▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
/* Broches */
const
int
LED_R =
8
;
const
int
LED_G =
9
;
const
int
LED_B =
10
;
void
setup() {
// Initialise les broches
pinMode
(LED_R, OUTPUT
);
pinMode
(LED_G, OUTPUT
);
pinMode
(LED_B, OUTPUT
);
}
void
loop() {
analogWrite
(LED_G, 0
);
delay
(1000
);
analogWrite
(LED_G, 75
);
delay
(1000
);
analogWrite
(LED_G, 125
);
delay
(1000
);
analogWrite
(LED_G, 250
);
delay
(1000
);
}
9-4. La photorésistance▲
Le code Arduino
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
const
int
broche =
A0;
void
setup() {
Serial
.begin(19200
);
}
void
loop() {
int
valeur =
analogRead
(broche);
Serial
.print(valeur);
Serial
.print("
\t
"
);
Serial
.println(millis
());
}
On ne conserve que les valeurs exploitables. On rappelle qu'il est possible de n'utiliser qu'une partie des valeurs d'une liste, soit L une liste, alors on écrit : L[debut, fin]. Dans notre exemple, on peut essayer de démarrer à partir de la valeur d'index 50 en gardant toutes les valeurs suivantes, ce qui donne : temps[50
:]. À vous d'ajuster en fonction de ce que vous obtenez.
2.
3.
4.
5.
6.
7.
8.
# attention les deux listes doivent contenir le même nombre de valeurs.
plt.plot
(
temps[50
:], mesure[50
:])
plt.title
(
"Fréquence d'un stroboscope"
)
plt.ylabel
(
'Intensité'
)
plt.xlabel
(
'Temps (ms)'
)
plt.grid
(
)
plt.show
(
)
9-4-1. Le bouton poussoir▲
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.
// État en cours de l'automate
int
etat;
// État à mémoriser
int
oldEtat;
//Les états possibles de l'automate
const
int
WAIT =
2
;
const
int
START =
1
;
const
int
STOP =
0
;
// Les broches utilisées
//capteur
const
int
broche =
A0;
//bouton-poussoir
const
int
BP =
3
;
void
setup() {
//initialisation des variables
oldEtat =
LOW
;
etat =
WAIT;
//config E/S
pinMode
(BP, INPUT
);
//liaison série
Serial
.begin(19200
);
}
void
loop() {
//Lecture du bouton
int
etatBP =
digi talRead (BP);
//gestion des états
if
(oldEtat ==
LOW
&&
etatBP ==
HIGH
) {
if
(etat ==
WAIT)
{
etat =
START;
}
else
if
(etat ==
STOP)
{
etat =
START;
}
else
if
(etat ==
START)
{
etat =
STOP;
}
}
//Traitement des états
if
(etat ==
START) {
int
valeur =
analogRead
(broche);
Serial
.print(valeur);
Serial
.print("
\t
"
);
Serial
.println(millis
());
}
else
if
(etat ==
STOP)
Serial
.println("-1
\t
-1"
);
oldEtat =
etatBP;
delay
(10
);
}
9-5. Le projet : vitesse du son▲
9-5-1. Le code Arduino▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
// Déclaration des variables globales : broches
int
trigg =
8
;
int
echo =
9
;
void
setup() {
pinMode
(trigg, OUTPUT
); // Configuration des broches
digitalWrite
(trigg, LOW
); // La broche TRIGGER doit être à LOW au repos
pinMode
(echo, INPUT
); // La broche ECHO en entrée
Serial
.begin(9600
); // Démarrage de la liaison série
}
void
loop() {
digitalWrite
(trigg, HIGH
); // Lance une mesure de distance en envoyant
delayMicroseconds
(10
); // Une impulsion HIGH de 10 microsecondes
digitalWrite
(trigg, LOW
); // Fin d'émission
int
temps =
pulseIn
(echo, HIGH
); // Mesure temps émission-réception
Serial
.print(temps);
Serial
.print("
\t
"
); // on ajoute une tabulation et la
Serial
.println("-1"
); // la valeur -1
delay
(500
);
}
Dans cet exemple, seule la valeur temps nous intéresse. Mais pour uniformiser le code, nous ajoutons une tabulation et la valeur −1. Cela permet de réutiliser les codes Python précédents. En effet, côté Python on attend toujours deux informations (deux grandeurs physiques). C'est un choix de programmation que nous avons fait dès le départ, mais qui est cohérent avec les besoins que nous avons en physique-chimie qui se traduit souvent par l'étude d'une grandeur en fonction du temps. Il suffira d'ignorer la lecture de la valeur −1 côté Python. En informatique, il est courant d'utiliser la valeur −1 pour indiquer soit une erreur soit une valeur à ignorer.
9-5-2. Le code Python▲
Penser à écrire une fonction pour calculer le temps moyen sur un nombre entier n de valeurs renvoyées par le capteur ultrason.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
def
temps_moyen
(
n, serial_port) :
"""
Cette fonction calcule une moyenne des temps ultrasons
reçus sur n valeurs
n -> <int> : nombre de valeurs à lire
serial_port -> <serial> : port série
"""
i =
0
t_somme =
0
serial_port.flushInput
(
)
while
i <
n:
val =
serial_port.readline
(
).split
(
)
try
:
t =
float(
val[0
]) # lecture temps ultrason
t_somme +=
t # la somme des temps ultrasons
i =
i +
1
# ajoute 1 à la variable comptant les mesures
except
:
pass
return
t_somme/
n
2.
3.
# les imports
import
serial
import
matplotlib.pyplot as
pl t
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
# ouverture du port série et synchronisation des données entre Arduino et Python.
serial_port =
serial.Serial
(
port =
"/dev/ttyACM0"
, baudrate =
9600
)
temps =
[] # une liste pour les mesures de temps
distances =
[] # une liste pour les mesures de distance
dist =
0
# juste pour entrer dans la boucle
nb_t =
10
# le nombre de mesures temps
while
dist !=
−1
:
dist =
float(
input(
"Entrez votre mesure : "
))
if
dist !=
−1
:
distances.append
(
dist)
tm =
temps_moyen
(
nb_t, serial_port)
temps.append
(
tm)
# fermeture du port série
serial_port.close
(
)
9-5-3. Comment faire les mesures ?▲
- Téléverser le programme Arduino dans la mémoire de la carte.
- Ouvrir un moniteur série et vérifier que les mesures de temps s'affichent. Faire varier la distance entre l'objet et le capteur HC-SR04 pour observer que les valeurs temps augmentent si la distance augmente.
- Valider les cellules contenant le code Python concernant cet exercice.
- Placer correctement votre capteur HC-SR04 à une distance déterminée de votre objet.
-
Normalement, vous devez avoir la possibilité de saisir cette distance dans une boite de dialogue qui s'est ouverte sur le Notebook.
- Valider avec la touche Enter, modifier la distance capteur-objet, entrer la valeur, etc.
L'affichage du graphique : distances en fonction du temps, je vous laisse ajouter les commentaires : title, xlabel, ylabel
2.
3.
4.
plt.figure
(
figsize =(
12
, 6
))
plt.plot (
mesures, distances, 'ro'
)
plt.grid
(
)
plt.show
(
)
9-6. La chute libre▲
9-6-1. Le code Arduino▲
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.
// Déclaration des variables globales : broches
int
trigg =
8
;
int
echo =
9
;
void
setup() {
pinMode
(trigg, OUTPUT
); // Configuration des broches
digitalWrite
(trigg, LOW
); // La broche TRIGGER doit être à LOW au repos
pinMode
(echo, INPUT
); // La broche ECHO en entrée
Serial
.begin(19200
); // Démarrage de la liaison série
}
void
loop() {
digitalWrite
(trigg, HIGH
); // Lance une mesure de distance en envoyant
delayMicroseconds
(10
); // Une impulsion HIGH de 10 microsecondes
digitalWrite
(trigg, LOW
); // Fin d'émission
int
temps_echo =
pulseIn
(echo, HIGH
); // Mesure temps émission-réception
Serial
.print(temps_echo);
Serial
.print("
\t
"
);
Serial
.println(millis
());
delay
(1
);
}
9-6-2. Le code Python▲
Les mesures ont été faites avec un paquet de mouchoirs en papier accroché à une ficelle d'environ 80 cm. J'ai lancé le code Python puis j'ai compté jusqu'à deux avant de lâcher le paquet bien à la verticale du capteur ultrason.
2.
3.
4.
# les imports
import
serial
import
time
import
matplotlib.pyplot as
plt
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.
# ouverture du port série
serial_port =
serial.Serial
(
port =
"/dev/ttyACM1"
, baudrate =
19200
)
serial_port.setDTR
(
False
)
time.sleep
(
0.1
)
serial_port.setDTR
(
True
)
serial_port.flushInput
(
)
# les mesures
mesure_dist =
[]
temps =
[]
duree =
3000
# durée d'acquisition
end =
False
while
end ==
False
or
temps[−1
] − temps[0
] <=
duree :
val =
serial_port.readline
(
).split
(
) # lecture des données
try
:
d =
float(
val[0
]) /
58
# distance en cm
t =
float(
val[1
]) # temps écoulé en ms
if
d >
1
and
d <
100
: # filtrage des valeurs aberrantes
mesure_dist.append
(
d) # entre 1 cm et 1 m
temps.append
(
t)
end =
True
except
:
pass
# fermeture du port série
serial_port.close
(
)
2.
3.
4.
5.
6.
plt.plot
(
temps, mesure_dist, "."
)
plt.title
(
"CHUTE LIBRE D'UN PAQUET DE MOUCHOIRS"
)
plt.ylabel
(
'Distance (cm)'
)
plt.xlabel
(
'Temps (ms)'
)
plt.grid
(
)
plt.show
(
)
2.
3.
4.
5.
6.
plt.plot
(
temps[100
:200
], mesure_dist[100
:200
], "."
)
plt.title
(
"CHUTE LIBRE D'UN PAQUET DE MOUCHOIRS"
)
plt.ylabel
(
'Distance (cm)'
)
plt.xlabel
(
'Temps (ms)'
)
plt.grid
(
)
plt.show
(
)
9-7. Le saut à l'élastique▲
Avec un capteur ultrason, il également possible d'étudier les différentes phases d'un saut à l'élastique.
Les codes Arduino et Python pour obtenir ces résultats sont exactement les mêmes que pour la chute libre. Il peut donc être intéressant de créer une fonction Python que les élèves pourraient utiliser à partir d'un module.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
# ouverture du port série
serial_port =
serial.Serial
(
port =
"/dev/ttyACM0"
, baudrate =
19200
)
serial_port.setDTR
(
False
)
time.sleep
(
0.1
)
serial_port.setDTR
(
True
)
serial_port.flushInput
(
)
temps, mesure_dist =
distance_ultrason
(
5000
, serial_port)
# fermeture du port série
serial_port.close
(
)
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.
def
distance_ultrason
(
duree, serial_port, inf =
1
, sup =
100
):
"""
Renvoie respectivement une liste temps (dates d'acquisition)
et une liste distance en (cm) mesurée par le capteur ultrason
durant une durée donnée et dans un intervalle de distance
fixée par défaut entre 1 cm et 1 m
duree -> <float> : durée de l'acquisition en (ms)
serial_port -> <serial> : port série ouvert à la communication
inf -> <float> : distance minimum d'acquisition en (cm)
sup -> <float> : distance maximum d'acquisition en (cm)
"""
mesure =
[]
temps =
[]
end =
False
while
end ==
False
or
temps[−1
] − temps [0
] <=
duree:
val =
serial_port.readline
(
).split
(
) # lecture des données
try
:
d =
float(
val[1
]) /
58
# distance en cm
t =
float(
val[0
]) # temps écoulé en ms
if
d >
inf and
d <
sup: # filtrage des valeurs aberrantes
mesure.append
(
d)
temps.append
(
t)
end =
True
except
:
pass
return
temps, mesure
10. Note de la rédaction▲
Ce document ressource (licence CC BY-NC-SA) a été donné en formation académique (Académie de Bordeaux) afin de découvrir la physique-chimie « computationnelle », Python et Arduino pour une utilisation au lycée.
Nous remercions les membres de Developpez pour le travail de mise en forme et de relecture du document, en particulier : Winjerome, f-leb et escartefigue.