Timer et nrf24l01 (Résolu)

Bonjour,
Je me suis fait une propre carte avec un 32u4 (avec un resonateur de 8MHz), un bno055 (centrale inertielle), et un nrf24l01+pa+lna (avec RFX2401C). J’ai mis le bootloader de la pro micro de Sparkfun (3.3V et 8MHz).
Je charge le code suivant

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#include <TimerOne.h>

Adafruit_BNO055 bno = Adafruit_BNO055(55);

char qw[7];
char qx[7];
char qy[7];
char qz[7];
char s[32];

RF24 radio(10, SS); // CE, CSN
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 011;
const uint16_t master_node = 00;

RF24NetworkHeader header;
RF24NetworkHeader headerM(master_node);

void setup() {
  //Serial.begin(115200);
  
  SPI.begin();
  radio.begin();
  network.begin(120, this_node); //(channel, node address)
  radio.setDataRate(RF24_2MBPS);
  radio.setPALevel(RF24_PA_MAX);
  radio.setRetries(2, 15);
  radio.enableDynamicPayloads();

  /* Initialise the sensor */
  if (!bno.begin())
  {
    /* There was a problem detecting the BNO055 ... check your connections */
    //    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while (1);
  }
  /* Crystal must be configured AFTER loading calibration data into BNO055. */
  bno.setExtCrystalUse(true);
}

void loop() {
  network.update();
  // Quaternion data
  imu::Quaternion quat = bno.getQuat();
  dtostrf(quat.w(), 3, 3, qw);
  dtostrf(quat.x(), 3, 3, qx);
  dtostrf(quat.y(), 3, 3, qy);
  dtostrf(quat.z(), 3, 3, qz);

  sprintf(s, "i0/%s/%s/%s/%s", qw, qx, qy, qz);
  bool ok = network.write(headerM, &s, sizeof(s)); // Send the data
}

Tout fonctionne correctement. Mais comme j’ai plusieurs de ces cartes et pour ne pas encombrer mon réseau nrf24, je veux pouvoir gérer précisément l’intervalle entre 2 envois. J’ai donc modifié le prescaler du Timer1

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

Adafruit_BNO055 bno = Adafruit_BNO055(55);

char qw[7];
char qx[7];
char qy[7];
char qz[7];
char s[32];
bool ok;

RF24 radio(10, SS); // CE, CSN
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 011;
const uint16_t master_node = 00;

RF24NetworkHeader header;
RF24NetworkHeader headerM(master_node);

void setup() {
  // Serial.begin(115200);
  
  // initialize timer1
  noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  
  OCR1A = 625;            // compare match register 8MHz/256/2Hz
  TCCR1B |= (1 << WGM12);   // CTC mode
  TCCR1B |= (1 << CS12);    // 256 prescaler
  TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
  interrupts();             // enable all interrupts
  
  SPI.begin();
  radio.begin();
  network.begin(120, this_node); //(channel, node address)
  radio.setDataRate(RF24_2MBPS);
  radio.setPALevel(RF24_PA_MAX);
  radio.setRetries(2, 15);
  radio.enableDynamicPayloads();

  /* Initialise the sensor */
  if (!bno.begin())
  {
    /* There was a problem detecting the BNO055 ... check your connections */
    //    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while (1);
  }
  /* Crystal must be configured AFTER loading calibration data into BNO055. */
  bno.setExtCrystalUse(true);
}

ISR(TIMER1_COMPA_vect)          // timer compare interrupt service routine
{
	bool ok = network.write(headerM, &s, sizeof(s)); // Send the data
	//  Serial.print(s); Serial.print("/"); Serial.println(millis());
}

void loop() {
  network.update();
  // Quaternion data
  imu::Quaternion quat = bno.getQuat();
  dtostrf(quat.w(), 3, 3, qw);
  dtostrf(quat.x(), 3, 3, qx);
  dtostrf(quat.y(), 3, 3, qy);
  dtostrf(quat.z(), 3, 3, qz);

  sprintf(s, "i0/%s/%s/%s/%s", qw, qx, qy, qz);
}

Et bien plus rien ne fonctionne, et il me “bricke” la carte. Si maintenant, je fais

ISR(TIMER1_COMPA_vect)          // timer compare interrupt service routine
{
	//bool ok = network.write(headerM, &s, sizeof(s)); // Send the data
	Serial.print(s); Serial.print("/"); Serial.println(millis());
}

le code fonctionne de nouveau.

Merci de me donner votre avis ou de me dire si il existe une solution pour ordonner mon réseau de nrf24

Je dirais qu'à priori il n'est jamais très bon d'appeler des fonctions complexes dans une routine d'interruption.
Il vaudrait mieux travailler avec une variable affectée à True dans la routine d'interruption, puis consultée dans la fonction loop() avant remise à False.

La variable devra être "volatile".

Merci de ta réponse.

Comme ceci

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

Adafruit_BNO055 bno = Adafruit_BNO055(55);

char qw[7];
char qx[7];
char qy[7];
char qz[7];
char s[32];
volatile bool sendDatas = false;

RF24 radio(10, SS); // CE, CSN
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 011;
const uint16_t master_node = 00;

RF24NetworkHeader header;
RF24NetworkHeader headerM(master_node);

void setup() {
  //  Serial.begin(115200);
  // initialize timer1
  noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;

  OCR1A = 625;            // compare match register 8MHz/256/2Hz
  TCCR1B |= (1 << WGM12);   // CTC mode
  TCCR1B |= (1 << CS12);    // 256 prescaler
  TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
  interrupts();             // enable all interrupts

  SPI.begin();
  radio.begin();
  network.begin(120, this_node); //(channel, node address)
  radio.setDataRate(RF24_2MBPS);
  radio.setPALevel(RF24_PA_MAX);
  radio.setRetries(2, 15);
  radio.enableDynamicPayloads();

  /* Initialise the sensor */
  if (!bno.begin())
  {
    /* There was a problem detecting the BNO055 ... check your connections */
    //    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while (1);
  }
  /* Crystal must be configured AFTER loading calibration data into BNO055. */
  bno.setExtCrystalUse(true);
}

ISR(TIMER1_COMPA_vect)          // timer compare interrupt service routine
{
  sendDatas = true;
}

void loop() {
  network.update();
  // Quaternion data
  imu::Quaternion quat = bno.getQuat();
  dtostrf(quat.w(), 3, 3, qw);
  dtostrf(quat.x(), 3, 3, qx);
  dtostrf(quat.y(), 3, 3, qy);
  dtostrf(quat.z(), 3, 3, qz);

  sprintf(s, "i0/%s/%s/%s/%s", qw, qx, qy, qz);

  if (sendDatas) {
    bool ok = network.write(headerM, &s, sizeof(s)); // Send the data
    sendDatas = false;
  }
}

Mais j’ai l’impression de ne plus bénéficier d’avoir deux boucles séparées, celle du loop, et celle du timer1

La routine d'interruption timer1 n'est pas du tout exécutée dans une boucle comme loop().

Je ne vois pas bien où est la gène.
Est-ce que cela fonctionne, au moins ?

Ben imaginons que le temps de mise à jour des valeurs de la centrale inertielle soit de 500ms, et que mon timer interrupt arrive 1ms plus tard, je dois attendre de nouveau 500ms avant de pouvoir émettre mes valeurs.
Bon je peux pas tester pour l'instant, j'ai pas de quoi remettre le bootloader mais je te tiens au courant dès que j'ai testé

Cela fonctionne mais en fait ça ne résout pas mon problème. Je pensais qu'en envoyant mes valeurs à un e fréquence régulière, le nrf24network recevrait les données dans l'ordre, mais en fait je reçois ça

i0/0.234/-0.017/0.002/0.091/55074
i2/0.996/0.005/0.011/-0.091/55119
i1/0.247/-0.005/0.008/0.969/55136
i0/0.234/-0.017/0.002/0.972/55212
i1/0.247/-0.005/0.008/0.969/55250
i0/0.234/-0.017/0.002/0.969/55283
i3/1.000/0.012/0.014/0.0972/55322
i0/0.234/-0.017/0.002/0.972/55388
i2/0.996/0.005/0.011/-0.091/55400
i2/0.996/0.005/0.011/-0.091/55437
i2/0.996/0.005/0.011/-0.091/55545
i1/0.247/-0.005/0.008/0.969/55615
i1/0.247/-0.005/0.008/0.969/55681
i2/0.996/0.005/0.011/-0.03/55691
i1/0.247/-0.005/0.008/0.969/55805
i3/1.000/0.012/0.014/0.0091/55842

Je fais quoi, je met le sujet en résolu (puisque la problématique du timer interrupt et de la commande writedu nrf est résolu) et j'ouvre un nouveau topic en changeant de sujet (nrf24 network, comment synchroniser les données)?