Raspberry PI – Thermostat Connecté

Une sonde DS18B20 est connectée au port GPIO du RPI. Via un formulaire on règle les consignes de température  Jour/nuit.

On clique sur ENVOYER et les consignes de température, autorisation de pilotage sont stockées dans une table d’une base MYSQL (table setpont).

Toutes les 10 minutes une tache cron lance un script PHP qui compare les consignes écrites dans la table setpoint à la mesure effectuée par la sonde DS18B20 .
Si la mesure est inférieure à la consigne, le relais de pilotage du chauffage est commandé.
Les heures de commutation Jour/Nuit sont écrites en dur dans le script PHP.

Schéma de câblage.


NB: Ne pas tenir compte du câble du BP, inutilisé dans ce projet.

Prérequis logiciel.

  • Installer APACHE
  • Installer PHP
  • Installer MYSQL ou MARIADB
  • Intaller WiringPi pour contrôler le port GPIO

Liens

Le formulaire HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Pilotage Chauffage Pouldu</title>
<link rel="stylesheet" type="text/css" href="view.css" media="all">
<script type="text/javascript" src="view.js"></script>

<SCRIPT LANGUAGE="Javascript">
	function message() {
	document.write("Bienvenue à ma page");
	}
</SCRIPT>

</head>
<body  id="main_body" >
	
	<?php
	
		//Récupération données sonde 1Wire
		$handle = fopen("/sys/bus/w1/devices/w1_bus_master1/w1_master_slaves", "r");
		if ($handle) {
			while (($sensors = fgets($handle)) !== false) {
				   $sensor = "/sys/bus/w1/devices/".trim($sensors)."/w1_slave";
				   $sensorhandle = fopen($sensor, "r");
					 if ($sensorhandle) {
						 $thermometerReading = fread($sensorhandle, filesize($sensor));
						 fclose($sensorhandle);
						 // We want the value after the t= on the 2nd line
						 preg_match("/t=(.+)/", preg_split("/\n/", $thermometerReading)[1], $matches);
						 //$celsius = round($matches[1] / 1000); //round the results
						 $celsius=number_format($matches[1] / 1000,2);
						 $fahrenheit = round($celsius*9/5+32);
						 //print "Sensor ID#: $sensors = $celsius &deg;C / $fahrenheit &deg;F<br>";
						 //print "Temperature= $celsius &deg;C<br>";
						 $sensors++;
					 } else {
						print "No motherfucking temperature read!";
					 }
			}
			fclose($handle);
		} else {
			print "No motherfucking sensors found!";
		}	
			
		//Récupération des données table setpoint
			//Connexion BDD pouldu
				$con = mysqli_connect('localhost', 'root', '12345', 'pouldu');
				if (!$con) {
					echo "Error: " . mysqli_connect_error();
					exit();
				}		
				$sql = "SELECT sh,sb,on_off,cfe FROM setpoint";
				$result = $con->query($sql);

				if ($result->num_rows > 0) {
					// output data of each row
					while($row = $result->fetch_assoc()) {
						$sh=$row["sh"];
						$sb=$row["sb"];
						$cfe=$row["cfe"];
						$on_off=$row["on_off"];

					}
				} else {
					echo "0 results";
				}
		
	?>
	<img id="top" src="top.png" alt="">
	<div id="form_container">
	
		<h1><a>Pilotage RPI3 B+ Pouldu - Sonde DS18B20</a></h1>
		<form id="form_46962" class="appnitro"  method="send" action="controle.php">
					<div class="form_description">
			<h2>Pilotage RPI3 B+ Pouldu - Sonde DS18B20</h2>
			<p>Dernière MAJ 02/03/2019</p>
		</div>						
		<ul >
		<li id="li_1" >
			<label class="description" for="mesure">Température  </label>
			<div>
				<input id="mesure" name="mesure" class="element text small" type="text" maxlength="255" value="<?php echo $celsius; ?>"/> 
			</div> 
		</li>	
		
		<li id="li_2" >
			<label class="description" for="sh">Consigne Température Jour </label>
			<div>
			<select class="element select small" id="sh" name="sh" required title="Consigne température de 06:00 à 23:00"> 
				<option value="" selected="selected"></option>
					<option value="12" >12</option>
					<option value="13" >13</option>
					<option value="14" >14</option>
					<option value="15" >15</option>
					<option value="16" >16</option>
					<option value="17" >17</option>
					<option value="18" >18</option>
					<option value="19" >19</option>
					<option value="20" >20</option>
					<option value="21" >21</option>
					<option value="22" >22</option>
					<option value="23" >23</option>
					<option selected="selected"><?php echo $sh; ?></option>

			</select>
			</div> 
		</li>	
		
		<li id="li_3" >
			<label class="description" for="sb">Consigne Température Nuit </label>
			<div>
			<select class="element select small" id="sb" name="sb" required title="Consigne température de 23:00 à 06:00"> 
				<option value="" selected="selected"></option>
					<option value="12" >12</option>
					<option value="13" >13</option>
					<option value="14" >14</option>
					<option value="15" >15</option>
					<option value="16" >16</option>
					<option value="17" >17</option>
					<option value="18" >18</option>
					<option value="19" >19</option>
					<option value="20" >20</option>
					<option value="21" >21</option>
					<option value="22" >22</option>
					<option value="23" >23</option>
					<option selected="selected"><?php echo $sb; ?></option>

			</select>
			</div> 
		</li>
		
		<li id="li_4" >
			<label class="description" for="cfe">Chauffe Eau AUTO / MANU </label>
			<div>
			<select class="element select small" id="cfe" name="cfe" required title="Chauffe Eau AUTO / MANU "> 
				<option value="M" >M</option>
				<option value="A" >A</option>
				<option selected="selected"><?php echo $cfe; ?></option>
			</select>
			</div> 
		</li>
		
		<li id="li_5" >
			<label class="description" for="onoff">Pilotage ON / OFF </label>
			<div>
			<select class="element select small" id="onoff" name="onoff" required title="Autorisation marche auto chauffage"> 
				<option value="0" >0</option>
				<option value="1" >1</option>
				<option selected="selected"><?php echo $on_off; ?></option>
				
			</select>
			</div> 
		</li>	
		
		<li class="buttons">
			    <input type="hidden" name="form_id" value="46962" />
				<input id="saveForm" class="button_text" type="submit" name="submit" value="Envoyer" />
		</li>
		</ul>
		</form>	
		<div id="footer">
			Patrice WITTE - 02/2019</a>
		</div>
	</div>
	<img id="bottom" src="bottom.png" alt="">

	</body>
</html>

Le script CONTROL.PHP

Il récupère les données du formulaire et les stocke dans la table setpoint.

<?php
	
//Init variables
	$coherence = 0;

//On récupère les variables envoyées par le formulaire (post)
	$mesure=$_GET['mesure'];
	$sh=$_GET['sh'];
	$sb=$_GET['sb'];
	$cfe=$_GET['cfe'];
	$onoff=$_GET['onoff'];
	echo $mesure;
	echo("<br>");
	echo $sh;
	echo("<br>");
	echo $sb;
	echo("<br>");
	echo $cfe;
	echo("<br>");
	echo $onoff;
	echo("<br>");
	
// Controle cohérence des saisies
	if ($sh >=$sb) {
	$coherence = 1;
	echo ("Consigne de température acceptée...");
}
if ($coherence <> 1) {
	echo ("Consigne nuit doit être inférieure à consigne jour");
	echo("<br>");
	echo ("Retour arrière dans votre navigateur pour retourner au formulaire ...");
	echo("<br>");
	exit();
}

//On va écrire les données dans une table
	//bdd		pouldu
	//table		setpoint
	//champ		id
	//champ		date_r
	//champ		sh
	//champ		sb
	
//Connexion BDD
	$con = mysqli_connect('localhost', 'root', '12345', 'pouldu');
	if (!$con) {
		echo "Error: " . mysqli_connect_error();
		exit();
	}

//Purge table
	$requete = "delete FROM setpoint";
	mysqli_query($con,$requete);

//Ecriture dans la BDD
	$request="INSERT INTO setpoint(sh,sb,cfe,on_off) VALUE('$sh','$sb','$cfe','$onoff')";	
	mysqli_query($con,$request); 
	
// Close connection
	mysqli_close ($con)
	
?>

 

Le script temp.php

Lancé via une tache cron toutes les 10 minutes il commande le relais permettant la mise en marche ou l’arrêt du chauffage.
Dans la foulée la température mesurée est stockée dans une table d’une base MYSQL (90 jours d’historique – 12960 enregistrements).

<?php
$date=date("Y-m-d");
$heure = date("H:i");
$handle = fopen("/sys/bus/w1/devices/w1_bus_master1/w1_master_slaves", "r");
$h=substr($heure,0,2);

//Gestion heures jour/nuit
		$digit1= (substr($h,0,1));
		$digit2= (substr($h,1,1));
		if ($digit1==0) {
			$h=$digit2;
		}
		//Heures de jour de 06:00 à 23:00
		if ($h >=6 and $h<23 ) {
			echo("Heures de jour");
			$periode="jour";
			echo ("<br>");
		} else {
			echo("Heures de nuit");
			$periode="nuit";
			echo ("<br>");
		}

//Lecture température sonde 1Wire Raspberry pi
	if ($handle) {
		while (($sensors = fgets($handle)) !== false) {
			   $sensor = "/sys/bus/w1/devices/".trim($sensors)."/w1_slave";
			   $sensorhandle = fopen($sensor, "r");
				 if ($sensorhandle) {
					 $thermometerReading = fread($sensorhandle, filesize($sensor));
					 fclose($sensorhandle);
					 // We want the value after the t= on the 2nd line
					 preg_match("/t=(.+)/", preg_split("/\n/", $thermometerReading)[1], $matches);
					 //$celsius = round($matches[1] / 1000); //round the results
					 $celsius=number_format($matches[1] / 1000,2);
					 $fahrenheit = round($celsius*9/5+32);
					 //print "Sensor ID#: $sensors = $celsius &deg;C / $fahrenheit &deg;F<br>";
					 //print "Temperature= $celsius &deg;C<br>";
					 print ("Mesure: ".$celsius);
					 $sensors++;
				 } else {
					print "No motherfucking temperature read!";
				 }
		}
		fclose($handle);
	} else {
		print "No motherfucking sensors found!";
	}
		
//Connexion BDD pouldu
	$con = mysqli_connect('localhost', 'root', '12345', 'pouldu');
	if (!$con) {
		echo "Error: " . mysqli_connect_error();
		exit();
	}
	
// Nb d' ENR ?
	$sql 	= 'SELECT * FROM temp_pouldu ORDER BY id';
	$query 	= mysqli_query($con, $sql);
	$nb_rows = mysqli_num_rows($query);
	
//1 Enr toutes les 10 mn - 90 jours d'historique - 12960 lignes
//On ne garde que les 12960 derniers ENR 
	if ($nb_rows >12960) {
	// On calcule le Nb d' ENR à supprimer
	$purge = $nb_rows - 12960;
	$requete = "delete FROM temp_poul ORDER BY id asc limit ".$purge;
	echo "<br>";
	mysqli_query($con,$requete);
	}
	
//Lecture des consignes de température jour et nuit et autorisation marche auto (table setpoint)
//Le formulaire form.php permet la saisie des consignes puis appelle
//le script controle.php qui update la table setpoint
	$sql = "SELECT sh,sb,on_off,cfe FROM setpoint";
	$result = $con->query($sql);

	if ($result->num_rows > 0) {
		// output data of each row
		while($row = $result->fetch_assoc()) {
			$sh=$row["sh"];
			$sb=$row["sb"];
			$cfe=$row["cfe"];
			$on_off=$row["on_off"];
			echo ("<br>");
			echo ("Consigne jour: ".$sh);
			echo ("<br>");
			echo ("Consigne nuit: ".$sb);
			echo ("<br>");
			echo ("Chauffe eau: ".$cfe);
			echo ("<br>");
			echo ("Marche auto ?  ".$on_off);
		}
	} else {
		echo "0 results";
	}
	
//Gestion Jour/Nuit
	if ($periode=="jour") {
		$consigne=$sh;
	} else {
		$consigne=$sb;
	}
		
//Ecriture dans la BDD
	$request="INSERT INTO temp_pouldu(date_r,heure,consigne,temperature,cfe,on_off) VALUE('$date','$heure','$consigne','$celsius','$cfe','$on_off')";	
	mysqli_query($con,$request); 
	echo ("<br>");
	echo $request;
	echo ("<br>");
	
	
//On regarde si le chauffage doit être piloté
	if (($celsius >=$consigne) or ($on_off ==0)){
		system ( "gpio mode 26 out" ); //Chauffage off
		system ( "gpio write 26 1" );
		
	} else {
		system ( "gpio mode 26 out" ); // Chauffage on
		system ( "gpio write 26 0" );
	}
	echo ("<br>");
	echo ("<br>");
	echo ("<br>");
	echo ("Consigne: ".$consigne);
	
//On regarde si le chauffe eau doit être piloté (Période nuit)
	if ($cfe == 'A' and $periode=="nuit") {
		system ( "gpio mode 27 out" ); // Chauffe eau on
		system ( "gpio write 27 0" );
	} else {
		system ( "gpio mode 27 out" ); // Chauffe eau off
		system ( "gpio write 27 1" );
	}

	
//Cloture connexion
	mysqli_close ();
?>

Remarque

J’ai opté pour un raspberry PI3 qui permet s’affranchir de la carte microsd en la remplaçant par une clef USB, ce qui assurera l’intégrité des données vu la fréquence des enregistrements …