Adafruit NRF52832 - Interruptions et registre LATCH

Bonjour à tous,

Je me tourne vers ce forum après plusieurs jours, pour ne pas dire semaines, de frustration >:(

Afin de faire un démonstrateur sur batterie de BLE iBeacon, j'ai acheté et reçu une carte Adafruit Feather nRF52 Bluefruit LE - nRF52832 PRODUCT ID: 3406.

Mon montage et mon objectif étant relativement simple, je suis parti peut être un peu trop confiant.

Voici mes besoins, mon cahier des charges initial:

  • une carte permettant de faire du BLE iBeacon (Adafruit_nRF52_Arduino)
    -5 boutons poussoirs câblés sur 5 GPIO distincts avec pull down 10K
    -une batterie 3.6Volts
    -une librairie permettant de plonger en sommeil profond le µC pour économiser la batterie et de la réveiller sur interruption déclenché par les 5 boutons poussoirs.

Je précise que dans mon cas pour atteindre mes objectifs d'autonomie, j'utilise le mode SYSTEM_OFF. Cela implique qu'à la détection de l'interruption le système redémarre comme si appui sur bouton RESET.

Jusqu'à là, j'ai réussi à faire ce que je souhaitais sans trop de difficulté et j'en étais très content.

Mais voila, le cahier des charges à évolué.
En plus de tout ce qui est déjà décrit ci-dessus, il me faut déterminer lequel des 5 boutons a été pressé et donc a déclenché le réveil via interruption car chacun de ces boutons a une fonction bien précise. Je me suis dit, facile, un "digitalread" au plus tôt dans le programme, et le tour est joué.

Erreur... En effet, je me suis vite rendu compte que le système mettait environ 2 secondes à sortir de veille. Conclusion, si je réalise un appui "normal" (~0.5 à 1 seconde, car non maintenu pendant au moins deux secondes), impossible avec cette technique de déterminer quel bouton a été appuyé. Le résultat du digitalread est toujours "0" sauf si je maintiens l'appui pendant 3 secondes.

Ayant vu sur le net la possibilité sur les cartes Arduino à base de 328P de supprimer le bootloader pour un démarrage plus rapide, c'est la première piste que j'ai explorée mais sans succès. En effet, il faudrait pour cela programmer directement le NRF52832 avec un IDE de type Segger Embedded Studio et le SDK Nordic SemiConductor. Mais on sort de l'IDE Arduino et cela dépasse mes compétences (en tout cas à court terme :wink: ).

J'ai donc décidé de me plonger dans la doc du NRF52832, et j'ai découvert qu'il y avait plusieurs registres qui me permettraient peut-être d'atteindre mon objectif dont un en particulier le registre LATCH. Aprsè des échanges sur la DevZone Nordic cela m'a été confirmé.
Mais voila, malgré toutes mes tentatives, à chaque fois que je lis ce registre j'obtiens en hex : 0xFFFFFFFF que j'appuie ou non sur un bouton ou plusieurs boutons. On m'a donc conseillé avant de plonger le µC en sommeil de réinitialiser le registre LATCH avec le code :

NRF_GPIO->LATCH = NRF_GPIO->LATCH;

Mais cela ne change rien du tout, le résultat est toujours le même: 0xFFFFFFFF.

Voici la totalité de mon code de test :

//Liste de librairies nécessaires
#include <Arduino.h>
#include <Arduino_nRF5x_lowPower.h> // LowPower Library for nRF5x

typedef volatile uint32_t REG32;
#define pREG32 (REG32 *)

#define LATCHO            (*(pREG32 (0x10000520)))
#define RESETREAS         (*(pREG32 (0x10000400)))


//Interruption

#define interruptPin16    16    /*Bouton 1 clavier Smilio A = Pin 16*/
#define interruptPin15    15    /*Bouton 2 clavier Smilio A = Pin 15*/
#define interruptPin7     7     /*Bouton 3 clavier Smilio A = Pin 7*/
#define interruptPin11    11    /*Bouton 4 clavier Smilio A = Pin 11*/
#define interruptPin27    27    /*Bouton 5 clavier Smilio A = Pin 27*/

#define LOOP_CYCLES     100   // Nombre de cycle
#define CYCLE_TIME_MS   50   // Délai en ms de chaque cycle
                              // dans ce cas tempo avant mise off du système de 100*50=5000 ms soit 5 secondes

volatile int cycles = 0;
volatile bool int1 = false;
int button1 = 0;

void intHandlerone() {

    cycles = 0;
    int1 = true;
}

void setup() {

//Setup interruptions
  //Définition du type d'entrée pour les interruptions
  pinMode(interruptPin27, INPUT);
  pinMode(interruptPin16, INPUT);
  pinMode(interruptPin15, INPUT);
  pinMode(interruptPin7, INPUT);
  pinMode(interruptPin11, INPUT);

  attachInterrupt(digitalPinToInterrupt(interruptPin27), intHandlerone, HIGH);
  nRF5x_lowPower.enableWakeupByInterrupt(interruptPin27, HIGH);
  attachInterrupt(digitalPinToInterrupt(interruptPin16), intHandlerone, HIGH);
  nRF5x_lowPower.enableWakeupByInterrupt(interruptPin16, HIGH);
  attachInterrupt(digitalPinToInterrupt(interruptPin15), intHandlerone, HIGH);
  nRF5x_lowPower.enableWakeupByInterrupt(interruptPin15, HIGH);
  attachInterrupt(digitalPinToInterrupt(interruptPin7), intHandlerone, HIGH);
  nRF5x_lowPower.enableWakeupByInterrupt(interruptPin7, HIGH);
  attachInterrupt(digitalPinToInterrupt(interruptPin11), intHandlerone, HIGH);
  nRF5x_lowPower.enableWakeupByInterrupt(interruptPin11, HIGH);
  
}

void loop() {
  
if (cycles >= LOOP_CYCLES) {

 
  Serial.begin(115200);
  Serial.print("LATCH REGISTER  : ");
  Serial.println(LATCHO, HEX);
  Serial.print("RESETREAS  : ");
  Serial.println(RESETREAS, BIN);

  NRF_GPIO->LATCH = NRF_GPIO->LATCH;
  
  nRF5x_lowPower.powerMode(POWER_MODE_OFF);
  
  }
   
  cycles++;
  delay(CYCLE_TIME_MS);

}

En persistant et en fouillant je suis tombé sur cette note du fabricant : Errata.

Malgré mes tentatives, je n'arrive pas à ce jour soit a écrire correctement dans le registre LATCH pour le remettre à zéro, ou alors il faut donc configurer PIN_CNF[n].INPUT avnat PIN_CNF[n].SENSE, mais dans ce cas il faut supprimer mes commandes "pinMode" et configurer à la main les registres dans le bon ordre. Mais voila, je ne suis absolument pas sur de ma méthode/code pour configurer/écrire dans un registre.

Est-ce que quelqu'un saurait m'aider sur ce sujet en me suggérant des exemples de codes Arduino me permettant de réaliser cela.

Sinon quelqu'un aurait-t-il peut être une autre méthode pour détecter quel bouton a été appuyé pour sortir le µC de veille. J'ai même envisagé de rajouter une "bascule D de type flip-flop" pour mémoriser l'état du bouton le temps que le système démarre. Mais je me dis que cela doit être réalisable via le firmware, et que le seul obstacle à cela, c'est mon incompétence et méconnaissance et "C" et Arduino....

Merci d'avance à tous ceux qui répondront et pourront peut-être m'aider à me sentir moins frustré et à me sortir de ce mauvais pas ;D

@+

Christophe

Bonjour

Est-ce que le cahier des charges autorise l'ajout d'un peu de hardware a l'extérieur du nRF52832 pour mémoriser (5 latches) ou prolonger (5 monostables) l'action sur les boutons ? (controurner avant de pouvoir traiter)

Trouver içi un bon connaisseur des entrailles des nRF52 n'est pas évident , encore moins un modèle très récent. Le problème a l'air très dépendant de la structure des ports d'E/S.

ou alors il faut donc configurer PIN_CNF[n].INPUT avnat PIN_CNF[n].SENSE, mais dans ce cas il faut supprimer mes commandes "pinMode" et configurer à la main les registres dans le bon ordre. Mais voila, je ne suis absolument pas sur de ma méthode/code pour configurer/écrire dans un registre.

En allant voir comment son codées les fonctions 'Arduino' de gestion des pins d'E/S du nRF52832 (/cores/nRF5/wiring_digital.c.......) ça ne donne pas d'idées pour attaquer les registres ?

pas d'aide sur des forums Adafruit ?

Bonjour al1fch,

Merci pour ta réponse. Effectivement comme précisé dans mon poste, j'ai aussi envisagé la solution hardware (5 Latches). Par contre monostable je connais moins voir pas, et je veux bien quelques infos sur le sujet.

Comme tu l'a compris, je souhaitais me sortir de ce mauvais pas avec élégance en trouvant une solution soft... Mais si trop compliqué j'opterai pour le hardware.

J'ai effectivement publié plusieurs post sur forum ADAFRUIT Feather depuis 1 mois, mais à ce jour pas une seule réponse...

Je vais aller voir dans le code "wiring_digital.ccp si cela me donne des idées.

En core merci pour ton aide.

par contre monostable je connais moins voir pas, et je veux bien quelques infos sur le sujet.

l'idée est là , réalisée ci dessous avec un circuit intégré logique spécialisé
une impulsion brève en entrée produit en sortie (polarité au choix) une impulsion de durée calibrée (durée déterminée par R et C)
monostabelpng.png
prendre par exemples des doubles monostables : 74HC123 , 74HC221
Leur doc indique comment sélectionner R et C pour une durée d'implusion déterminée en sortie.
Fonctionnent avec une alimentation comprise entre 2V et 6V
ça permettrait de présenter au nRF des implusion de durée suffiasnte pour qu'il ait le temps au réveil d'agir en conséquence et comme le monostable reprend tout seul son éta stable (état de repos) il n'y a pas à agir pour 'effacer' la mémoire

monostabelpng.png