IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Voir le flux RSS

f-leb

PSoC 4 : ma carte configurée en esclave I2C, et pilotée par une Raspberry Pi - Partie 6

Noter ce billet
par , 07/05/2020 à 11h41 (319 Affichages)
Partie 6 – Communication I2C en langage C sur Raspberry Pi

Cette fois, ça y est ! Ma carte PSoC est configurée en esclave pour le protocole I2C et communique avec mon Raspberry Pi 3. Il me reste à vous présenter une petite application de démonstration…


Trois glissières pour faire varier l'intensité de chaque composante Rouge, Vert ou Bleu
Rappels sur la synthèse additive des couleurs : rouge+vert=jaune ; rouge+bleu=magenta ; vert+bleu=cyan et rouge+vert+bleu=blanc.

En langage C, plusieurs bibliothèques existent pour exploiter le port GPIO du Pi. La plus populaire, Wiring Pi est hélas dépréciée depuis les mésaventures de son auteur.
Je me tourne alors vers la bibliothèque bcm2835 écrite par Mike McCauley, toujours maintenue, fonctionnant même avec le dernier Raspberry Pi 4 et toutes les versions de Debian, y compris le dernier Debian Buster 10. L’installation, très simple, de cette bibliothèque est décrite sur le site.
Bien entendu, elle dispose d’un module pour la communication I2C : I2C access.
Pour l’IHM avec les trois glissières, j’utilise GTK, la version 2… Je sais, je sais… une vielle version qui a dix ans alors qu’il y a une version 3 depuis gna gna gna

Le programme n’étant pas très long, l’éditeur Geany installé par défaut avec la distribution Raspbian suffit largement.

Nom : Rpi-geany.PNG
Affichages : 105
Taille : 792,0 Ko

Je donne ici le code complet (certainement perfectible) et les commandes de compilation.

psoc-i2c-slave.h
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
#include <stdint.h>
 
#ifndef PSOC_I2C_SLAVE_
#define PSOC_I2C_SLAVE_
 
#define SLAVE_ADDR		(0x08)
 
#define LED_ON			(0xFF)
#define LED_OFF			(0x00)
 
#define RED_LABEL		"Rouge"
#define GREEN_LABEL		"Vert"
#define BLUE_LABEL		"Bleu"
 
enum color_reg {red_register = 0x01, green_register, blue_register};
 
uint8_t slaveInit(void);
uint8_t slaveClose(void);
uint8_t setColor(const enum color_reg reg, const char lum);
uint8_t* getColors(void);
 
#endif

psoc-i2c-slave.c
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
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <bcm2835.h>
#include "psoc-i2c-slave.h"
 
uint8_t slaveInit(void){ // Initialisation de la connexion I2C
	if (!bcm2835_init()) {
		return 0u;
	} else {
		bcm2835_i2c_begin();
		bcm2835_i2c_setSlaveAddress(SLAVE_ADDR);
		return 1u;
	}
	}
 
uint8_t slaveClose(void){ // Fermeture de la connexion I2C
	bcm2835_i2c_end();	
	}
 
/* Modification de composante R, V ou B */	
uint8_t setColor(const enum color_reg reg, const char lum) {
	char buf[] = {reg, lum};
	uint8_t er = bcm2835_i2c_write(buf, 2); //écriture dans le buffer writeBuffer
	switch (er) {
		case BCM2835_I2C_REASON_OK:
			//printf("SUCCES\n");
			break;
		default:
			printf("ERROR\n");			
		}	
	return er;
	} 
 
/* Récupération des composantes R, V et B */	
uint8_t* getColors(void) {
	uint8_t *t = malloc(3);
	if (!t)
		return NULL;
	bcm2835_i2c_read(t, 3); // Lecture du buffer ReadBuffer
	return t;
	}

main.c
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
 
#include "psoc-i2c-slave.h"
 
static void scaleMoved (GtkRange *range, gpointer user_data)
{ /* Modification de l'éclairage de la led 
	 sur chaque mouvement de glissière */
	char *c = user_data; // Glissière Rouge, Vert ou Bleu
	char lum = (char)gtk_range_get_value(range); // Nouvelle valeur glissière
 
	if (!strcmp(c, RED_LABEL)) { // si la glissière Rouge est déplacée
		printf("Rouge détecté %i\n", lum);
		setColor(red_register, lum);
	}
	else
	if (!strcmp(c, GREEN_LABEL)) { // si la glissière Vert est déplacée
		printf("Vert détecté %i\n", lum);
		setColor(green_register, lum);
	}
	else
	if (!strcmp(c, BLUE_LABEL)) { // si la glissière Bleu est déplacée
		printf("Bleu détecté %i\n", lum);
		setColor(blue_register, lum);
	}
	else {
		printf("Erreur couleur");
	}
}
 
static void destroy( GtkWidget *widget, gpointer data )
{
    slaveClose();
    gtk_main_quit ();
}
 
 
int main(int argc,char **argv)
{
	if (!slaveInit()) { // Erreur connexion I2C
		printf("ERREUR I2C\n");
		return EXIT_FAILURE;
	}
 
   GtkWidget *pWindow;
   GtkWidget *pMainVBox;
   GtkWidget *pFrame;
   GtkWidget *pScaleRed, *pScaleGreen, *pScaleBlue;
 
   gtk_init(&argc,&argv);
 
   pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); // Fenêtre principale
   gtk_window_set_title(GTK_WINDOW(pWindow), "Gtk SelectColor");
   gtk_window_set_default_size(GTK_WINDOW(pWindow), 320, 200);
   gtk_container_set_border_width(GTK_CONTAINER(pWindow), 4);
 
   pMainVBox = gtk_vbox_new(TRUE, 0); // Boîte verticale
   gtk_container_add(GTK_CONTAINER(pWindow), pMainVBox);
 
   pFrame = gtk_frame_new(RED_LABEL);
   pScaleRed = gtk_hscale_new_with_range(0, 255, 1); // Glissière Rouge
   gtk_container_add(GTK_CONTAINER(pFrame), pScaleRed);
   gtk_box_pack_start(GTK_BOX(pMainVBox), pFrame, FALSE, FALSE, 0);
 
    g_signal_connect (pScaleRed, 
                    "value-changed", 
                    G_CALLBACK (scaleMoved), 
                    (gpointer)gtk_frame_get_label (GTK_FRAME(pFrame)));
 
   pFrame = gtk_frame_new(GREEN_LABEL);
   pScaleGreen = gtk_hscale_new_with_range(0, 255, 1); // Glissière Vert
   gtk_container_add(GTK_CONTAINER(pFrame), pScaleGreen);
   gtk_box_pack_start(GTK_BOX(pMainVBox), pFrame, FALSE, FALSE, 0);
 
   g_signal_connect (pScaleGreen, 
                    "value-changed", 
                    G_CALLBACK (scaleMoved), 
                    (gpointer)gtk_frame_get_label (GTK_FRAME(pFrame)));
 
 
   pFrame = gtk_frame_new(BLUE_LABEL);
   pScaleBlue = gtk_hscale_new_with_range(0, 255, 1); // Glissière Bleu
   gtk_container_add(GTK_CONTAINER(pFrame), pScaleBlue);
   gtk_box_pack_start(GTK_BOX(pMainVBox), pFrame, FALSE, FALSE, 0);
 
   g_signal_connect (pScaleBlue, 
                    "value-changed", 
                    G_CALLBACK (scaleMoved), 
                    (gpointer)gtk_frame_get_label (GTK_FRAME(pFrame)));
 
   gtk_widget_show_all(pWindow);
 
   g_signal_connect(G_OBJECT(pWindow), "destroy", G_CALLBACK(destroy), NULL);
 
   uint8_t *col = getColors();
   if (col) { // Initialisation des glissières RVB
	gtk_range_set_value(GTK_RANGE(pScaleRed), col[0]);
	gtk_range_set_value(GTK_RANGE(pScaleGreen), col[1]);
	gtk_range_set_value(GTK_RANGE(pScaleBlue), col[2]);
	free(col);
   }
 
   gtk_main();
 
   return EXIT_SUCCESS;
}

Commandes de compilation
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
gcc -c -o main.o main.c `pkg-config --cflags gtk+-2.0`
gcc -c -o psoc-i2c-slave.o psoc-i2c-slave.c `pkg-config --cflags gtk+-2.0`
gcc -o final main.o psoc-i2c-slave.o `pkg-config --cflags gtk+-2.0` -lbcm2835 `pkg-config --libs gtk+-2.0`
Le principe du programme est très simple. Au démarrage de l'application, on requiert les composantes RVB définie initialement sur la carte esclave (fonction getColors()) pour positionner les glissières.
À chaque déplacement d'une des trois glissières, la fonction événementielle scaleMoved() est appelée avec en paramètre la glissière sollicitée et la nouvelle valeur d'intensité sur celle-ci. La fonction setColor() permet alors de transmettre la modification de couleur, via la liaison I2C, au composant esclave qui reconfigurera la LED de la carte.

Et voilà qui clôt cette série, même s'il n'est pas exclu que je revienne la compléter si des idées me viennent...
Si votre carte à microcontrôleur bardée de capteurs ou actionneurs peut être configurée en esclave pour le protocole I2C, la Raspberry Pi en tant que maître est tout à fait apte à la communication dans ce protocole, aussi bien en C, en Python, Java, Go, JavaScript, et certainement d'autres langages encore.

Envoyer le billet « PSoC 4 : ma carte configurée en esclave I2C, et pilotée par une Raspberry Pi - Partie 6 » dans le blog Viadeo Envoyer le billet « PSoC 4 : ma carte configurée en esclave I2C, et pilotée par une Raspberry Pi - Partie 6 » dans le blog Twitter Envoyer le billet « PSoC 4 : ma carte configurée en esclave I2C, et pilotée par une Raspberry Pi - Partie 6 » dans le blog Google Envoyer le billet « PSoC 4 : ma carte configurée en esclave I2C, et pilotée par une Raspberry Pi - Partie 6 » dans le blog Facebook Envoyer le billet « PSoC 4 : ma carte configurée en esclave I2C, et pilotée par une Raspberry Pi - Partie 6 » dans le blog Digg Envoyer le billet « PSoC 4 : ma carte configurée en esclave I2C, et pilotée par une Raspberry Pi - Partie 6 » dans le blog Delicious Envoyer le billet « PSoC 4 : ma carte configurée en esclave I2C, et pilotée par une Raspberry Pi - Partie 6 » dans le blog MySpace Envoyer le billet « PSoC 4 : ma carte configurée en esclave I2C, et pilotée par une Raspberry Pi - Partie 6 » dans le blog Yahoo

Mis à jour 08/03/2021 à 17h10 par f-leb

Catégories
Raspberry Pi , Programmation , C

Commentaires