Projet IMA3 P7, 2015/2016, TD2 : Différence entre versions
(→Montage expérimental) |
m (a déplacé Projet IMA3 P7, 2014/2015, TD2 vers Projet IMA3 P7, 2015/2016, TD2) |
||
(16 révisions intermédiaires par 2 utilisateurs non affichées) | |||
Ligne 6 : | Ligne 6 : | ||
Portique d'un magasin où la détection de présence à la porte informe le caissier l'arrivée d'un nouveau client pour décider de lui ouvrir la porte ou pas. | Portique d'un magasin où la détection de présence à la porte informe le caissier l'arrivée d'un nouveau client pour décider de lui ouvrir la porte ou pas. | ||
− | On se servira alors d'un | + | On se servira alors d'un sonar pour détecter l'arrivée du client ,afficher sur l'ordinateur du caissier le message suivant " Client à la porte" ensuite attendre la réponse du caissier pour pouvoir tourner le servomoteur qui servira à ouvrir la porte . |
== Matériel == | == Matériel == | ||
*Un servomoteur; | *Un servomoteur; | ||
− | * | + | *2 sonars |
*NanoBoard | *NanoBoard | ||
*Une carte Rasberry Pi | *Une carte Rasberry Pi | ||
Ligne 74 : | Ligne 74 : | ||
Notre PWM ainsi implémenté sur Altium, on refait le même protocole qu'au tutoriel fait à la séance n° 1 pour compiler notre montage et l'envoyer sur la nanobaord. | Notre PWM ainsi implémenté sur Altium, on refait le même protocole qu'au tutoriel fait à la séance n° 1 pour compiler notre montage et l'envoyer sur la nanobaord. | ||
+ | |||
+ | A travers nos expérimentations, on trouve que pour avoir 1.5ms d'état haut( position 0 donc), il faut envoyer le mot 0b00001111 | ||
+ | |||
+ | Pour 90°: 0b00100000 | ||
+ | |||
On branche la sortie sur un oscilloscope et on obtient le graphe ci-dessous, relatif à un PWM | On branche la sortie sur un oscilloscope et on obtient le graphe ci-dessous, relatif à un PWM | ||
− | [[Fichier: | + | [[Fichier:Oscillo1.PNG]] |
On réalise alors le montage ci-dessous à l'aide d'un servomoteur, d'une plaque d'essai, d'un générateur et notre nanoboard. | On réalise alors le montage ci-dessous à l'aide d'un servomoteur, d'une plaque d'essai, d'un générateur et notre nanoboard. | ||
Ligne 87 : | Ligne 92 : | ||
[[Fichier:Frequence.PNG]] | [[Fichier:Frequence.PNG]] | ||
− | |||
− | |||
=== Partie informatique === | === Partie informatique === | ||
Ligne 99 : | Ligne 102 : | ||
=== Partie électronique === | === Partie électronique === | ||
+ | Lors de cette troisième séance, on s'est intéressé à la partie détection de notre système. Pour cela, nous avons essayer d'intégrer le sonar. | ||
+ | Le fonctionnement de celui- ci est le suivant: | ||
+ | Il faut envoyer une impulsion niveau haut (à + 5v) pendant au moins 10 µs sur la broche ‘Trig Input’; cela déclenche la mesure. En retour la sortie ‘Output’ ou ‘Echo’, va fournir une impulsion + 5v dont la durée est proportionnelle à la distance si le module détecte un objet. | ||
+ | Voici une représentation graphique de la séquence de fonctionnement du module : | ||
+ | |||
+ | [[Fichier:Sonar.PNG]] | ||
+ | |||
+ | Etant donné que nous voulons seulement détecter la présence d'une personne, la distance nous importe peu. Ainsi j'ai décidé d'utiliser deux sonars : un n'ayant pas d'obstacle, qu'on nommera sonar étalon et un deuxième positionné sur la porte. Ces deux sonars seront piloté grâce à un montage PWM similaire à celui créé lors de la première séance.On comparera les Echo des deux sonars grâce à un comparateur de 8 bits renvoyant 1 si tout les bits sont égaux, 0 sinon. | ||
+ | |||
+ | Au départ, n'ayant personne devant la porte, l' Echo du sonar aura la même valeur que celle de l'étalon. Mes collègues de la partie informatique ayant choisit une transmission sur 2 bits. Le poste de contrôle recevra 0b11 s'il y a une personne, 0b00 sinon. | ||
+ | |||
+ | A ce moment l'utilisateur pourra choisir d'ouvrir la porte en envoyant le mot 0b11 qu'on comparera avec 0b11 grâce à un comparateur 2 bits. Ainsi on aura 1 à la sortie du comparateur, si l'on souhaite ouvrir la porte, 0 sinon | ||
+ | |||
+ | Cette démarche est représenté ci-dessous | ||
+ | |||
+ | [[Fichier:Système 1.png]] | ||
+ | |||
+ | On connecte alors la sortie de système à la broche CLR du compteur du système réaliser lors de la première séance. On obtient alors le schéma suivant | ||
+ | |||
+ | |||
+ | [[Fichier:Projet SC3.png]] | ||
+ | |||
+ | Ainsi si l'utilisateur ne souhaite pas ouvrir la porte, il doit envoyer n'importe quel de deux bits différents de 0b11. On aura alors 0 à la sortie du système 1 qu'on inverse pour avoir 1 à l'entrée du CLR et du coup toute les sorties du compteur seront mises à zéros et le servomoteur qui actionnera la porte ne se mettra pas en marche pas. | ||
=== Partie informatique === | === Partie informatique === | ||
+ | |||
+ | =====Programmes de la configuration et la mise en marche de la liaison série===== | ||
+ | |||
+ | Serial.c | ||
+ | |||
+ | /* | ||
+ | * Serial library | ||
+ | */ | ||
+ | |||
+ | //// | ||
+ | // Include files | ||
+ | //// | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <unistd.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <termios.h> | ||
+ | #include <strings.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/ioctl.h> | ||
+ | #include <sys/file.h> | ||
+ | #include <linux/serial.h> | ||
+ | |||
+ | #include "serial.h" | ||
+ | |||
+ | //// | ||
+ | // Functions | ||
+ | //// | ||
+ | // | ||
+ | // Open serial port device | ||
+ | // | ||
+ | int serialOpen(char *device,int mode){ | ||
+ | int flags=(mode==SERIAL_READ?O_RDONLY:(mode==SERIAL_WRITE?O_WRONLY:O_RDWR)); | ||
+ | int fd=open(device,flags|O_NOCTTY|O_NONBLOCK); | ||
+ | if(fd<0){ perror(device); exit(-1); } | ||
+ | return fd; | ||
+ | } | ||
+ | |||
+ | // | ||
+ | // Serial port configuration | ||
+ | // | ||
+ | void serialConfig(int fd,int speed){ | ||
+ | struct termios new; | ||
+ | bzero(&new,sizeof(new)); | ||
+ | new.c_cflag=CLOCAL|CREAD|speed|CS8; | ||
+ | new.c_iflag=0; | ||
+ | new.c_oflag=0; | ||
+ | new.c_lflag=0; /* set input mode (non-canonical, no echo,...) */ | ||
+ | new.c_cc[VTIME]=0; /* inter-character timer unused */ | ||
+ | new.c_cc[VMIN]=1; /* blocking read until 1 char received */ | ||
+ | if(tcsetattr(fd,TCSANOW,&new)<0){ perror("serialInit.tcsetattr"); exit(-1); } | ||
+ | } | ||
+ | |||
+ | // | ||
+ | // Serial port termination | ||
+ | // | ||
+ | void serialClose(int fd){ | ||
+ | close(fd); | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | Serial.h | ||
+ | |||
+ | /* | ||
+ | * Public definitions for serial library | ||
+ | */ | ||
+ | |||
+ | //// | ||
+ | // Constants | ||
+ | //// | ||
+ | |||
+ | #define SERIAL_READ 0 | ||
+ | #define SERIAL_WRITE 1 | ||
+ | #define SERIAL_BOTH 2 | ||
+ | |||
+ | //// | ||
+ | // Public prototypes | ||
+ | //// | ||
+ | int serialOpen(char *device,int mode); | ||
+ | void serialConfig(int fd,int speed); | ||
+ | void serialClose(int fd); | ||
+ | |||
+ | =====Programme du WEBSOCKETS===== | ||
+ | |||
+ | ( | ||
+ | #include <string.h> | ||
+ | #include <libwebsockets.h> | ||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <unistd.h> | ||
+ | #include <fcntl.h> | ||
+ | #include <termios.h> | ||
+ | #include <sys/types.h> | ||
+ | #include <sys/ioctl.h> | ||
+ | #include <sys/file.h> | ||
+ | #include <linux/serial.h> | ||
+ | #include "serial.h" | ||
+ | |||
+ | |||
+ | #define MAX_FRAME_SIZE 1024 | ||
+ | #define WAIT_DELAY 50 | ||
+ | #define TAILLE_MESS 2 | ||
+ | #define SERIAL_DEVICE "/dev/ttyACM0" | ||
+ | |||
+ | int serie; | ||
+ | |||
+ | static int callback_http( | ||
+ | struct libwebsocket_context *this, | ||
+ | struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason, | ||
+ | void *user,void *in,size_t len) | ||
+ | { | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | static int callback_my( | ||
+ | struct libwebsocket_context * this, | ||
+ | struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason, | ||
+ | void *user,void *in,size_t len) | ||
+ | { | ||
+ | static char message[TAILLE_MESS+LWS_SEND_BUFFER_PRE_PADDING+LWS_SEND_BUFFER_POST_PADDING]; | ||
+ | unsigned char valeur; | ||
+ | |||
+ | switch(reason){ | ||
+ | case LWS_CALLBACK_ESTABLISHED: | ||
+ | printf("connection established\n"); | ||
+ | // Declenchement d'un prochain envoi au navigateur | ||
+ | libwebsocket_callback_on_writable(this,wsi); | ||
+ | break; | ||
+ | case LWS_CALLBACK_RECEIVE: | ||
+ | // Ici sont traites les messages envoyes par le navigateur | ||
+ | printf("received data: %s\n",(char *)in); | ||
+ | |||
+ | break; | ||
+ | case LWS_CALLBACK_SERVER_WRITEABLE: | ||
+ | // Ici sont envoyes les messages au navigateur | ||
+ | if(read(serie,&valeur,1)==1){ | ||
+ | char *out=message+LWS_SEND_BUFFER_PRE_PADDING; | ||
+ | sprintf(out,"%02d",valeur); | ||
+ | libwebsocket_write(wsi,(unsigned char *)out,TAILLE_MESS,LWS_WRITE_TEXT); | ||
+ | } | ||
+ | libwebsocket_callback_on_writable(this,wsi); | ||
+ | break; | ||
+ | default: | ||
+ | break; | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | static struct libwebsocket_protocols protocols[] = { | ||
+ | { | ||
+ | "http-only", // name | ||
+ | callback_http, // callback | ||
+ | 0, // data size | ||
+ | 0 // maximum frame size | ||
+ | }, | ||
+ | {"myprotocol",callback_my,0,MAX_FRAME_SIZE}, | ||
+ | {NULL,NULL,0,0} | ||
+ | }; | ||
+ | |||
+ | |||
+ | int main(void) { | ||
+ | int port=9000; | ||
+ | struct lws_context_creation_info info; | ||
+ | memset(&info,0,sizeof info); | ||
+ | info.port=port; | ||
+ | info.protocols=protocols; | ||
+ | info.gid=-1; | ||
+ | info.uid=-1; | ||
+ | struct libwebsocket_context *context=libwebsocket_create_context(&info); | ||
+ | if(context==NULL){ | ||
+ | fprintf(stderr, "libwebsocket init failed\n"); | ||
+ | return -1; | ||
+ | } | ||
+ | printf("starting server...\n"); | ||
+ | |||
+ | int c=0; | ||
+ | int serie=serialOpen(SERIAL_DEVICE,SERIAL_BOTH); | ||
+ | serialConfig(serie,B9600); | ||
+ | if(write(serie,&c,sizeof(char))!=1){ perror("main.write"); exit(-1); } | ||
+ | int i; | ||
+ | for(i=0;i<3;i++){ | ||
+ | if(read(serie,&c,sizeof(char))!=1){ perror("main.read"); exit(-1); } | ||
+ | printf("%02x\n",c); | ||
+ | } | ||
+ | serialClose(serie); | ||
+ | exit(0); | ||
+ | |||
+ | |||
+ | while(1){ | ||
+ | libwebsocket_service(context,WAIT_DELAY); | ||
+ | } | ||
+ | libwebsocket_context_destroy(context); | ||
+ | return 0; | ||
+ | } | ||
== Démonstration == | == Démonstration == | ||
== Conclusion == | == Conclusion == | ||
+ | |||
+ | Nous venons de réaliser un système de détection pour magasin. Mais, faute de temps, nous n'avons pas pu le tester totalement. Ce qui nous aurait peut-être permis de le peaufiner( utiliser seulement un sonar au lieu de deux par exemple). |
Version actuelle datée du 31 décembre 2016 à 23:40
Sommaire
Projet IMA3-SC 2015/2016 : Détection de présence
Cahier des charges
Portique d'un magasin où la détection de présence à la porte informe le caissier l'arrivée d'un nouveau client pour décider de lui ouvrir la porte ou pas.
On se servira alors d'un sonar pour détecter l'arrivée du client ,afficher sur l'ordinateur du caissier le message suivant " Client à la porte" ensuite attendre la réponse du caissier pour pouvoir tourner le servomoteur qui servira à ouvrir la porte .
Matériel
- Un servomoteur;
- 2 sonars
- NanoBoard
- Une carte Rasberry Pi
Séance 1
Partie électronique
Le servomoteur fourni dans le projet est piloté grâce à une MLI( ou PWM en anglais). Cet MLI nous permettra de controler la position angulaire du servomoteur, qui est régi de la manière suivante, d'après sa datasheet
Pour initialiser à 0°, il faut fournir un signal de 50Hz avec 1,5 ms à l'état haut
Et pour avoir un angle de 90°, on fournit toujours un signal de 50 Hz mais avec un état haut de 2.5 ms cette fois-ci
Nous nous devons alors d'utiliser un PWM . Ce PWM qu'on implémentera sur Altium, aura la structure suivante:
Nous avons alors entamé la prise en main du complexe Nanoboard-Altium à travers un tutoriel qui nous a permis de réaliser l'affichage d'un compteur 4 bits sur des leds
Partie informatique
Partie informatique
Configuration, via connexion série, de la raspberry accessible via ssh (pi@172.26.79.7).
Installation de la bibliothèque libwebsockets.
Installation d'apache2 pour avoir un serveur web.
Partie Arduino
Montage effectué
Test du matériels fournis avec des fonctions simple sous le logiciels Arduino
Séance 2
Partie électronique
Lors de cette deuxième séance, nous avoir réaliser sur Altium la MLI pensée lors de la première séance et qui va ainsi nous permettre de piloter notre servomoteur
CLKBRD:Horloge interne
CLKGEN:Générateur de fréquence
CB8CEB: Compteur 8 bits
COMPM8B:Comparateur 8 bits
SW_USER0:Bouton poussoir
Montage expérimental
Notre PWM ainsi implémenté sur Altium, on refait le même protocole qu'au tutoriel fait à la séance n° 1 pour compiler notre montage et l'envoyer sur la nanobaord.
A travers nos expérimentations, on trouve que pour avoir 1.5ms d'état haut( position 0 donc), il faut envoyer le mot 0b00001111
Pour 90°: 0b00100000
On branche la sortie sur un oscilloscope et on obtient le graphe ci-dessous, relatif à un PWM
On réalise alors le montage ci-dessous à l'aide d'un servomoteur, d'une plaque d'essai, d'un générateur et notre nanoboard.
Pour avoir une fréquence de 50 Hz à la sortie du PWM on doit régler la fréquence du générateur de fréquence à 12,698 KHz
Partie informatique
Réalisation de Programme Arduino
Séance 3
Partie électronique
Lors de cette troisième séance, on s'est intéressé à la partie détection de notre système. Pour cela, nous avons essayer d'intégrer le sonar. Le fonctionnement de celui- ci est le suivant: Il faut envoyer une impulsion niveau haut (à + 5v) pendant au moins 10 µs sur la broche ‘Trig Input’; cela déclenche la mesure. En retour la sortie ‘Output’ ou ‘Echo’, va fournir une impulsion + 5v dont la durée est proportionnelle à la distance si le module détecte un objet. Voici une représentation graphique de la séquence de fonctionnement du module :
Etant donné que nous voulons seulement détecter la présence d'une personne, la distance nous importe peu. Ainsi j'ai décidé d'utiliser deux sonars : un n'ayant pas d'obstacle, qu'on nommera sonar étalon et un deuxième positionné sur la porte. Ces deux sonars seront piloté grâce à un montage PWM similaire à celui créé lors de la première séance.On comparera les Echo des deux sonars grâce à un comparateur de 8 bits renvoyant 1 si tout les bits sont égaux, 0 sinon.
Au départ, n'ayant personne devant la porte, l' Echo du sonar aura la même valeur que celle de l'étalon. Mes collègues de la partie informatique ayant choisit une transmission sur 2 bits. Le poste de contrôle recevra 0b11 s'il y a une personne, 0b00 sinon.
A ce moment l'utilisateur pourra choisir d'ouvrir la porte en envoyant le mot 0b11 qu'on comparera avec 0b11 grâce à un comparateur 2 bits. Ainsi on aura 1 à la sortie du comparateur, si l'on souhaite ouvrir la porte, 0 sinon
Cette démarche est représenté ci-dessous
On connecte alors la sortie de système à la broche CLR du compteur du système réaliser lors de la première séance. On obtient alors le schéma suivant
Ainsi si l'utilisateur ne souhaite pas ouvrir la porte, il doit envoyer n'importe quel de deux bits différents de 0b11. On aura alors 0 à la sortie du système 1 qu'on inverse pour avoir 1 à l'entrée du CLR et du coup toute les sorties du compteur seront mises à zéros et le servomoteur qui actionnera la porte ne se mettra pas en marche pas.
Partie informatique
Programmes de la configuration et la mise en marche de la liaison série
Serial.c
/*
* Serial library */
//// // Include files ////
- include <stdio.h>
- include <stdlib.h>
- include <unistd.h>
- include <fcntl.h>
- include <termios.h>
- include <strings.h>
- include <sys/types.h>
- include <sys/ioctl.h>
- include <sys/file.h>
- include <linux/serial.h>
- include "serial.h"
//// // Functions //// // // Open serial port device // int serialOpen(char *device,int mode){ int flags=(mode==SERIAL_READ?O_RDONLY:(mode==SERIAL_WRITE?O_WRONLY:O_RDWR)); int fd=open(device,flags|O_NOCTTY|O_NONBLOCK); if(fd<0){ perror(device); exit(-1); } return fd; }
// // Serial port configuration // void serialConfig(int fd,int speed){ struct termios new; bzero(&new,sizeof(new)); new.c_cflag=CLOCAL|CREAD|speed|CS8; new.c_iflag=0; new.c_oflag=0; new.c_lflag=0; /* set input mode (non-canonical, no echo,...) */ new.c_cc[VTIME]=0; /* inter-character timer unused */ new.c_cc[VMIN]=1; /* blocking read until 1 char received */ if(tcsetattr(fd,TCSANOW,&new)<0){ perror("serialInit.tcsetattr"); exit(-1); } }
// // Serial port termination // void serialClose(int fd){ close(fd); }
Serial.h
/*
* Public definitions for serial library */
//// // Constants ////
- define SERIAL_READ 0
- define SERIAL_WRITE 1
- define SERIAL_BOTH 2
//// // Public prototypes //// int serialOpen(char *device,int mode); void serialConfig(int fd,int speed); void serialClose(int fd);
Programme du WEBSOCKETS
(
- include <string.h>
- include <libwebsockets.h>
- include <stdio.h>
- include <stdlib.h>
- include <unistd.h>
- include <fcntl.h>
- include <termios.h>
- include <sys/types.h>
- include <sys/ioctl.h>
- include <sys/file.h>
- include <linux/serial.h>
- include "serial.h"
- define MAX_FRAME_SIZE 1024
- define WAIT_DELAY 50
- define TAILLE_MESS 2
- define SERIAL_DEVICE "/dev/ttyACM0"
int serie;
static int callback_http(
struct libwebsocket_context *this, struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason, void *user,void *in,size_t len)
{ return 0; }
static int callback_my(
struct libwebsocket_context * this, struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason, void *user,void *in,size_t len)
{ static char message[TAILLE_MESS+LWS_SEND_BUFFER_PRE_PADDING+LWS_SEND_BUFFER_POST_PADDING]; unsigned char valeur;
switch(reason){
case LWS_CALLBACK_ESTABLISHED: printf("connection established\n"); // Declenchement d'un prochain envoi au navigateur libwebsocket_callback_on_writable(this,wsi); break; case LWS_CALLBACK_RECEIVE: // Ici sont traites les messages envoyes par le navigateur printf("received data: %s\n",(char *)in); break; case LWS_CALLBACK_SERVER_WRITEABLE: // Ici sont envoyes les messages au navigateur if(read(serie,&valeur,1)==1){
char *out=message+LWS_SEND_BUFFER_PRE_PADDING; sprintf(out,"%02d",valeur);
libwebsocket_write(wsi,(unsigned char *)out,TAILLE_MESS,LWS_WRITE_TEXT); }
libwebsocket_callback_on_writable(this,wsi);
break; default: break; }
return 0; }
static struct libwebsocket_protocols protocols[] = {
{ "http-only", // name callback_http, // callback 0, // data size 0 // maximum frame size }, {"myprotocol",callback_my,0,MAX_FRAME_SIZE}, {NULL,NULL,0,0} };
int main(void) {
int port=9000;
struct lws_context_creation_info info;
memset(&info,0,sizeof info);
info.port=port;
info.protocols=protocols;
info.gid=-1;
info.uid=-1;
struct libwebsocket_context *context=libwebsocket_create_context(&info);
if(context==NULL){
fprintf(stderr, "libwebsocket init failed\n"); return -1; }
printf("starting server...\n");
int c=0; int serie=serialOpen(SERIAL_DEVICE,SERIAL_BOTH); serialConfig(serie,B9600); if(write(serie,&c,sizeof(char))!=1){ perror("main.write"); exit(-1); } int i; for(i=0;i<3;i++){
if(read(serie,&c,sizeof(char))!=1){ perror("main.read"); exit(-1); } printf("%02x\n",c); }
serialClose(serie); exit(0);
while(1){
libwebsocket_service(context,WAIT_DELAY); }
libwebsocket_context_destroy(context); return 0; }
Démonstration
Conclusion
Nous venons de réaliser un système de détection pour magasin. Mais, faute de temps, nous n'avons pas pu le tester totalement. Ce qui nous aurait peut-être permis de le peaufiner( utiliser seulement un sonar au lieu de deux par exemple).