ATtiny85 (DIGISPARK) : lecture analogique bloquée après une Interruption.

Bonjour,

J’ai besoin d’aide pour terminer mon projet de commande d’interrupteur à distance dans une vieille maison dans laquelle il n’est pas simple de passer de nouveaux câbles.

J’utilise des nrf24L01 pour transmettre et recevoir les ordres de mise en marche ou d’arrêt.
Les émetteurs sont commandés par des ATtiny85 (DIGISPARK). Le récepteur est fait avec un NANO.

Les émetteurs envoient une chaine de commande au récepteur qui lui actionne un télérupteur.
La chaine contient le nom de la zone à allumer, le N° de l’interrupteur actionné et une mesure de la tension de la pile qui l’alimente.

Le principe fonctionne (morceaux par morceau) mais je rencontre un problème lorsque j’utilise une interruption pour déclencher l’envoi du message au récepteur.
Lorsque l’interruption est ajoutée à mon programme, elle remplie bien son rôle d’interruption mais elle m’empêche de lire la tension de tension de la pile. Je ne lis plus rien alors que si je retire la ligne “attachPCINT” du programme, la tension est bien lue. Je me demande si la fonction ADC de l’ATtiny85 n’est pas désactivée lorsque la fonction “attachPCINT” est exécutée.
J’utilise la librairie “PinChangeInterrupt.h”
Si je remplace l’interruption par une simple lecture de l’état de la broche sur laquelle est connecté le poussoir cela fonctionne.
Je souhaite utiliser une interruption car je voudrais au final passer le montage en mode très faible consommation et le réveiller par cette interruption lorsque le poussoir est enfoncé puis le remettre en low power.

Voici le code de l’émetteur :

#include <RF24.h>
#include "PinChangeInterrupt.h"

#define CE_PIN 3
#define CSN_PIN 3 //Since we are using 3 pin configuration we will use same pin for both CE and CSN


RF24 radio(CE_PIN, CSN_PIN);

byte address[11] = "SimpleNode";

const int pin_inter_poussoir = 4; // Entrée bouton poussoir associée à l'Interruption (Même Numéro)
const int pin_Lecture_Tension_Pile = 3; // Entrée analogique pour mesure tension pile
int Tension_Pile_Digit = 0;
const int iType_ADC=1023;
const int iRef_ADC=5000;
int State_Interruption = 0;

/** Différents messages de commande */
const char CMD_BOUTTON_A[] = "IT_LUM_COUL";  //Interrupteur Lumière Couloir
const char Numero_interrupteur[] = "01";


void setup() {
  pinMode(pin_inter_poussoir, INPUT_PULLUP);
  radio.begin(); // Start up the radio
  radio.setAutoAck(1); // Ensure autoACK is enabled
  radio.setRetries(15,15); // Max delay between retries & number of retries
  radio.openWritingPipe(address); // Write to device address 'SimpleNode'
  attachPCINT(digitalPinToPCINT(pin_inter_poussoir), Fonction_Interruption, FALLING); //Active l'interruption liée à l’action sur le poussoir (Le signal passe de VCC à GND)

}

//***********************************************************************
void loop(void){
  
}
//***********************************************************************

void Fonction_Interruption()
{
int Tension_Pile_Digit = 0;
  int Tension_Pile_Analog_mv = 0;
  char Buffer_Message [30] = "message";
  int n;
  
  Tension_Pile_Digit=analogRead(pin_Lecture_Tension_Pile);  // lire la tension de la pile (Lecture entre 0 et 1023.) 
  //Tension_Pile_Digit=700;
  Tension_Pile_Analog_mv = (map(Tension_Pile_Digit,0,iType_ADC,0,iRef_ADC));  // Transformation valeur digit => Analog 
  n=sprintf(Buffer_Message,"%s %s %d", CMD_BOUTTON_A, Numero_interrupteur, Tension_Pile_Analog_mv); // Transformation des différentes données en un seul mots qui sera envoyé. 
  radio.write(Buffer_Message, n); //Send data to 'Receiver' ever 2 second
}

J’ai essayé de stopper l’interruption par un “disablePCINT()” ou un “detachPCINT()” avant de faire la mesure de tension mais cela ne change rien. J’ai aussi ajouté des tempos avant la lecture de la tension, sans effet.

HARDWARE :
J’utilise le montage 3 Wires pour connecter le nrf24L01 qui utilise PB0, PB1, PB2.
La mesure de tension se fait sur PB3.
Le poussoir est connecté en PB4 et envoie un GND lorsqu’il est activé. (Capa de 10nF en parallèle.)

L’interruption fonctionne mais elle a un effet pervers sur l’entrée analogique d’à coté .Avez-vous des pistes/solutions à me proposer ?

Merci d’avance pour votre aide.

Bien cordialement.

Christian

[56 ans et débutant sur Arduino.] :wink:

Le µcontrôlleur ne sait gérer qu’une interruption à la fois.
Lorsqu’une interuption intervient, elle bloque la détection d’une aute interruption.

La fonction analogRead utilise une interruption pour savoir quand la conversion analogique est terminée.
De ce fait comme tu es déjà dans une interruption, la fonction analogRead ne peut pas fonctionner

Une solution simple consiste à déplacer le code contenu dans la routine d’interruption, vers la fonction loop()

#include <RF24.h>
#include "PinChangeInterrupt.h"

#define CE_PIN 3
#define CSN_PIN 3 //Since we are using 3 pin configuration we will use same pin for both CE and CSN


RF24 radio(CE_PIN, CSN_PIN);

byte address[11] = "SimpleNode";

const int pin_inter_poussoir = 4; // Entrée bouton poussoir associée à l'Interruption (Même Numéro)
const int pin_Lecture_Tension_Pile = 3; // Entrée analogique pour mesure tension pile
int Tension_Pile_Digit = 0;
const int iType_ADC=1023;
const int iRef_ADC=5000;
int State_Interruption = 0;

/** Différents messages de commande */
const char CMD_BOUTTON_A[] = "IT_LUM_COUL";  //Interrupteur Lumière Couloir
const char Numero_interrupteur[] = "01";

volatile boolean Interrupt_Flag = false;


void setup() {
  pinMode(pin_inter_poussoir, INPUT_PULLUP);
  radio.begin(); // Start up the radio
  radio.setAutoAck(1); // Ensure autoACK is enabled
  radio.setRetries(15,15); // Max delay between retries & number of retries
  radio.openWritingPipe(address); // Write to device address 'SimpleNode'
  attachPCINT(digitalPinToPCINT(pin_inter_poussoir), Fonction_Interruption, FALLING); //Active l'interruption liée à l'action sur le poussoir (Le signal passe de VCC à GND)

}

//***********************************************************************
void loop(void){
 int Tension_Pile_Digit = 0;
  int Tension_Pile_Analog_mv = 0;
  char Buffer_Message [30] = "message";
  int n;

if(Interrupt_Flag) {
  
  Tension_Pile_Digit=analogRead(pin_Lecture_Tension_Pile);  // lire la tension de la pile (Lecture entre 0 et 1023.) 
  //Tension_Pile_Digit=700;
  Tension_Pile_Analog_mv = (map(Tension_Pile_Digit,0,iType_ADC,0,iRef_ADC));  // Transformation valeur digit => Analog 
  n=sprintf(Buffer_Message,"%s %s %d", CMD_BOUTTON_A, Numero_interrupteur, Tension_Pile_Analog_mv); // Transformation des différentes données en un seul mots qui sera envoyé. 
  radio.write(Buffer_Message, n); //Send data to 'Receiver' ever 2 second

    Interrupt_Flag=false;

    }

}
//***********************************************************************

void Fonction_Interruption()
{
Interrupt_Flag=true;
}

Bonjour Alain,

Merci pour cette réponse, je ne savais pas que "analogRead()" utilise une interruption.
Néanmoins, à l'origine mon code était écrit dans la fonction "LOOP()" et j'avais le même problème.

J'ai, dans le doute, réessayé en chargeant directement la séquence que vous avez modifiée et hélas, j'ai toujours le même problème, la tension n'est pas lue.

Un fois l'interruption déclenchée, n'y a-t-il pas un moyen pour retirer, annuler, suspendre, l'interruption afin de laisser la place à la lecture de la tension puis de réactiver l'interruption initiale ?

Comme je l'ai évoqué dans mon premier message, j'ai déjà essayé d'enlever l'interruption mais sans y parvenir.

Cordialement.

Christian

#define CE_PIN 3
...
const int pin_Lecture_Tension_Pile = 3; // Entrée analogique pour mesure tension pile


...
Tension_Pile_Digit=analogRead(pin_Lecture_Tension_Pile);  // lire la tension de la pile (Lecture entre 0 et 1023.)

Il y a peut-être aussi une erreur sur la référenciation de la broche analogique
pin_LectureTension_Pile est égal à 3
La pin 3 n'est pas une entrée analogique et dans ton cas elle est déjà utilisée pour autre chose (#define CE_PIN 3)

Je suppose qu'il s'agit de la pin A3

Dans ce cas il te faut définir

const byte pin_Lecture_Tension_Pile = A3; // Entrée analogique pour mesure tension pile

ou

const byte pin_Lecture_Tension_Pile = 17; // Entrée analogique pour mesure tension pile

Ce qui revient au même pour une Uno