Bonjour !

Après le COVID-19 (et l’ennuie qui va avec), je me suis lancé pour petit projet de créer une plante connectée. L’idée est que je n’ai rien à faire à part l’a surveiller et voir comment elle se comporte.

L’heureuse élu ! Une « Zamioculcas », Elle n’a pas besoin d’être souvent arrosée, parfait pour les tests !

Le système devra récupérer les informations suivantes et les sauvegarder sur un serveur :

  • Exposition à la lumière
  • Capteur d’humidité ambiante
  • Capteur de température
  • Capteur d’humidité du sol

N’ayant pas beaucoup de matériel pour commencer, il faut commencer par commander ! Commençons par définir un petit cahier des charges :

  • L’alimentation doit être autonome
  • La communication se fera sans fil
  • L’arrosage doit être automatique
  • Les données doivent être sauvegarder à intervalle régulier

Au niveau de la communication sans fil, j’utiliserais un module Bluetooth 4.0 LE que je possède déjà (HM-10). Mais je pense qu’un ESP8266 (Module WiFi) aurais mieux fait l’affaire 😉

La commande finale

Étude de la communication sans fil

Le temps de tout recevoir, je vais pouvoir me concentrer sur la partie communication. Au vu de l’utilisation du module Bluetooth 4.0 LE, je vais devoir utiliser le RaspberryPI 4 qui possède un module Bluetooth 5.0.

Le Raspberry devra contrôler l’intégralité des données, c’est lui qui décidera des actions et des transmissions de l’Arduino. Pour faire les essais, je vais simplement changer la couleur d’une LED RGB à distance.

La configuration, désolé de ne pas avoir mis de schéma mais je cherche un bon programme pour pouvoir en faire si vous avez !

Le programme sera très simple, si je reçois un bytes (ici le caractère C). Je vais simplement lire les 3 prochains bytes pour récupérer la couleur et changer la couleur de la LED.

Diagramme simplifié du programme de l’Arduino
#include <SoftwareSerial.h>

const int R_PIN = 6;       // R pin at Arduino pin 9
const int G_PIN = 5;       // G pin at Arduino pin 10
const int B_PIN = 3;       // B pin at Arduino pin 11

//Variables
//int lightAmbiant;          // Store value from photoresistor (0-1023)

SoftwareSerial BluetoothSerial(11, 10); // RX, TX

void RGB_color(int R, int G, int B)
 {
  analogWrite(R_PIN, R);
  analogWrite(G_PIN, G);
  analogWrite(B_PIN, B);
}

void setup() {
 Serial.begin(9600);
 BluetoothSerial.begin(9600);
 while (!BluetoothSerial) {}

 /*
 delay(1500);
 BluetoothSerial.print("AT+PASS0");
 delay(1500);
 BluetoothSerial.print("AT+NAMEBPlante");
 delay(1500);
 BluetoothSerial.print("AT+UUID0x1815");
 delay(1500);
 BluetoothSerial.print("AT+CHAR0x2A4A");
 */
 
 delay(5000);
 BluetoothSerial.print("AT+START");

 pinMode(R_PIN, OUTPUT);
 pinMode(G_PIN, OUTPUT);
 pinMode(B_PIN, OUTPUT);

 Serial.print("Bluetooth Ready !");
}

void loop() {
  char cmd = 0;
  if (BluetoothSerial.available())
    cmd = char(BluetoothSerial.read());

  switch (cmd) {
    case 'C': {
      while (BluetoothSerial.available() < 3) {}
      // Change la couleurs de la led
      int r = BluetoothSerial.read();
      int g = BluetoothSerial.read();
      int b = BluetoothSerial.read();

      RGB_color(r, g, b);
    }
  }
}

Au tour de la partie Raspberry maintenant ! Je vais utiliser python et le module BLEPY (https://github.com/IanHarvey/bluepy) pour communiquer avec l’Arduino.

L’idée va être de créer un serveur web intermédiaire en python. Lorsque nous allons recevoir des arguments sur le serveur intermédiaire, nous communiquerons ces arguments par Bluetooth à l’Arduino.

from bluepy.btle import Scanner, Peripheral, DefaultDelegate
from BaseHTTPServer  import HTTPServer, BaseHTTPRequestHandler
from urlparse import parse_qs

p = None
svc = None
ch = None

def FindAndConnect():
	global p
	global svc
	global ch
	scanner = Scanner()
	devices = scanner.scan(10.0)

	for dev in devices:
		if dev.addr == "f8:30:02:29:67:fe":
			print "La plante est trouver ! %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi)
			print "Recuperation du Peripherique ..."
			p = Peripheral( dev.addr )
			print "Recuperation du service ..."
			svc = p.getServiceByUUID( 0x1815 )
			print "Recuperation de la characteristique ..."
			ch = svc.getCharacteristics( 0x2A4A )[0]
			print "Connecter a la Plante !"

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):

    def do_GET(self):
		value = parse_qs(self.path[2:])
		if len(value) > 0:
			r = int(value['r'][0])
			g = int(value['g'][0])
			b = int(value['b'][0])
			print "R: ", r 
			print "G: ", g
			print "B: ", b
			if ch is None:
				FindAndConnect()
			
			if ch is not None:
				payload = 'C'
				payload += "{:02x}".format(r).decode("hex")
				payload += "{:02x}".format(g).decode("hex")
				payload += "{:02x}".format(b).decode("hex")

				try:
					ch.write( payload )
				except:
					print "Connexion avec la plante perdu, tentative de reconnexion"
					FindAndConnect()

		self.send_response(200)
		self.end_headers()

print "Initialisation de la premiere connexion bluetooth .."
FindAndConnect()
httpd = HTTPServer(('192.168.1.155', 8080), SimpleHTTPRequestHandler)
print "Le serveur a ete lancer sur le port 8080"
httpd.serve_forever()

Techniquement, ici il me suffira d’envoyer une requête et de mettre à jour les données avec MySQL (donc pas de serveur web intermédiaire nécessaire)

Néanmoins j’avoue que j’ai pas résisté à l’idée de la piloter en ligne ^^’ On va passer par de l’Ajax. Nous utiliserons la librairie SpectrumJS (https://bgrins.github.io/spectrum/) qui est un excellent Color Picker !


<!DOCTYPE html>
<html>
<head>
  <title>BLE Test</title>
  <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/spectrum/1.8.1/spectrum.min.css">
</head>
<body>
  <input type='input' id="picker1" />
</body>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/spectrum/1.8.1/spectrum.min.js"></script>
<script>
  const fromHexString = hexString => new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));

  var myCharacteristic;

  function updateColor(element, color) {
    let colorData = fromHexString(color.toHexString().substr(1));
    $.ajax({url: "https://theorywrong.me:8080/?r="+colorData[0]+"&g="+colorData[1]+"&b="+colorData[2]})
  }

  $("#picker1").spectrum({
      color: "#f00",
      move: function (color) { updateColor(".output.render", color); },
      hide: function (color) { updateColor(".output.render", color); }
  });
</script>
</html>

Après essai, je me suis rendu compte de l’erreur suivante. Il s’agit d’une erreur de sécurité, il est interdit d’effectuer des requêtes HTTP Ajax sur un site en HTTPS.

Erreur de sécurité !

Je vais donc créer une page intermédiaire pour les requêtes AJAX, PHP fera ses requêtes lui-même au serveur.

<?php
$r = $_GET["r"];
$g = $_GET["g"];
$b = $_GET["b"];

if (is_numeric($r) && is_numeric($g) && is_numeric($b)) {
        $url = "http://theorywrong.me:8080/?r=".$r."&g=".$g."&b=".$b;
        file_get_contents($url);
} else {
        echo "Invalid args";
}
?>

Après avoir modifié l’adresse du script AJAX, il est temps de refaire un essai.

Serveur de communication Web / Bluetooth démarré
Ça marche !

Voilà ! Le tout est pilotable à distance (Testé avec succès). Je ferais bien sur un prochain article dès que je reçois le matériel 😉

Ciao !


2 commentaires

Badboy · 10 juin 2020 à 19 h 15 min

Tiens ca me rappel quelque chose cette petite led qui change de couleur ^^

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.