Here is the code (I didn't want to, it is such a mess!)
Sorry for the rawdata and horloge structures I didn't transfer into a library and make the code longer.
this code give me what I want (BLE enabled, I can communicate with the board, even battery powered and disconnected from USB), but can operate only with the included "delay" function.
I2C and signal processing functions are not given here.
// // DEFINE valeurs pour buffer I2C - module LSM9DS1
#define READ_BUFFER_SIZE (18) // taille max 12: gyro + accel + 6: magneto
#define WRITE_BUFFER_SIZE (2) // taille max 2: envoie registre + valeur à écrire
#define NB_RAWDATA (9) // nombre d'éléments rawdata (3 pour gyro/Accel/magneto)
uint8_t rx_buffer_I2C[READ_BUFFER_SIZE];
uint8_t tx_buffer_I2C[WRITE_BUFFER_SIZE];
// // DEFINE valeurs GPIOTE
#define PIN_PWM_LEFT (P1_12) // Pin D3
#define PIN_PWM_RIGHT (P1_11) // Pin D2
#define PIN_HIGH_LEFT (P1_15) // Pin D4
#define PIN_LOW_LEFT (P1_13) // Pin D5
#define PIN_HIGH_RIGHT (P1_14) // Pin D6
#define PIN_LOW_RIGHT (P0_23) // Pin D7
#define COUNTERTOP_MAX 5250 // durée max de la phase pour roues - aligné sur calcul _y
#define phase_servo (20000) // durée max de la phase pour servomoteur ultrason
#define SERVO_max_left (600) //
#define SERVO_max_right (2600) //
#define DUTY1 0 // PWM pour channel LEFT
#define DUTY2 0 // PWM pour channel RIGHT
uint16_t buf[] = { 1 << 15 | DUTY1, 1 << 15 | DUTY2 }; // counter pour moteurs roues
// // DEFINE valeurs calculs depuis module LSM9DS1
int32_t CAP = 0; // direction relative du nez de la voiture (en degrés: 0 à 359)
int32_t magnetic_field_intensity = 0;
int32_t accel_field_intensity = 0;
int32_t time_new_mesure; // chrono relevé I2C gyro+accel pour mesure du cap
int32_t time_last_mesure; // chrono relevé I2C gyro+accel pour mesure du cap
// // DEFINE valeurs calculs ultrasons
int DISTANCE_US;
// // DEFINE valeurs calculs servomoteur
int impulse_servo = 1650;
// // DEFINE classes de données
typedef class rawdata { // stocke une valeur du module LSM9DS1: Axe X pour acceleromètre...
private:
int16_t scale = 0; // ex: 4000 pour +/-4 millig pleine échelle (-32767 à +32767)
int32_t old_valeur = 0; // dernière valeur transférée depuis rx_buffer_I2C
uint8_t *registre = NULL; // adresse de départ dans rx_buffer_I2C
int16_t offset_usine = 0; // calibration "usine"
int16_t treshold_low = 0;
int16_t treshold_high = 0;
int16_t max_valeur = 0; // pour stat en fonctionnement
int16_t min_valeur = 0; // pour stat en fonctionnement
uint16_t DEAD_ZONE = 0;
public:
int32_t offset_position = 0; // offset de position
int16_t VALEUR_RAW(void) {
// renvoi old_valeur + offset_usine
return (old_valeur + offset_usine);
}
int16_t VALEUR(void) {
// renvoi old_valeur corrigée
return (VALEUR_RAW() - offset_position);
}
int16_t VALEUR_SCALED(void) {
// renvoi la valeur old_valeur corrigée et mise à l'échelle
float a = VALEUR() * scale;
a = a / 32768;
return (a);
}
void FIND_MAX_MIN(int16_t *_max_min) {
// met à jour max ou min en fonction de la valeur proposée
if (max_valeur == 0) { max_valeur = *_max_min; }
if (min_valeur == 0) { min_valeur = *_max_min; }
if (*_max_min > max_valeur) { max_valeur = *_max_min; }
if (*_max_min < min_valeur) { min_valeur = *_max_min; }
}
byte MET_A_JOUR_SELF() {
// transfère le registre buffer vers old_valeur et filtre min/max
int16_t _valeur = RETURN_INT();
FIND_MAX_MIN(&_valeur);
old_valeur = _valeur;
return (1);
}
byte MET_A_JOUR(int16_t _valeur) {
// transfère la valeur indiquée vers old_valeur et filtre min/max
FIND_MAX_MIN(&_valeur);
old_valeur = _valeur;
return (1);
}
int16_t RETURN_INT(void) {
// renvoi la valeur registre
return (int16_t(*registre | *(registre + 1) << 8));
}
int16_t *RETURN_MAX() {
// renvoi la valeur max
return (&max_valeur);
}
int16_t *RETURN_MIN() {
// renvoi la valeur min
return (&min_valeur);
}
byte RETURN_NOT_IN_TRESHOLD(int16_t _valeur) {
// renvoi 1 si _valeur est différente de old_valeur +/- threshold
if ((_valeur > old_valeur + treshold_high) | (_valeur < old_valeur - treshold_low)) {
return 1;
} else {
return 0;
}
}
byte RETURN_NOT_DEAD_ZONE(void) {
// renvoi 1 si la valeur est différente de 0 (hors dead zone)
if (VALEUR() > DEAD_ZONE | VALEUR() < -DEAD_ZONE) {
return 1;
} else {
return 0;
}
}
void SET_DEAD_ZONE(uint16_t _dead_zone) {
// définit la valeur dead zone
DEAD_ZONE = _dead_zone;
}
void SET_OFFSET_USINE(int16_t _offset_usine) {
// définit l'offset spécial du capteur (non position)
offset_usine = _offset_usine;
}
void SET_REGISTER(uint8_t &_registre) {
// définit l'adresse registre dans rx_buffer
registre = &_registre;
}
void SET_SCALE(int16_t _scale) {
// définit l'échelle
scale = _scale;
}
byte SET_TRESHOLD_HIGH(int16_t _valeur) {
// met à jour trshld high ou low en fonction de la valeur proposée
treshold_high = _valeur;
}
byte SET_TRESHOLD_LOW(int16_t _valeur) {
// met à jour trshld high ou low en fonction de la valeur proposée
treshold_low = _valeur;
}
void MONITOR(void) {
// affiche les valeurs (utilisé par calibration)
Serial.print("last raw: ");
Serial.print(old_valeur);
Serial.print(" offset: ");
Serial.print(offset_position);
Serial.print(" dead zone: ");
Serial.print(DEAD_ZONE);
Serial.print(" THLD+/-: ");
Serial.print(treshold_high);
Serial.print(" / ");
Serial.print(treshold_low);
Serial.print(" max/min: ");
Serial.print(max_valeur);
Serial.print(" / ");
Serial.println(min_valeur);
}
};
typedef class horloge { // génére une horloge qui gère les timers
private:
uint16_t horloge_overflowed = 0; // overflow totaux de RTC2
uint16_t old_heure = 0; // dernier relevé dans WHAT_TIME_IT_IS
// byte NB_timer = 0; // additionne le nombre de timer ouverts en simultané
void SETUP_RTC() {
const int PRESCALER_RTC2 = 31;
NRF_RTC2->TASKS_STOP = 1; // arrete le compteur pour set up
NRF_RTC2->TASKS_CLEAR = 1; // met à 0 le compteur
NRF_RTC2->PRESCALER = PRESCALER_RTC2; // frequence à 1000 Hz
NRF_RTC2->TASKS_START = 1; // démarre le compteur
}
public:
struct to_time {
// timer indépendant
uint16_t delai_total; // délai à écouler avant déclenchement. 0 = timer off
uint32_t dernier_compteur; // dernière heure relevée
to_time() {
// constructeur
delai_total = 0;
}
};
uint32_t WHAT_TIME_IS_IT(void) {
// renvoi le compteur de RTC additionné du nb overflow
uint16_t new_heure = NRF_RTC2->COUNTER;
if (new_heure < old_heure) { horloge_overflowed++; } // détecte overflow
old_heure = new_heure;
return (new_heure | horloge_overflowed << 16); // 32bit: [heure actuelle] | [overflowed]
}
void begin(void) {
// démarre RTC. à lancer à la 1ère instanciation d'horloge
SETUP_RTC();
}
void START_TIMER(struct to_time *_timer, uint16_t _delai_total) {
// démarre le timer (pour TIME_TO)
_timer->dernier_compteur = WHAT_TIME_IS_IT();
if (_delai_total > 1) { _timer->delai_total = _delai_total - 1; }
}
void STOP_TIMER(struct to_time *_timer) {
// arrête le timer
_timer->delai_total = 0;
}
byte TIME_TO(struct to_time *_timer, byte _update = 0) {
//renvoi 1 si délai écoulé.
if (_timer->delai_total > 0) {
uint32_t heure_actuelle = WHAT_TIME_IS_IT();
if ((heure_actuelle - _timer->dernier_compteur) > _timer->delai_total) {
// update valeur si _update = 0 (laisse une autre methode reset le compteur)
if (!_update) { _timer->dernier_compteur = heure_actuelle; }
return 1;
} else {
return 0;
}
}
return 0;
}
};
// instanciation des familles de valeurs
rawdata
GYRO_X,
GYRO_Y, GYRO_Z,
ACCEL_X, ACCEL_Y, ACCEL_Z,
MAGNETO_X, MAGNETO_Y, MAGNETO_Z,
DIST_US, CAP_ACTUEL;
rawdata *Pool_data[NB_RAWDATA] = { &GYRO_X, &GYRO_Y, &GYRO_Z,
&ACCEL_X, &ACCEL_Y, &ACCEL_Z,
&MAGNETO_X, &MAGNETO_Y, &MAGNETO_Z };
horloge Horloge_1;
horloge::to_time
Timer_Mesure_I2C,
Timer_Report, Timer_Wait,
Timer_Manage_Led, Timer_Servo, Timer_US;
//horloge::to_time *Pool_timer[3] = { &Timer_Mesure_I2C, &Timer_Report, &Timer_Wait };
// DEBUG bytes
const byte DEBUG_BYTE_I2C = 0;
const byte DEBUG_BYTE_SETUP = 0;
const byte DEBUG_BYTE_CALIB = 1;
const byte DEBUG_BYTE_BLE = 1;
// // DEFINE valeurs pour noyau BLE
#include <ArduinoBLE.h>
BLEService FourWheels("1819"); // Bluetooth® Low Energy Vehicle Toy
// Bluetooth® Low Energy LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEIntCharacteristic Servoimpulse("0601", BLERead | BLEWrite); // Frequency Hertz
BLEIntCharacteristic USmesure("0602", BLERead | BLENotify); // Lenght meter
BLEIntCharacteristic CAPmesure("0603", BLERead | BLENotify); // Apparent Wind Direction
BLEStringCharacteristic stringcharacteristic("1904", BLERead | BLEWrite, 31);
BLEDescriptor Phase("2901","Phase Servo micros");
BLEDescriptor Mesure("2901","Distance US mm");
BLEDescriptor Angle("2901","CAP en degres");
BLEDescriptor Texte("2901","text log");
uint8_t _clignote = 0; // séquence led orange quand central deconnected
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
delay(400);
Serial.println("Hello world!");
//// // SETUP_serial.begin: allume led verte et allume led orange
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(LED_PWR, HIGH);
//// // SETUP_début: éteint led verte et allume led orange
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(LED_PWR, LOW);
// // DEBUT SETUP "module LSM9DS1"
SETUP_LIST(); //paramètre les raw data accel, gyro et magneto
Horloge_1.begin(); // contient setup_RTC
SETUP_MODULES_I2C(); // Setup I2C + gyro/accel + magneto
CALIB_ACCEL_GYRO();
// // DEBUT SETUP "ultrason et servomoteur"
SETUP_GPIOTE_PPI();
// // DEBUT SETUP bluetooth
SETUP_BLE();
//// // SETUP_fin: éteint led orange et allume led verte
EXIT_BLE();
}
void loop() {
// put your main code here, to run repeatedly:
BLEDevice central = BLE.central();
if (central) { // if a central is connected to peripheral:
ENTER_BLE();
while (central.connected()) { // while the central is still connected to peripheral:
ROUTINE_INSIDE_BLE();
ROUTINE_ASK_BLE();
} // FIN de while (central.connected)
EXIT_BLE();
} // FIN de if (central)
ROUTINE_OUTSIDE_BLE();
}
Thanks for your time and help.