Écran de télémétrie embarquée

On aurait pu l’appeler « SmartPort Display ». Il lit les informations sur le SmartPort du récepteur et les affiche sur un écran. Donc on aurait pu.

Il existe, d’une part, des afficheurs pour modèles réduit affichant des informations telles que la pression d’huile et la tension de la batterie, pour des modèles de grues plutôt haut de gamme, et d’autre part un projet de capteurs open source pour la famille FrSky sur base d’Arduino. En combinant ces 2 idées, on peut imaginer lire les formations de la télémétrie FrSky sur le port SmartPort, et les afficher sur un petit écran dans le modèle réduit.

Le modèle sur lequel je vais disposer ce petit afficheur possède un capteur de tension, un capteur de puissance et deux capteurs de vitesse. Ils sont tous connectes à un même bus, utilisant un protocole série. La librairie est aisément disponible sur Github. Le pilotage de l’écran est lui aussi tout aussi aisé, via u8glib.

L’écran 1 pouce coûte ~ 5 euros et l’Arduino une vingtaine d’euros. On alimente l’Arduino directement depuis la batterie, on branche le câble de données du SmartPort sur le port 12 et la masse au GND, et le câblage de l’écran est relativement simple.

Un peu de code

Pour lire les informations du SmartPort, il faut un objet FrSkySportDecoder, qui sert a piloter le tout, et un objet par capteur, du bon type. Chaque capteur a un ID. Par défaut, chaque capteur a un ID qui dépend de son type. De cette façon, sans rien faire, connecter plusieurs capteurs de types différents fonctionne parfaitement. Il faut uniquement le faire quand on a plusieurs capteurs du même type, ce qui est relativement rare. Qui mettrait 2 GPS dans son modèle? Dans notre cas, il va falloir créer 2 capteurs de type RPM, l’un sur l’ID par défaut, l’autre sur l’ID 6, valeur programmée arbitrairement sur le capteur.

L’Arduino fonctionne comme ceci:
– on crée des variables globales
– on initialise le tout dans une fonction setup qui sera appelée une fois au démarrage
– on utilise le tout dans une fonction loop appelée en boucle

Dans ce cas-ci, on pourrait résumer le code à :

/* Smartport */
#include "FrSkySportSensor.h"
#include "FrSkySportSensorFcs.h"
#include "FrSkySportSensorFlvss.h"
#include "FrSkySportSensorRpm.h"
#include "FrSkySportSingleWireSerial.h"
#include "FrSkySportDecoder.h"
#include "SoftwareSerial.h"
 
FrSkySportSensorFcs fcs;            // FCS-40A sensor with default ID
FrSkySportSensorFlvss flvss;        // FLVSS sensor with default ID
FrSkySportSensorRpm rpm1;           // RPM sensor with default ID
FrSkySportSensorRpm rpm2(FrSkySportSensor::ID6);// RPM sensor with given ID
FrSkySportDecoder decoder;          // Create decoder object without polling

void setup(void) {
  decoder.begin(FrSkySportSingleWireSerial::SOFT_SERIAL_PIN_12, &fcs, &flvss, &rpm1, &rpm2);
}

void loop()
{
    int rssi=0;
    float rxbatt = 0.0;
    int swr = 0;  

    decodeResult = decoder.decode();

    // Get current/voltage sensor (FCS) data
    String power=String(fcs.getCurrent())+"A";
    String voltage=String(fcs.getVoltage())+"V";
  
    // Get LiPo voltage sensor (FLVSS) data
    float c[4]={flvss.getCell1(), flvss.getCell2(), flvss.getCell3(), flvss.getCell4()};
   
    // Get RPM/temperature sensor data
    uint32_t rpm[2] = {rpm1.getRpm(), rpm2.getRpm()};
    int32_t temp[4] = {rpm1.getT1(), rpm1.getT2(), rpm2.getT1(), rpm2.getT2()}; // Temperature #1 in degrees Celsuis (can be negative, will be rounded)
}

Rien de bien complexe quand on sait comment est structuré le code pour l’Arduino. Il faut maintenant afficher le tout. A nouveau, rien de compliqué. On va juste créer une fonction, qu’on appellera dans loop pour ne pas pourrir le code, déjà suffisamment complexe, de cette fonction. Et au préalable, inclure la bonne librairie et déclarer l’écran qui va bien.

/* Display */
#include "U8glib.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST);

void drawScreen(String power, String voltage, float cell[], uint32_t rpm[], int32_t temp[], float rxbatt, int rssi, int swr) {
  String tmp;
  
  u8g.setFont(u8g_font_courB10);
  u8g.drawStr( 0, 12, power.c_str());
  u8g.drawStr( 64, 12, voltage.c_str());

  u8g.setFont(u8g_font_courR10);
  tmp = "1:"+String(cell[0])+"v";
  u8g.drawStr( 0, 26, tmp.c_str());
  tmp = "2:"+String(cell[1])+"v";
  u8g.drawStr( 64, 26, tmp.c_str());
  tmp = "3:"+String(cell[2])+"v";
  u8g.drawStr( 0, 40, tmp.c_str());
  tmp = "4:"+String(cell[3])+"v";
  u8g.drawStr( 64, 40, tmp.c_str());

  u8g.setFont(u8g_font_courB10);
  tmp = String(rpm[0])+"T/m";
  u8g.drawStr( 0, 63, tmp.c_str());
  tmp = String(rpm[1])+"T/m";
  u8g.drawStr( 64, 63, tmp.c_str());
}

Et voilà, le tour est joué. Un bel écran sympa, tellement inutile qu’il est indispensable, affichant la télémétrie dans le modèle. Le code complet est disponible ici. Il est un peu plus complexe car affiche 2 écrans différents, et cycle dans l’affichage des écrans. Cela n’aurait pas apporté grand chose à cet article, donc je l’ai volontairement ignoré ici.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.