Ottimizzazione del codice

Buingiorno a tutti.
Sto svolgendo il mio lavoro di tesi magistrale: ho creato un dispositivo con Wemos D1 Mini che collezione i battiti cardiaci e la temperatura periferica della pelle e, attraverso un algoritmo di apprendimento che segue un'estrazione delle caratteristiche del segnale, individua i picchi di stress.
Per il mio progetto ho utilizzato il sensore max30101 e mlx90614.
Tuttavia, necessito di apportare dei miglioramenti alla parte software, avevo in mente dunque di ottimizzare il codice anche in termini di consumo, per poi calcolare il consumo del dispositivo (ad esempio, ho trovato questo strumento, ma non so utilizzarlo perchè non ho idea di come calcolare il consumo del dispositivo.)

Io non mi sono mai approcciata a tecniche di ottimizzazione del codice, mi chiedevo se qualcuno fosse disposto ad aiutarmi, anche fornendomi delle risorse di semplice comprendonio. Quello che vorrei applicare è cercare di diminuire il più possibile il consumo "inutile" dell'energia e aumentare lo spazip disponibile, aggiungendo ad esempio delle condizioni, il delay o lo sleep mode.

La board si connette ad Arduino IoT Cloud tramite WiFi e il codice contiene due librerie aggiuntive create da me: una per l'estrazione delle caratteristiche statistiche dei segnali e l'altra che implementa l'algoritmo. Per evitare di incollare papelli potrei aggiungerla su richiesta, anche perchè è stata automaticamente generata tramite questa libreria

#include "arduino_secrets.h"
#include <MAX30105.h> // --> Sparkfun library for MAX30101 sensor [https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library]
#include <heartRate.h> // --> Optical Heart Rate Detection (PBA Algorithm) [https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/blob/master/src/heartRate.h]
#include <DFRobot_MLX90614.h> // --> Melexis temperature sensor library
#include "Scaler.h" // --> Feature extraction library [https://github.com/eloquentarduino/everywhereml]
#include "Classifier.h" // --> Classification library containing Logistic Regression algorithm [https://github.com/eloquentarduino/micromlgen]
#include <Arduino.h>
#include <U8x8lib.h>
U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
#include "thingProperties.h"
MAX30105 particleSensor; // --> defining particle sensor object used for BPM 
Eloquent::ML::Port::LogisticRegression clf; // --> declare classifier library
DFRobot_MLX90614_I2C tempSensor; // --> defining temperature sensor object used for st

const byte RATE_SIZE = 3; //Averaging
byte rates[RATE_SIZE]; //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0; //Time at which the last beat occurred
int beatsPerMinute; // --> raw BPM 
//st
byte st_values[RATE_SIZE];
byte st_spot = 0;
int degree; // --> raw peripheral skin temperature in °C

void setup() {
  
  particleSensor.begin(Wire, I2C_SPEED_FAST, 0x57);
  tempSensor.begin(); 
  //Serial.begin(9600);
  u8x8.begin();
  u8x8.setBusClock(100000);
  byte ledBrightness = 0x1F;
  byte sampleAverage = 1; 
  byte ledMode = 3; 
  byte sampleRate = 50;
  int pulseWidth = 411;
  int adcRange = 4096; 
  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); 
  particleSensor.setPulseAmplitudeRed(0); //0 mA
  particleSensor.setPulseAmplitudeIR(0);  // 0 mA
  particleSensor.setPulseAmplitudeGreen(0x19); // 1 mA
  
  u8x8.setFont(u8x8_font_chroma48medium8_r);
  u8x8.drawString(0, 4, "Initializing...");
  delay(2000);
  u8x8.clearDisplay();
  u8x8.drawString(3, 0, "Enjoy!");

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
}

void hrCollection() {
/**
* The particle sensor capture the green led emission from the inner wrist. When a blood pulse happen, the photodiode capture a pulse of light which corresponds to a heart beat.
* In order to be able to capture peaks throw the wrist, the green led has been accurately set up in the setup() section, following the instructions published by the authors
* on page 22 of the paper. [https://pdfserv.maximintegrated.com/en/an/AN6409.pdf]
* The peaks, corresponding to the BPM, are computed throw a PBA algorithm, then, they are averaged with a moving window of size 3. 
*/
  long irValue = particleSensor.getGreen();

  if (checkForBeat(irValue) == true)
  {
    //We sensed a beat!
    
    long delta = millis() - lastBeat;
    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);
    
    // removing signal error
    if (beatsPerMinute < 255 && beatsPerMinute > 20)
    {
      rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array
      rateSpot %= RATE_SIZE; //Wrap variable

      //computing average of 3 samples
      beatAvg = 0;
      for (byte j = 0 ; j < RATE_SIZE ; j++)
        beatAvg += rates[j];
      beatAvg /= RATE_SIZE;
    }
  }

}

void stCollection() {
/**
* Peripheral skin Temperature has been measured in degree Celsius thanks to an InfraRed thermophile that capture the emissivity of the human skin.
*/
  
  degree = tempSensor.getObjectTempCelsius();

  if (degree > 10 && degree < 50) // removing signal error
  {
    //computing average of 3 samples
    st_values[st_spot++] = (byte)degree;
    st_spot %= RATE_SIZE;
    st = 0;
    for (byte z = 0 ; z < RATE_SIZE ; z++)
      st += st_values[z];
    st /= RATE_SIZE;

  }

}

void loop() {
  ArduinoCloud.update();
  hrCollection();
  stCollection(); 

  int features[] = {beatAvg, st};

  if (!processor.transform(features))
  return;

  response = clf.predictLabel(processor.X);

  u8x8.setFont(u8x8_font_chroma48medium8_r);
  u8x8.setCursor(5, 2);
  u8x8.print(beatAvg);
  u8x8.setCursor(5, 3);
  u8x8.print(st);
  u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
  u8x8.drawGlyph(3, 2, 0x46);
  u8x8.drawGlyph(3, 3, 0x45);
  u8x8.setFont(u8x8_font_open_iconic_check_2x2);
  if (response == "Baseline") {
    u8x8.drawGlyph(5, 5, 0x40);
  }
  if (response == "Stress") {
    u8x8.drawGlyph(5, 5, 0x44);
  }
  
  //Serial is used to collect data throw Excel Data Streamer only
  //Serial.print(BeatAvg); Serial.print(","); Serial.print(st); Serial.print(","); Serial.println(response);
 
}

Buongiorno e benvenuto nella sezione Italiana del forum,

cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto. :wink:

Salve, ho già fatto la presentazione qui

Ok, grazie per averla indicata, NON l'avevo trovata :slight_smile:

Guglielmo

1 Like

Un primo alleggerimento potrebbe essere non usare gli oggetti String. Questo:
response = clf.predictLabel(processor.X);
di sicuro la tua lib ritorna una String che in realtà viene usata poi solo nei test ma a display stampi una icona/disegnino

if (response == "Baseline") { u8x8.drawGlyph(5, 5, 0x40); }
if (response == "Stress") { u8x8.drawGlyph(5, 5, 0x44);  }

Sarebbe più leggero lavorare con una serie di valori numerici, magari gestiti con una enum

enum StatiLabel { Baseline=0, Stress, Boh };          // gestito come un int
...
StatiLabel s = clf.predictLabel(processor.X);
...
switch(s) 
{ case Baseline: u8x8.drawGlyph(5, 5, 0x40); break;
  case Stress:   u8x8.drawGlyph(5, 5, 0x44); break; 
}

Salve,
in realtà è disponibile anche una funzione "predict" che ritorna un bool, dunque ho rimpiazzato la String con quel bool. Grazie per l'accorgimento!

La millis() ritorna un "unsigned long" e non un semplice "long"

P.S. a me il codice sembra già buono, abbastanza ben strutturato. Bisognerebbe vedere le tue due lib.

1 Like

Grazie mille, il problema è che i sensori sono molto articolati e temo consumino parecchio, in più, c'è la connessione wifi.
Mi sarebbe piaciuto fare un ulteriore miglioramento per diminuire il consumo, come l'inserimento di una modalità sleep o delle condizioni.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.