Le BLE simplement avec la carte Adafruit Feather nRF52840 Sense

Dans cet article, je vais décrire comment faire un montage utilisant le protocole Bluetooth Low Energy (BLE) très simplement.
Je me suis inspiré du livre « Bluetooth Low Energy Projets pour Arduino, Raspberry Pi et smartphones » (traduit en Français) et disponible chez Dunod :
https://www.dunod.com/sciences-techniques/bluetooth-low-energy-projets-pour-arduino-raspberry-pi-et-smartphones
Copyright 2016 Alasdair Allan et Don Coleman, Dunod 978-2-10-076085-5

Ce livre propose de réaliser plusieurs montages pour se familiariser avec le protocole BLE. Le premier montage est un « commutateur d’éclairage intelligent » mais le module BLE utilisé dans le livre n’est plus commercialisé. https://www.adafruit.com/product/1697
C’est le grand problème de ce livre dont la publication date de 2017. Une éternité dans le domaine de l’électronique, l’IoT, les objets connectés, etc..
Donc je propose ici d’utiliser la carte Adafruit Feather nrf52840 Sense. Elle embarque le nRF52840 de chez Nordic Semiconductors. Un chip très populaire actuellement.
https://www.adafruit.com/product/4516
Vous pouvez aussi prendre l’Adafruit Feather nRF5240 Express :
https://www.adafruit.com/product/4062 C’est presque la même chose, la seule différence est que la « Sense » intègre des capteurs qui permettrons de faire d’autres montages rapidement sans rajouter d’autre module.

1. Installer l’IDE Arduino

La procédure se trouve sur le site Adafruit en Anglais : https://learn.adafruit.com/adafruit-feather-sense
Installer Arduino IDE (Au minimum la version 1.8.6)
Ensuite il faut rajouter la prise en charge de la carte Feather.
Aller dans « Préférences » et ajouter dans « URL de gestionnaire de cartes supplémentaires » https://www.adafruit.com/package_adafruit_index.json

Redémarrer Arduino IDE.
Dans « Boards Manager » rechercher Adafruit nRF52.

Le packet Adafruit nRF52 va s’afficher, cliquer sur « Installer ». Quand le package est installé, aller dans le menu « Outils » « Type de carte » et sélectionner la carte « Adafruit Bluefruit nRF52840 Feather Bluefruit Sense »

Installer le driver Adafruit pour Windows (uniquement si la carte n’est pas détectée au branchement sur le port USB) https://learn.adafruit.com/adafruit-arduino-ide-setup/windows-driver-installation%C2%A0

2. Exécuter son premier sketch

Depuis l’IDE Arduino, aller dans « File » puis « Examples » « 01.Basics » puis « Blink »
C’est le sketch (programme) de base en Arduino.
Il fait juste clignoter une LED présente sur la carte.
Dans le menu « sketch » cliquer sur «  Upload » Le sketch va être compilé et transféré sur la carte.
Puis la LED rouge sur la carte va clignoter.

3. Faire clignoter une LED externe

Nous allons maintenant faire un montage avec une LED comme si c’était une ampoule.
Prendre une LED et une résistance d’environ 100 Ω.
Attention : dans le livre, la résistance est de 220 Ω car la carte est sur 5V, alors que la Feather est sur 3,3V. Relier la patte 3V de la carte à la barre d’alimentation positive de la plaque. Idem pour la patte GND à la barre négative commune. Relier la résistance 100Ω à la patte 5 de la carte, puis à la patte la plus longue de la LED. Relier l’autre patte de la LED à la masse (GND).

Montage carte Feather avec LED

Modifier le sketch « Blink » pour utiliser la sortie 5 :

#define LED_PIN 5
void setup() {
  pinMode(LED_PIN, OUTPUT);
}
void loop() {
  digitalWrite(LED_PIN, HIGH);
  delay(1000);
  digitalWrite(LED_PIN, LOW);
  delay(1000);
}

4. Ajouter un bouton-poussoir

Rajouter un bouton sur la carte d’expérimentation. Brancher l’une des pattes à la broche 6 de la carte, puis l’autre au +3V. Rajouter une résistance de rappel de 10k Ω depuis la broche 6 pour éviter des faux appuis. Voir la page 30 figure 3.7 du livre pour le schéma du montage.

Montage carte Feather avec LED et bouton poussoir

Le sketch Arduino est le suivant :

#define LED_PIN 5
#define BUTTON_PIN 6
int val;
void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);

}
void loop() {
  val = digitalRead(BUTTON_PIN);
  if (val == HIGH) {
    digitalWrite(LED_PIN, HIGH);
  }
   if (val == LOW) {
    digitalWrite(LED_PIN, LOW);
  }
}

Amélioration avec un Anti-Rebond logiciel.

#define LED_PIN 5
#define BUTTON_PIN 6
int currentState;
int debounceState;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);

}

void loop() {
  currentState = digitalRead(BUTTON_PIN);
  delay(10) ;
  debounceState = digitalRead(BUTTON_PIN);

  if (currentState == debounceState) {
   if (currentState == HIGH) {
     digitalWrite(LED_PIN, HIGH);
   }
   if (currentState == LOW) {
     digitalWrite(LED_PIN, LOW);
   }
  }
}

Pour finir, nous allons rajouter la prise en charge du BLE. Le but est de pouvoir lire le status de la LED depuis un smartphone connecté en BLE à la carte, mais aussi de pouvoir allumer la LED à distance. La carte Adafruit Feather nRF52840 Sense intègre déjà un module BLE, il n’y a donc pas de modification du montage à faire.
Le sketch ci-dessous est basé sur celui du livre Exemple 3.1 page 39. Il reprend exactement le même fonctionnement mais a été adapté pour la carte Feather :

#include <bluefruit.h> ❶

#define LED_PIN 5
#define BUTTON_PIN 6

int currentState;
int debounceState;
int switchState = 0;   
int ledState = 0;

BLEService    lightswitch = BLEService(0xFF10); ❷

BLECharacteristic switchCharacteristic = BLECharacteristic(0xFF11);  ❸
BLECharacteristic stateCharacteristic = BLECharacteristic(0xFF12);

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT);
  Bluefruit.begin();
  Bluefruit.setName("Light Switch"); ❹
  lightswitch.begin();
  
  switchCharacteristic.setProperties(CHR_PROPS_READ | CHR_PROPS_WRITE); ❺
  switchCharacteristic.setPermission(SECMODE_OPEN, SECMODE_OPEN);
  switchCharacteristic.setFixedLen(1);
  switchCharacteristic.setUserDescriptor("Switch");
  switchCharacteristic.begin();
 
  stateCharacteristic.setProperties(CHR_PROPS_NOTIFY);
  stateCharacteristic.setFixedLen(1);
  stateCharacteristic.setUserDescriptor("State");
  stateCharacteristic.begin(); 
  
  startAdv(); 
  Serial.println("Smart Light Switch");
}

void startAdv(void) ❻
{
  // Advertising packet
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();
  Bluefruit.Advertising.addService(lightswitch);
  Bluefruit.Advertising.addName();
  
  /* Start Advertising
   * - Enable auto advertising if disconnected
   * - Interval:  fast mode = 20 ms, slow mode = 152.5 ms
   * - Timeout for fast mode is 30 seconds
   * - Start(timeout) with timeout = 0 will advertise forever (until connected)
   * 
   * For recommended advertising interval
   * https://developer.apple.com/library/content/qa/qa1931/_index.html   
   */
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
  Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds  
}

void loop() {
  
  currentState = digitalRead(BUTTON_PIN);
  delay(10);
  debounceState = digitalRead(BUTTON_PIN);
  

  if( currentState == debounceState  ) { 
    if ( currentState != switchState ) { 

      if ( currentState == LOW ) { 
        // Button just released
        
      } else { 
        Serial.print(F("Button event: "));
        if ( ledState == 0 ) {
          stateCharacteristic.notify8(1); ❼
          switchCharacteristic.write8(1);
          digitalWrite(LED_PIN, HIGH);
          ledState = 1;
           Serial.println(F("light on"));
       } else {
          stateCharacteristic.notify8(0); ❽
          switchCharacteristic.write8(0);
          digitalWrite(LED_PIN, LOW);
          ledState = 0;
           Serial.println(F("light off"));
       }
      }
      switchState = currentState;
    }
  
  }
}

❶ Inclusion de la librairie Arduino Bluefruit
❷ Création du service avec l’UUID 0xFF10
❸ Création des caractéristiques
❹ Définition du nom du périphérique BLE qui sera affiché sur le smartphone
❺ Définition des propriétés des caractéristiques
❻ Définition de la configuration pour l’ « Advertising ». C’est un élément essentiel du BLE. Le code a été repris de la documentation de la librairie Bluefruit. https://learn.adafruit.com/adafruit-feather-sense/bleadvertising
❼ Bascule les valeurs de switch et state à 1 lors d’un appui sur le bouton-poussoir
❽ Bascule les valeurs de switch et state à 0 lors d’un autre appui

Une fois le code téléversé, vous devriez pouvoir allumer et éteindre la LED comme avant avec le bouton-poussoir mais en plus vous pouvez afficher le status sur un smartphone.
Sur Iphone vous pouvez utilisez l’application LightBlue. Au lancement, l’application scanne les périphériques BLE à proximité. Le périphérique « Light Switch » devrait apparaitre dans la liste. En cliquant dessus, la connexion est établie et les deux caractéristiques « Switch » et « State » vont apparaître.

Pour le moment, il est possible de lire le status de la LED mais pas de changer l’état depuis le smartphone. Pour faire cela, il faut rajouter un gestionnaire d’événements (ou handler).
Rajouter la ligne suivante juste après switchCharacteristic.begin();

switchCharacteristic.setWriteCallback(switchCharacteristicWritten);

Puis à la fin du sketch rajouter :

void switchCharacteristicWritten(uint16_t conn_hdl, BLECharacteristic* chr, uint8_t* data, uint16_t len) {
  (void) conn_hdl;
  (void) chr;
  (void) len; // len should be 1
  
  Serial.print(F("Characteristic event: "));
  if (data[0]) {
    Serial.println(F("light on"));
    digitalWrite(LED_PIN, HIGH);
    ledState = 1;
    stateCharacteristic.notify8(1); 
    
  } else {
    Serial.println(F("light off"));
    digitalWrite(LED_PIN, LOW);
    ledState = 0;
    stateCharacteristic.notify8(0);   
    
  }
}

Voilà maintenant, dans l’application LightBlue, cliquez sur la caractéristique Switch, puis sur « Write new value », entrez la valeur « 01 », puis cliquez sur Done, la LED va s’allumer, ou entrez la valeur « 00 », la LED va s’éteindre.
Le programme complet est disponible en téléchargement ici :
https://1drv.ms/u/s!AnDlERvozWJSiH0mic39i0BAGQDF?e=QXrVsk