Des interrupteurs et des leds (Chenillard) !

Proposer ou rechercher un tutoriel concernant le Raspberry Pi

Modérateur : Francois

Répondre
Artemus24
Raspinaute
Messages : 1077
Enregistré le : ven. 15 sept. 2017 19:15

Des interrupteurs et des leds (Chenillard) !

Message par Artemus24 » jeu. 31 oct. 2019 05:23

Bonjour à tous.

Au lieu de faire un traditionnel clignotement de leds, j'ai volontairement complexifié ce projet, en me contraignant les points suivants :

1) deux rangés de leds, soit au total 2x9 leds. Il y a alternances de leds vertes, jaunes et rouges par bloque de trois leds.

2) deux interrupteurs. Le premier sert à sélectionner un groupe, et le second à sélectionner un effet visuel dans le groupe.

3) il y a au total six groupes :
--> 1er groupe : 18 effets, soit un clignotement par led.
--> 2ème groupe : 4 effets en faisant clignoter seulement les leds vertes.
--> 3ème groupe : 4 effets en faisant clignoter seulement les leds jaunes.
--> 4ème groupe : 4 effets en faisant clignoter seulement les leds rouges.
--> 5ième groupe : 4 effets sous la forme d'un chenillard à une seule led allumée.
--> 6ième groupe : 4 effets sous la forme d'un chenillard à deux leds allumées.

4) gestion d'un timer qui permet de séquencer le clignotement.
Ce timer permet de ne pas monopoliser la CPU par une activité qui ne sert à rien.
Autrement dit, si l'affichage dure un laps de temps très court, le reste du temps quand la led ne clignote pas, le programme ne fait rien.

5) gestion des deux interrupteurs indépendamment l'un de l'autre, au sein, de deux timers.
Au total, dans le programme, il y a trois timers.

6) j'ai utilisé la bibliothèque "BCM2835" pour gérer les GPIO.

7) j'ai ajouté une gestion des signaux.
Quand le programmes fonctionne, et que vous désirez l'arrêter brutalement, il suffit de faire un CTRL-C.
Un signal est transmit au programme et celui-ci sort sort correctement.
Ce qui permet de ne pas laisser les GPIO dans un état disons instable.

8) pour réaliser le pontage, je n'ai pas utilisé des jumpers car j'avais des problèmes de faux-contacts.
J'ai utilisé un câble rigide de 0.2mm2 ce qui m'a permis d'avoir un ensemble compact.

9) un T-Cobbler, une natte à 40 fils, et ma Raspberry PI 2.

10) voici le programme écrit en 'C' :

Code : Tout sélectionner

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>
#include <bcm2835.h>

/***********************/
/*                     */
/*     Définitions     */
/*                     */
/***********************/

#define _NBRE_LOOP			23	/* Nombre de Boucle avant arrêt  */
#define _NBRE_THREAD			 3	/* Nombre de Tâches Lancées      */
#define _NBRE_KEY			 2	/* Nombre de Boutons Poussoirs   */
#define _NBRE_LED			18	/* Nombre de Leds Clignottantes  */
#define _NBRE_EFFET			 6	/* Nombre de Groupe de Séquences */
#define _NBRE_MODE			38	/* Nombre Total     de Séquences */

/*============================================*/
/*     Liste des GPIO & Broches Utilisées     */
/*============================================*/

							/*-----------+--------*/
							/* Broche 01 | 3.3Vcc */
							/* Broche 06 | Ground */
							/*-----------+--------*/
uint8_t  iKey[_NBRE_KEY] =     {RPI_V2_GPIO_P1_08,	/* Broche 08 | GPIO14 */
				RPI_V2_GPIO_P1_11};	/* Broche 11 | GPIO17 */
							/*-----------+--------*/
uint8_t  iLed[_NBRE_LED] =     {RPI_V2_GPIO_P1_40,	/* Broche 40 | GPIO21 */
				RPI_V2_GPIO_P1_38,	/* Broche 38 | GPIO20 */
				RPI_V2_GPIO_P1_36,	/* Broche 36 | GPIO16 */
							/*-----------+--------*/
				RPI_V2_GPIO_P1_32,	/* Broche 32 | GPIO12 */
				RPI_V2_GPIO_P1_26,	/* Broche 26 | GPIO07 */
				RPI_V2_GPIO_P1_24,	/* Broche 24 | GPIO08 */
							/*-----------+--------*/
				RPI_V2_GPIO_P1_22,	/* Broche 22 | GPIO25 */
				RPI_V2_GPIO_P1_18,	/* Broche 18 | GPIO24 */
				RPI_V2_GPIO_P1_16,	/* Broche 16 | GPIO23 */
							/*-----------+--------*/
				RPI_V2_GPIO_P1_37,	/* Broche 37 | GPIO26 */
				RPI_V2_GPIO_P1_35,	/* Broche 35 | GPIO19 */
				RPI_V2_GPIO_P1_33,	/* Broche 33 | GPIO13 */
							/*-----------+--------*/
				RPI_V2_GPIO_P1_31,	/* Broche 31 | GPIO06 */
				RPI_V2_GPIO_P1_29,	/* Broche 29 | GPIO05 */
				RPI_V2_GPIO_P1_23,	/* Broche 23 | GPIO11 */
							/*-----------+--------*/
				RPI_V2_GPIO_P1_21,	/* Broche 21 | GPIO09 */
				RPI_V2_GPIO_P1_19,	/* Broche 19 | GPIO10 */
				RPI_V2_GPIO_P1_15};	/* Broche 15 | GPIO22 */
							/*-----------+--------*/
							/*  Raspberry PI  2B  */
							/*-----------+--------*/

/******************************/
/*                            */
/*     Variables Globales     */
/*                            */
/******************************/

pthread_cond_t		tCond;
pthread_mutex_t		tMutex;

struct	sigaction	action;

/*====================================*/
/*     Déclaration des structures     */
/*====================================*/

typedef struct {
	pthread_t	tThread;
	int		iNumero;
	void		(*function)(union sigval);
	time_t		period_sec;
	long		period_nsec;
} PARAMS, *LPARAMS;

typedef struct {
	int		iArret;
	int		iOnOff;
	int		iEffet;
	int		iMode;
	int		iRang;
} ARGS, *LARGS;

ARGS			args = {_NBRE_LOOP, 1, 0, 0, 0};

/*===============================*/
/*     Enchaînement des leds     */
/*===============================*/

int	tBegin[_NBRE_EFFET] = { 0,18,22,26,30,34};
int	tQuant[_NBRE_EFFET] = {18, 4, 4, 4, 4, 4};

int	tSuivant[_NBRE_MODE][2*_NBRE_LED+1] = {
	{ 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 3, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 5, 0, 0, 0, 0, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 7, 0, 0, 0, 0, 0, 0, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{ 9, 0, 0, 0, 0, 0, 0, 0, 0,10, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,12,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,14,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,16,15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,18,17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,20,19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,22,21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,24,23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,26,25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
	{27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,28,27, 0, 0, 0, 0, 0, 0, 0, 0},
	{29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,30,29, 0, 0, 0, 0, 0, 0},
	{31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,32,31, 0, 0, 0, 0},
	{33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,34,33, 0, 0},
	{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,36,35},

	{ 1, 2, 7, 0, 0, 0, 0, 8,13, 0, 0, 0, 0,14,19, 0, 0, 0, 0,20,25, 0, 0, 0, 0,26,31, 0, 0, 0, 0,32, 1, 0, 0, 0, 0},
	{31, 2,31, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0,14, 7, 0, 0, 0, 0,20,13, 0, 0, 0, 0,26,19, 0, 0, 0, 0,32,25, 0, 0, 0, 0},
	{ 1, 2,19, 0, 0, 0, 0, 8,25, 0, 0, 0, 0,14,31, 0, 0, 0, 0,20, 7, 0, 0, 0, 0,26,13, 0, 0, 0, 0,32, 1, 0, 0, 0, 0},
	{31, 2,31, 0, 0, 0, 0, 8,19, 0, 0, 0, 0,14,25, 0, 0, 0, 0,20, 1, 0, 0, 0, 0,26, 7, 0, 0, 0, 0,32,13, 0, 0, 0, 0},

	{ 3, 0, 0, 4, 9, 0, 0, 0, 0,10,15, 0, 0, 0, 0,16,21, 0, 0, 0, 0,22,27, 0, 0, 0, 0,28,33, 0, 0, 0, 0,34, 3, 0, 0},
	{33, 0, 0, 4,33, 0, 0, 0, 0,10, 3, 0, 0, 0, 0,16, 9, 0, 0, 0, 0,22,15, 0, 0, 0, 0,28,21, 0, 0, 0, 0,34,27, 0, 0},
	{ 3, 0, 0, 4,21, 0, 0, 0, 0,10,27, 0, 0, 0, 0,16,33, 0, 0, 0, 0,22, 9, 0, 0, 0, 0,28,15, 0, 0, 0, 0,34, 3, 0, 0},
	{33, 0, 0, 4,33, 0, 0, 0, 0,10,21, 0, 0, 0, 0,16,27, 0, 0, 0, 0,22, 3, 0, 0, 0, 0,28, 9, 0, 0, 0, 0,34,15, 0, 0},

	{ 5, 0, 0, 0, 0, 6,11, 0, 0, 0, 0,12,17, 0, 0, 0, 0,18,23, 0, 0, 0, 0,24,29, 0, 0, 0, 0,30,35, 0, 0, 0, 0,36, 5},
	{35, 0, 0, 0, 0, 6,35, 0, 0, 0, 0,12, 5, 0, 0, 0, 0,18,11, 0, 0, 0, 0,24,17, 0, 0, 0, 0,30,23, 0, 0, 0, 0,36,29},
	{ 5, 0, 0, 0, 0, 6,23, 0, 0, 0, 0,12,29, 0, 0, 0, 0,18,35, 0, 0, 0, 0,24,11, 0, 0, 0, 0,30,17, 0, 0, 0, 0,36, 5},
	{35, 0, 0, 0, 0, 6,35, 0, 0, 0, 0,12,23, 0, 0, 0, 0,18,29, 0, 0, 0, 0,24, 5, 0, 0, 0, 0,30,11, 0, 0, 0, 0,36,17},

	{ 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, 1},
	{35, 2,35, 4, 1, 6, 3, 8, 5,10, 7,12, 9,14,11,16,13,18,15,20,17,22,19,24,21,26,23,28,25,30,27,32,29,34,31,36,33},
	{ 1, 2,19, 4,21, 6,23, 8,25,10,27,12,29,14,31,16,33,18,35,20, 3,22, 5,24, 7,26, 9,28,11,30,13,32,15,34,17,36, 1},
	{35, 2,35, 4,19, 6,21, 8,23,10,25,12,27,14,29,16,31,18,33,20, 1,22, 3,24, 5,26, 7,28, 9,30,11,32,13,34,15,36,17},

	{ 1,36, 5, 2, 7, 4, 9, 6,11, 8,13,10,15,12,17,14,19,16,21,18,23,20,25,22,27,24,29,26,31,28,33,30,35,32, 1,34, 3},
	{35, 4,33, 6,35, 8, 1,10, 3,12, 5,14, 7,16, 9,18,11,20,13,22,15,24,17,26,19,28,21,30,23,32,25,34,27,36,29, 2,31},
	{ 1,36, 3,20, 5,22, 7,24, 9,26,11,28,13,30,15,32,17,34, 1, 2,21, 4,23, 6,25, 8,27,10,29,12,31,14,33,16,35,18,19},
	{35,20,17,22, 1,24, 3,26, 5,28, 7,30, 9,32,11,34,13,36,15, 4,35, 6,19, 8,21,10,23,12,25,14,27,16,29,18,31, 2,33}};

/****************************/
/*                          */
/*     Gestion des GPIO     */
/*                          */
/****************************/

void gpio_init(void)
{
	for (int i=0; i<_NBRE_KEY; i++)
	{
		bcm2835_gpio_fsel(   iKey[i], BCM2835_GPIO_FSEL_INPT);
		bcm2835_gpio_set_pud(iKey[i], BCM2835_GPIO_PUD_OFF);
	}

	for (int i=0; i<_NBRE_LED; i++)
		bcm2835_gpio_fsel(   iLed[i], BCM2835_GPIO_FSEL_OUTP);
}

void raz_leds(void)
{
	for (int i=0; i<_NBRE_LED; i++)
		bcm2835_gpio_write(iLed[i], LOW);
}

void gpio_reset(void)
{
	for (int i=0; i<_NBRE_KEY; i++)
	{
		bcm2835_gpio_fsel(   iKey[i], BCM2835_GPIO_FSEL_INPT);
		bcm2835_gpio_set_pud(iKey[i], BCM2835_GPIO_PUD_OFF);
	}

	for (int i=0; i<_NBRE_LED; i++)
	{
		bcm2835_gpio_fsel(   iLed[i], BCM2835_GPIO_FSEL_INPT);
		bcm2835_gpio_set_pud(iLed[i], BCM2835_GPIO_PUD_OFF);
	}
}

/************************************************/
/*                                              */
/*     Handler sur Signal "SIGINT" (ctrl-c)     */
/*                                              */
/************************************************/

void handler(int signo)
{
	printf("\nReçu Signal %d (SIGINT=2), sortie normale du programme\n", signo);

	action.sa_handler = SIG_DFL;
	sigemptyset(&action.sa_mask);
	sigaction(SIGINT, &action, NULL);

	args.iArret = 0;
}

/********************************/
/*                              */
/*     Création des Threads     */
/*                              */
/********************************/

void button1(union sigval sv)
{
	static		int	iPrev=0;
	volatile	int	iPress;

	pthread_mutex_lock(&tMutex);
	LARGS largs = sv.sival_ptr;

	if ((iPress = bcm2835_gpio_lev(iKey[0])) != iPrev)
	{
		if (iPress == HIGH)
		{
			(largs->iArret)--;
			largs->iOnOff = !largs->iOnOff;

			if (largs->iOnOff)
			{
				largs->iEffet = (largs->iEffet+1) % _NBRE_EFFET;
				largs->iMode  = tBegin[largs->iEffet];
				largs->iRang  = 0;

				printf("Bouton 1 --> ON   Reste=%d\n", largs->iArret);
			}
			else	printf("Bouton 1 --> OFF  Reste=%d\n", largs->iArret);
		}
		iPrev = iPress;
	}

	if (largs->iArret<=0)
		pthread_cond_signal(&tCond);

	pthread_mutex_unlock(&tMutex);
	pthread_exit(NULL);
}

void button2(union sigval sv)
{
	static		int	iPrev=0;
	volatile	int	iPress;

	pthread_mutex_lock(&tMutex);
	LARGS largs = sv.sival_ptr;

	if ((iPress = bcm2835_gpio_lev(iKey[1])) != iPrev)
	{
		if (iPress == HIGH)
		{
			raz_leds();

			largs->iMode = ((largs->iMode + 1 - tBegin[largs->iEffet]) % tQuant[largs->iEffet]) + tBegin[largs->iEffet];
			largs->iRang = 0;

			printf("Bouton 2 --> Mode=%d\n", largs->iMode);
		}
		iPrev = iPress;
	}

	if (largs->iArret<=0)
		pthread_cond_signal(&tCond);

	pthread_mutex_unlock(&tMutex);
	pthread_exit(NULL);
}

void led(union sigval sv)
{
	pthread_mutex_lock(&tMutex);
	LARGS largs = sv.sival_ptr;

	if (largs->iOnOff)
	{
		largs->iRang = tSuivant[largs->iMode][largs->iRang];
		bcm2835_gpio_write(iLed[(largs->iRang-1)/2], 1 - (largs->iRang-1)%2);
	}
	else	raz_leds();

	if (largs->iArret<=0)
		pthread_cond_signal(&tCond);

	pthread_mutex_unlock(&tMutex);
	pthread_exit(NULL);
}

/*******************************/
/*                             */
/*     Création des Timers     */
/*                             */
/*******************************/

void *timer(void *ptr)
{
	int			iStatus;
	timer_t			tTimerid;
	struct sigevent		sSevt;
	struct itimerspec	sIts;

	pthread_mutex_lock(&tMutex);
	LPARAMS	lparams = ptr;

	/*===========================*/
	/*     Création du Timer     */
	/*===========================*/

	memset(&sSevt, 0, sizeof(struct sigevent));

	sSevt.sigev_notify		= SIGEV_THREAD;
	sSevt.sigev_notify_function	= lparams->function;
	sSevt.sigev_notify_attributes	= NULL;
	sSevt.sigev_value.sival_ptr	= &args;

	if ((iStatus = timer_create(CLOCK_REALTIME, &sSevt, &tTimerid)) == -1)
	{
		printf("%s : %d : timer %d create failed : %d\n", __FILE__, __LINE__, lparams->iNumero, iStatus);
		pthread_exit(NULL);
	}

	/*============================*/
	/*     Lancement du Timer     */
	/*============================*/

	memset(&sIts, 0, sizeof(struct itimerspec));

	sIts.it_interval.tv_sec	= lparams->period_sec;
	sIts.it_interval.tv_nsec= lparams->period_nsec;

	sIts.it_value.tv_sec	= lparams->period_sec;
	sIts.it_value.tv_nsec	= lparams->period_nsec;

	if ((iStatus = timer_settime(tTimerid, 0, &sIts, NULL)) == -1)
	{
		printf("%s : %d : timer %d settime start failed : %d\n", __FILE__, __LINE__, lparams->iNumero, iStatus);
		pthread_exit(NULL);
	}

	/*=================================================*/
	/*     Condition d'attente de l'arrêt du Timer     */
	/*=================================================*/

	pthread_cond_wait(&tCond, &tMutex);

	/*========================*/
	/*     Arrêt du Timer     */
	/*========================*/

	sIts.it_interval.tv_sec	= 0;
	sIts.it_interval.tv_nsec= 0L;
	sIts.it_value.tv_sec	= 0;
	sIts.it_value.tv_nsec	= 0L;

	if ((iStatus = timer_settime(tTimerid, 0, &sIts, NULL)) == -1)
	{
		printf("%s : %d : timer %d settime stop failed : %d\n", __FILE__, __LINE__, lparams->iNumero, iStatus);
		pthread_exit(NULL);
	}

	/*==============================*/
	/*     Destruction du Timer     */
	/*==============================*/

	if ((iStatus = timer_delete(tTimerid)) == -1)
	{
		printf("%s : %d : timer %d delete failed : %d\n", __FILE__, __LINE__, lparams->iNumero, iStatus);
		pthread_exit(NULL);
	}

	pthread_mutex_unlock(&tMutex);
	pthread_exit(NULL);
}

/********************************/
/*                              */
/*     Procédure Principale     */
/*                              */
/********************************/

int main(void)
{
	int	iStatus;

	/*====================================*/
	/*     Déclaration des paramètres     */
	/*====================================*/

	PARAMS	params[_NBRE_THREAD] =
		{{0, 1, button1, 0L, 50000000L},
		 {0, 2, button2, 0L, 50000000L},
		 {0, 3, led,     0L, 80000000L}};

	/*=====================================*/
	/*     Gestion du signal 'SIGINTR'     */
	/*=====================================*/

	action.sa_handler = handler;
	sigfillset(&action.sa_mask);
	sigaction(SIGINT, &action, NULL);

	/*=================================*/
	/*     Initialisation des GPIO     */
	/*=================================*/

	printf("Début : Boutons & Leds !\n");

	if (!(iStatus = bcm2835_init()))
	{
		printf("%s : %d : bcm2835 init failed : %d\n", __FILE__, __LINE__, iStatus);
		exit(-1);
	}

	gpio_init();

	/*=============================*/
	/*     Création d'un mutex     */
	/*=============================*/

	if ((iStatus = pthread_mutex_init(&tMutex, NULL)))
	{
		printf("%s : %d : mutex init failed : %d\n", __FILE__, __LINE__, iStatus);
		exit(-1);
	}

	/*===========================================*/
	/*     Création d'une variable condition     */
	/*===========================================*/

	if ((iStatus = pthread_cond_init(&tCond, NULL)))
	{
		printf("%s : %d : condition variable init failed : %d\n", __FILE__, __LINE__, iStatus);
		exit(-1);
	}

	/*=======================================*/
	/*     Démarrage de tous les threads     */
	/*=======================================*/

	for (int i=0; i<_NBRE_THREAD; i++)
	{
		if ((iStatus = pthread_create(&params[i].tThread, NULL, timer, (void *) &params[i])))
		{
			printf("%s : %d : thread %4d create failed : %d\n", __FILE__, __LINE__, params[i].iNumero, iStatus);
			exit(-1);
		}
	}

	/*===============================================*/
	/*     Attente de la fin de tous les Threads     */
	/*===============================================*/

	for (int i=0; i<_NBRE_THREAD; i++)
	{
		if ((iStatus = pthread_join(params[i].tThread, NULL)))
		{
			printf("%s : %d : thread %4d join failed : %d\n", __FILE__, __LINE__, params[i].iNumero, iStatus);
			exit(-1);
		}

//		if ((iStatus = pthread_detach(params[i].tThread)))
//		{
//			printf("%s : %d : thread %4d detach failed : %d\n", __FILE__, __LINE__, params[i].iNumero, iStatus);
//			exit(-1);
//		}
	}

	/*==============================================*/
	/*     Destruction de la variable condition     */
	/*==============================================*/

	if ((iStatus = pthread_cond_destroy(&tCond)))
	{
		printf("%s : %d : condition variable destroy failed : %d\n", __FILE__, __LINE__, iStatus);
		exit(-1);
	}

	/*==============================*/
	/*     Destruction du Mutex     */
	/*==============================*/

	if ((iStatus = pthread_mutex_destroy(&tMutex)))
	{
		printf("%s : %d : mutex destroy failed : %d\n", __FILE__, __LINE__, iStatus);
		exit(-1);
	}

	/*============================*/
	/*     Fermeture des GPIO     */
	/*============================*/

	raz_leds();
	gpio_reset();

	if (!(iStatus = bcm2835_close()))
	{
		printf("%s : %d : bcm2835 close failed : %d\n", __FILE__, __LINE__, iStatus);
		exit(-1);
	}

	printf("Fin   : Boutons & Leds !\n");
	exit(EXIT_SUCCESS);
}
Si vous avez des questions, n'hésitez-pas ! :)
@+
RPI4B/8GB + Argon FanHAt
Rpi3A+, Rpi3B+
RPi 2B + Joy-It I2C Serial 20x4 2004 LCD Module
RPi 2B + PIM273 Unicorn HAT HD 16x16 Leds RGB
RPi0v1.3, RPi0W + LibreElec/Kodi, Rpi0WH + Tuner TV HAT
NodeMCU ESP32

destroyedlolo
Raspinaute
Messages : 1583
Enregistré le : dim. 10 mai 2015 18:44
Localisation : Dans la campagne à côté d'Annecy
Contact :

Re: Des interrupteurs et des leds (Chenillard) !

Message par destroyedlolo » jeu. 31 oct. 2019 13:32

Salut,

Tout d’abord, merci du partage : c'est suffisamment rare pour etre signaler :)

Par contre, pourquoi utiliser la librairie BCM2835 qui est spécifique aux Raspberry alors qu'une fonctionnalité aussi simple est prise en compte par le kernel ?
L'avantage de SysFS est que ca fonctionnera sur n'importe quelle machine.

Par exemple : http://destroyedlolo.info/BananaPI/Led/
(je l'ai fait directement depuis le shell, mais la transition au C est évidente :mrgreen: ).

A+
  • BananaPI : Gentoo, disque SATA de 2 To
  • Domotique : 1-wire, TéléInfo, Tablette passée sous Gentoo, ESP8266
  • Multimedia par DNLA
  • Et pleins d'idées ... et bien sûr, pas assez de temps.
Un descriptif de ma domotique 100% fait maison.

Artemus24
Raspinaute
Messages : 1077
Enregistré le : ven. 15 sept. 2017 19:15

Re: Des interrupteurs et des leds (Chenillard) !

Message par Artemus24 » jeu. 31 oct. 2019 20:35

Salut destroyedlolo.

Pourquoi avoir utilisé la bibliothèque "BCM2835" ?
Je ne voulais pas utiliser la bibliothèque de Mr. Gordon Henderson (WiringPi) car elle est obsolète.
Comme "Bud Spencer" m'avait parlé d'une autre bibliothèque, j'ai voulu la tester.
Et du coup, peut-être par fainéantise, je l'ai conservé dans ce petit programme.

En effet, on peut ne pas se servir de cette bibliothèque pour faire référence aux GPIO de la raspberry.
Voici des exemples bien documentés de l'accès direct aux GPIO :
--> https://www.blaess.fr/christophe/2012/1 ... pberry-pi/
--> https://www.blaess.fr/christophe/2018/1 ... -partie-1/
--> https://www.blaess.fr/christophe/2018/1 ... -partie-2/
--> http://silanus.fr/bts/activites/raspber ... SN2V1.html
--> https://arduino103.blogspot.com/2019/01 ... -mort.html

Il y a ça aussi :
--> https://www.kernel.org/doc/Documentation/gpio/sysfs.txt

J'ai comme projet de créer ma propre bibliothèque pour gérer les accès aux périphériques.
Genre GPIO, I2C, SPI, tty, ...

Cela ne se fait pas directement comme dans ton exemple, mais on passe par la fonction "ioctl".
--> https://fr.wikipedia.org/wiki/Ioctl
C'est juste de l'habillage, mais cela permet d'encapsuler des requêtes à envoyer aux périphériques.

Tant que je n'ai pas réalisé et testé ma propre bibliothèque, je ne vais pas toucher à ce petit programme.

P.S.: quand j'aurai l'occasion, je vais photographier la breadbord où j'ai disposé les fils rouges et jaunes ainsi que les leds et interrupteurs.
C'est juste pour illustrer le montage. Je ne vais pas documenter le montage car il est par ailleurs suffisamment décrit sur le net.

@+
RPI4B/8GB + Argon FanHAt
Rpi3A+, Rpi3B+
RPi 2B + Joy-It I2C Serial 20x4 2004 LCD Module
RPi 2B + PIM273 Unicorn HAT HD 16x16 Leds RGB
RPi0v1.3, RPi0W + LibreElec/Kodi, Rpi0WH + Tuner TV HAT
NodeMCU ESP32

Bud Spencer
Raspinaute
Messages : 1089
Enregistré le : lun. 15 août 2016 21:38

Re: Des interrupteurs et des leds (Chenillard) !

Message par Bud Spencer » sam. 2 nov. 2019 11:43

sysfs pour les GPIO, faut oublier, c'est deprecated.
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).

destroyedlolo
Raspinaute
Messages : 1583
Enregistré le : dim. 10 mai 2015 18:44
Localisation : Dans la campagne à côté d'Annecy
Contact :

Re: Des interrupteurs et des leds (Chenillard) !

Message par destroyedlolo » dim. 3 nov. 2019 21:46

Artemus24 a écrit :
jeu. 31 oct. 2019 20:35
Cela ne se fait pas directement comme dans ton exemple, mais on passe par la fonction "ioctl".
--> https://fr.wikipedia.org/wiki/Ioctl
C'est juste de l'habillage, mais cela permet d'encapsuler des requêtes à envoyer aux périphériques.
Ben dans ce cas la, regarde du coté de libgpiod qui le permet directement comme on peut le voir dans cet exemple.

Perso, je n'ai pas essayé car je suis bloqué a un antédiluvien 3.xx.xx car j'ai un périph dont le DTS n'a jamais été fourni, mais je me promet d'essayer le jour ou j'aurai le temps (la neige arrivant, ca ne sera pas tout de suite). Surtout pour voir si on a toujours un accès à la SysFS ce qui est vraiment pratique.
  • BananaPI : Gentoo, disque SATA de 2 To
  • Domotique : 1-wire, TéléInfo, Tablette passée sous Gentoo, ESP8266
  • Multimedia par DNLA
  • Et pleins d'idées ... et bien sûr, pas assez de temps.
Un descriptif de ma domotique 100% fait maison.

Artemus24
Raspinaute
Messages : 1077
Enregistré le : ven. 15 sept. 2017 19:15

Re: Des interrupteurs et des leds (Chenillard) !

Message par Artemus24 » mar. 5 nov. 2019 02:18

Salut à tous.

Merci pour ces informations. Quand j'aurai le temps, je me consacrerais à ces nouvelles fonctionnalités.
J'espère que c'est standard. :)

@+
RPI4B/8GB + Argon FanHAt
Rpi3A+, Rpi3B+
RPi 2B + Joy-It I2C Serial 20x4 2004 LCD Module
RPi 2B + PIM273 Unicorn HAT HD 16x16 Leds RGB
RPi0v1.3, RPi0W + LibreElec/Kodi, Rpi0WH + Tuner TV HAT
NodeMCU ESP32

Bud Spencer
Raspinaute
Messages : 1089
Enregistré le : lun. 15 août 2016 21:38

Re: Des interrupteurs et des leds (Chenillard) !

Message par Bud Spencer » mar. 5 nov. 2019 09:51

Artemus24 a écrit :
mar. 5 nov. 2019 02:18
J'espère que c'est standard. :)
libgpiod est une nouvelle api standard. sysfs gpio qui en plus d’être très limité et extrêmement lent posait des problèmes de persistance des états. libgpiod est censé régler tout ça tout en restant standard. A titre informatif, il faut savoir que juste suivant les modèles de PI, le simple changement d’état d’une sortie est 1000 à 3000 fois plus lent avec sysfs que la même action exécutée avec une lib comme wiringpi ou bcm2835.

Pour résumer :
sysfs/class/gpio : standard, pauvre, peut performant , déprécié
libgpiod : standard, riche, bonne performance, kernel >= 4.8
/dev/mem : non standard, riche, très performant

Toujours à titre informatif pour ceux qui s’intéressent aux méthodes de développement moderne et innovante, le package System.Device.Gpio de .Net Core 3 pour les systems Unix,Linux prend déjà en charge libgpiod en plus de sysfs/class/gpio et /dev/mem.
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).

Artemus24
Raspinaute
Messages : 1077
Enregistré le : ven. 15 sept. 2017 19:15

Re: Des interrupteurs et des leds (Chenillard) !

Message par Artemus24 » jeu. 7 nov. 2019 08:10

Salut Bud Spencer.

Merci pour les informations ! :)

Cordialement.
Artemus24
@+
RPI4B/8GB + Argon FanHAt
Rpi3A+, Rpi3B+
RPi 2B + Joy-It I2C Serial 20x4 2004 LCD Module
RPi 2B + PIM273 Unicorn HAT HD 16x16 Leds RGB
RPi0v1.3, RPi0W + LibreElec/Kodi, Rpi0WH + Tuner TV HAT
NodeMCU ESP32

Répondre

Retourner vers « Tutoriels »