Sondes i2c X10-RF

De MicElectroLinGenMet.

Sommaire

Description

Suite à l'article Generation signaux X10-RF avec un AVR permettant d'envoyer des commandes X10-RF de type A1-ON avec un micro-controleur de type AVR, j'ai constaté qu'il était possible d'envoyer plusieurs octets avec ce même protocole pouvant être capté par le rfxcom
.

Par exemple, je peux envoyer jusqu'à 6 octets quelconques au rfxcom qui ne seront pas interprétés comme des commandes X10.
Exemple d'envoi d'une trame quelconque (codes: 01 02 03 04 05 06):
Le programme xpl-rfxcom-rx de la librairie xpl-perl affiche en mode verbeux:

Processed: 30010203040506


L'idée sera d'envoyer des donnée de sondes i2c qui seront interprétées par un module xpl-perl rajouté. Un message xPL sensor.basic sera émis sur le réseau.


Mise en oeuvre

Je n'ai pas encore pu tester l'interface i2C sur AVR, j'utiliserai ici un micro-controleur de la famille 8051, l'AT89C2051 aussi de chez Atmel.
Il est identique au niveau brochage et mémoire flash à l'ATtiny2313 mais sera programmé en assembleur 8051.

Pour un premier test, le ucontroleur 89C2051 lira une sonde de température i2c (ds1621) et un convertisseur analogique numérique le pcf8591 et émettera leurs données en X10-RF codées sur 48bits (6 octets).
Ce montage test sera relié à un Capteur de courant sur une des entrée du pcf8591 pour lire la consommation électrique d'un appareil à distance.


L'émetteur RF utilsé ici sera un module miniature Laipac le TLP434A mais fonctionne aussi avec le modulle Aurel TX-433-SAW:



Détail du codage

Il faudra créer un codage personnel pour les 6 octets à émettre. j'ai codé de façon arbitraire tout en faisant en sorte que le module xpl-perl reconnaisse ces données comme étant les siennes.

1 entête:	(Octet de valeur quelconque figé servant d'entête.)
2 idcarte:	(Octet correspondant à un ID donné à la carte émettrice pour la différencier d'une autre.)
3 adri2c:	(Adr. i2c du composant lu.)
4 data1:	(Donnée lu sur le circuit i2c limité à 3 octets.)
5 data2:
6 data3:


Montage

Montage en développement

Utilisation d'une carte Scalp Elektor et d'outils perso. pour la mise au point du programme assembleur.
Le connecteur gigogne sera remplacé par le microcontroleur AT89C2051.


la carte Scalp reliée par un connecteur gigogne à la plaque de test.
Un ds1621, pcf8591 et l'émetteur HF Laipac.


Shéma / photos du montage


Montage avec le micro-controleur

Une LDR a été reliée sur une des entrée du pcf8591 pour test.


Vue du uC AT89C2051 et des ds1621/pcf8591
Vue de l'émetteur HF Laipac et du Capteur de courant


Source du programme assembleur

; X10 RF transmitter
; Version 2051
 
; 12/2/2010
; Test envoie de la t° lu sur ds1621 i2c en X10 RF.
; Rajout pcf8591 avec capteur de courant + LDR pour test.
; Canal 0 et 1 forcés à Gnd, canal2 = LDR, canal3 = capteur de courant.
 
; Testé avec le module HF Aurel: TX-433-SAW, et le module miniature Laipac TLP434.
 
;=============================================================================
; Copyright (C) 2010 Domos, domos78 at free point fr
; Ce programme est libre, vous pouvez le redistribuer et/ou le modifier selon 
; les termes de la Licence Publique Générale GNU publiée par la Free Software 
; Foundation (version 2 ou bien toute autre version ultérieure choisie par vous).
 
; Ce programme est distribué car potentiellement utile, mais SANS AUCUNE 
; GARANTIE, ni explicite ni implicite, y compris les garanties de 
; commercialisation ou d'adaptation dans un but spécifique. Reportez-vous à la 
; Licence Publique Générale GNU pour plus de détails.
 
; Vous devez avoir reçu une copie de la Licence Publique Générale GNU en même 
; temps que ce programme. Si ce n'est pas le cas, écrivez à la Free Software 
; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, États-Unis.
 
;==============================================================================
include "8051_equ.asm"
 
; Assemblage conditionnel (Ces routines seront assemblées si #define présent)
AFFNL		equ 1
AFFACC		equ 1
TX_RS		equ 1
RX_RS		equ 1
RX_RS3		equ 1
INIT_RS19200	equ 1
TX_TXT		equ 1
TST_I2C_ACQ	equ 1
TST_ACQ		equ 1
LITTEMP_P	equ 1
DELAY1MS	equ 1
DELAY1S		equ 1
X10_SENDATA	equ 1
LITADI2C	equ 1
LIT4ADI2C	equ 1
 
;==============================================================================
; Adresses RAM interne utilisées.
; En 80h début pile.
x10_buff	equ	21h				; Buffer de 4/6 octets trame X10.
i2c_acq 	equ 	27h                 		; Adresse d'acquittement I2C (00h=OK).
i2c_buf 	equ 	28h                 		; Buffer de lecture/écriture I2C.
 
; Ports utilisés
x10_pin		equ	p3_3				; Pin X10 (INT1).
led		equ	P3_2				; Led indiquant émission (INT0).
 
bsda    	equ 	0B5H				; P3_5 (T1)
bscl    	equ 	0B4H				; P3_4 (T0)
 
; Labels
nbtrames	equ	5
entete		equ	5Ah
idcarte		equ	61h
therm		equ 	09Eh				; Adresse I2C thermomètre/thermostat DS1621.
adda		equ 	090h				; Adresse PCF8591, 90h à 9Eh possibles.
 
;=============================================================================
	org 	0000h 	;------------------------------------------------------
	ajmp 	prog
 
; Interruptions. 
      	org   03h                   		; external interrupt 0
    	reti
   	org   0Bh                   		; timer 0 interrupt
    	reti
  	org   13h                   		; external interrupt 1
   	reti
   	org   1Bh                   		; timer 1 interrupt
    	reti
   	org   23h                   		; serial port interrupt
    	reti
   	org   2Bh                   		; I2C port interrupt
    	reti
 
	org 	0030h 	;------------------------------------------------------
 
prog	mov 	sp, #40h			; Initialise la pile.
    	mov 	ie, #00h        		; disable interrupts;
	mov	p1, #0FFh
	mov	p3, #0FFh
 
	clr	x10_pin			; Pin X10 à 0.
	acall 	init_rs19200		; Débit uart 19200 Bds.
 
	acall	initther_p		; Init therm.
	jc	lab000			; Saut si ok.
	mov 	dptr, #txt1
	acall	tx_txt
	sjmp	$			; Boucle si erreur ds1621.
 
lab000	acall	initaddai2c		; Init. pcf8591
	jc	lab001			; Saut si ok.
	mov 	dptr, #txt2
	acall	tx_txt
	sjmp 	$			; Boucle si erreur pcf8591 
 
lab001	mov 	dptr, #txt3		; Affiche message.
	acall	tx_txt
 
	; Envoie trame temp. et canal ain0 à ain3.
lab002
	clr	led			; Allume led.	
 
	; lecture temp. ds1621 et envoie trame x10
	acall	littemp_p		; Lecture 3 octets t° (temp, compteur, slope) dans r5, r6, r7.
	mov	a, #therm		; Contient adr. i2c chip
	acall	x10_sendata		; Envoie trame X10, temperature
 
	; lecture canals pcf8591 et envoie trame x10
	mov	r6, #00			; N° de canal de départ.
lab003	mov	a, r6
	acall	litadi2c		; Lit canal A => A.
 
	mov	r5, #00h		; Data1 trame x10 à 0x00, non utilisé.
	mov	r7, a			; Val lu sur canal.
	mov	a, #adda		; Contient adr. i2c chip
	acall	x10_sendata		; Envoie trame X10, 3 octets par canal (0x00, n°canal, data) dans r5, r6, r7.
 
	inc	r6			; Incrémente n° canal.
	cjne	r6, #04h, lab003	; Boucle si n° canal < 4 .
 
	setb	led			; Eteind led.	
 
	mov	r4, #50			; Pause de 50 secondes.
	acall	delayR4s
 
	sjmp 	lab002
 
txt1	db "Erreur init DS1621 !", 0Dh, 0Ah, 00h
txt2	db "Erreur init PCF8591 !", 0Dh, 0Ah, 00h
txt3	db "Envoi trame Data X10-RF", 0Dh, 0Ah, 00h
 
 
;==============================================================================
	include "term.lib"
	include "utils.lib"
	include "delai.lib"
	include "x10_rf.lib"
	include "i2c.lib"
	include "ds1621.lib"
	include "pcf8591.lib"
;=============================================================================
        end

Librairies personnelles assembleur 8051 utilisées: 8051_X10-RF-i2c_lib.tgz


Montage en situation

Le Capteur de courant est intercalé sur une prise avec un boitier vide de programmateur.

Montage en test


Résultat à la réception

  • Réception sur le Rfxcom et librairie xpl-perl en mode verbeux:
Processed: 305a619e170310 	=> nb_bits-entete/idcarte/adri2c/temp/compteur/slope
xpl-trig/sensor.basic: bnz-rfxcomrx.vesta -> * - ds1621_2051_619e[temp]=23.6

Processed: 305a6190000001 	=> nb_bits-entete/idcarte/adri2c/0x00/canal/valeur
xpl-trig/sensor.basic: bnz-rfxcomrx.vesta -> * - pcf8591_2051_6190_00[voltage]=0.02
Processed: 305a6190000100
xpl-trig/sensor.basic: bnz-rfxcomrx.vesta -> * - pcf8591_2051_6190_01[voltage]=0.00
Processed: 305a6190000252
xpl-trig/sensor.basic: bnz-rfxcomrx.vesta -> * - pcf8591_2051_6190_02[voltage]=1.61
Processed: 305a61900003fe
xpl-trig/sensor.basic: bnz-rfxcomrx.vesta -> * - pcf8591_2051_6190_03[voltage]=4.98


  • Dans la log xPL avec décodage du module perl xPL (I2CSensors.pm):
10/02/20 14:31:16 xpl-trig {bnz-rfxcomrx.vesta *} sensor.basic { device='ds1621_2051_619e' type='temp' current='23.6' }
10/02/20 14:31:17 xpl-trig {bnz-rfxcomrx.vesta *} sensor.basic { device='pcf8591_2051_6190_00' type='voltage' current='0.00' }
10/02/20 14:31:17 xpl-trig {bnz-rfxcomrx.vesta *} sensor.basic { device='pcf8591_2051_6190_01' type='voltage' current='0.00' }
10/02/20 14:31:18 xpl-trig {bnz-rfxcomrx.vesta *} sensor.basic { device='pcf8591_2051_6190_02' type='voltage' current='2.84' }
10/02/20 14:31:19 xpl-trig {bnz-rfxcomrx.vesta *} sensor.basic { device='pcf8591_2051_6190_03' type='voltage' current='1.50' }

Le nom des devices est composé du nom du chip i2c suivi de la référence du uC + idcarte/adri2c_n°canal.


Module xpl-perl I2CSensors.pm

Module Perl pour interpréter la réception des trames X10-RF envoyée par mes cartes à AT89C2051.

Ce module est sommaire et serai à améliorer.
Il teste l'adresse i2c pour envoyer le type de message sensor.basic à envoyer.
Attention le ds1621 et pcf8591 sont sur la même plage d'adresses: 0x090 à 0x9E.

Fichier I2CSensors.pm à copier dans un répertoire de la librairie xpl-perl: /usr/share/perl5/xPL/RF (valable pour Debian).



package xPL::RF::I2CSensors;
 
# $Id$
# Dan, /usr/share/perl5/xPL/RF/I2CSensors.pm
 
=head1 NAME
 
xPL::RF::ATIRemote - Perl extension for decoding I2CSensors device RF messages
 
=head1 SYNOPSIS
 
  use xPL::RF::I2CSensors;
 
=head1 DESCRIPTION
 
This is a module for decoding RF messages from I2CSensors devices.
 
=head1 METHODS
 
=cut
 
use 5.006;
use strict;
use warnings;
use English qw/-no_match_vars/;
use xPL::Message;
use Exporter;
#use AutoLoader qw(AUTOLOAD);
 
our @ISA = qw(Exporter);
our %EXPORT_TAGS = ( 'all' => [ qw() ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
our $VERSION = '0.01';
our $SVNVERSION = qw/$Revision: 519 $/[1];
 
my $SPACE = q{ };
 
 
=head2 C<parse( $parent, $message, $bytes, $bits )>
 
This method attempts to recognize and parse RF messages corresponding
to personnal I2C sensors X10.  If messages are identified a reference to a list of
xPL::Message objects is returned.  If the message is not recognized,
undef is returned.
 
Processed: 305a619e180210 	=> nb_bits-entete/idcarte/adri2c/data1/data2/data3
xpl-trig/sensor.basic: bnz-rfxcomrx.vesta -> * - ds1621_2051_619e[temp]=24.6
10/02/12 22:53:12 xpl-trig {bnz-rfxcomrx.vesta *} sensor.basic { device='ds1621_2051_619e' type='temp' current='24.6' }
 
=cut
 
sub parse
{
  my $self = shift;
  my $parent = shift;
  my $message = shift;
  my $bytes = shift;
  my $bits = shift;
 
  $bits == 48 or return ;			# 48 (0x30) bits (6 octets) !
  $bytes->[0] == 0x5A or return ;		# 5A = entete !
 
  my %body ;
 
  my $idcard = $bytes->[1] ;
  my $i2cadr = $bytes->[2] ;
 
  # Si adri2c du ds1621
  if ( $i2cadr == 0x9E )
  {
	my $device =  sprintf("ds1621_2051_%02x%02x", $idcard, $i2cadr) ; 
	my $temp = $bytes->[3] ;
	my $count = $bytes->[4] ;
	my $slope = $bytes->[5] ;
	my $valtemp = $temp  * 100 ;
	if ($slope)
	{
		$valtemp = $temp * 100 - 25 + ( 100 * ($slope - $count) ) / $slope ;
	}
	$valtemp = sprintf("%2.1f" , $valtemp / 100) ;
	%body = (
		current => $valtemp,
		type => "temp",
		device => $device,
             );
  }
  # Si adri2c du pcf8591
  elsif ( $i2cadr == 0x90 )
  {
	my $canal = $bytes->[4] ;
	my $ain = $bytes->[5] ;
	my $val = sprintf( "%.2f", $ain * (5/255) ) ;
	my $device =  sprintf("pcf8591_2051_%02x%02x_%02x", $idcard, $i2cadr, $canal) ; 
	%body = (
		current => $val ,
		type => "voltage",
		device => $device,
             );
  }
  else { return } ;
 
  return [xPL::Message->new(
                            message_type => 'xpl-trig',
                            class => 'sensor.basic',
                            head => { source => $parent->source, },
                            body => \%body,
                           )];
}
 
1;
__END__
 
=head1 EXPORT
 
None by default.
 
=head1 SEE ALSO
 
Project website: http://www.xpl-perl.org.uk/
 
=head1 AUTHOR
 
Domos, E<lt>domos78 at free point frE<gt>
 
=head1 COPYRIGHT
 
Copyright (C) 2009 by Domos
 
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.7 or,
at your option, any later version of Perl 5 you may have available.
 
=cut


Autre idée

Une autre idée est d'utiliser une des broches d'interruptions du uC qui permettrai de gérer un compteur d'impulsions pour par exemple lire un pluviomètre à augets ou suivre sa consommation d'eau comme ici en 1-wire mais sans fils.



20/2/2010