Raspberry Pi et domotique

raspberry-ban
Afin d’appareiller nos maisons respectives, nous cherchions une solution domotique abordable.
Après avoir fait le tour du net et des magasins de bricolage, nous nous sommes fixés sur les équipements avec une fréquence de 433Mhz. Ces équipements sont économiques, les protocoles utilisés sont statiques et il est très simple de trouver de quoi communiquer avec.

Le projet

Nous avons profité d’un projet lancé par l’ENSICAEN en partenariat avec Radiospare. Nous souhaitons d’ailleurs les remercier tous les deux pour nous avoir accompagner tant financièrement que techniquement durant ce projet.

La base du projet est la réalisation d’un projet domotique avec Raspberry Pi.

Nous avons choisi de réaliser un petit module à greffer sur les ports du Raspberry Pi afin de pouvoir éteindre et allumer des équipements en RF433 (volets roulants, prises, lumières, etc…).
Une fois ce module réalisé, nous avons développé une interface web afin de pouvoir utiliser et scénariser les équipements.

L’architecture

Nous avons développé notre module à l’aide d’un composant permettant de moduler et démoduler les signaux RF433, le RTX MID 3V.

Afin de capturer les signaux, nous avions besoin d’un système temps réel. La première solution consiste à installer un OS temps réel sur le Raspberry Pi. La seconde consiste à utiliser un micro-contrôleur. Nous sommes partis sur la seconde solution et avons développé sur un PIC18F24k50. Il présente l’avantage d’être petit, économique et de disposer de suffisamment de RAM.

architexture_hard

Les signaux

Les signaux qui permettent de commander les équipements sont statiques. Ceci implique que pour chaque commande allumer et éteindre, le signal émit est identique. La figure ci dessous représente un signal quelconque.

signal

L’objectif de notre module est donc de faire un enregistreur de signal capable de le réémettre. Nous avons remarqué que le signal de commande était réémis plusieurs fois de suite par les émetteurs du commerce. Ceci est dû au fait que le protocole est à sens unique. Il n’y a donc pas de validation (ACK) une fois le signal reçu. Ces espaces vides sont cependant présents sur plusieurs protocoles RF433 que nous avons observé à l’oscilloscope (équipements des marques DIO et Carrefour).

Afin d’acquérir correctement le signal émis à l’intention de ces équipements, nous utilisons l’algorithme suivant :

  1. Lire état (haut/bas)
  2. Si état haut continuer, sinon revenir à 1
  3. Enregistrer le plus longtemps possible
  4. Chercher la plus longue série d’états bas consécutifs
  5. Chercher la plus proche série d’états bas consécutifs de longueur équivalente
  6. Le signal se trouve entre les deux séries d’états bas

Il suffit ensuite d’émettre plusieurs fois ce signal pour allumer ou éteindre un équipement. Cet algorithme a été implémenté en C. L’enregistrement fonctionne sur le module et la recherche du signal (étape 4 à 6) tourne sur le Raspberry Pi.

Le module

Le module se connecte sur les PIN du Raspberry Pi. La communication entre le Raspberry Pi et le PIC18F24k50 est assuré au travers du port série. Pour cela, il a été nécessaire d’utiliser une astuce pour retirer la console du port série d’un Raspberry Pi.
Le module tient dans un boîtier de Raspberry Pi avec une antenne de 8.175 cm de long.
IMG_20141122_172059

Les prochains travaux consisterons à améliorer l’antenne afin d’optimiser la porté en réception afin de permettre l’ajout de nouveaux modules.

Interface Web

Afin de mettre en place l’interface web, nous avons installé un serveur Nginx. La base php et les interfaces ont été développés par Antoine Choquet.

home

equipements

Quand est ce que ça sort

Nous réalisons encore quelques tests avec l’antenne, ce qui peut entraîner quelques changements sur le PCB. En parallèle, nous testons encore un peu le scripts d’installation. Tout ça devrait être prêt dans le courant de décembre, avant noël. Comme toujours, les sources et les schematics seront libres.

Cross compilation avec un raspberry pi

raspberry-ban

Qu’est ce qu’un cross compiler?

Un cross compiler est une chaîne de compilation qui tourne sur une architecture mais qui génère un exécutable binaire pour une autre plate forme.

Avec notre raspberry pi, s’il est assez simple de compiler un code de petite taille,il devient très difficile de compiler de gros programmes.

Enfin, il est beaucoup plus agréable de compiler sur votre machine de guerre vos fichiers en une fraction de seconde que d’attendre une minute entre chaque retouche du code compilé par le petit processeur du raspeberry pi.

NOTE : Afin de fonctionner correctement, il est nécessaire d’utiliser une distribution utilisant le hard-float ABI. Ceci est le cas de la raspian et de la dernière version de d’arch pour le raspberry.

Le jeu d’instruction

Chaque processeur utilise son propre jeu d’instructions. Celui ci correspond au jeu d’instructions assembleur. Ce jeu d’instructions est dépendant de l’architecture du microprocesseur. Il dépend directement de la manière dont sont gravé les circuits en silicium.
L’article suivant en anglais explique le fonctionnement des portes logiques que l’on peut trouver dans un microcprocesseur : Article

247x180xQuiz-Silicon-ARM-247x180.jpg.pagespeed.ic.0dZq6IhOZ8

Le jeu d’instructions supporté par les pc et qui est bien connu des reverser est le x86 qui correspond aux architectures Intel. Pour les AMD, c’est assez simple, c’est le même jeu d’instructions. Donc lorsqu’un code, par exemple du C, est compilé pour votre PC, il génère un assembleur x86 qui correspond à des instructions propres aux processeurs Intel et AMD.
Le problème c’est que le processeur présent sur le raspberry pi est un processeur ARM : 700 MHz ARM11 ARM1176JZF-S

Nous allons donc utiliser une chaîne de compilation qui générera un binaire pour le ARM1176JZF-S. Pour cela nous allons utiliser l’outil crosstool-ng.

Installation de crosstool-ng

Crosstool-ng est un outil permettant de construire des chaînes de compilation pour des plate-formes données.
Pour installer crosstool :

$ wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.17.0.tar.bz2
$ tar xjf crosstool-ng-1.17.0.tar.bz2
$ cd crosstool-ng-1.17.0/
$ sudo ./configure --prefix=/opt/crosstool
$ make
$ sudo make install

J’ai du installer quelques programmes supplémentaires. Le script configuré indique ce qu’il manque. Dans tous les cas, n’hésitez pas à poster dans les commentaires si vous avez besoin de plus d’informations.

Réaliser la chaîne de compilation pour le raspberry pi

Il va falloir créer un répertoire dans lequel crosstool-ng va enregistrer votre chaîne de configuration.

  • Créer un répertoire pour héberger votre chaîne de compilation
  • Lancer /opt/crosstool/bin/ct-ng menuconfig

Le menu suivant apparaît:
menuconfig

  • Dans Path and misc options cocher Try features marked as EXPERIMENTAL (touche Y)
  • Toujours dans Path and misc options Changer Shell to use as CONFIG SHELL et choisir sh
  • Revenir au menu principal et sélectionner Target options
    • Target architecture : ARM
    • Endianess : little endian
    • Bitness : 32 bits
  • Revenir au menu principal et sélectionner Operating system
  • Choisir Target OS linux
  • Revenir au menu principal et sélectionner Binary utilities
  • Changer binutils version pour la 2.21.1a
  • Revenir au menu principal et sélectionner C compiler
  • Cocher Show Linaro versions (EXPERIMENTAL) (touche Y)
  • Choisir linaro-4.6-2012.04 (EXPERIMENTAL)
  • Quitter et sauvegarder les changements

Cross compilons

La compilation s’effectue alors de la manière suivante :

$ ~/x-tools/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi-gcc helloWorld.c -o helloWord
$ ls
helloWord  helloWorld.c
$ scp helloWorld pi@192.168.1.107:helloWorld
pi@192.168.1.107's password: 
helloWord                                     100% 4985     4.9KB/s   00:00

On l’execute maintenant sur le raspeberry pi :

$ ssh pi@192.168.1.107
pi@192.168.1.107's password: 
Linux raspberrypi 3.2.27+ #250 PREEMPT Thu Oct 18 19:03:02 BST 2012 armv6l
 
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
 
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Jan 13 13:33:49 2013 from 192.168.1.100
pi@raspberrypi ~ $ ./helloWorld 
Oversimple says hello!

Conclusion

On remarque qu’il est relativement difficile de monter une chaîne de compilation pour un processeur ARM et surtout assez long. La réalisation de la chaîne à pris presque une heure chez moi. Cependant, il devient très vite quasi indispensable de le faire si vous souhaitez développer sur le raspberry.
La conception et la compilation de gros projets devient donc plus simple. A titre d’information, les kernels que l’on récupère sur le site du projet raspberry sont compilé de cette manière.

Source :
helloWorld.c

Halloween tricks

 

 

 

Il faut dire qu’on aime la citrouille. Et puis on vient de recevoir nos raspeberry pi.  En y regardant de plus prêt, on se rend rapidement compte qu’il faut faire quelque chose pour Halloween.

L’idée originale est donc de faire une lampe en citrouille qui s’active par la présence.

Prise en main du Raspberry pi

La première chose à faire est de voir si tout fonctionne. On va utiliser un Debian embarqué tel qu’il est proposé sur le site du raspberry pi. Pour notre projet, nous avons besoin d’allumer une lampe.
Les GPIO sont des broches d’entrée sortie dont on peut lire le niveau électrique (haut ou bas) et sur lequel on peut imposer un niveau de sortie (haut ou bas). Le niveau logique haut est une tension de 3.3V et le bas une tension de 0V.

Le mappage des GPIO est indiqué sur l’image suivante. Remarquez le petit p1 sur votre board et sur le schéma qui permettent de s’orienter.

Nous allons nous en servir en sortie pour activer une led dans un premier temps. Voici une photographie du montage :


Pour ce faire il faut définir la GPIO et indiquer le mode output :

echo "17" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio17/direction

Pour information: les GPIO fonctionnent sur les microcontroleurs (comme l’ARM du Raspberry pi) en three-state logic : Wikipédia

Il suffit maintenant de mettre à l’état haut le GPIO associé avec la commande suivante :

echo "1" > /sys/class/gpio/gpio17/value

Pour le mettre à l’état bas, mettre la valeur 0.

Pour le détecteur de mouvement en pratique il aurait été bon de prendre un détecteur infrarouge. Mais bien que terriblement efficace ce n’est pas aussi amusant que d’utiliser une webcam et de faire un peu de traitement d’image.

Conception du détecteur de mouvement

En ce qui concerne le détecteur de mouvement, nous avons utilisé une webcam ainsi que la librairie OpenCV. Voici un extrait de notre main simplifié :

int main(int argc, char **argv) {
 
	// Initialisation de notre lampe qui se trouve connecté au gpio 17
	// (voir ci-dessus)
 
	// Image
	IplImage *image1=NULL;
	IplImage *image2=NULL;
	IplImage *subImage=NULL;
 
	// Capture vidéo
	CvCapture *capture;
 
	// Ouvrir le flux vidéo,  mettre en paramètre le device de la cam (pour X = /dev/videoX)
	capture = cvCreateCameraCapture(atoi(argv[1]));
 
	//Configuration de la capture par défaut, donc la taille d'une image que l'on va récupérer. 640*480
	cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 640);
	cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480);
	cvSetCaptureProperty(capture, CV_CAP_PROP_BRIGHTNESS, 0.65);
 
	// Vérifier si l'ouverture du flux est ok
	if (!capture) {
		printf("Ouverture du flux vidéo impossible !\n");
		return 1;
	}
 
	printf("Enjoy !");
 
	// On allume notre lampe 2 fois avec une pause de 1 seconde 
 
	while(1) {
		// On récupère une image 
		image1 = cvQueryFrame(capture);
 
		// On attend 50 milisecondes
		cvWaitKey(50);
 
		// On sauvegarde notre image 1.
		cvSaveImage("buffer1.jpg",image1,0);
 
		// On récupère une image 2
		image2 = cvQueryFrame(capture);
 
		// On sauvegarde notre image 2
		cvSaveImage("buffer2.jpg",image2,0);
 
		// On recherche les 2 images
		image1 = cvLoadImage("buffer1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
		image2 = cvLoadImage("buffer2.jpg", CV_LOAD_IMAGE_GRAYSCALE);
 
		// On soustrait les 2 images une à une afin d'avoir une différence.
		subImage = substract(image1, image2);
 
		// On calcul le nombre de pixel différents
		int trigger = count(subImage);
 
		// On compare la différence avec notre TRIGGER de test.
		if(trigger > TRIGGER) {	
			// Si plus de pixel modifié par rapport a notre TRIGGER, 
			// On allume la lampe pendant 10 secondes
		}
	}
 
	// On Libère notre webcam.
	cvReleaseCapture(&capture);
 
	return 0;
}

L’ensemble du code est présent en archive.

Assemblage

Une fois le programme lancé, on lui a apporté quelques modifications afin de changer l’état d’un GPIO en 5V. Pour allumer notre lampe allimentée sur le secteur nous utiliserons un relais activable en 5V.
Cependant, les GPIO du raspberry pi ne peuvent fournir que 3.3V. Pour pouvoir activer notre relais il faut amplifier le signal. Pour cela nous avons utilisé la sortie 5V du raspberry pi et un ampli audio (LM386) avec un montage non inverseur.

L’ensemble des pièces aillant été récupéré ici et là. Ci-dessous le schéma du montage :

Résultat final


OVERSIMPLE : Halloween détecteur de mouvement par oversimple

Source

Site officiel d’OpenCV

GPIO Raspberry Pi

Codes : complete source code
It’s Oversimple isn’t it?

Open the door

Il n’y a pas si longtemps, je repensais à une scène de 60 secondes chrono. Celle où ils sont devant un garage à attendre que le propriétaire ouvre pour cracker le signal et récupérer le code de l’entrée.

En y repensant de plus près, je me suis souvenu que ma copine avait un badge du genre qui lui permet d’ouvrir une porte de garage en centre ville et on m’a prêté un oscilloscope.

Ni une ni deux je saute sur l’occasion pour vérifier la légende. Let’s open the door -> http://www.youtube.com/watch?v=eIrRPLzDrHU#t=2m03s

Ok c’était naze..

Conception de l’antenne

L’antenne se compose simplement d’un fil que l’on va enrouler. Avant d’entrer dans le vif du sujet, on peut faire un petit point sur la conception de la bobine et se souvenir comment un message électromagnétique peut être transformé en électricité. Wikipédia nous dit que

« Le champ électrique d’une onde électromagnétique induit une tension dans chaque petit segment de tout conducteur électrique.Le champ électrique d’une onde électromagnétique induit une tension dans chaque petit segment de tout conducteur électrique. La tension induite dépend de la valeur du champ électrique et de la longueur du segment. Mais la tension dépend aussi de l’orientation du segment par rapport au champ électrique. »

Ceci nous indique qu’il suffit de faire une antenne en réalisant un cercle avec du fil et de brancher notre fil à l’oscilloscope afin de voir le signal transmis par notre émetteur qui ouvre la porte de garage.

En effet le signal obtenu est très parlant (voir capture ci dessous). On voit apparaître un signal en tout ou rien, modulé en amplitude à 100%, avec une porteuse à 31Mhz environ. Lorsqu’on ouvre le boitier de notre émetteur radio qui ouvre la porte de garage, on retrouve un quartz oscillant à 30.975 Mhz. Tout semble donc en accord avec notre mesure.

Enregistrer le signal

La chose étonnante est que le signal est toujours le même. Il est donc tout à fait envisageable de l’enregistrer bêtement avec une carte d’acquisition et de rejouer le signal. Un simple montage ADC – mémoire – DAC permet de rejouer ce signal radio. Cependant, une carte d’acquisition coûte assez cher et on préférerait utiliser un montage moins lourd. Pour se faire, direction démodulation du signal. Le montage classique est un démodulation avec une diode au germanium. L’objectif étant de faire un détecteur de crêtes, les explications et le montage de ce type de circuit se trouve un peu partout sur le net. Dans le cas précis dans lequel nous nous trouvons (trop pauvre pour une diode au germanium), nous utiliserons une diode infrarouge avec un phototransistor.

Si on reprend la courbe capturée à l’oscilloscope, on voit deux phases: une première avec un niveau électrique à zéro, et une seconde avec un niveau électrique oscillant. Lorsque le niveau sera oscillant, la LED s’allumera de manière quasi continue. De l’autre côté un photo-transistor détectera l’allumage de la LED et il ne nous restera plus qu’à lisser ce signal afin d’obtenir un signal logique démodulé.

Montage

La diode émettrice est branchée directement sur notre antenne artisanale. Cette diode a été récupérée sur une vieille télécommande.

Le photo-transistor est simplement relié à la pile, en série, avec une résistance. Un petit condensateur a été ajouté afin de filtrer le bruit environnant. Ce dernier est maintenu au dessus de notre diode avec un scotch. Pour un meilleur rapport signal sur bruit, il eût été préférable d’écarter le plus possible le circuit émetteur du récepteur. Cependant lors de la découpe de la diode de la télécommande, une petite boulette nous a empêché de profiter pleinement des contacts de celle ci. Enfin ça marche.

Le signal obtenu au borne de la résistance vu à l’oscilloscope :

On observe un signal assez bruité mais ça reste lisible. Nous n’avons malheureusement pas le temps de nous plonger d’avantage dans l’étude et la fabrication d’espion plus puissant, mais on peut cependant noter qu’il ne semble pas y avoir de sécurité de type cryptographique sur la clé radio que nous avons testé.
Il est tout a fait possible d’écouter le signal avec du matériel adapté et relativement simple de le démoduler. Le reproduire consiste alors à refaire le même circuit que celui de la clé ce qui est à la portée de n’importe quel bidouilleur en électronique. Celui peut alors être rejoué simplement puisque dans les observation que nous avons faites, le même signal a toujours été émis ce qui permet le rejeu.

Pour éviter ce genre de chose, il aurait fallut envisager un protocole plus sur avec au moins un échange et permettant d’éviter le rejeu. Une question à laquelle nous espérons pouvoir répondre dès que nous aurons un peu de temps.

It’s oversimple isn’t it?

Synchronisation sur un protocole bas niveau

Nous sommes en mesure d’espionner les premières transactions. Il ne nous reste plus qu’à configurer l’affichage sur la dalle tactile. Cet article va présenter la façon dont nous avons choisi de nous synchroniser avec le signal que nous espionnons. Cette méthode peut être extrapolée à d’autres protocoles de communication.

Synchronisation entre l’espion, le terminal et la carte

Les communications avec cartes à contact suivent la norme iso7816. Les communications sont réalisées en passant, sur la ligne, un état haut ou un état bas. Ce niveau logique doit être appliqué pendant une certaine durée; la durée de transmission d’un caractère. Afin de faire simple, cette durée dépend de la fréquence d’horloge appliquée à la carte par le terminal.

On peut le définir tel que :

Tc = a*f 
où :
f est la fréquence
Tc est la durée d'un caractère
a est un facteur de proportionnalité

Le temps que dure un caractère peut changer durant la transmission mais il sera toujours fonction de la fréquence. Pour le modifier, la carte demande à ce que se soit la valeur de a qui évolue.

Une explication plus détaillée (et surtout plus juste) est faite dans la norme iso 7816 ou bien dans l’EMV book 1 téléchargeable sur le site d’EMVco : http://www.emvco.com/specifications.aspx?id=223

Trame observée

La première action consistait à visualiser le signal obtenu. Pour ce faire,  j’ai décortiqué la norme et pris un oscilloscope. Dans le cas étudié, la première chose transmise est un octet décrivant le codage des caractères (Big endian / Little endian). Il est transmis par la carte et ressemble à ceci :

On remarque alors qu’aux temps t1 et t2, nous avons, bien que le caractère soit différent, un front descendant. Ceci correspond, d’après la norme, à la transmission de trois bits. Nous allons donc nous synchroniser sur ces deux fronts descendants lancer un compteur de temps et diviser le résultat par trois afin d’obtenir la durée de transmission d’un bit.

Code

Nous codons ceci sur un micro-contrôleur pic32. Le modèle de notre PIC est le pic32mx795F512L.
Configuration de l’interruption qui doit se déclencher sur les fronts descendants:

 /* Configure the interupt on IO to answer on each falling edge*/
    ConfigINT2(EXT_INT_ENABLE | FALLING_EDGE_INT | EXT_INT_PRI_1);

Implémentation de l’interruption pour lancer le timer 1 lors du premier front descendant puis le couper lors du second.

unsigned int state = 0;
unsigned int bitDuration = 0;
 
/* INT2 ISR */
/* Interruption externe 2 */
void __ISR(_EXTERNAL_2_VECTOR, IPL1) _Int2Handler(void) {
 
    /* State = 0 il s'agit du premier front descendant */
    if(0 == state)
    {
        /* Configure le Timer1*/
        mT1ClearIntFlag();
        /*Lance le timer 1 */
        OpenTimer1(T1_ON | T1_SOURCE_INT | T1_PS_1_1, 64000);
        state = 1;
    }
    else if(1 == state)
    {
          ConfigIntTimer1(T1_INT_OFF);
          bitDuration = ReadTimer1()/3;
    }
    /*Efface le flag d'interruption*/
    mINT2ClearIntFlag();
}

bitDuration contient alors le nombre de coups de clock que l’on doit compter pour obtenir le temps de transmission d’un bit.

It’s OverSimple, isn’t it?