Du simple clignotement de LED, je vais vous emmener à la mesure d’une température à l’aide d’une sonde pilotée via le bus I2C et à la consultation de cette température par le biais d’une page Web, le tout en Go !
Tout un programme qui je l’espère ne vous donnera pas de sueur froide.
Au sommaire :
Description du projet
L’application lira la température de la sonde à interval régulier via le bus I2C du Raspberry Pi. La sonde sera de type HTU21D (sonde de température et d’humidité). J’ai effectué tous mes développements avec la carte miniature de Sparkfun. La valeur de la température sera stockée dans une variable. L’application servira de serveur Web et délivrera une page avec la température stockée dans la variable.
Je couperai le programme en 2 parties :
- L’utilisation d’I2C en Go pour interagir avec la sonde
- Réalisation du serveur Web
Définition du bus I2C
Le protocole permet de mettre en communication un composant maître (le Raspberry Pi) et plusieurs périphériques esclaves (sonde HTU21D dans cet article). Plusieurs maîtres peuvent partager le même bus, et un même composant peut passer du statut d’esclave à celui de maître, ou inversement. Toutefois, la communication n’a lieu qu’entre un seul maître et un seul esclave. Notons également que le maître peut également envoyer un ordre à tous ses esclaves simultanément (par exemple, une mise en sommeil ou une demande de réinitialisation).
(Source : GNU/Linux Magazine Hors-Série n°75)
Spécification du composant HTU21D
Interface de communication : bus I2C
Précision de la sonde d’humidité : ±2%
Précision de la sonde de température : ±0.3°C
Fonctionnement de 0% à 100% d’humidité, toutefois le composant ne doit pas être mis en contact avec l’eau (comme la pluie)
Alimentation : 3,3V
Limitation : 1 composant par bus I2C vu que le composant ne dispose que d’une seule adresse de communication
Schéma de câblage
3V3 -> Plot +
GND -> Plot –
SDA -> Plot DA
SCL -> Plot CL
Installation de Go
Reportez vous aux instructions de mon précédent article ici
Configuration du Rasberry Pi
Initialement, le noyau Linux de Raspbian ne détecte aucun contrôleur I2C.
Pour l’activer, lancez raspi-config depuis la console :
sudo raspi-config
Choisissez “Advanced Options”.
Choisissez “I2C”.
Validez l’option “Oui”.
Le contrôleur I2C de votre Raspberry Pi est maintenant actif.
Programmation
La première partie du programme va se contenter de lire à intervalle régulier la température, de la stocker et de l’afficher dans la console.
Installez depuis la console une librairie native Go pour piloter les composants I2C ainsi que ma librairie liée au composant HTU21D :
go get github.com/davecheney/i2c go get github.com/mlgd/sensors
Créez le dossier du projet :
mkdir -p $HOME/go/src/mondomaine.ext/webtemp
Créez le fichier source depuis la console :
cd $HOME/go/src/mondomaine.ext/webtemp nano webtemp.go
Le contenu du programme est le suivant :
package main import ( "fmt" "log" "os" "os/signal" "sync" "syscall" "time" "github.com/mlgd/sensors" ) var ( // Variable globale de stockage de la dernière température lue temperature float32 // Variable d'accès au composant de la sonde via I2C htu21d *sensors.HTU21D wg sync.WaitGroup finLecture chan bool ) func main() { // Initialisation de la variable pour transmettre la fin de lecture finLecture = make(chan bool, 1) // Création d’une variable pour l’interception du signal de fin de programme c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) signal.Notify(c, syscall.SIGTERM) signal.Notify(c, syscall.SIGKILL) // Go routine (thread parallèle) d’attente de fin du programme go func() { <-c // Notification de fin de lecture pour quitter la focntion litSonde() finLecture <- true // Attend que le compteur de groupe soit à 0 wg.Wait() htu21d.Close() os.Exit(0) }() var err error htu21d, err = sensors.NewHTU21D(sensors.HTU21D_ADDR, 1) if err != nil { log.Println("Erreur d'initialisation du composant HTU21D") return } // Incrémente de 1 le compteur de groupe wg.Add(1) // Lecture infinie de la sonde litSonde() } func litSonde() { // Instructions exécutées lorsque la fonction sera quitter defer func() { // Décrémente de 1 le compteur de groupe wg.Done() }() for { select { case <-finLecture: // Fin de lecture demandée, quitter la fonction return default: // Lecture de la température if temp, err := htu21d.ReadTemperature(); err == nil { // Si aucune erreur, mémoriser la valeur temperature = temp fmt.Printf("Température : %.2f° C\n", temperature) } } // Attente d’une seconde time.Sleep(time.Second) } }
Exécution du programme
Exécutez la commande de compilation :
go build webtemp.go
Puis lancez le programme :
sudo ./webtemp
Observez votre console qui affiche la température :
Évolution du programme
Maintenant que vous avez créé la base du programme pour lire la température, nous voici à la deuxième partie du programme.
Vous allez rendre la consultation plus “user-friendly” (conviviale) en transformant l’application en un serveur Web répondant sur le port TCP 8080 de l’IP locale de votre Raspberry Pi. Cela vous permettra de consulter la température depuis un smartphone par exemple.
Commencez par remplacer les 2 dernières lignes de la fonction main() :
// Lecture infinie de la sonde litSonde()
par
// Go routine (thread parallèle) de lecture de la sonde go litSonde() // Démarrage du serveur Web http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil)
Ajoutez la fonction suivante à la fin du fichier :
func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "<div style='text-align: center'><p>Température</p><h1>%0.2f° C</h1></div>", temperature) }
Retirez la ligne suivante de la fonction litSonde() pour rendre le programme moins verbeux :
fmt.Printf("Température : %.2f° C\n", temperature)
Ce qui vous donne le programme suivant :
package main import ( "fmt" "log" "net/http" "os" "os/signal" "sync" "syscall" "time" "github.com/mlgd/sensors" ) var ( // Variable globale de stockage de la dernière température lue temperature float32 // Variable d'accès au composant de la sonde via I2C htu21d *sensors.HTU21D wg sync.WaitGroup finLecture chan bool ) func main() { // Initialisation de la variable pour transmettre la fin de lecture finLecture = make(chan bool, 1) // Création d’une variable pour l’interception du signal de fin de programme c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) signal.Notify(c, syscall.SIGTERM) signal.Notify(c, syscall.SIGKILL) // Go routine (thread parallèle) d’attente de fin du programme go func() { <-c // Notification de fin de lecture pour quitter la focntion litSonde() finLecture <- true // Attend que le compteur de groupe soit à 0 wg.Wait() htu21d.Close() os.Exit(0) }() var err error htu21d, err = sensors.NewHTU21D(sensors.HTU21D_ADDR, 1) if err != nil { log.Println("Erreur d'initialisation du composant HTU21D") return } // Incrémente de 1 le compteur de groupe wg.Add(1) // Go routine (thread parallèle) de lecture de la sonde go litSonde() // Démarrage du serveur Web http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) } func litSonde() { // Instructions exécutées lorsque la fonction sera quitter defer func() { // Décrémente de 1 le compteur de groupe wg.Done() }() for { select { case <-finLecture: // Fin de lecture demandée, quitter la fonction return default: // Lecture de la température if temp, err := htu21d.ReadTemperature(); err == nil { // Si aucune erreur, mémoriser la valeur temperature = temp } } // Attente d’une seconde time.Sleep(time.Second) } } func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "<div style='text-align: center'><p>Température</p><h1>%0.2f° C</h1></div>", temperature) }
Exécutez la commande de compilation :
go build webtemp.go
Puis lancez le programme :
sudo ./webtemp
Vous constaterez que le programme se lance et reste en attente (si vous avez bien retiré la ligne de la fonction litSonde()) :
Pour consulter la température, utilisez un navigateur Web et entrez l’adresse IP de votre Raspberry Pi suivie du port 8080. Ex : http://192.168.0.114:8080
Pour ceux d’entre vous qui ne connaîtrait pas l’adresse IP de leur Raspberry Pi, exécutez la commande suivante dans votre console :
ifconfig
Votre adresse IP apparaîtra comme ceci :
Conclusion
Vous voilà armés de quelques clés supplémentaires pour transformer votre Raspberry Pi en objet connecté avec Go. Le code source du programme reste très sommaire et quelques évolutions sont facilement intégrables pour les plus débutants, comme par exemple la lecture du taux d’humidité (inclus dans la sonde) et son affichage sur la page Web. Le site de Golang reste une très bonne source de départ pour faire évoluer les fonctionnalités Web : Writing Web Application
Bonjour,
Merci ça fait plaisir de voir un peu de go. 🙂
Ping : Prenez la température en Go | Radioamateur France
Merci de ces articles avec Go, ça va me remotiver à en faire à nouveau.
C’est plaisant mais je trouve un peu lourd la mise en place de l’environnement des projets pour un langage si léger à manipuler ensuite.