IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

[Linux][C] tasse de café -- phénomène bien connu


Sujet :

C

  1. #1
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut [Linux][C] tasse de café -- phénomène bien connu
    Salutations !!

    Je suis en train de développer une application avec mes élèves basée sur le langage C. Il s'agit de simuler une partie de "blind test": un programme "moniteur" joue des morceaux et les joueurs armés d'un arduino et d'un bouton poussoir
    peuvent interrompre la lecture du morceau et introduire au clavier le titre l'artiste ou l'année d'édition du morceau en question.

    Le soucis c'est que la saisie peut provoquer l'effet dit "la tasse de café": si le joueur décide de ne jamais répondre, le jeu est bloqué... en effet la lecture du morceau va reprendre uniquement si le joueur a mal répondu, dans le cas contraire
    le "moniteur" va sélectionner au hasard un autre morceau et le jouer (tout ça grâce à SDL).

    Je n'ai pas encore vraiment planché sur la problématique mais je me pose la question suivante:

    Comment en Langage C, dans l'environnement Linux, serait-il possible de ne permettre la saisie au clavier que pendant un certain laps de temps (disons 30 secondes) ?
    Comment faire en sorte d'interrompre une fonction comme fgets() ?

    Piste:

    J'ai une fonction non bloquante de saisie au clavier que je pourrais utiliser, je vais soumettre d'ici peu une première approche mais je ne suis pas certain de mon coup.

  2. #2
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Tu peux envoyer un signal au processus pour débloquer la saisie. À ta place cela dit je me ferais pas suer et j'utiliserais les évènements clavier SDL avec lesquels il est très simple de gérer tout ça.

  3. #3
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Voilà la fonction sur laquelle je pense m'appuyer pour permettre dans la boucle/fonction de saisie de notre programme de faire la saisie au clavier pendant un certain temps.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    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
     
    #ifdef LINUX
    int nbgetch(void)
    {
    	char							Buffer;
    	struct termios		oldt;
    	struct termios		newt;
     
    	tcgetattr(STDIN_FILENO, &oldt);
      newt = oldt;
     
    	//newt.c_lflag &= ~(ICANON | ECHO); // | ECHONL | ECHOCTL); 			// affiche le caractère alors que je dis de ne pas faire l'écho...
    	//tcsetattr(STDIN_FILENO, TCSANOW, &newt);
     
    	//newt.c_lflag=0;
    	// tcsetattr(STDIN_FILENO, TCSADRAIN, &newt);
     
    	// mode non bloquant...
     
    	newt.c_cc[VMIN] = 0;
    	newt.c_cc[VTIME] = 0;
    	tcsetattr(STDIN_FILENO, TCSANOW, &newt);
     
    	Buffer=getchar();	// retourne EOF (-1) si il y a rien dans le buffer
     
    	// on restitue "l'ancienne configuration"
    	tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 
    	return Buffer;
    }
    #endif
    Voici l'idée de mon approche...
    Comme cette fonction ne saisit qu'un seul caractère, et encore je ne prends pas en compte les caractères UTF8, (faudra voir cela plus tard...), il faudra remplir un tableau/liste/pile FIFO avec chaque lettre/caractère saisi.
    En soi ce n'est pas la mort...

    Je vais utiliser cette fonction dans une fonction fct_getReponse() qui contient une boucle dans laquelle je vais saisir un caractère jusqu'à ce que la taille maximum du champs soit atteinte ou que le code ASCII 10 soit saisi.
    Incrémenter un compteur et sortir de la boucle dès que celui-ci aura atteint une certaine valeur me semble peu idéal, car, en fonction de la puissance du processeur, la valeur maximum peut être atteinte plus vite ou plus lentement...
    Je vais donc récupérer AVANT la boucle l'EPOCH à la seconde près dans une variable, et comparer dans la boucle si cette variable est égale à EPOCH+30... si tel est le cas j'interromperais la boucle.

    Qu'en pensez-vous ??

  4. #4
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    @Matt --> Oui j'y ai pensé aussi... une sorte de SIGUSR1, ou un timer système...
    Je vais essayer un peu tout ce que me propose. D'autant que je n'ai pas encore exploré SDL2 à fond, je me doute bien qu'il doit y avoir de quoi me sortir de cette petite galère.
    Merci.

  5. #5
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    C'est vraiment pas sorcier : tu défiles les évènements comme d'habitude, en testant les keycodes pour les caractères imprimables qui t'intéressent que tu empiles dans un buffer jusqu'à ce que tu tombes sur la touche Entrée. C'est pas super UTF-8-compliant mais bon, je pense que ça fera l'affaire dans ton cas non ?

    Comme c'est au sein de la boucle de jeu, tu mets tout ça dans un état dédié à la saisie et lorsque l'utilisateur a validé la saisie ou que le compte à rebours est terminé tu passes à l'état suivant qui va bien.

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 373
    Points : 23 629
    Points
    23 629
    Par défaut
    Bonjour,

    Citation Envoyé par hurukan Voir le message
    Comment en Langage C, dans l'environnement Linux, serait-il possible de ne permettre la saisie au clavier que pendant un certain laps de temps (disons 30 secondes) ?
    Comment faire en sorte d'interrompre une fonction comme fgets() ?
    Matt Houston t'a donné de très bonnes indications mais puisque tu en es déjà à envisager termios, tu peux explorer ces pistes :

    • Soit tu t'appuies entièrement sur la SDL ;
    • Soit tu utilises alarm() (le timer système) pour définir ton laps de temps et tu fais un appel bloquant normal, comme fgetc(). À l'échéance, alarm() va envoyer SIGALRM à ton processus, et le fait en soi de recevoir un signal va provoquer l'échec de tout appel bloquant, qui va rendre la main avec un code spécial. Dans le cas de fgetc(), ce sera toujours EOF. À toi également de vérifier si ce EOF correspond bien à une fin de fichier (ou à la fermeture de l'entrée standard avec Ctrl+D). Il faudra aussi penser à mettre en place le handler du signal et à le réarmer à chaque fois, sinon le signal va tuer ton processus ;
    • Soit encore, tu utilises select() même s'il n'y a qu'un seul descripteur à surveiller et tu spécifies la valeur de timeout dans cet appel. C'est la manière la plus propre de procéder, à mon avis. L'avantage est que tout tient dans un seul appel et que le même code te permet éventuellement de surveiller plusieurs entrées à la fois.


    Bon courage.

  7. #7
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Ceci fonctionne...

    J'ai perdu trois heures à essayer de comprendre pourquoi quand je fais un "back space" je n'obtiens pas un retour en arrière normal... je vais m'y pencher plus tard... sinon ceci fonctionne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    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
    59
    60
    61
    62
    63
     
    char* getTimedUTF8String(short maxlen,short maxtime)
    {
    	int		cpt=0;
    	char*	tmp;
    	char	cCaractere=-1;
    	char	*pCaractere;
    	time_t start=time(NULL);
    	time_t current;
     
    	LinkedList *ll_Chaine;
     
    	maxlen++;	// pour ajouter le '\0'
    	ll_Chaine=lc_init();
     
    	// 1. Effectuer la boucle 
     
    	while(cCaractere!=10 && cpt<maxlen)
    	{
    		cCaractere=nbgetch();
    		current=time(NULL);
     
    		if(cCaractere!=-1) 
    		{
    			if(cCaractere==27) continue;
    			if(cCaractere>127) continue;
    			if(cCaractere<32 && cCaractere>0) continue;
    			cpt++;
    			pCaractere=malloc(1);
    			*pCaractere=cCaractere;
    			if(cCaractere!=10)
    				lc_add((void*)pCaractere,ll_Chaine,cssmbyte,sizeof(char));
    		}
     
    		int debug=current-start;
     
    		if(debug>maxtime) break;
    	}
     
    	cpt=0;
     
    	// 2. constituer la chaîne de caractères...
     
    	if(!ll_Chaine->NbElem) return NULL;
     
    	tmp=malloc(sizeof(char)*ll_Chaine->NbElem);
    	memset(tmp,0,ll_Chaine->NbElem);
     
    	while(ll_Chaine->NbElem>0)
    	{
    		lc_Datas *tmpDatas=lc_pop(ll_Chaine);
    		char	*ctmp;
    		ctmp=(char*)tmpDatas->value;
    		*tmp=*ctmp;
    		tmp++;
    		cpt++;
    	}
    	*(tmp)='\0';
     
    	lc_empty(ll_Chaine);
     
    	return tmp-cpt;
    }
    Le code permettant la saisie sur lequel je me basais était bloquant... il faut le modifier...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #ifdef LINUX
    int nbgetch(void)
    {
    	char							Buffer;
    	struct termios		oldt;
    	struct termios		newt;
    		
    	tcgetattr(STDIN_FILENO, &oldt);
      newt = oldt;
    	
    	// mode non bloquant...
    		
    	newt.c_cc[VMIN] = 0;
    	newt.c_cc[VTIME] = 0;
    	newt.c_lflag &= ~ICANON;																					// n'a pas besoin d'appuyer sur "entrée" (caractère non bloquant de la procédure)
    	tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    	
    	Buffer=getchar();	// retourne EOF (-1) si il y a rien dans le buffer
    	
    	// on restitue "l'ancienne configuration"
    	tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 
    	return Buffer;
    }
    #endif

  8. #8
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    J'ai déjà, je pense, partagé la librairie linkedlist sur ce forum, c'est une sorte d'essai sur la manière de gérer des listes chaînées pouvant prendre en compte n'importe quoi comme type de données.

    Je vous la file de nouveau si vous n'arriviez pas à mettre la main dessus...

    Dans mes essais j'ai remarqué que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    newt.c_lflag &= ~(ICANON|ECHOCTL);
    Ne m'affiche plus les saloperies de ^H ou ^? quand j'appuie sur backspace en mode terminal...
    Je sens que j'approche de la vérité...

    Oui !!! En fait je suis bon ^^
    Ca marche !!
    Reste maintenant à enlever le dernier élément inséré dans la liste dès que l'on appuie sur back space...

  9. #9
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Pourquoi faire simple, hein ?

    Je n'ai pas bien compris l'intérêt de l'étape avec la liste chaînée. Pourquoi ne stockes-tu pas directement la chaîne dans un tableau de char déclaré sur la pile ? C'est un blind test, le gars ne va pas saisir une biographie de l'interprète en trois volumes.

  10. #10
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Pour faire le malin, probablement...

    ...il y a "plus simple" effectivement, vu que je connais la taille maximum du tableau... un super char tmp[maxlen] et hop nous voilà parti... je vais d'ailleurs revoir ma copie plus c'est simple mieux c'est ^^

    Et autre chose aussi: il faut faire attention avec les paramètres c_cc[VMIN] et c_cc[VTIME]... il faut éviter de mettre à 0 c_cc[VTIME] sinon ça bouffe des ressources processeur (un de mes coeurs montait jusque 100%).
    J'ai mis une valeur de 50 et là tout va bien.

  11. #11
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    J'ai du mal à comprendre vraiment tout le souci: Pourquoi ne pas s'appuyer simplement sur la SDL? Pour ton cas, cela semble le plus simple...

  12. #12
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Voilà la version "plus simple"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    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
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    char* getTimedUTF8String(short maxlen,short maxtime)
    {
    	int		cpt=0;
    	char	cCaractere=-1;
    	time_t start=time(NULL);
    	time_t current;
     
    	char Debug[255];
     
    	maxlen++;	// pour ajouter le '\0'
     
    	// tmp est un pointeur: il contient (il pointe sur) une adresse en mémoire à partir de laquelle sont réservés "maxlen" caractères...
     
    	unsigned char*	tmp=malloc(maxlen);		
     
    	// 1. Effectuer la boucle 
     
    	while(cCaractere!=10 && cpt<maxlen)
    	{
    		cCaractere=nbgetch();							// nous saisissons au clavier un caractère de manière non bloquante... si il n'y a rien dans le buffer cCaractere vaut -1.
    		current=time(NULL);
     
    		if(cCaractere!=-1) 
    		{
    			if(cCaractere!=10)
    				*tmp=cCaractere;							// A l'adresse pointée par tmp, nous mettons cCaractere cela revient au même que de faire tmp[cpt]=cCaractere...
     
    			if(cCaractere==127) 
    			{
    				// traitement du backspace
    				printf("\x1b[1D");						// ??? ne fonctionne pas... tous les autres codes ANSI fonctionnent mais pas celui-ci là !!
    																			// ...essayé plein de fois dans d'autres codes source mais ici ça ne marche pas ???
    																			// Il suffit de spécifier ~ECHOCTL pour que cela fonctionne (au niveau de nbgetch())
    				printf(" ");
    				printf("\x1b[1D");
    				fflush(stdout);
     
    				// prévoir l'effacement de caractères UTF8 (deux bytes voire plus :{ )
     
    				if(*(tmp-2)==195 || *(tmp-2)==194) // je me base uniquement sur le code latin1-be
    				{
    					tmp--;
    					cpt--;
    				}
     
    				if(cpt>0) cpt--;
    				tmp--;
     
    				continue;
    			}
    			// Traitement des touches de direction
    			if(cCaractere==27) 
    			{
    				// déterminer la direction 
    				cCaractere=nbgetch();
    				if(cCaractere==91)
    				{
    					cCaractere=nbgetch();
    					if(cCaractere=='A') printf("\x1b[B");
    					if(cCaractere=='B') printf("\x1b[A");
    					if(cCaractere=='C') printf("\x1b[D");
    					if(cCaractere=='D') printf("\x1b[C");
    				}
    				else
    				{
    					// Vider le buffer
    					while((cCaractere=nbgetch())!=-1);
    				}
    				continue;
    			}
    			cpt++;
    			tmp++;	// passer à la case suivante (un byte) en mémoire... 
    		}
    		int debug=current-start;
    		if(debug>maxtime) break;
    	}
    	return tmp-cpt;	// comme nous avons changé la valeur de l'adresse en mémoire pour y mettre tous nos caractères, il faut restituer l'adresse de DEBUT du tableau...
    }
    Pourquoi ne pas m'appuyer sur la librairie SDL ? Parce que le programme que mes élèves vont faire pour la gestion de l'Arduino n'est pas censé fonctionner en SDL mais en C pur dans un premier temps.
    Le jeu du blindtest qu'ils avaient envie de développer consiste en deux applications, l'une qui communique avec un Arduino branché à la machine, et l'autre (en SDL2) qui fait office d'application de "monitoring" exposant sur un écran de projecteur ce qu'il se passe (qui a cliqué sur son bouton poussoir, quelle équipe à le plus de points, au niveau de SDL2_mixer: quel morceau est en train d'être joué, etc...).
    La fonction permettant d'éviter le phénomène de la tasse de café devra être utilisée au niveau du programme de gestion de l'Arduino qui recevra l'autorisation de répondre lorsque le joueur aura été le plus rapide à pousser sur son bouton.
    A ce moment-là il aura 30 secondes pour répondre, pendant le temps qu'il répondra, la musique et le jeu s'interrompt, et ne reprend que si la réponse est mauvaise, et dans ce cas, le deuxième plus rapide pourra répondre à son tour, peu importe dans quelle équipe il se situe.
    Si il n'y a plus rien dans la liste des joueurs qui peuvent répondre via le clavier, la musique reprend jusqu'à ce qu'elle s'arrête (je pense jouer les morceaux maximum 80 secondes puis passer au suivant) et ainsi de suite.

  13. #13
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonjour,
    Personnellement, le programme utilisant SDL, Arduino et clavier est excessif.
    Le projet est-il pour des élèves ou étudiants ?:
    • Si élèves : En première STI2D options SIN (systèmes d'information et numérique) c’est hors programme (en France) pour la simple raison que la programmation avancée (système) en langage C sur les entrées et sorties sur les terminaux GNU/Linux ne sont pas au programme sauf si vous faites tout le boulot en amont et que vous leur fournissez les fonctions pour qu’ils puissent les utiliser.
    • Si Terminale, il faut changer de registre et s’orienter sur la programmation orienté objet en utilisant le langage python 3 (pygame par exemple) et sur un Raspberry Pi.
    • Si cas personnel oui, mais alors il faut opter pour un Arduino Due ou Arduino Yun et se lancer dans l’interfaçage et autre.
    • Si étudiants, possible mais là encore c’est excessif et je ne vois pas vraiment l’intérêt.


    Cependant, si on se penche bien dans la démarche projets, on peut très bien opter pour du Processing qui se marie très bien avec Arduino. Plus simple encore, utiliser deux Arduino (ou éventuellement deux Arduino en esclave et un Raspberry Pi en maître par exemple). Tout de même, deux Arduino et éventuellement Processing suffisent largement (ou un moniteur LCD tout basique).
    En ce qui concerne la saisie au clavier, des boutons poussoirs peuvent être mis à disposition des équipes (des joueurs) pour effectuer un choix en appuyant soit sur A, B, C ou D selon les choix qui leur sont proposés, ce qui vous permet d’une part d’éviter la gestion des terminaux (saisie de mots phrase ; surtout si l’on se trompe dans la saisie). D'autre part, pour la gestion ou temporisation, pas besoin de SDL ou autres artifices, Arduino le fait très bien comme un grand Exemple en utilisant la bibliothèque timer ci-dessous source JChristensen: blog

    Attention le code source est susceptible de comporter des erreurs

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    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
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
     
    ============================================================================
     Name        : source.c
     Date        : 03/03/2017
     Author      : SAMBIA39
     Version     : 0.1
     Copyright   : Copyright © 2017 SAMBIA39 All rights reserved.
     Description : Ansi-style C and Arduino
     ============================================================================
     */
     
    /*
     * definition des constante
     */
    #define OUTBUZZER 4             //Sortie Buzzer
    #define BAUDRATES 9600          //bauds rate UART
    #define TIMEOSCIL 500           //delay d'attente
     
    #include <Wire.h>
    #include <Event.h>
    #include <Timer.h>
    #include <SeeedOLED.h>
     
    /* 
     *  Object timer
     */
    Timer t_time;
     
    /*
     * Fonction qui est interrogée tous les TIMEOSCIL 
     * si aucune action est entreprise dans le Delay TIMEOSCIL 
     * elle affiche à l'écran qu'aucun buzzer est activé 
     * si on active le boutton alors elle affiche BUZZERR!
     * et fait sonner le buzzer à intervalles de TIMEOSCIL 
     * si l'on ne relâche pas le boutton elle affiche NO-BUZZER et ne fait pas sonner
     * ( Attention ce n'est qu'un test pour montrer utilisation du trimer)
     */
    void f_Choix(){
     
      int ret = analogRead(1);
      char c_str1[] = " BUZZERRR!!!!";
      char c_str2[] = " NO-BUZZERRR!";
     
      digitalWrite( OUTBUZZER, LOW );
      if( ret ){
        SeeedOled.clearDisplay();
        SeeedOled.putString( c_str1 );
        digitalWrite( OUTBUZZER, HIGH );
        delay(300);
      }
      SeeedOled.clearDisplay();
      SeeedOled.putString( c_str2 );
    }
     
    void setup(){
      /*
       * Initialisation
       */
      Wire.begin();  
      Serial.begin(BAUDRATES);
      pinMode(OUTBUZZER, OUTPUT );
      const char c_str0[] = "ATTENTES";       // Message aprés initialisation
      /*
       * (1)Initialisation écrans oled
       * (2)Pin oled I2C
       * (3)Clean écrans oled
       * (4)Message initialisation Ok
       * (5)Appel de fonction f_choix tout les TIMEOSCIL -> 500 milliseconde
       */
      SeeedOled.init();                       //(1)
      DDRB|=0x21;                             //(2)
      PORTB |= 0x21;
      SeeedOled.clearDisplay();               //(3)
      SeeedOled.putString( c_str0 );          //(4)
      t_time.every( TIMEOSCIL*2, f_Choix );   //(5)
    }
     
    void loop() {
      digitalWrite( OUTBUZZER, LOW );
      t_time.update();                          //Actualisation du timer
    }

    Je pense peut-être apporter quelques éléments, à vous par la suite de faire le nécessaire si vous estimez que c’est une des nombreuses approches proposées.
    si vous avez toutefois besoin que l'on vous aide bien volontiers. Je sais combien ce n'est pas si facile les projets scolaires
    à bientôt
    Fichiers attachés Fichiers attachés
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  14. #14
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Merci pour les exemples de gestion de timeout directement au niveau de l'arduino... très intéressant.

    Pour rassurer tout le monde, en Belgique, "le programme", personnelement je m'en tape, je retiens juste que les étudiants (qui n'étudient pas mais ça tout le monde est passé par là) doivent connaître l'algèbre de Boole, les branchements conditionnels, les boucles, le mécanisme des fonctions, les pointeurs (en terminale, comme on dit en France).

    Pour le projet, il y a un "socle commun" comprenant des fonctions déjà écrites, plus ou moins testées, mettant en place la gestion du terminal sous Linux, tout ce que les élèves doivent faire c'est respecter un protocole et se servir des exemples fonctionnels
    permettant aux différents éléments du projet de communiquer. Ils vont avec mon aide tester l'application principale qui consiste en un programme permettant de détecter un Arduino, détecter les clics sur le bouton poussoir et communiquer cela dans une base de données qui est lue par une machine d'état développée par mes soins.

    Les derniers tests, qui datent d'environ deux semaines sont concluants... ça marche (juste un soucis avec la librairie SDL2_mixer mais ça va aller... il reste un mois, nous y arriverons).

    Je suis en train de faire des simulations pour vérifier que l'application "tient le coup" avec les huit arduinos prévus. J'ai développé un "simulateur d'arduino" qui lit un script qui simule des clics pour vérifier si le protocole fonctionne toujours
    aussi bien avec plus de deux Arduinos connectés... les derniers tests ont en effet été testés sur deux ordinateurs chacuns connectés à un module Arduino.

Discussions similaires

  1. Changer la tasse de café de Java
    Par midoscofield dans le forum Graphisme
    Réponses: 9
    Dernier message: 07/08/2013, 10h08
  2. [Associé] Développeur PHP MySQL connaissant bien Linux
    Par Mindiell dans le forum Autres
    Réponses: 0
    Dernier message: 14/12/2009, 23h15
  3. Réponses: 2
    Dernier message: 14/01/2008, 12h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo