Projet : IRTiny_Cat , Question !!!

Bonsoir à vous, j’essaye de faire un petit projet à base d’ATtiny85 pour repérer le chat dans une piéce (chambre bébé), ça devrais marcher avec du code IR sur le principe des télécommandes.
J’ai fait le code pour l’émetteur sur ATtiny85, avec un mode sleep/Watchdog entre deux envois de code, ça marche mais j’ai un soucis au niveau du timing…

Dans le code la ligne : int WDT_Time = 7;// Réglage du délais de veille: 0=16ms, 1=32ms, 2=64ms, 3=125ms, 4=250ms, 5=500ms, 6=1 sec, 7=2 sec, 8=4 sec, 9= 8sec, marche bien quand je saisie 7/8/9 , Régle le temps de veille du timing Watchdog.
Mais si je saisie 6 (donc timing de 1sec de “veille”) ça bloque complétement, en principe l’envoi du code prend moins de 1 seconde, je ne comprends donc pas pourquoi ça bloque avec le paramétrage de veille à 1Sec, en dessous de 6 ça me parait juste pour l’envois du code et le bon déroulement du sketch…
C’est pas que c’est bloquant pour le reste de mon projet, mais j’aime bien savoir pourquoi ça marche pas, et là je vois pas vraiment et comme on dit un oeil extérieur (et qui plus est expérimenté) est toujours source de bonne idée pour résoudre des Couacs…

Donc voila mon code :

#include <avr/sleep.h>
#include <avr/wdt.h>

#define IR_Pin PORTB // Registre du PORTB Définit en Ecriture et Lecture
#define IR_Led 3 // Définit le pin de la Led IR > Pin2 (PB3)

byte Code_IR = B01010101;//Code IR envoyé
int WDT_Time = 7;// Réglage du délais de veille: 0=16ms, 1=32ms, 2=64ms, 3=125ms, 4=250ms, 5=500ms, 6=1 sec, 7=2 sec, 8=4 sec, 9= 8sec
byte WDP_Set; // Réglage WDP (bit de réglage délais de veille)

void setup(){
   Set_Time_WDT(WDT_Time); //Délais de veille
   OSCCAL = 0x56; // Calibration Oscillateur Interne de l'ATtiny85, voir Tiny Tuner
   DDRB |= _BV(IR_Led); // Met le pin IRled en OUTPUT > 0000 1000
   ADCSRA = 0; // Désactive l'ADC (Analog to Digital Converter) pour économiser du courant en mode veille
}
	
void loop(){
   IRCode(); // Lance la Boucle IRCode
   DDRB &= ~_BV(IR_Led); // Mets le port de la Led en INPUT pour économiser du courant
   Veille(); // Mise en veille de l'ATtiny
   DDRB |= _BV(IR_Led); // Remet le port en OUTPUT
}

void Veille() { // Met l'ATtiny en veille
   MCUSR &= ~(1<<WDRF);  // Met à 0 le bit "Watchdog Reset Flag" dans le Registre MCU (Registre de statut) qui est remis à 1 quand l'ATtiny sort de veille (indicateur sur la façon de sortir du reset)
   WDTCR = _BV (WDCE) | _BV (WDE); // Régle les bits WDE et WDCE sur 1 du WDTCR (Watchdog Timer Control Register) pour pouvoir configurer les délais de mise en veille
   WDTCR = _BV (WDIE) | WDP_Set; // Met le bit WDIE sur 1, ce qui active l'interruption du watchdog et met le bit WDE à 0, les bits WDP sont réglé et à la fin du délais configuré le Watchdog fait un reset
   wdt_reset();
   set_sleep_mode (SLEEP_MODE_PWR_DOWN);  //ZZZzz..ZZzzz..Zzz
   sleep_enable();
   sleep_cpu ();   
   sleep_disable();
}
	
void pulseIR(long microsecs){ // Envoit les pulsations à 38Khz durant le temps définit par les microsecondes de PulseIR
   while (microsecs >= 0){ // Tant que les microsecondes de la valeur pulseIR n'ont pas atteint 0 on continu
     IR_Pin &= ~_BV(IR_Led); // Met le Pin2 (PB3) à l'état haut
     delayMicroseconds(13); //38Khz = 13 microsecondes haut + 13 microsecondes bas
     IR_Pin |= _BV(IR_Led); // Met le Pin2 (PB3) à l'état bas
     delayMicroseconds(13); //38Khz = 13 microsecondes haut + 13 microsecondes bas
     microsecs -= 26; // on Retire 26 microsecondes de la valeur PulseIR
    }
}
	
void IRCode() {
  	pulseIR(2600);
	delay(26);
	for(int x = 0 ; x < 8; x++){
		if ( bitRead(Code_IR, x) == 1){
		pulseIR(780);
		delayMicroseconds(780);
		}
		else{
		pulseIR(390);
		delayMicroseconds(390);
		}
	}
}
	
void Set_Time_WDT(int Time){ // Conversion valeur du délais de veille en Décimal pour régler les bits WDP
   if ( Time <= 7 ) WDP_Set = Time ;
   if ( Time == 8 ) WDP_Set = ( Time * 4 ) ;
   if ( Time == 9 ) WDP_Set = ( Time * 4 ) + 1 ;

}

ISR(WDT_vect){ // Vecteur Watchdog lancé à la fin du délais configuré
   wdt_disable();
}

Vala Merci à vous pour l’éventuelle aide…

Bonjour,

Effectivement c'est bizarre l'envoi de la trame devrait prendre une trentaine de millisecondes pourtant ...
Le morceau de code modifiant la calibration de l'horloge CPU et ce calcul bizarre pour le watchdog pourrait bien être la cause du probléme.

Si tu as un oscilloscope il serait intéressant de jeter un coup de sonde au niveau de la led pour voir la durée réelle du signal.

Salut ta toua, c’est à peut pres ce que je pensais pour chaque trame IR, par contre j’ai pas d’oscilloscope, enfin j’ai un Xminilab que je me suis acheté derniérement, et j’ai un peu de mal à comprendre comment marche le bouzzin…j’aurais aimé pouvoir le brancher sur le PC, mais le FW n’est pas compatible, il faut que je flash et j’ai pas de prog AVRISP PDI pour le flasher donc je suis un peu bloqué (je pense pas qu’un arduino puisse le faire …??).
Donc pour le moment j’ai juste pu voir que la fréquence qui est bien en 38Khz (enfin plutot 38.46Khz), mais j’ai pas encore capté comment voir le signal en totalité et calculé le temps d’une trame, c’est la première fois que je me sert d’un “oscilloscope” (les guillemets sont pour le pseudo oscillo, qui reste basique mais qui va me permettre de mettre un petit pied dedans…j’avais pas envie de dépenser plus que 50€ pour quelquechose que je ne connais/maitrise pas)

Pour la partie Réglage de l’horloge interne, j’ai fait ça avec Tiny Tuner, et j’ai cru comprendre qu’il fallait mettre dans le setup la valeur retourné par tiny tuner, en l’occurence 0x56 pour l’ATtiny85 que j’ai; mais j’ai peut être loupé un truc !?!

Pour ce qui est du Watchdog et du mode veille, j’ai brodé avec ce que j’ai lu, j’avais posé une question ici mais le topics est parti au oubliette sans réponse, donc j’ai fait comme je le pensais, aprés si il y a des erreurs dans ma façon je reste ouvert à tes conseils pour modifier le code…

En tous les cas merci à toi ^^

Bonjour à toi,

J’ai écrit l’année dernière un ensemble de librairies optimisées pour les ATtiny. Je l’avais initialement posté ici mais les membres de ce forum m’ont tellement gonflé que j’ai traduit le post pour le publier uniquement sur le site anglophone.

La librairie IR décode le RC5 avec une fiabilité parfaite et ceci avec une empreinte mémoire minimale. Si tu as des problèmes avec l’anglais dis le moi je te traduirai la partie IR.

Voici le lien : http://arduino.cc/forum/index.php/topic,118794.0.html

Je te reproduis ici la partie IR :

ATTENTION : TinyIRrc5.h utilise TinyIrqHandler.h que tu dois aussi inclure dans ton projet.


The provided example run on 16 MHz clock ATtiny45 (internal oscillator).

TinyIrqHandler.h

Full management of PCINT0 . Only one function to install your interrupts routines. Nothing else to handle.

IRQvecteur(byte irq, void (*adresse)())

example:

void MyPin1Routine()
{
   // your code here
}

void MyPin2Routine()
{
   // your code here
}

void MyPin3Routine()
{
   // your code here
}

etc...

void setup
{
   IRQvecteur(1, MyPin1Routine);
   IRQvecteur(2, MyPin2Routine);
   IRQvecteur(3, MyPin3Routine);
}

The library saves the value of micros() at the start of interrupt in the data IRQmicros. I’s interesting to enable interrupts at the start or inside your routine by the Arduino’s function interrupts(), but if you have to use the value IRQmicros you have to save it before enable interrupts to ensure the value doesn’t change because of another interrupt. The provided libraries TinyIRrc5 & TinySerialPlus are always doing this to let the timer’s routine execute as soon as possible in order to keep a good synchro on serial transmit.

TinyIRrc5.h

Infrared receive of RC5 codes under interrupts. This library contains 2 functions and one flag data.

IRdemarre(pin number)
int IRdecode()

The repeatbit of RC5 protocole is automatically managed. If the key is a repeat then the high bit of the return is set if not this bit is clear.

Variable IRok indicate an available key.

example:

 IRdemarre(1);

byte car;
 
   // Avec suppression de la répétition
   for (;;)
   {
      if (IRok)
      {
        car = IRdecode();
        if (car < 0x800)     // Test for no repeat key
          {
          switch(car)
	{
	  case 0x41:
	     // your code
               break;
          etc..	

   // Avec répétition
   for (;;)
   {
      if (IRok)
      {
        car = IRdecode() & 0x7FF;    // suppress the repeat bit
        switch(car)
	{
	  case 0x41:
	     // your code
                break;
          etc..

Voici également le lien pour télécharger le zip avec les librairies et exemple : http://balbarie.com/arduino/TinyLibrariesSet.zip

Bon courage…