Décodage des protocoles Oregon Scientific sur Arduino (3/3)
Suite et fin de cette série (Décodage des protocoles Oregon Scientific sur Arduino (1/3), Décodage des protocoles Oregon Scientific sur Arduino (2/3)). Je vous présente aujourd’hui une modification du décodeur lui permettant de traiter les informations de toutes les sondes Oregon v2, on parlera aussi du montage et de sa portée .
[adsGrandRectangleTexte]
Modification du décodeur Oregon Scientific
Dans l’article précédant, nous avons vu comment identifier à quelle sonde nous avons à faire. Nous allons utiliser ceci pour identifier les sondes au plus tôt, c’est à dire pendant la réception des trames. Ceci va nous permettre de savoir de quelle taille devrait être la trame que nous sommes en train de recevoir. On obtient ainsi une condition de sortie du décodeur qui marchera pour toutes les sondes.
Tailles des trames :
J’ai repris le tableau de l’article précédant en y indiquant pour chaque type de sonde, la taille des trames émises :
Code | Taille des trames |
0x0A4D | 80 |
0xEA4C | 68 |
0xCA48 | ?? |
0x1A2D | 80 |
0xFA28 | 80 |
0x*ACC | 80 |
0xCA2C | 80 |
0xFAB8 | 80 |
0x1A3D | 80 |
0x5A5D | 88 |
0x5A6D | 96 |
0x2A1D | 84 |
0x2A19 | 92 |
0x1A99 | 88 |
0x1A89 | ?? |
0x3A0D | 80 |
0xEA7C | 120 |
0xDA78 | 72 |
0x*AEC | 104 |
0xEAC0 | ?? |
Par rapport au premier article de la série, nous allons modifier la fonction virtual void gotBit (char value). Pour que le décodeur fonctionne avec toutes les sondes Oregon v2, nous allons détecter à quelle type de sonde la trame en cours de décodage appartient afin de modifier à la volé la condition de sortie du décodeur (trame de longueur variable).
En effet, l’identifiant de sonde étant codé dans les deux premiers octets, il suffit de les lires dès qu’ils sont réceptionnés :
virtual void gotBit (char value) { if(!(total_bits & 0x01)) { data[pos] = (data[pos] >> 1) | (value ? 0x80 : 00); } total_bits++; pos = total_bits >> 4; if(pos == 2) { // Taille de trame par défaut (utilisée dans la majorité des sondes) max_bits = 160; // Exceptions : if(data[0] == 0xEA) { if(data[1] == 0x4C) max_bits = 136; // TH132N : 68 * 2 else if(data[1] == 0x7C) max_bits = 240; // UV138 : 120 * 2 } else if(data[0] == 0x5A) { if(data[1] == 0x5D) max_bits = 176; // THGR918 : 88 * 2 else if(data[1] == 0x6D)max_bits = 192; // BTHR918N : 96 * 2 } else if(data[0] == 0x1A && data[1] == 0x99) max_bits = 176; // WTGR800 : 88 * 2 else if(data[0] == 0xDA && data[1] == 0x78) max_bits = 144; // UVN800 : 72 * 2 else if((data[0] == 0x8A || data[0] == 0x9A) && data[1] == 0xEC) max_bits = 208; // RTGR328N 104 * 2 else if(data[0] == 0x2A) { if(data[1] == 0x19) max_bits = 184; // RCR800 : 92 * 2 else if(data[1] == 0x1d) max_bits = 168; // WGR918 : 84 * 2 } } if (pos >= sizeof data) { Serial.println("sizeof data"); resetDecoder(); return; } state = OK; }
Cette trame est elle valide ? … Calcul de la checksum
J’en ai profité pour ajouter le calcul de la checksum et pour être simple Oregon Scientific à choisi des calculs de checksum différents selon les types de sondes … forcement c’est plus drôle … humm :/
Il suffit d’ajouter ces fonctions au sketch précédant et de tester le retour de l’une ou l’autre (suivant le type de sonde) dans la fonction reportSerial(…) :
- checksum(data) pour les sondes de type THN132N
- et checksum2(data) pour les sondes de type THGR228N
byte checksum(const byte* data) { int c = ((data[6]&0xF0) >> 4) + ((data[7]&0xF)<<4); int s = ((Sum(6, data) + (data[6]&0xF) - 0xa) & 0xff); return s == c; } byte checksum2(const byte* data) { return data[8] == ((Sum(8, data) - 0xa) & 0xff); } int Sum(byte count, const byte* data) { int s = 0; for(byte i = 0; i<count;i++) { s += (data[i]&0xF0) >> 4; s += (data[i]&0xF); } if(int(count) != count) s += (data[count]&0xF0) >> 4; return s; }
La portée
La portée est très variable selon le matériel utilisé. Dans mon cas, il dépend principalement de deux choses :
- La tension aux bornes du récepteur RF433. Plus il est proche de 5v (pour mon récepteur) meilleure est la portée.
- Au récepteur RF433 lui-même. Certains sont plus sensibles que d’autres au « bruit », d’où les _gros_ écarts de prix.
On peut ensuite jouer sur d’autres points :
- L’antenne. J’avais réalisé quelques tests avec une antenne type Rfxcom et la portée était meilleure, à confirmer.
- l’électronique. On peut ajouter un filtre en entrée du récepteur pour atténuer le bruit (condensateur de découplage).
Pour ma part, j’utilise un récepteur bas de gamme à ~4€. Ci-dessous un tableau récapitulant mes différents tests avec deux cartes Arduino et différentes méthodes d’alimentation. L’antenne utilisée est un simple fil de 17.3cm.
Carte | Alimentation | Voltage mesuré aux bornes 5v de la carte Arduino |
Portée |
Mega | 5v USB | 4.82v | 10cm |
Mega | Adaptateur secteur 12V | 4.94v | 10m avec dalle béton ou mur parpaing/brique |
Duemilanove | 5v USB | 4.92v | 10m avec dalle béton ou mur parpaing/brique |
Duemilanove | Adaptateur secteur 12V | 4.99v | +15m avec dalle béton ou mur parpaing/brique |
On voit que c’est super sensible, est ce dû à mon récepteur « cheap » ? Avec une bonne alimentation, on atteint quand même déjà de bonnes distances.
J’ai reçu quelques résultats de tests d’un lecteur qui malgré un bon 5v aux bornes du récepteurs obtient une mauvaise portée. si vous faites quelques expérimentations vos résultats m’intéresse, n’hésitez pas à poster un commentaire.
Je mettrai l’article à jour en fonction des éventuels retours et après quelques tests qu’il me reste à faire : meilleur récepteur et meilleure antenne entre autre.
Schéma de montage
Pour réaliser ce montage, il vous faudra un émetteur RF433Mhz (J’utilise personnellement celui-ci). Le schéma de câblage de l’émetteur en lui même est plutôt simple, je vous laisse en juger :
Condensateur de découplage
Le découplage capacitif consiste à mettre des capacités de diverses valeurs en parallèle au point à découpler. Son but est de nettoyer la tension à découpler. Il faut placer le condensateur au plus près du point à découpler, dans notre cas, entre le gnd et le +5v du récepteur. On m’avait conseillé un condensateur de 47nF.
Conclusion
Voila, nous avons tout ce qu’il faut pour réceptionner les informations de nos chères sonde Oregon Scientific :). Avec le code ci-dessus vous devriez récupérer les trames non décodées de toutes les sondes v2.1. Coté décodage j’en suis resté aux sondes THN132N et THGR228N auxquelles j’ai ajouté le calcul de la checksum.
Une librairie propres est en court d’écriture, j’en profiterai pour y ajouter le décodage des autres type de sondes. En attendant, je vous rappelle que vous pouvez trouver tout ce dont vous avez besoin dans les sources de xpl-perl.
Salut Olivier,
Ne manquerait-il pas un morceau dans la fonction Sum au niveau de la boucle for ?
Salut Julien,
Il me semblais que j’avais répondu mais je ne retrouve pas mon commentaire :/ effectivement j’ai corrigé.
Merci
Bonjour,
Excellent article !
Je développe ma propre solution domotique depuis quelque temps en delphi/php/mysql, basé sur un RFXTRX433 de rfxcom.
Depuis peu je m’intéresse a l’arduino.
J’ai donc voulu combiner arduino + rf433.
Je galérais depuis quelques jours pour décoder mes trames oregon sur mon arduino (avec un recepteur fs1000a) et cet article m’a permis d’arriver à mes fins 🙂
Pour info, une trame vu coté arduino et une trame coté rfxcom :
OSV2 1A2D40C4512170463EE6[THGR228N,…] Id:C4 ,Channel:3 ,temp:21.50 ,hum:67 ,bat:90
RFXTRX433 : 0A 52 01 54 C404 00D7 43 01 89
len=10
type=$52 (temp_hum) sub_type=1
id=$c404 (50180)
temp=21,50 ($00*256+$d7 /10)
humidity=67 ($43)
battery=8 (bit 0-3)
rssi=9 (bit 4-7)
Question : serait t il possible de publier un exemple pour envoyer une trame oregon?
On peut acheter un arduino, un DS18B20 et un TX433 pour moins de 20€ ce qui représente une alternative intéréssante à une sonde oregon.
Merci encore pour toute cette bonne littérature !
Erwan
j’aurais du mentionner que les trames ci dessous sont en fait une seule et meme trame vu par 2 périphériques differents (arduino vs rfxtrx433).
/Erwan
Bonsoir Erwan,
Bravo 🙂 et merci. As tu réussi à obtenir une portée correcte ?
Concernant l’émission je ne m’y suis pas encore penché mais j’aimerai bien essayer. On pourrait même descendre sous 10€ en utilisant un « arduino standalone » voir moins avec un plus petit uc.
Bonjour Erwan,
J.ai galéré tout le we pour lire les trames de mon RFXtrx433 USB sans succès ;(
Pourrais-tu me montrer ton code et un diagramme de confection stp?
Merci a toi pour cette info, je pensais plus y arriver. Même le supprort chez RFXCom m’a dit que c’était impossible à lire.
Merci a Olivier, j’ai découverts un site passionnant, plein du trucs intéressant.
Olivier
Bonjour, tout d’abord merci pour votre TUTO, ceci m’a permis de mettre en réseau les capteurs orégons situés dans les différentes pièces de la maison. J’ai un problème lorsque je débranche l’USB et passe en alimentation 5Volts sur l’arduino UNO. il n’y a plus de décodage.
Pourriez vous me renseigner si dans le programme le port série doit être activé, pour la réception du signal, ou si ça vient de mon alimentation qui pourrait être trop faible.
Et encore un grand merci .
Sinon pour faire ses propres sondes il y a les jnode, cela semble pas mal fichu et pas cher en plus (avec beaucoup de possibilité également).
Sorry j’ai mal fermé la balise a href 🙂 -> Jeenode
corrigé 🙂
J’ai ma réponse, ça fonctionne très bien avec une alimentation 12V 1A.
Merci
Bonjour, merci pour ce tuto. Je suis en train de tester et j’ai des soucis de fiabilité. J’ai 3 sondes Oregon THGR122NX. Au delà de 3 mètres plus aucune trame n’est décodée, donc question portée bof bof. Mais même en mettant une sonde juste à côté du récepteur j’ai un taux de réussite sous les 50%. Je me demande s’il n’y a pas moyen de rendre le code plus « tolérant » en jouant sur le nombre de bits de préambule ou bien sur les délais? D’autant plus que j’ai mis une led sur la pin logique et je « vois » bien les trames qui viennent des sondes même lorsqu’elles sont éloignées.
Bonjour Olivier,
je découvre tes explications (billet 1-2-3) avec beaucoup d’attention car je voudrais récupérer les infos de ma sonde THR128 avec mon Arduino Uno.
Malheureusement je suis carrément nul en programmation et ici, je ne trouve que des « morceaux » de code. Je n’arrive pas à mettre tout en place.
Serait-il possible de poster un lien vers le code complet et fonctionnel (qu’il me suffirait de téléverser dans l’arduino) ?
Ceci en attendant d’améliorer mes connaissances…
Merci d’avance et bravo pour tout ce beau travail.
Salut,
Normalement tu peux prendre le code du premier article (il est complet) puis ajouter les fonctions de l’article 2 où tu veux dans le code et enfin remplacer ou ajouter celles présente dans l’article 3 … c’est vrai qu’en le disant comme ça, ça fait un peu bordélique 😉 … j’essaie de te poster ici rapidement le code complet de l’article 3.
++
Bonjour,
Bravo pour le boulot réalisé, je ne suis guère calé sur le sujet et je me suis pas lancé encore dans la réalisation de la chose
je me posais une question, j’ai vu ceci http://shop.openenergymonitor.com/rfm12pi-v2-raspberry-pi-expansion-board-433-mhz/
http://wiki.openenergymonitor.org/index.php?title=RFM12Pi_V2#Hacks.2C_Modifications_.26_Extensions
la carte comporte un atmega128, pour renvoyer en serie vers un raspberry pi est ce que cela peut être possible d’utiliser ce hard avec le code de l’article moyennant adaptation ?
je découvre les arduinos mais je pense que c’est jouable ?
le but étant d’envoyer les infos de mes sondees oregon vers emoncms
Merci de vos réponses éclairées
Salut,
Merci pour le tuto. J’ai réussi à tout faire fonctionner avec un Compatible Uno (XDRduino) et un récepteur à quelques euros sur Ebay. Ma sonde est une THGR122NX.
Il ne me reste plus qu’à le rendre autonome et à archiver les données.
Encore merci
Au fait, je ne vois pas le condensateur sur le schéma. Est-il vraiment nécessaire ?
Je t’avoue que lors de mes tests je n’ai pas vraiment vu la différence.
De rien 🙂
J’emménage bientôt dans ma nouvelle maison et je vais donc tout reprendre ça de plus près.
Je pense faire des versions autonomes également, je mettrai ma solution ici mais si tu avance n’hésite pas à donner des nouvelles 🙂
Salut,
Merci pour ces articles très intéressants, je les avait mis sous le coude et j’ai pris le temps de les tester aujourd’hui. Aurais-tu la possibilité de poster le sketch complet ? Car jusqu’à la partie 1 et 2 çà fonctionne mais la fonction gotBit() de la partie 3 çà coince chez moi. J’imagine que c’est celle de la classe OregonDecoderV2 qu’il faut modifier ?
seulement la nouvelle variable max_bits que tu préconises n’est pas déclarée, j’ai donc regardé aussi ce qu’elle faisait, mais à part sont affection je ne vois pas à quoi elle sert et quand est testé cette variable ?
J’ai raté un truc ou c’est une coquille ?
Merci par avance pour ton aide
Salut,
Bien vu, si je ne dis pas de bêtises il faut le déclarer dans la classe DecodeOOK
class DecodeOOK {
protected:
byte total_bits, max_bits, bits, flip, state, pos, data[25];
[...]
et modifier la condition de sortie du décodeur, et cette partie n’apparait pas … un oubli de ma part. Il faut que je remette la main sur le code complet.
Je le post ce soir ici même.
je viens de voir que j’ai fais la même promesse l’année dernière … pas bien 😉 … je me m’auto-flagellerai une fois le code en ligne!
Ahhh, tu me rassures, je vois qu’il n’y a pas que moi qui peine avec mes lignes codes epparpillés un peu partout, c’est pas bien bouhhhh :-):-)
Merci pour tes éclaircissements, pour le moment je suis passé sur autre chose, mon récepteur doit être pas terrible car je ne vois que 10% de mes sondes passer, c’est pour ça que je voulais essayer la partie 3 avec les autres types de sondes pour vérifier si je les recevais. J’attends donc pour essayer à nouveau.
Pour le code si tu veux, je peux l’héberger sur mon github, je trouve que çà reste quand même très simple et pratique, et de plus on peu tous travailler dessus pour les mises à jour. Bon si tu t’auto-flagelles une fois le code en ligne, je ne suis plus sur de ta motivation ;-);-)
Bonjour et merci pour ton travail .
Est-il possible d’avoir le code intéral modifié comme tu le dis plus haut stp ?
Merci par avance.
Salut,
Merci, oui je prépare un article avec le code intégral et de vrais sondes.
salut ,
Ou peut on trouver le code complet ?