Projet d ISN : Stationnement Automatique Bonjour, je m appelle Benoit GILLES. Élève de terminale S, j ai choisi la spécialité ISN. Cependant, j étais le seul de mon groupe pour le projet de SI à avoir choisi cette spécialité. Je ne me voyais donc pas continuer le projet de SI seul. De plus, le groupe dans lequel je suis actuellement était constitué de 2 élèves, Angelo et Anthony. J ai donc choisi de participer et de les aider dans leur projet, le stationnement automatique. De nos jours il est de plus en plus difficile de se garer en particulier dans les grandes villes. C'est pour cela que les développeurs sont de plus en plus sollicités afin d'y trouver des solutions. Comment faciliter le parkage d'une voiture? Pour cela, il est possible de réduire la taille de la voiture, cependant, lors de ce projet (de si), nous allons procéder au parkage de la voiture par une translation de celle-ci, afin de supprimer les créneaux et de réduire l'emplacement nécessaire à cela. Une communication entre la voiture et l'utilisateur devra donc être effectuée via une interface avec l'utilisateur que nous allons traiter lors de ce projet. Tout d abord, nous avons élaborés une sorte de cahier des charges, avec comme fonction principale l envoi des ordres de l utilisateur à la carte arduino. Elle devra donc transmettre les informations du clavier à la carte arduino et informer l utilisateur de l état de la voiture (position des roues, vitesse actuelle, etc). Comme interface, nous avons utilisé processing, dont le langage se rapproche de celui d arduino. 1
Nous nous sommes servis de cet organigramme pour nous répartir les taches : Au début, nous nous sommes répartis 3 grandes taches : Création visuelle de l interface Anthony Réception des informations du clavier Moi-même Transmission d information entre arduino et processing Angelo Puis, nous nous sommes rassemblés et nous nous sommes aidés mutuellement. Chacun faisait quelques améliorations de code, ou d interface. Voici le diagramme prévisionnel des taches : 2
Voici le code final : import processing.serial.*; Serial mon_port; int y=0; boolean avancer=false; boolean reculer=false; boolean gauche=false; boolean droite=false;
boolean reset=false; 3 boolean arret=false; boolean translater=false; boolean parking=false; boolean plus=false; boolean moins=false; boolean obstacle=false; boolean translater2=false; actif //variable servant à indiquer si le mode translation est int v=125; double vitesse=0; double distance=0; double vitesse_max=0; int[] recep= new int[11]; String reception=""; int reception_precedente; PFont police; PImage voiture; PImage img_gauche; PImage img_droite; PImage img_haut; PImage img_bas; PImage img_gauche2; PImage img_droite2; PImage img_haut2; PImage img_bas2;
PImage img_plus; 4 PImage img_moins; PImage p; PImage r; PImage a; PImage t; PImage img_plus2; PImage img_moins2; PImage p2; PImage r2; PImage a2; PImage t2; PImage fleche_bas; PImage fleche_haut; Roue Roue1=new Roue(125,167.5); modèle de la roue (voir fct "class Roue") //création des quatres roues sous le Roue Roue2=new Roue(125,380); Roue Roue3=new Roue(315,167.5); Roue Roue4=new Roue(315,380); class Roue { //modèle des roues float x; float y; Roue (float newx,float newy) { //récuperation des paramètres de l'appelation de la fonction (<=> création des quatres roues(voir début de code))
x = newx; //cela correspondra aux coordonnées du centre de la roue 5 y = newy; void affichage(float angle) { //sous fonction permetant d'afficher la roue n... d'après les coordonnées de son centre et avec une rotation anti-horaire de "angle"rad translate(x,y); rotate(angle); (sens anti-horaire) //translate le repère vers le centre de la roue //fait pivoter le repère suivant la valeur de la variable: "angle" if(!avancer &&!reculer)fill(0); if(avancer)fill(100,150,0); if(reculer)fill(230,0,0); rect(-10,-30,20,60); //trace un rectangle de centre A(x;y), de hauteur 60px, de largeur 20px et remplis (noire (<=> fill(0)) rotate(-angle); translate(-x,-y); //replace le repère à son inclinaison de départ //et à sa position d'origine void initialisation(){ img_gauche=loadimage("gauche.png"); type image correspondant //associe les images a l'objet de de img_droite=loadimage("droite.png"); img_haut=loadimage("haut.png"); img_bas=loadimage("bas.png"); img_gauche2=loadimage("gauche(2).png"); img_droite2=loadimage("droite(2).png");
img_haut2=loadimage("haut(2).png"); img_bas2=loadimage("bas(2).png"); 6 img_plus=loadimage("+.png"); img_moins=loadimage("-.png"); p=loadimage("p.png"); r=loadimage("r.png"); a=loadimage("a.png"); t=loadimage("t.png"); img_plus2=loadimage("+2.png"); img_moins2=loadimage("-2.png"); p2=loadimage("p2.png"); r2=loadimage("r2.png"); a2=loadimage("a2.png"); t2=loadimage("t2.png"); fleche_haut=loadimage("flèche_haut.png"); fleche_bas=loadimage("flèche_bas.png"); voiture=loadimage("voiture.png"); fill(220); //affiche les différents cardes des parties rect(650,0,1000,600); fill(255); rect(850,525,150,75); fill(0); police = loadfont("serif.italic-48.vlw"); dossier "data") //charge la police (se situant dans le
textfont(police,38); 7 //applique la police //affichage de tous le texte de l'interface: text("schéma voiture:",250,30); line(250,35,490,35); text("commandes:", 725,30); line(725,35,910,35); textfont(police,25); text("-mode Manuel:",652,100); text("-mode Parking:",652,480); textfont(police,19); text("avancer",840,140); text("reculer",840,250); text("droite",875,195); text("gauche",660,195); text("activer/désactiver translation:",660,285); text("augmenter la vitesse max:",660,380); text("diminuer la vitesse max:",660,425); textfont(police,15); text("vitesse actuelle=",5,520); text(":arrêt d'urgence",890,550); text(":reset",890,585); //affichage des touches: touche) (car ne s'affichent par la suite que lors d'un appui de image(img_gauche,725,170); image(img_droite,800,170); image(img_haut,762,128);
image(img_bas,762,214); 8 image(img_plus,875,310); image(img_moins,875,395); image(t,775,290); image(p,725,510); image(a,860,529); image(r,860,565); void actualisation_interface(){ affichage_touches(); affichage_voiture(); affichage_jauge(); affichage_info(); affichage_fleche(); void affichage_voiture(){ nostroke(); fill(255); rect(75,75,310,420); stroke(0); image(voiture,100,75); //affiche l'image de la variable voiture Roue1.affichage(radians(recep[4])); Roue2.affichage(radians(recep[7]));
9 Roue3.affichage(radians(recep[6])); Roue4.affichage(radians(recep[5])); void affichage_jauge(){ fill(255); rect(925,250,50,250); if(plus) v+=4; if(moins) v-=4; if(v>250) v=250; if(v<3) v=3; fill(120,150,0); rect(925,500, 50, -v); void affichage_fleche(){ fill(255); nostroke(); rect(450,263,100,74); stroke(153); translate(500,300); rotate(radians(recep[4])); if(avancer)image(fleche_haut,-25,-37); if(reculer)image(fleche_bas,-25,-37); translate(-500,-300); rotate(radians(-recep[4]));
10 void affichage_info(){ String affichage=""; fill(220); rect(0,500,175,400); textfont(police,15); fill(0); vitesse=(recep[0]-1500)*0.251/1100; en vitesse (type double) String vitesse2= Double.toString(vitesse); //converssion de la valeur d'impulssion //converssion en string if(vitesse2.length()>3)affichage= str(vitesse2.charat(0))+str(vitesse2.charat(1)) +str(vitesse2.charat(2))+str(vitesse2.charat(3))+str(vitesse2.charat(4)); //récupération des 5 premiers caractères else affichage="0"; text("vitesse actuelle= text(affichage,110,520); m/s",5,520); //affichage vitesse distance=recep[9]/1000; //idem String distance2= Double.toString(distance); if(distance2.length()>3)affichage= str(distance2.charat(0))+str(distance2.charat(1)) +str(distance2.charat(2))+str(distance2.charat(3)); else affichage="0"; text("distance parcourue=",5,540); text(affichage,140,540);
11 vitesse_max=v*0.251/500; String vitesse_max2=double.tostring(vitesse_max); if(distance2.length()>3)affichage= str(vitesse_max2.charat(0)) +str(vitesse_max2.charat(1))+str(vitesse_max2.charat(2)) +str(vitesse_max2.charat(3)); else affichage="0"; text("vitesse max= m/s",5,560); text(affichage,95,560); if(recep[10]!=0){ stroke(5,5,250); fill(150); rect(600,150,370,300); fill(0); textfont(police,38); text("mode Parking activé:",625,185); textfont(police,15); switch(recep[10]){ case 1: text("lancement du mode parking...",625,210); text("recharche de la place...",625,230); break; case 2: text("place détéctée!",625,250); text("parkage en cours...",625,270); break; case 3: text("voiture garée!",625,290);
12 break; case 4: text("problème lors du parkage rencontré...",625,290); break; case 5: text("pas de place trouvée...",625,290); break; case 6: text("fin du mode parking...",625,310); text("reprise du mode manuel dans 5 secondes...",625,330); break; void affichage_touches(){ if(!gauche)image(img_gauche,725,170); if(!droite)image(img_droite,800,170); if(!avancer)image(img_haut,762,128); if(!reculer)image(img_bas,762,214); if(gauche)image(img_gauche2,725,170); if(droite)image(img_droite2,800,170); if(avancer)image(img_haut2,762,128); if(reculer)image(img_bas2,762,214); if(!plus)image(img_plus,875,310); if(!moins)image(img_moins,875,395); if(!translater2)image(t,775,290); if(!parking)image(p,725,510); if(!arret)image(a,860,529);
if(!reset)image(r,860,565); 13 if(plus)image(img_plus2,875,310); if(moins)image(img_moins2,875,395); if(translater2)image(t2,775,290); if(parking)image(p2,725,510); if(arret)image(a2,860,529); if(reset)image(r2,860,565); void reception_info(string test, int emplacement){ int n=reception.length(); int n2=0; String reception2 =""; int k=1; for(int x=0; x!=n ;x++){ // str() <==> convertir en string if(str(reception.charat(x)).equals(test)){ // var_string.charat(rang) <==> caractère de la chaîne se trouvant à la n ième place (de type char) while( ((x+k)!=n) &&!( (str(reception.charat(x+k)).equals("a")) str(reception.charat(x+k)).equals("b") str(reception.charat(x+k)).equals("c") str(reception.charat(x+k)).equals("d") str(reception.charat(x+k)).equals("e") str(reception.charat(x+k)).equals("f") str(reception.charat(x+k)).equals("g") str(reception.charat(x+k)).equals("h") str(reception.charat(x+k)).equals("j") str(reception.charat(x+k)).equals("k")) ){ == "..." k++; //var_string.equals("...") <==> var_string reception2=""; for(int a=x+1;a!=x+k;a++){ reception2+=str(reception.charat(a));
14 k=0; envoyée, il faut maintenant la convertir //reception2 comporte la valeur recep[emplacement]=0; n2=reception2.length(); while(k!=n2){ //reception_precedente=recep[emplacement]; recep[emplacement] +=(reception2.charat(k)-48)*pow(10,n2-k-1); //if(recep[emplacement]<300) recep[emplacement]=reception_precedente; //afin de résoudre le problème de reception k=1; k++; void reception(){ while(mon_port.available()!=0){ delay(100); reception+=mon_port.readstring(); mon_port.clear(); reception_info("a",0); reception_info("b",1); reception_info("c",2); reception_info("d",3); reception_info("e",4);
reception_info("f",5); 15 reception_info("g",6); reception_info("h",7); reception_info("j",9); reception_info("k",10); fill(0); reception=""; void keypressed() { if (key == CODED){ if (keycode == LEFT) { gauche=true; mon_port.write(3); if (keycode == RIGHT) { droite=true; mon_port.write(4); if (keycode == UP) { avancer=true; mon_port.write(5); if (keycode == DOWN) { reculer=true; mon_port.write(6); if (key == 'p') {parking=true;mon_port.write(7); if (key == 'a') {arret=true; mon_port.write(8); if (key == 't') {translater=true; translater2=!translater2; mon_port.write(9); delay(4000); if (key == 'r') {reset=true; mon_port.write(10); if (key == '+') {plus=true;mon_port.write(v/10+20); if (key == '-') {moins=true;mon_port.write((v+200)/10); void keyreleased() { if (key == CODED){
if (keycode == UP) { avancer=false; mon_port.write(11); 16 if (keycode == DOWN) { reculer=false; mon_port.write(12); if (keycode == LEFT) { gauche=false; mon_port.write(13); if (keycode == RIGHT) { droite=false; mon_port.write(14); if (key == 'a') {arret=false; mon_port.write(16); if (key == 'r') {reset=false; mon_port.write(18); if (key == 't') mon_port.write(17); if (key == '+') {plus=false;/*mon_port.write(v*44);*/ if (key == '-') {moins=false;/*mon_port.write(v*44);*/ void setup(){ smooth(); size(1000,600); background(255); //lissage des dessins //création de la fenêtre //couleur de fond blanche framerate(50); println("liste des ports: \n" + Serial.list()); String nom_du_port = Serial.list()[1]; mon_port=new Serial(this, nom_du_port, 9600); initialisation(); void draw() { reception(); actualisation_interface();
17 // void keypressed() { if (key == CODED){ if (keycode == LEFT) { gauche=true; mon_port.write(3); if (keycode == RIGHT) { droite=true; mon_port.write(4); if (keycode == UP) { avancer=true; mon_port.write(5); if (keycode == DOWN) { reculer=true; mon_port.write(6); if (key == 'p') {parking=true;mon_port.write(7); if (key == 'a') {arret=true; mon_port.write(8); if (key == 't') {translater=true; translater2=!translater2; mon_port.write(9); delay(4000); if (key == 'r') {reset=true; mon_port.write(10); if (key == '+') {plus=true;mon_port.write(v/10+20); if (key == '-') {moins=true;mon_port.write((v+200)/10); void keyreleased() { if (key == CODED){ if (keycode == UP) { avancer=false; mon_port.write(11); if (keycode == DOWN) { reculer=false; mon_port.write(12); if (keycode == LEFT) { gauche=false; mon_port.write(13); if (keycode == RIGHT) { droite=false; mon_port.write(14);
18 if (key == 'a') {arret=false; mon_port.write(16); if (key == 'r') {reset=false; mon_port.write(18); if (key == 't') mon_port.write(17); if (key == '+') {plus=false;/*mon_port.write(v*44);*/ if (key == '-') {moins=false;/*mon_port.write(v*44);*/ // Au départ, je me suis lancé dans ce programme, la réception des touches du clavier, comme il était dit dans la répartition des tâches. Avec l aide d Angelo nous avons abouti sur ce programme. Ce programme détermine si on appuie sur une touche du clavier et si c est le cas, il envoie une valeur numérique qui sera convertie en une chaine de caractères sur un port série de l ordinateur. La carte arduino va, par la suite, lire l information sur ce port série. Ce programme s exécute en priorité par rapport au code principal. Peu importe où en est le programme principal, si une touche est enfoncée, cette partie du programme s exécutera. Le programme fini, je me suis penché sur la partie dynamique de l interface, affichage de la voiture en temps réel, de la jauge de vitesse : on a créé un rectangle dans lequel la jauge de vitesse est affichée. Si la touche + est enfoncée, le rectangle se remplit grâce à une incrémentation de la variable v. On a fixé une limite à 250, ce chiffre suffisait largement. Pour décélérer, c est le processus inverse : lorsque la touche est enfoncée, la jauge se vide par l intermédiaire d une décrémentation de la variable v. Celle-ci ne peut pas aller en dessous de 3 pour éviter que la voiture s arrête. J ai contribué à cette partie du programme en ajoutant la fenêtre située à droite de l écran. Après, nous avons retouchés quelques petits défauts tous ensemble et mis nos idées en commun pour concrétiser l interface. Voici une capture d écran de l interface processing :
19 En conclusion, ce projet m a permis tout d abord de travailler sur quelque chose de nouveau. Ce qui implique donc un enrichissement de connaissances, que ce soit sur la programmation avec processing ou tout simplement sur le parkage automatique, ceci en plus du travail de groupe. Le projet était assez intéressant, malgré quelques relâches de temps en temps. J ai apprécié le travail qu on a fait ensemble, cela s est passé dans de bonnes conditions. De plus le projet était sympathique. Donc si c était à recommencer, je le ferait sans hésiter.
20