Cunsumtion of LoRa module is 1.2 mA in deep-sleep mode


Hello. Thanks for your answer. But.... and it was the purpose of my other question, is that may be the board I'm using is not OK for optimising the energy consumption. There is no NSS pin available.....
For your info, here is the code I have writte trying to optimise the Consumption

:slight_smile:

saisissez ou collez du code ici
/* 
  file = ESP32 Ruch connectee - Remote - IDE -20240xxx---

  Sketch pour Ruche connectee / LORA & OLED / Sondes poid HX711
  P2P Lora - scenario remote / Emission only
  PASSAGE EN HIBERNATION
  https://m1cr0lab-esp32.github.io/sleep-modes/hibernation-mode/

Projet ruche connectée - HX711 04 Avril 2023
Pour ne pas s'embarasser avec la tare : le calibrage de la balance de JN est codée ds le pgrm
*/

// *** PARAMETRAGE * TO BE UPDATED/DEBUT *********************
// ***********************************************************
// 1) Numero de la balance
const int numero_de_la_balance_int = 1;

// 2) carte utilisée
// #define ESP32-TTGO
#define ESP32-LILYGOT31.6.1

// 3) Données de l'envoi des mesures
// #define TIME_TO_SLEEP  duree_entre_envoi_mn*60        /* Time ESP32 will go to sleep (in seconds) */
int   duree_entre_envoi_mn = 20; // Duree entre envoi en mn = duree du sleep

// 4) numero de la balance
// #define BALANCE_1 // Balance JAUNE Métal
// #define BALANCE_2 // ALU PROFILE - lourde
#define BALANCE_RANDOM

//***********************************************************
//*** Autres variable

// 5) BW Lora
#define BANDWITH433
// #define BANDWITH868

// 6) DEBUG pas DEBUG
// #define DEBUG // on est en compilation pour du DEBUG. Sinon, on minimise donc la consommation

// 7) Outil de compilation
// #define COMPILATION CLOUD IoT // Si pas sélectionné, alors complilation IDE

// ****************************************************************************************
//*** CONTEXT/CONSTANTE/FIN *************************************************************

// Calibrage balance
float Balance_random_facteur_de_calibration = 0;
float Balance_random_decallage_poids = 0;
float Balance_1_facteur_de_calibration = 29.4025;
float Balance_1_decallage_poids = 2844.285;
float Balance_2_facteur_de_calibration = 21.84;
float Balance_2_decallage_poids = 4270;
float Balance_3_facteur_de_calibration = 0;
float Balance_3_decallage_poids = 0;
float Balance_4_facteur_de_calibration = 0;
float Balance_4_decallage_poids = 0;
float Balance_5_facteur_de_calibration = 0;
float Balance_5_decallage_poids = 0;
float Balance_6_facteur_de_calibration = 0;
float Balance_6_decallage_poids = 0;
float Balance_7_facteur_de_calibration = 0;
float Balance_7_decallage_poids = 0;
float Balance_8_facteur_de_calibration = 0;
float Balance_8_decallage_poids = 0;
float Balance_9_facteur_de_calibration = 0;
float Balance_9_decallage_poids = 0;
float Balance_10_facteur_de_calibration = 0;
float Balance_10_decallage_poids = 0;

const byte Header1 = 0x06; // pour reconnaire la trame Ruche
const byte Header2 = 0x07; // pour reconnaire la trame Ruche
const byte Version_du_protocole_lora = 0x01;
const byte Adresse_gway = 0xFE; 		// address of the remote gateway

// Librairies pour Lora
#include <SPI.h>
#include <LoRa.h>

//Libraries pour OLED Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#ifdef BANDWITH433
#define BAND 433E6
#endif
#ifdef BANDWITH868
#define BAND 868E6 
#endif

// version TTGO ESP32
// ****************************************************************************************
#ifdef ESP32-TTGO
//define the pins used by the LoRa transceiver module
#define RADIO_SCLK_PIN 5
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 27
#define RADIO_CS_PIN 18
#define RADIO_RST_PIN 14 // Changed CH - OLD = 16; NEW = 14
#define RADIO_DIO0_PIN 26
#define RADIO_DIO1_PIN 33
#define DIO2 32
//OLED pins
#define OLED_SDA 4
#define OLED_SCL 15 
#define OLED_RST 16
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#endif

// version 2 ESP32 LillyGo [from Bidouilleurs https://www.youtube.com/watch?v=o8Pd-hZDYwc]
// ****************************************************************************************
# ifdef ESP32-LILYGOT31.6.1
//define the pins used by the LoRa transceiver module
//OLED pins LiLYGo / T3 version 1.6.1
// #define OLED_RST 2   // n'est peut être pas le 2 mais e, tout cas, pas le 16
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_SDA                     21
#define OLED_SCL                     22
#define UNUSE_PIN                   (0)
#define OLED_RST                    UNUSE_PIN
#define RADIO_SCLK_PIN              5
#define RADIO_MISO_PIN              19
#define RADIO_MOSI_PIN              27
#define RADIO_CS_PIN                18
#define RADIO_DIO0_PIN               26
#define RADIO_RST_PIN               23
#define RADIO_DIO1_PIN              33
#define RADIO_BUSY_PIN              32
#define SDCARD_MOSI                 15
#define SDCARD_MISO                 2
#define SDCARD_SCLK                 14
#define SDCARD_CS                   13
#define BOARD_LED                   25
#define LED_ON                      HIGH
#define ADC_PIN                     35
#define HAS_SDCARD
#define HAS_DISPLAY
#endif

// Sonde HX711
// ****************************************************************************************
// Balance
#include "HX711.h"
// HX711 circuit wiring
const int LOADCELL_DOUT_PIN = 15;
const int LOADCELL_SCK_PIN = 12;
int alimentation_de_la_balance = 13;

#ifdef BALANCE_RANDOM
float facteur_de_calibration = Balance_random_facteur_de_calibration;
float decallage_poids = Balance_random_decallage_poids;
#endif
#ifdef BALANCE_1
facteur_de_calibration = Balance_1_facteur_de_calibration;
decallage_poids = Balance_1_decallage_poids;
#endif
#ifdef BALANCE_2
facteur_de_calibration = Balance_2_facteur_de_calibration;
decallage_poids = Balance_2_decallage_poids;
#endif
#ifdef BALANCE_3
facteur_de_calibration = Balance_3_facteur_de_calibration;
decallage_poids = Balance_3_decallage_poids;
#endif
#ifdef BALANCE_4
facteur_de_calibration = Balance_4_facteur_de_calibration;
decallage_poids = Balance_4_decallage_poids;
#endif
#ifdef BALANCE_5
facteur_de_calibration = Balance_5_facteur_de_calibration;
decallage_poids = Balance_5_decallage_poids;
#endif
#ifdef BALANCE_6
facteur_de_calibration = Balance_6_facteur_de_calibration;
decallage_poids = Balance_6_decallage_poids;
#endif
#ifdef BALANCE_7
facteur_de_calibration = Balance_7_facteur_de_calibration;
decallage_poids = Balance_7_decallage_poids;
#endif
#ifdef BALANCE_8
facteur_de_calibration = Balance_8_facteur_de_calibration;
decallage_poids = Balance_8_decallage_poids;
#endif
#ifdef BALANCE_9
facteur_de_calibration = Balance_9_facteur_de_calibration;
decallage_poids = Balance_9_decallage_poids;
#endif
#ifdef BALANCE_10
facteur_de_calibration = Balance_10_facteur_de_calibration;
decallage_poids = Balance_10_decallage_poids;
#endif

HX711 scale;

// Balance Parametre Christophe H.
float valeur_de_lecture_brute = 0;
float poids_de_lobjet = 0;

// Données des mesures
const unsigned long duree_entre_envoi_secondes = duree_entre_envoi_mn*60;	// en s - durée avant chaque envoi

// Données du sleep mode
#define uS_TO_S_FACTOR 1000000  /* Conversion factor for micro seconds to seconds */
// RTC_DATA_ATTR int bootCount = 0; // The last variable we declare is bootCount, which is a counter for how many times the ESP32 has booted.

// Structure Lora
struct __attribute__((packed)) MessageLora {
  byte header1;  // pour reconnaitre trame
  byte header2;  // pour reconnaitre trame
  byte version;  // pour évolutions future
  byte emetteur; 
  byte destinataire;
  byte relais; // enregistre les relais potentiels
  int numero_du_message;
  float donnee1; // Poid
  float donnee2; // pour évolution future
  boolean donnee3; // pour évolution future
  boolean donnee4; // pour évolution
  float checksum; // pour évolution future
  char text[30]; // pour évolution future
};
MessageLora messageLora;

// Donnees pour traitement Lora des infos reçues
byte header1_du_message;
byte header2_du_message;
byte version_du_message;
byte emetteur_du_message;
byte destinataire_du_message;
byte relais_du_message;
int numero_du_message;
float donnee1_du_message;
float donnee2_du_message;
boolean donnee3_du_message;
boolean donnee4_du_message;
float checksum_du_message;
char text_du_message[30];

// Autres données de traitement
byte Adresse_device = numero_de_la_balance_int;		// address of this device
const int debut_numero_du_message = numero_de_la_balance_int * 100;

unsigned long currentTime = 0;
int etat_automate = 0;
int message_status = 0;
int message_ERR = 0;
int n, t;
int numero_device = 0;
int taille_du_message;
int delay_de_temporisation_pour_fonction_delay_ms = 3000;

// constante OLED
const int increment_ligne = 8;
const int debut_ligne_status = 0;
const int debut_ligne_received = increment_ligne * 2;
const int debut_ligne_sent = increment_ligne * 5;

// ****************************************************************************************
// Initialisation ecran OLED
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);

void setup()  {
// ****************************************************************************************

#ifdef DEBUG
  // Initialize serial and wait for port to open
  Serial.begin(115200);
  // This delay gives the chance to wait for a Serial Monitor without blocking if  none is found
  delay(delay_de_temporisation_pour_fonction_delay_ms);

  //  ++bootCount;  // Add 1 to the current value of bootCount - it is recorded
  // Defined in thingProperties.h
  // Enlever pour tests - A REMETTRE
  // initProperties();
   
 //reset OLED display via software
  pinMode(OLED_RST, OUTPUT);
  digitalWrite(OLED_RST, LOW);
  delay(20);
  digitalWrite(OLED_RST, HIGH);

  //initialize OLED
  Wire.begin(OLED_SDA, OLED_SCL);
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) 
  {
    // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  Serial.println("Lancement - etat[" + String(etat_automate) +"]");
  // displayOLED(1, 0, 0, debut_ligne_status + increment_ligne*0, 1, "Start Rem. [" + String(bootCount) + "]boot",1);
  displayOLED(1, 0, 0, debut_ligne_status + increment_ligne*0, 1, "Start Rem. [" + String(Adresse_device) + "]",1);
#endif

  // override the default CS, reset, and  IRQ pins (optional)
  //SPI LoRa pins
  SPI.begin(RADIO_SCLK_PIN, RADIO_MISO_PIN, RADIO_MOSI_PIN, RADIO_CS_PIN);
  //setup LoRa transceiver module
  LoRa.setPins(RADIO_CS_PIN, RADIO_RST_PIN, RADIO_DIO0_PIN);

  if (!LoRa.begin(BAND)) {             // initialize ratio for Europe
#ifdef DEBUG
    Serial.println("LoRa init failed. Check your connections.");
#endif
    while  (true);                       // if failed, do nothing
  } 

#ifdef DEBUG
  // displayOLED(1, 0, 0, debut_ligne_status + increment_ligne*0, 1, "Rem[" + String(Adresse_device) + "]/LoRa OK/Boot " + String(++bootCount),1);
#endif

  LoRa.setSpreadingFactor(12);
  LoRa.setSignalBandwidth(62.5E3);
  LoRa.setCodingRate4(5); //min 5- max 8

#ifdef DEBUG
  // Balance - NOTE : on ne veut pas tarer à chaque fois car on ne peut pas déplacer la ruche à chaque reboot.
  // les paramètres de calcul du poids sont donc "hardcodé". Ils ont été calculé précédement. Les paramètres sont propres à chaque balance
  Serial.println("HX711 Demo");
  Serial.println("Initializing the scale");
#endif
  
  pinMode(alimentation_de_la_balance, OUTPUT);
  digitalWrite(alimentation_de_la_balance, HIGH);
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
  scale.tare();

  delay(delay_de_temporisation_pour_fonction_delay_ms);

}

void  loop() {
// ****************************************************************************************
  currentTime = millis();

  lecture_des_mesures();

  // Preparation & envoi du message
  preparation_du_message();
  ecriture_du_message();
  sendMessage();
  // nettoyage_structure_lora();
  delay(delay_de_temporisation_pour_fonction_delay_ms); // pour s'assurer que le message est bien parti

#ifdef DEBUG
  displayOLED(0, 1, 0, debut_ligne_status + increment_ligne*0, 1, "Rem[" + String(Adresse_device) +"]/Sleep",1);
  displayOLED(0, 1, 0, debut_ligne_status + increment_ligne*1, 1, "Duree = " + String(duree_entre_envoi_secondes) + "s/" + String(duree_entre_envoi_secondes/60) + "mn" ,1);
  // Mise en mode veille
  Serial.println("Passage en mode HIBERNATION " + String(duree_entre_envoi_secondes) +"s");
  delay(delay_de_temporisation_pour_fonction_delay_ms);
#endif

  LoRa.sleep();
  // 
  //u8g2->sleepOn();
  SPI.end();
  // SDSPI.end();

  pinMode(RADIO_CS_PIN, INPUT);
  pinMode(RADIO_RST_PIN, INPUT);
  pinMode(RADIO_DIO0_PIN, INPUT);
  pinMode(RADIO_CS_PIN, INPUT);
  pinMode(OLED_SDA, INPUT);
  pinMode(OLED_SCL, INPUT);
  pinMode(OLED_RST, INPUT);
  pinMode(RADIO_SCLK_PIN, INPUT);
  pinMode(RADIO_MISO_PIN, INPUT);
  pinMode(RADIO_MOSI_PIN, INPUT);
  pinMode(SDCARD_MOSI, INPUT);
  pinMode(SDCARD_MISO, INPUT);
  pinMode(SDCARD_SCLK, INPUT);
  pinMode(SDCARD_CS, INPUT);
  pinMode(BOARD_LED, INPUT);
  pinMode(ADC_PIN, INPUT);

  // Specifique au mode hibernation / C'est un paramétrage du DeepSleep pour désactiver la mémoire
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH,   ESP_PD_OPTION_OFF);
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
  esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL,         ESP_PD_OPTION_OFF);

  // Passage en deep_sleep - Set up timer as the wake up source and set sleep duration
  esp_sleep_enable_timer_wakeup(duree_entre_envoi_secondes * uS_TO_S_FACTOR);
  Serial.flush();  // Wait for the transmission of outgoing serial data to complete.
  esp_deep_sleep_start();

}

void lecture_des_mesures(){
// ****************************************************************************************

// calculs
  valeur_de_lecture_brute = scale.read_average(20);
  poids_de_lobjet = valeur_de_lecture_brute/facteur_de_calibration - decallage_poids;

  if (poids_de_lobjet < 0) // pour corriger les erreurs de calibrage de balance - on met 1g
    poids_de_lobjet = 1;

#ifdef BALANCE_RANDOM
  // TEST - LECTURE RANDOM
  poids_de_lobjet = random(10, 80);
#endif  

#ifdef DEBUG
  Serial.println("Mesure brute = " + String(valeur_de_lecture_brute) + " / " + String(poids_de_lobjet/1000) + "kg");
  displayOLED(0, 1, 0, debut_ligne_sent + increment_ligne * 0, 1, "Poids = " + String(poids_de_lobjet) + "g" ,1);
#endif

  scale.power_down();			        // put the ADC in sleep mode
  digitalWrite(alimentation_de_la_balance, LOW);

}

void preparation_du_message()
// ****************************************************************************************
{
  header1_du_message = Header1;
  header2_du_message = Header2;
  version_du_message = Version_du_protocole_lora;
  emetteur_du_message = Adresse_device;
  destinataire_du_message = Adresse_gway;
  relais_du_message = 0x00;
  numero_du_message = random(debut_numero_du_message, debut_numero_du_message+99);
  donnee1_du_message = poids_de_lobjet;
  donnee2_du_message = 0;
  donnee3_du_message = 0;
  donnee4_du_message = 0;
  checksum_du_message = numero_du_message + donnee1_du_message + donnee2_du_message;
  for (n = 0; n < 30; n++)
    text_du_message[n] = ' ';
}

/*
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!
!!   FONCTIONS COMMUNES AUX DEVICES - SYSTEMES, RELAIS, GATEWAY
!!   A recopier
!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/

void onReceive(int  packetSize)
// ****************************************************************************************
{
  if (packetSize == 0) {
    message_status = 0;
    return;          // if there's no packet,  return
  }
  taille_du_message = packetSize;

#ifdef DEBUG
  Serial.println("Message recu");
  Serial.println("Lora receive RSSI = " + String(LoRa.packetRssi()) + " / packet size " + String(packetSize));
  displayOLED(0, 1, 0, debut_ligne_received + increment_ligne * 0, 1, "RSSI = " + String(LoRa.packetRssi()),1);
#endif

  message_status = 1;
  if (packetSize == 0) {
    message_status = 0;
    return;          // if there's no packet,  return
  }
#ifdef DEBUG
  Serial.println("Message recu");
#endif

  message_status = 1;
}

void nettoyage_structure_lora()
// ****************************************************************************************
{
  messageLora.header1 = 0x00;
  messageLora.header2 = 0x00;
  messageLora.version = 0x00;
  messageLora.emetteur = 0x00;
  messageLora.destinataire = 0x00;
  messageLora.relais = 0x00;
  messageLora.numero_du_message = 0;
  messageLora.donnee1 = 0;
  messageLora.donnee2 = 0;
  messageLora.donnee3 = false;
  messageLora.donnee4 = false;
  messageLora.checksum = 0;
  for (n = 0; n < 30; n++)
    messageLora.text[n] = ' ';
}

void ecriture_du_message()
// ****************************************************************************************
{
  messageLora.header1 = header1_du_message;
  messageLora.header2 = header2_du_message;
  messageLora.version = version_du_message;
  messageLora.emetteur = emetteur_du_message;
  messageLora.destinataire = destinataire_du_message;
 messageLora.relais = relais_du_message;
  messageLora.numero_du_message = numero_du_message;
  messageLora.donnee1 = donnee1_du_message;
  messageLora.donnee2 = donnee2_du_message;
  messageLora.donnee3 = donnee3_du_message;
  messageLora.donnee4 = donnee4_du_message;
  messageLora.checksum = checksum_du_message;
  *messageLora.text =   *text_du_message;
}

void lecture_du_message()
// ****************************************************************************************
{
  volatile int packetReceived = 0;
  packetReceived = taille_du_message;

  // lecture du message recu
  LoRa.readBytes((byte *)&messageLora, packetReceived);
  header1_du_message = messageLora.header1;
  header2_du_message = messageLora.header2;
  version_du_message = messageLora.version;
  emetteur_du_message = messageLora.emetteur;
  numero_device = hexTodec(String(emetteur_du_message));
  destinataire_du_message = messageLora.destinataire;
  relais_du_message = messageLora.relais;
  numero_du_message = messageLora.numero_du_message;
  donnee1_du_message = messageLora.donnee1;
  donnee2_du_message = messageLora.donnee2;
  donnee3_du_message = messageLora.donnee3;
  donnee4_du_message = messageLora.donnee4;
  checksum_du_message = messageLora.checksum;
  *text_du_message = *messageLora.text;

#ifdef DEBUG
  // display des données reçues
  Serial.print(" header 1 = " + String(header1_du_message) + " header 2 = " + String(header2_du_message) + " version = " + String(version_du_message) + " De : " + String(emetteur_du_message) + " A : " + String(destinataire_du_message) + " Num de msg = " + String(numero_du_message));
  Serial.println(" donnee1 = " + String(donnee1_du_message) + " donnee2 = " + String(donnee2_du_message) + " donnee3 = " + String(donnee3_du_message) + " donnee4 = " + String(donnee4_du_message) + " cheksum = " + String(checksum_du_message) + " text = " + String(text_du_message));
#endif

  packetReceived = 0;  // clear for next time
}

void  sendMessage() {
// ****************************************************************************************

  LoRa.beginPacket();                             // start packet
  LoRa.write((byte *)&messageLora, sizeof(messageLora));  // transmit packet
  LoRa.endPacket(true);  // finish packet and send it

#ifdef DEBUG
  Serial.print("Message envoyé : ");
  Serial.println("Sent  to: 0x" + String(messageLora.destinataire) + " - From: 0x" + String(messageLora.emetteur) + " - Relais: 0x" + String(messageLora.relais) + " - Message ID: " + String(messageLora.numero_du_message) + "Message:  " + *messageLora.text);

  //Serial.println("Msg envoyé " + String(msgCount) + " destination= " + String(destination));
  displayOLED(0, 1, 0, debut_ligne_sent + increment_ligne*0, 1, "Sent > " + String(messageLora.emetteur) + "/" + String(messageLora.destinataire),1);
  displayOLED(0, 1, 0, debut_ligne_sent + increment_ligne*1, 1, "Num:" + String(messageLora.numero_du_message) + " - Poid:" + String(donnee1_du_message), 1);
#endif

}

void displayOLED(int clearEcran, int ClearLigne, int positionHorizontale, int positionVerticale, int tailleText, String messageText, int couleur)
// ****************************************************************************************
{
#ifdef DEBUG
  // Affichage OLED
  if (clearEcran == 1)
  {
    display.clearDisplay();
  }
  else
  {
    if (ClearLigne == 1)
      nettoyage_ligne_OLED(positionVerticale, couleur);
  }

  display.setTextColor(couleur);
  display.setTextSize(tailleText);
  display.setCursor(positionHorizontale, positionVerticale);
  display.print(messageText);
  display.display();
#endif
}

void nettoyage_ligne_OLED(int ligne_a_nettoyer, int couleur_ligne)
// ****************************************************************************************
{
  const int largeur_ecran = 127;
  const int hauteur_d_une_ligne = 7;
  int couleur_inverse =0;

  if (couleur_ligne == 1)
    couleur_inverse = 0;
   if (couleur_ligne == 0)
    couleur_inverse = 1;

  for (int h = ligne_a_nettoyer; h < ligne_a_nettoyer + hauteur_d_une_ligne; h++)
  {
    for (int l = 0; l < largeur_ecran; l++)
    {
      display.drawPixel(l, h, couleur_inverse); 
    }
  }
}

unsigned int hexTodec(String hexString)
// ****************************************************************************************
{
  // Procedure qui converti HEX en Dec - utilisé pour convertir l'adresse HEX des devices en increment ds le tableau des données

  unsigned int decValue = 0;
  int nextInt;
  for (int i = 0; i < hexString.length(); i++)
  {
    nextInt = int(hexString.charAt(i));
    if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9);
    if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15);
    if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15);
    nextInt = constrain(nextInt, 0, 15);
    decValue = (decValue * 16) + nextInt;
  }
  return decValue;
}

long hexStringToDecimal(String hexString) {
  long decimalValue = 0;
  int hexLength = hexString.length();
  
  for (int i = 0; i < hexLength; i++) {
    char c = hexString.charAt(i);
    int digitValue;
    
    if (c >= '0' && c <= '9') {
      digitValue = c - '0';
    } else if (c >= 'A' && c <= 'F') {
      digitValue = 10 + (c - 'A');
    } else if (c >= 'a' && c <= 'f') {
      digitValue = 10 + (c - 'a');
    } else {
      // Handle invalid characters if necessary
      continue;
    }
    
    decimalValue = (decimalValue * 16) + digitValue;
  }
  
  return decimalValue;
}