Vous prendrez bien un peu de Wifi avec votre RFLink ?

Merci d'utiliser cette section pour vos questions concernant EXCLUSIVEMENT les modules rflink

Modérateur : deennoo

Charly86
Messages : 14
Enregistré le : 29 févr. 2016, 10:51

Re: Vous prendrez bien un peu de Wifi avec votre RFLink ?

Message par Charly86 »

snips
bon j'ai fait des tests avec les nouveaux fichiers, sur l'ESP c'est la zone, ça ne fonctionne pas mieux, mais je reste persuadé que ça vient de l'architecture du code employé pour détecter les trames, je m'explique, le même code sur Mega et ESP (dans LoopPerMillis mais avec des Micros() pour être certain du timing) ne fonctionne pas sur ESP (enfin ça rate des trames) alors que sur le Mega ça fonctionne.

Bien entendu sur l'ESP j'ai adapté la lecture du port pour accélérer le traitement mais sans succès (GPIP) mais je pense que c'est parce que la routine est potentiellement interrompue pour faire d'autres tâches et ça perturbe les timing.

Voilà le code pour info

Code : Tout sélectionner

boolean FetchSignal(byte DataPin, boolean StateSignal) {
   uint8_t FstateMask = StateSignal ? 1 : 0;

   if (GPIP(DataPin) == FstateMask) {                       // Als er signaal is
     // Als het een herhalend signaal is, dan is de kans groot dat we binnen hele korte tijd weer in deze
     // routine terugkomen en dan midden in de volgende herhaling terecht komen. Daarom wordt er in dit
     // geval gewacht totdat de pulsen voorbij zijn en we met het capturen van data beginnen na een korte 
     // rust tussen de signalen.Op deze wijze wordt het aantal zinloze captures teruggebracht.

     if (RawSignal.Time) {                                                       //  Eerst een snelle check, want dit bevindt zich in een tijdkritisch deel...
        if (RawSignal.Repeats && (RawSignal.Time+SIGNAL_REPEAT_TIME)>millis()) { // ...want deze check duurt enkele micro's langer!
           PulseLength=micros()+SIGNAL_TIMEOUT*1000;                             // delay
           while ((RawSignal.Time+SIGNAL_REPEAT_TIME)>millis() && PulseLength>micros())
           if ( GPIP(DataPin) == FstateMask )
                  PulseLength=micros()+SIGNAL_TIMEOUT*1000;
           while((RawSignal.Time+SIGNAL_REPEAT_TIME)>millis() &&  ( GPIP(DataPin) != FstateMask));
        }
     }
     RawCodeLength=1;                                                           // Start at 1 for legacy reasons. Element 0 can be used to pass special information like plugin number etc.
     Ftoggle=false;                  
    do {                                                                         // read the pulses in microseconds and place them in temporary buffer RawSignal
       my_start = micros();
      do {
        PulseLength = micros()-my_start ;
        if (PulseLength > SIGNAL_TIMEOUT*1000 )
          break;
      }
      while ( (GPIP(DataPin)==FstateMask) ^ Ftoggle  );

      if (PulseLength<MIN_PULSE_LENGTH) 
        break;                                                                  // Pulse length too short
      Ftoggle=!Ftoggle;    
      RawSignal.Pulses[RawCodeLength++]=PulseLength/(unsigned long)(RAWSIGNAL_SAMPLE_RATE); // store in RawSignal !!!! 
    } while (RawCodeLength<RAW_BUFFER_SIZE);               // For as long as there is space in the buffer, no timeout etc.

    if (RawCodeLength>=MIN_RAW_PULSES) {
       RawSignal.Repeats=0;                                                      // no repeats
       RawSignal.Multiply=RAWSIGNAL_SAMPLE_RATE;                                 // sample size.
       RawSignal.Number=RawCodeLength-1;                                         // Number of received pulse times (pulsen *2)
       RawSignal.Pulses[RawSignal.Number+1]=0;                                   // Last element contains the timeout. 
       RawSignal.Time=millis();                                                  // Time the RF packet was received (to keep track of retransmits
       return true;
    } else {
      RawSignal.Number=0;    
    }
  }
  return false;
}
@deennoo, oui le RXB6 c'est une tuerie et même en 3V3 ;-)

jackslayter
Messages : 954
Enregistré le : 30 sept. 2014, 14:40
Localisation : Isère (38)

Re: Vous prendrez bien un peu de Wifi avec votre RFLink ?

Message par jackslayter »

Charly86 a écrit :oui le RXB6 c'est une tuerie et même en 3V3 ;-)
c'est quoi son homologue en Tx ?
Raspberry Pi + RFLink + Domoticz Beta
Oregon - 3x Thgr122Nx / Chacon - micromodule 200w, télécommande 3b et 16b, 2x module 1000w, détecteur de fumée, contact de porte, 2x prise 3500w / OWL - CM180 / TRC02 v2 RGB 3M / Cheap - PIR, contact de porte

Charly86
Messages : 14
Enregistré le : 29 févr. 2016, 10:51

Re: Vous prendrez bien un peu de Wifi avec votre RFLink ?

Message par Charly86 »

moi c'était livré avec le récepteur, mais je ne l'ai pas encore testé

http://www.ebay.fr/itm/433MHz-Superhete ... xycD9TRKeu

snips
Messages : 272
Enregistré le : 18 mars 2015, 22:37

Re: Vous prendrez bien un peu de Wifi avec votre RFLink ?

Message par snips »

Charly86 a écrit :snips
bon j'ai fait des tests avec les nouveaux fichiers, sur l'ESP c'est la zone, ça ne fonctionne pas mieux, mais je reste persuadé que ça vient de l'architecture du code employé pour détecter les trames, je m'explique, le même code sur Mega et ESP (dans LoopPerMillis mais avec des Micros() pour être certain du timing) ne fonctionne pas sur ESP (enfin ça rate des trames) alors que sur le Mega ça fonctionne.
Bien entendu sur l'ESP j'ai adapté la lecture du port pour accélérer le traitement mais sans succès (GPIP) mais je pense que c'est parce que la routine
Ok, donc cette piste est écartée.
Je vais comparer le code que tu as donné et qui semble 100% opérationnel sur ESP (https://github.com/zoid921/esp8266_osc_to_mqtt) avec RawSignal.ino du RFLINK pour essayer de dénicher les subtilités.

Charly86
Messages : 14
Enregistré le : 29 févr. 2016, 10:51

Re: Vous prendrez bien un peu de Wifi avec votre RFLink ?

Message par Charly86 »

Oh yes bon courage, car le fichier Oregon avec MQTT pour ESP ne capte que les trames oregon, ce qui doit changer un peu la donne, mais si tu y arrives c'est cool ;-)

tiens la version Arduino sans le loopPerMillis et qui fonctionne, ça peut servir

Code : Tout sélectionner

boolean FetchSignal(byte DataPin, boolean StateSignal) {
   uint8_t Fbit = digitalPinToBitMask(DataPin);
   uint8_t Fport = digitalPinToPort(DataPin);
   uint8_t FstateMask = (StateSignal ? Fbit : 0);
   uint32_t my_lpm;
   uint16_t my_time;

   if ((*portInputRegister(Fport) & Fbit) == FstateMask) {                       // Als er signaal is
     // Als het een herhalend signaal is, dan is de kans groot dat we binnen hele korte tijd weer in deze
     // routine terugkomen en dan midden in de volgende herhaling terecht komen. Daarom wordt er in dit
     // geval gewacht totdat de pulsen voorbij zijn en we met het capturen van data beginnen na een korte 
     // rust tussen de signalen.Op deze wijze wordt het aantal zinloze captures teruggebracht.

     if (RawSignal.Time) {                                                       //  Eerst een snelle check, want dit bevindt zich in een tijdkritisch deel...
        if (RawSignal.Repeats && (RawSignal.Time+SIGNAL_REPEAT_TIME)>millis()) { // ...want deze check duurt enkele micro's langer!
           PulseLength=micros()+SIGNAL_TIMEOUT*1000;                             // delay
           while ((RawSignal.Time+SIGNAL_REPEAT_TIME)>millis() && PulseLength>micros())
           if ((*portInputRegister(Fport) & Fbit) == FstateMask)
                  PulseLength=micros()+SIGNAL_TIMEOUT*1000;
           while((RawSignal.Time+SIGNAL_REPEAT_TIME)>millis() &&  (*portInputRegister(Fport) & Fbit) != FstateMask);
        }
     }
     RawCodeLength=1;                                                            // Start at 1 for legacy reasons. Element 0 can be used to pass special information like plugin number etc.
     Ftoggle=false;                  
     maxloops = (SIGNAL_TIMEOUT * LoopsPerMilli);  

     do{                                                                         // read the pulses in microseconds and place them in temporary buffer RawSignal

        my_start = micros();
        while ( (((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle) && (micros()-my_start) < SIGNAL_TIMEOUT*1000 );
        PulseLength=micros()-my_start;

       if (PulseLength<MIN_PULSE_LENGTH) break;                                  // Pulse length too short
       Ftoggle=!Ftoggle;    
       RawSignal.Pulses[RawCodeLength++]=PulseLength/(unsigned long)(RAWSIGNAL_SAMPLE_RATE); // store in RawSignal !!!! 
    } while (RawCodeLength<RAW_BUFFER_SIZE);                // For as long as there is space in the buffer, no timeout etc.

    if (RawCodeLength>=MIN_RAW_PULSES) {
       RawSignal.Repeats=0;                                                      // no repeats
       RawSignal.Multiply=RAWSIGNAL_SAMPLE_RATE;                                 // sample size.
       RawSignal.Number=RawCodeLength-1;                                         // Number of received pulse times (pulsen *2)
       RawSignal.Pulses[RawSignal.Number+1]=0;                                   // Last element contains the timeout. 
       RawSignal.Time=millis();                                                  // Time the RF packet was received (to keep track of retransmits
       return true;
    } else {
      RawSignal.Number=0;    
    }
  }
  return false;
}
bien sur il faut déclarer aussi unsigned long my_start , mais je suis sûr que t'avais capté ;-)

snips
Messages : 272
Enregistré le : 18 mars 2015, 22:37

Re: Vous prendrez bien un peu de Wifi avec votre RFLink ?

Message par snips »

Parfait merci.

il va me falloir en effet quelques aspirines et nuits blanches ;-) mais je vais le faire car tu as déjà fait le gros boulot et ce serait dommage d'en rester la !

snips
Messages : 272
Enregistré le : 18 mars 2015, 22:37

Re: Vous prendrez bien un peu de Wifi avec votre RFLink ?

Message par snips »

Charly86 a écrit : La mauvaise nouvelle c'est qu'avec le même code sur ESP8266 je rate 60% des trames, même en essayant aussi différentes valeurs de LoopPerMilli (ancien code) et en changeant la lecture de l'I/O via des direct read de ports, que ce soit a 80MHz ou 160MHz.
Bonjour Charly86
Après relecture du code original RFLINK (qui est dépendant de la vitesse du processeur avec LoopPerMilli) et ton code (PulseLength = micros()-my_start) je peux déjà dire que je préfère ton code ! (qui est moins dépendant de la vitesse du processeur !)

J'en viens à la même conclusion que toi, c'est que le problème est peut être au niveau du LoopPerMilli (je sais tu as déjà testé différentes valeurs....et pas mieux). Il n'y a que là où il me semble qu'il y ait eu une modification "sensible" du code.
Code modifié

Code : Tout sélectionner

do {                                                                         // read the pulses in microseconds and place them in temporary buffer RawSignal
       my_start = micros();
      do {
        PulseLength = micros()-my_start ;
        if (PulseLength > SIGNAL_TIMEOUT*1000 )
          break;
      }
      while ( (GPIP(DataPin)==FstateMask) ^ Ftoggle  );
           if (PulseLength<MIN_PULSE_LENGTH)  break;  
Code original

Code : Tout sélectionner

const unsigned long LoopsPerMilli=345;
const unsigned long Overhead=0;
......
maxloops = (SIGNAL_TIMEOUT * LoopsPerMilli); 
 numloops = 0;
       while (((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle)      // while() loop *A*
       if (numloops++ == maxloops) break;                                        // timeout 
       PulseLength=((numloops + Overhead)* 1000) / LoopsPerMilli;                // Contains pulslength in microseconds
       if (PulseLength<MIN_PULSE_LENGTH) break;                                  // Pulse length too short
Je me dis que l'on a toujours supposé que le code orignal est bon, et quand il dit que sur une mega 2560, en une milliseconde on peut exécuter 345 boucles (=LoopsPerMilli) cela doit être vrai. Ca vaut le coup de le mesurer pour de vrai (je ferai cela ce soir).

Or si ce n'est pas exactement 345 boucles / milliseconde.... cela decale tout :
1 -à la fois le filtre TIMEOUT : if (numloops++ == maxloops) break; traduit dans ta version en if (PulseLength > SIGNAL_TIMEOUT*1000 ) break;
2 -et plus ennuyeux, cela peut décaler la mesure de la durée d'un pulse : PulseLength=((numloops + Overhead)* 1000) / LoopsPerMilli; traduit dans ta version en PulseLength = micros()-my_start ;

Mon hypothèse est que ce n'est pas exactement 345 boucles par millisecondes sur le programme original / Arduino 2560.
En écrivant Vrai (mesuré) Loops Per Milliseconde = LoosPerMilli + epsilon = 345 + epsilon (epsilon = différence du nombre de boucles, à mesurer sur la mega 2560, par milli avec le nombre de boucles théoriques dans le code RFLINK soit 345) et en repartant du code original pour arriver à ton code modifié... on doit introduire quelques petites corrections liées à epsilon, comme ci-dessous

Code : Tout sélectionner

do {                                                                         // read the pulses in microseconds and place them in temporary buffer RawSignal
       my_start = micros();
      do {
        PulseLength = micros()-my_start ;
        if (PulseLength > SIGNAL_TIMEOUT*1000 * (1-epsilon/345 )) //****************new **********************
          break;
      } 
      while ( (GPIP(DataPin)==FstateMask) ^ Ftoggle  );
      PulseLength = PulseLength *(1+epsilon/345);         //****************new **********************
           if (PulseLength<MIN_PULSE_LENGTH)  break;  
Attention peut être qu'il faut convertir les types de format pour faire un calcul précis avec l' epsilon/345... epsilon peut être négatif ou positif suivant la mesure sur mega 2560

Voilà une première piste pour essayer d'améliorer le taux de trames rejetées par ESP8266
P.S.1 Comment expliquer que l'algo modifié (en éliminant LoopsPerMilli) tourne parfaitement sur Mega 2560 sans perte de trames alors que sur ESP8266 on en perd ? peut-être à cause de la différence de vitesse des 2 CPU qui fait que la Mega 2560 est moins "sensible" au changement opéré sur le deuxième algo.

Je ne suis absolument pas sur que c'est la solution .... et si tu mesures que par miiliseconde on a bien 345 boucles alors il faudrait chercher ailleurs !!
Modifié en dernier par snips le 07 avr. 2016, 14:00, modifié 2 fois.

rimram31
Messages : 657
Enregistré le : 04 oct. 2015, 11:22
Localisation : Toulouse

Re: Vous prendrez bien un peu de Wifi avec votre RFLink ?

Message par rimram31 »

@Charly86 et @snips ca fait quelques temps que j'avais parcouru le code rflink lorsque j'ai développé ma carte fille RF pour le pi (viewtopic.php?f=21&t=924#p8956) et je suis très perplexe de voir des changements d'etat gérés par un while(...) dans un boucle principale.

Surpris que les développeurs n'aient pas utilisé des interruptions, https://www.arduino.cc/en/Reference/AttachInterrupt, qui sont faites justement pour ça pour faire du temps réel, en tout cas au mieux, et avoir des mesures précises car une interruption est gérée au plus près du hardware. D'ailleurs on évite de trop trainer dans le code d'une interruption pour éviter de tout bloquer, on n'utilise par exemple jamais de print beaucoup trop longs.

C'est ce que fait 433utils https://github.com/ninjablocks/433Utils (https://github.com/sui77/rc-switch). J'utilise ce principe sur ma carte pi même si le pi n'est pas "temps réel" au sens d'un microcontrôleur.

Je ne sais pas s'il est facile ou pas de réécrire le "scanEvent" sur ce principe. On installe la fonction d'interruption qui intercepte les changements d'etat, cette fonction se contente de remplir la "trame", la boucle principale fait alors un while() sur "nouvelle trame", idéalement on gère les trames sur une pile (dépilée par ailleurs par la boucle principale) afin de désynchroniser parfaitement le tout.
Raspberry Pi 2 + carte RF pi "maison" + Domoticz
Sonde Oregon + Aliexpress - Prises Chacon (3500W) - 1wire DS18B20

snips
Messages : 272
Enregistré le : 18 mars 2015, 22:37

Re: Vous prendrez bien un peu de Wifi avec votre RFLink ?

Message par snips »

+1 !

Stuntteam
Messages : 34
Enregistré le : 13 janv. 2016, 17:41

Re: Vous prendrez bien un peu de Wifi avec votre RFLink ?

Message par Stuntteam »

We have extensively tested RFLink with interrupts but that did not work as well..
Also, Nijablocks/rc-switch etc. are not even close to RFLink when it comes to the number of supported protocols and devices.

Répondre