Programmation en C: Série 4

Exercice 1: Le capteur SHT3x

Les capteurs de température et humidité SHT3x de Sensirion sont très répandus dans l'industrie. Après chaque mesure, ces capteurs nous fournissent 3 valeurs de 2 bytes:

statusH statusL
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
H E
temperatureH temperatureL
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
· · · · · · · · · · · · · · · ·
humiditeH humiditeL
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
· · · · · · · · · · · · · · · ·
Chaque valeur a 16 bits: H (high byte) contient les bits 8 à 15, et L (low byte) les bits 0 à 7.

A l'aide d'un petit programme, on aimerait convertir et afficher ces valeurs. Vous pouvez commencer avec le code suivant:

			#include <stdio.h>
			#include <inttypes.h>

			int main(int argc, char * argv[]) {
				// Valeurs venant du capteur
				uint8_t statusH = 0x90;
				uint8_t statusL = 0x10;
				uint8_t temperatureH = 0x58;
				uint8_t temperatureL = 0xd7;
				uint8_t humiditeH = 0x81;
				uint8_t humiditeL = 0xe5;

				// A. Vérifier le status
				...

				// B. Temperature
				int temperatureHL = ((int) temperatureH << 8) | temperatureL;

				// C. Humidité relative

				// D. Point de rosée

				return 0;
			}
		

A. Vérifier la mesure

Vérifiez que le bit E = 0 (mesure OK, pas d'erreur), et quittez le programme sinon. Affichez si le chauffage du capteur est enclenché (H = 1) ou pas (H = 0).

Vous pouvez utiliser les valeurs suivantes pour tester votre code:

		uint8_t statusH = 0xa0;
		uint8_t statusL = 0x12;
	

B. Calcul de la température

Calculez et affichez la température selon la formule correspondante à la page 14 du datasheet. Dans cette formule, ST est la valeur 16-bit fourni par le capteur.

C. Calcul de l'humidité relative

Calculez et affichez l'humidité relative selon la formule correspondante à la page 14 du datasheet. Dans cette formule, SRH est la valeur 16-bit fourni par le capteur.

D. Calcul du point de rosée

Calculez et affichez le point de rosée.

			#load solutions/capteur.c
		
Le chauffage est étaint.
Temperature:     15.7 °C
Humidité:        50.7 %
Point de rosée:  5.5 °C

Plusieurs m'ont demandé pourquoi on peut écrire

			int temperatureHL = (temperatureH << 8) | temperatureL;
		

Vu que temperatureH est un entier 8 bit (sans signe), le résultat de temperatureH << 8 devrait être 0. Pourtant, cette ligne fonctionne parfaitement. Visiblement, les opérations << et | sont exécutées sur plus que 8 bits.

Effectivement, C fait une integer promotion ici. Les valeurs temperatureH et temperatureL sont silencieusement converties en int. Ce qui est exécuté correspond donc à ça:

			int temperatureHL = ((int) temperatureH << 8) | (int) temperatureL;
		

Exercice 2: Terrain

En topographie, on utilise des modèles numériques de terrain (MNT) pour représenter l'altitude. On dispose d'un MNT de la suisse romande et une partie de l'Italie, de la France et de l'Allemagne:

Les données ont été acquit par la NASA Space Shuttle Radar Topography Mission (SRTM), et forment un maillage de 2501 sur 3601 points espacés 90 m:

Terrain

Chaque point du maillage indique l'altitude (de type double) à cet endroit.

Le code suivant peut servir comme point de départ. Il crée un tableau unidimensionnel de 2501 * 3601 cases, et lit le fichier mnt-suisse-romande:

			#include <stdio.h>
			#include <stdlib.h>
			#include <string.h>
			#include <math.h>

			int main(int argc, char * argv[]) {
				// Tableau avec les altitudes: 2501 valeurs en x (largeur), 3601 valeurs en y (hauteur)
				double * altitudes = malloc(2501 * 3601 * sizeof(double));

				// Lire les données du fichier "mnt-suisse-romande" et les mettre dans le tableau "altitudes"
				FILE * fileToRead = fopen("mnt-suisse-romande", "r");
				fread(altitudes, sizeof(double), 2501 * 3601, fileToRead);
				fclose(fileToRead);

				// L'altitude d'un point (x, y) se trouve dans la case altitudes[y * 2501 + x]
				// TON CODE

				// Libérer le tableau
				free(altitudes);
				return 0;
			}
		

A. Le point le plus haut

Cherchez le point le plus haut, et affichez

Vérification

Le point le plus haut se trouve à la position (1555, 1001) avec un altitude de 4679.0 m.

Il s'agit du sommet du Mont Blanc, qui a une altitude de 4810 m. Donc nos données ne sont pas exceptionnelles.

#load solutions/terrainA.c
Altitude max 4679.0 m
à la position 1555, 1001

B. Interpolation linéaire

Entre les points de mesure, on doit estimer l'altitude à partir des points voisins. Une méthode souvent utilisée est l'interpolation linéaire:

Interpolation linéaire

Ecrivez une fonction qui estime et retourne l'altitude d'un point X, Y avec cette méthode. Si le point se trouve en dehors de la carte, le fonction returne NaN comme altitude (return nan("")).

Vérification

altitude(1555.2, 1001.5) 4625.700
altitude(1554.86 1001.37) 4662.211
altitude(5000.0 1001.5) NaN
#load solutions/terrainB.c
Altitude au point 1555.200 1001.500 => 4625.700

C. Les sommets

Voisinage circulaire de 900 m

Admettons qu'un point est un sommet ssi dans un voisinage circulaire de 10 cases (voir schéma à droite):

Ecrivez une fonction qui vérifie si un point (x, y) est un sommet.

Vérification

Le point (1555, 1001) est un sommet (Mont Blanc). Les points autour, comme (1550, 1001), ne sont pas des sommets.

D. Liste des sommets

A l'aide la fonction précédente, affichez une liste des sommets. Vouez pouvez ignorer les 10 cases de chaque coté du terrain où le voisinage dépasse les bords du tableau.

Vérification

Il y a environ 2430 sommets sur notre MNT. Voici quelques positions (x, y):

309 13
1176 15
617 16
...
1669 3587
1620 3590

Vérification visuelle

Si votre programme affiche la liste des sommets sous le format en haut (un sommet par ligne, valeurs X et Y séparées par une espace), vous pouvez générer une image terrain.png avec vos sommets (petites croix) afin de vérifier votre algorithme.

Pour cela, téléchargez le fichiers suivants:

Compilez le code:

$$ gcc terrain2image.c image.c -lpng -ljpeg -lm -o terrain2image

Sauvegardez la sortie de votre programme dans un fichier sommets:

$$ ./ex4 > sommets

et lancez terrain2image pour générer l'image terrain.png:

$$ ./terrain2image mnt-suisse-romande < sommets
Lire les altitudes du fichier 'mnt-suisse-romande' ...
Générer le terrain ...
Lire les sommets de STDIN ...
Ecrire terrain.png ...
#load solutions/terrainCD.c
309 13
1176 15
617 16
1259 16
617 17
1496 19
1586 20
186 21
1587 21
564 22
...