Pages: [1]   Go Down
Author Topic: [Résolue] ISR perturbé par un Ecran Lcd I2c  (Read 227 times)
0 Members and 4 Guests are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

bonjour a tous, j'ai un petit problème de code que je n'arrive pas a solutionner j'utilise un  récepteur infrarouge type TSOP34856 surveiller par un une fonction ISR comme ceci :

Code:

//ISR ROUTINE

ISR(TIMER2_OVF_vect, ISR_NOBLOCK){
  
//RECEPTION
        

        rxRead1 = (PIND & B10000000) >> 7; //aka read pin 7, the fast way
        rxRead2 = (PIND & B00010000) >> 4; //aka read pin 7, the fast way

    
        rxTimer++;      
        
        switch (rxState) { //check current state of rx message CAPTEUR 1
          case STATE_IDLE: //idle, waiting for something to start
            if (rxRead1 == MARK) {
              if(rxRead2 == MARK){
                dircapteur = 1;
              }
              else{
                dircapteur = 0;
              }
              rxTimer = 0;
              rxState = STATE_MARK;  // transmission begins, check HDR (header)
            }
          break;
          case STATE_MARK: // timing MARK
            if (rxRead1 == SPACE){   // MARK ended, record time
              rawData[rawIndex] = rxTimer;
              rawIndex++;
              
              rxTimer = 0;
              rxState = STATE_SPACE;
            }
          break;
          case STATE_SPACE: // timing SPACE
            if (rxRead1 == MARK){   // MARK ended, record time
            
              rawData[rawIndex] = rxTimer;
              rawIndex++;
              
              rxTimer = 0;
              rxState = STATE_MARK;
            }
            else if(rxTimer > 34) {rxState = STATE_STOP;}
          break;      
        }
}

Cette fonction marche très bien sauf quel est perturbé par la librairie LIquid_CrystalI2c ou wire.


Le récepteur infrarouge reçoit des trame de code en rafale et si l’écran est utilisé en même temps certains code sont erronée, par-contre si je n'envoie pas de commande a l’écran  il décode 100% des trame.

Code:
...
     receivehit(); //Il s'agit de la fonction qui décode les trame
    
       //osd(); //Gestion de l'affichage de parametre
       //Gestion backlight
       if(backlightlcd == 1){
         //lcd.backlight();
         backlightoff = 0;
       }else if(backlightlcd == 0 && backlightoff == 0){
         backlightoff = 1;
         //lcd.noBacklight();
       }
    
....

void receivehit(){
  // COMPUTE INCOMING DATA
  if(rxState == STATE_STOP){          // DATA! a STOP has been issued meaning there's something to compute
        for(rawIndex = 0; rawIndex < 40; rawIndex++){    
          if(rawIndex % 2 == 0){ //even positions, no spaces        
            if(rawIndex == 0 && !match_hdr(rawData[rawIndex])) {  //first position (hdr)
              break;
            }
            else if(rawIndex != 0) { //not the hdr
            
              if(match_one(rawData[rawIndex])) rxData = (rxData << 1) | 1;
              else if(match_zero(rawData[rawIndex])) rxData <<= 1;
              else{
                break;
              }
            }
          }
          else{  //odd positions, spaces        
            if(rawData[rawIndex] == 0) break;
            else if(!match_zero(rawData[rawIndex])){
             break;
            }        
          }
          //Serial.print(" ");
          //Serial.print(rawData[rawIndex]);
        }
         //Serial.println("");
         Serial.println(rxData,HEX);
        
  
      //prepare for next data
      for(rawIndex=0; rawIndex<40; rawIndex++){ //clear rawData array    
        rawData[rawIndex] = 0;  
      }
      
      rxData = 0;
      rawIndex = 0;
      rxState = STATE_IDLE; // sets the state of the receiver to idle (default)
  }  
}
Si je dé commente une de ces lignes la réception infrarouge n'est plus fiable.

Quelqu’un aurais une idée ?

Merci d'avance.
« Last Edit: September 30, 2014, 05:27:41 pm by lemat » Logged

France
Offline Offline
Faraday Member
**
Karma: 55
Posts: 5405
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour,

Regarde le code de LiquidCrystal_I2C mais j'ai comme l'impression que tu as un conflit de ressource.

Ton code utilise le timer 2 pour la réception et je suis quasi sûr que LiquidCrystal_I2C utilise ce même timer 2 pour faire la PWM qui fait marcher le rétroéclairage de l'écran.

Une lecture rapide du code source de la lib te donneras toutes les réponses à tes questions.
Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Merci pour ton aide skywodd c'est pas le première fois ^^

J'avais déjà penser a ca mais je n'ai pas réussi a trouver de référence a ce timer dans la lib lcd.

Je poste la librairie si tu peut y jeter un oeuil.

* LiquidCrystal_I2C.cpp (8.64 KB - downloaded 3 times.)
* LiquidCrystal_I2C.h (3.35 KB - downloaded 2 times.)
Logged

France
Offline Offline
Faraday Member
**
Karma: 55
Posts: 5405
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

En fait je suis idiot (ou alors vraiment pas réveillé ... je sais pas).

Ta version de LiquidCrystal_i2c n'utilise pas de PWM pour le rétro-éclairage.
Il est juste éteint ou allumé. Donc pas de problème de Timer2.

Par contre la lib utilise Wire pour l'I2C. Et Wire utilise en interne une interruption pour fonctionner.

Donc si tu utilises l'écran trop souvent, l'interruption de Wire s’exécute tout le temps et bloque ton interruption à toi.
Le mieux que tu puisses faire c'est de réduire/limiter la fréquence de rafraîchissement de l'écran pour éviter de perdre trop d'interruptions de ton côté. Tu peux pas faire grand chose d'autre ...
Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah ok, enbetant cette histoire, la réception infrarouge correspond a tir d'un autre joueur car il s'agit d'un système de laser game donc je ne peut pas vraiment perdre de trame pour l’équité du jeu.

Je ne peut pas donner la priorité a mon instruction, ou autre ?

Logged

France
Offline Offline
Faraday Member
**
Karma: 55
Posts: 5405
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah ok, enbetant cette histoire, la réception infrarouge correspond a tir d'un autre joueur car il s'agit d'un système de laser game donc je ne peut pas vraiment perdre de trame pour l’équité du jeu.
Effectivement c'est assez embêtant ...

Je ne peut pas donner la priorité a mon instruction, ou autre ?
Non ce n'est pas possible.
Et il me semble pas avoir vu un jour une version modifié de Wire n'utilisant pas d'interruptions ...
Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok tampis je vais essayer de limiter au maximum l'actualisation de l’écran si un tir peut arriver.
Si quelqu'un a d'autres idée je suis preneur ^^

Merci quand même skywodd, j'y voit plus clair ^^

Ps: si j'utilise sei() et cli() en debut et fin de mon ISR est-ce que cela peut changer quelques chose ?
« Last Edit: September 28, 2014, 04:06:51 pm by lemat » Logged

Offline Offline
Sr. Member
****
Karma: 12
Posts: 302
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Peut-être essayer de diminuer la fréquence du bus I²C. Ça ne résoudra sans doute pas le problème, mais ça peut en diminuer la fréquence d'apparition.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Dans twi.h le réglage est déjà sur :
Code:
  #ifndef TWI_FREQ
  #define TWI_FREQ 100000L
Donc 100Khz d'après la doc c'est le minimum.

Je sèche complètement sur ce problèmes je ne pense qu'en même pas avoir attend les limites du 328p.
Logged

France
Offline Offline
Faraday Member
**
Karma: 55
Posts: 5405
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Peut-être essayer de diminuer la fréquence du bus I²C. Ça ne résoudra sans doute pas le problème, mais ça peut en diminuer la fréquence d'apparition.
Diminuer la fréquence de l'i2c risque d'être compliqué vu que c'est la lib qui fait l’initialisation.
Diminuer la fréquence de rafraîchissement de l'écran est plus simple et plus rapide, en bonus on peux aussi essayer de rendre l'interruption de l'IR pour la rendre plus rapide (mais c'est déjà plus complexe).
Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Pour le rafraîchissement de l’écran je peut le limiter a toutes les une seconde (Car affichage d'un compte a rebours avec MM:SS).
J'ai des événement qui demande a être plus rapide que ça mais je peut les afficher que lorsque c'est vraiment nécessaire.

Diminuer la fréquence de rafraîchissement de l'écran est plus simple et plus rapide, en bonus on peux aussi essayer de rendre l'interruption de l'IR pour la rendre plus rapide (mais c'est déjà plus complexe).
De quelle manière pourrait t'on rendre l'ISR plus rapide ?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonsoir, après optimisation de mon osd :

- Mise a jour de l'affichage des donnée quand celle ci sont modifié
- Compte a rebours mis a jour a l'affichage toutes les 5s quand le rétroéclairage de l’écran est éteint (quand même lisible).
J'ai aussi fait en sorte qu'il n’écrive pas en boucle sur l’écran des donnée qui vont être remplacer quelques seconde puis ré-afficher ensuite surtout pour celle ou ça peut arriver seulement 3-4 fois par partie.

Voila ci c'est quelques petites infos sur la correction de ce problèmes peuvent en aider d'autre tant mieux smiley-wink

Merci beaucoup skywodd, le problème est résolue je ne ressent presque plus du tout l'interruption wire.
 smiley
Logged

Online Online
Full Member
***
Karma: 2
Posts: 146
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

tu as tenté un
ISR(TIMER2_OVF_vect, ISR_BLOCK){
?

quel type d'ecran i2C est-ce?
ce que tu as sur ton montage s'en tiend a IR + 1 lcd + I/O basique?

1ere solution simple: passer sur un ecran en com // 7 fils: la lib n'est pas interruptive
2eme solution plus penible: reproduire la com i2c pour piloter l'ecran (le briquoler un peu si besoin)
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 39
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Je ne savais même pas que je pouvais faire :
ISR(TIMER2_OVF_vect, ISR_BLOCK){

Je viens de faire un essais même en déclenchant des action de l’écran pendant les réception, plus aucuns code raté smiley

Tu vient de régler définitivement mon problèmes jean-l MERCI smiley

J'ai un écran alphanumérique 2x16 lignes de caractères.

J'utilise presque tout ce que sais faire l'arduino :
Bluetooth en serial
NRf24l01+ en SPI
I2C pour l'ecran
I/0 basique et pwm pour émission et réception IR

L’écran était obligatoirement en I2C sinon je n'avait pas assez de pin sur le 328PU ^^

Mais bon maintenant que tout roule ce n'est plus un problèmes smiley-grin
Logged

Online Online
Full Member
***
Karma: 2
Posts: 146
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

les interruptions c'est tres simple et tres compliqué a la fois.

ISR(TIMER2_OVF_vect, ISR_BLOCK)
est la meme chose que
ISR(TIMER2_OVF_vect)

une interruption peut en interrompre une autre, c'est a toi de gerer l'imbrication.
d'une maniere generale, une interruption materielle sera prioritaire.

il faut dans la mesure du possible reduire au minimum le temps d'interruption.
l'utilisation de

Code:
rxRead1 = (PIND & B10000000) >> 7; //aka read pin 7, the fast way
rxRead2 = (PIND & B00010000) >> 4; //aka read pin 7, the fast way

est donc plus que judicieuse. et si tu te sert de rxRead que dans cette routine, tu peut meme t'abstenir de shifter >>.

...
c'est quoi comme module bluetooth que t'utilise?
« Last Edit: Today at 01:35:13 am by jean-I » Logged

Pages: [1]   Go Up
Jump to: