UNO R4 lettura sensore di temperatura interno (TSN)

Ciao a tutti, e' da un po di tempo che cerco di leggere il sensore di temperatura interno della UNO R4 MINIMA, finalmente ci sono riuscito ... condivido il progetto nel caso potesse tornare utile a qualcuno.
Il microcontrollore a bordo delle UNO R4 ha al suo interno un sensore di temperatura, spesso chiamato TSN, oppure viene fatto riferimento al "chip die temperature", ma nel framework di Arduino non ci sono comandi che fanno riferimento a questo sensore. La lettura della temperatura interna viene fatta con il modulo ADC, perciò ho configurato i vari registri del modulo direttamente utilizzando le API FSP contenute nei file r_adc.h ed r_adc_api.h.
Il progetto puo' tornare utile, ad esempio, se si vuole gestire la finestra di una serra senza collegare sensori di temperatura esterni oppure per segnalare una temperatura troppo alta del microcontrollore...


#include "r_adc.h"
#include "IRQManager.h"

#define PERIOD          1000    // Intervallo di lettura
#define SLOPE          -0.0034  // Sensibilità del sensore di temperatura V/℃ ((vs - v1) / (24 - 125)) --> Correggere qui eventuale errore di temperatura reale/misurata (con termometro su chip)
#define T125            125     // Temperatura di calibrazione di fabbrica del microcontrollore RA4M1
#define VREF            1.45    // Tensione interna di riferimento (vedere datasheet RA4M1), correggere qui eventuale discrepanza tra la tensione letta con un tester e quella stampata su serial monitor

// Configurazione dei registri del modulo ADC per leggere la tensione sul pin aref del microcontrollore
  adc_instance_ctrl_t aref_ctrl;
  adc_cfg_t aref_cfg;
  adc_extended_cfg_t aref_extended_cfg_t;
  adc_channel_cfg_t aref_channel_cfg;

// Configurazione dei registri del modulo ADC per leggere la vCC del microcontrollore
adc_instance_ctrl_t vcc_ctrl;
adc_cfg_t vcc_cfg;
adc_extended_cfg_t vcc_extended_cfg_t;
adc_channel_cfg_t vcc_channel_cfg;

// Configurazione dei registri del modulo ADC per il sensore di temperatura
adc_instance_ctrl_t tsn_ctrl;
adc_cfg_t tsn_cfg;
adc_extended_cfg_t tsn_extended_cfg_t;
adc_channel_cfg_t tsn_channel_cfg;
adc_info_t tsn_info; // lettura valori delle conversioni (dai registri del modulo ADC)

adc_status_t status; // status del campionamento adc


GenericIrqCfg_t cfg = {FSP_INVALID_VECTOR, 12, ELC_EVENT_ADC0_SCAN_END}; // Configura l'interrupt che richiama la funzione adc0_callback

float degC, vAref, vCC; // Variabili dove memorizzare i valori letti

void setup() {
  initialize_aref_reg(); // Configura il modulo ADC per leggere la tensione AREF
  initialize_vcc_reg();  // Configura il modulo ADC per leggere la tensione Vcc
  initialize_tsn_reg();  // Configura il modulo ADC per leggere la temperatura interna del microcontrollore
  pinMode(21,OUTPUT);    // il led TX della UNO R4 indica la lettura dell'interrupt dal modulo ADC
  IRQManager::getInstance().addGenericInterrupt(cfg, adc0_callback);//Richiama la funzione adc0_callback ad ogni lettura della temperatura
  Serial.begin(115200);
  delay(2000);  
}

void loop() {
  static uint32_t last = millis();
  uint32_t now = millis();
  if(now - last >= PERIOD) {
    last = now;
  degC  = readTemp();      // Misurazione della temperatura con sensore integrato nella CPU
  vAref = readAref();      // Misurazione della tensione del pin Aref (3,3 V)
  //vCC   = readVcc();     // Misura della tensione Vcc (5V) --- Lo fa già la funzione readTemp()
  Serial.print("Temp:");Serial.print(degC, 2);Serial.print("°C");  // Temperatura di uscita su seriale
  Serial.print(", ");
  Serial.print("vAref:");Serial.print(vAref, 3);Serial.print("V");  // Uscita in tensione Aref su seriale
  Serial.print(", ");
  Serial.print("vCC:");Serial.print(vCC, 3);Serial.println("V");  // Uscita tensione Vcc su seriale
  }
}

void initialize_aref_reg(){
  aref_channel_cfg.scan_mask           = ADC_MASK_VOLT;//ADEXICR
  aref_extended_cfg_t.adc_vref_control = ADC_VREF_CONTROL_VREFH0_AVSS0;//ADHVREFCNT
  aref_cfg.p_extend = &aref_extended_cfg_t;
}

void initialize_vcc_reg(){
vcc_channel_cfg.scan_mask           = ADC_MASK_VOLT;//ADEXICR
vcc_extended_cfg_t.adc_vref_control = ADC_VREF_CONTROL_AVCC0_AVSS0; //ADHVREFCNT
vcc_cfg.p_extend = &vcc_extended_cfg_t;
}

void initialize_tsn_reg(){
tsn_channel_cfg.scan_mask           = ADC_MASK_TEMPERATURE; //ADEXICR
tsn_cfg.p_extend = &tsn_extended_cfg_t;
}


float readTemp(){
  uint16_t adc_data = 0; // R_ADC0->ADTSDR & 0xFFFF;
  float mcu_temp_c = 0;
  int16_t v125;
  float v1,vs;
  vCC   = readVcc();
  R_BSP_IrqEnable((IRQn_Type)cfg.irq); // la funzione adc0_callback viene richiamata soltanto quando viene letta la temperatura
  analogReference(AR_INTERNAL);
  R_ADC_Open(&tsn_ctrl, &tsn_cfg);
  R_ADC_ScanCfg(&tsn_ctrl, &tsn_channel_cfg);
  R_ADC_ScanStart(&tsn_ctrl);
  delay(1);
    
    R_ADC_Read (&tsn_ctrl, ADC_CHANNEL_TEMPERATURE, &adc_data);
    while( ADC_STATE_SCAN_IN_PROGRESS == status.state) {
     R_ADC_StatusGet(&tsn_ctrl, &status);
    }
    R_ADC_InfoGet(&tsn_ctrl, &tsn_info); 
    v125 = (int16_t) tsn_info.calibration_data; // v125   = (R_TSN->TSCDRH << 8) + R_TSN->TSCDRL
    v1 = 3.3f * v125 / 4096; // Voltage output by the TNS at 125 degreeC
    vs = vCC * adc_data / 4096; // Voltage output by the TNS at the time of measurement of T1 (volt)
    //Serial.print("v125: ");Serial.print(v125);Serial.print(" v1: ");Serial.print(v1);Serial.print(" vs: ");Serial.println(vs);
    mcu_temp_c = (vs - v1) / SLOPE + T125;
    //Serial.println(mcu_temp_c);
    return mcu_temp_c;
}

float readAref(){
  uint16_t adc_data = 0; // R_ADC0->ADTSDR & 0xFFFF;
  R_ADC_Open(&aref_ctrl, &aref_cfg);
  R_ADC_ScanCfg(&aref_ctrl, &aref_channel_cfg);
  R_ADC_ScanStart(&aref_ctrl);
  delay(1);
    R_ADC_Read (&aref_ctrl, ADC_CHANNEL_VOLT, &adc_data);
    while( ADC_STATE_SCAN_IN_PROGRESS == status.state) {
     R_ADC_StatusGet(&aref_ctrl, &status);
    }
    vAref = VREF * 4096.0 / adc_data;
    //Serial.println(vCC);
    return vAref;
}

float readVcc(){
  uint16_t adc_data = 0; // R_ADC0->ADTSDR & 0xFFFF;
  R_ADC_Open(&vcc_ctrl, &vcc_cfg);
  R_ADC_ScanCfg(&vcc_ctrl, &vcc_channel_cfg);
  R_ADC_ScanStart(&vcc_ctrl);
  delay(1);
    R_ADC_Read (&vcc_ctrl, ADC_CHANNEL_VOLT, &adc_data);
    while( ADC_STATE_SCAN_IN_PROGRESS == status.state) {
     R_ADC_StatusGet(&vcc_ctrl, &status);
    }
    vCC = (VREF * 4096.0) / adc_data;
    delay(1);
    //Serial.println(vCC);
    return vCC;
}

static void adc0_callback (){ //adc_callback_args_t * p_args
  IRQn_Type irq = R_FSP_CurrentIrqGet();
  R_BSP_IrqStatusClear(irq);
  //R_ICU->IELSR[irq] &= ~(R_ICU_IELSR_IR_Msk); // Same to R_BSP_IrqStatusClear(irq);
  digitalWrite(21, !digitalRead(21));
  R_BSP_IrqDisable((IRQn_Type)cfg.irq); // Disabilita la funzione di callback(viene abilitata soltanto per il controllo temperatura, non per vcc e vref)
}

Oltre alla temperatura interna del microcontrollore che avviene con la funzione readTemp() ho aggiunto anche la funzione readVcc() che restituisce la tensione di alimentazione e la funzione readAref() che indica la tensione interna di riferimento ... se, ad esempio, viene ponticellato il pin 3.3V sul pin AREF, oppure viene alimentato quest'ultimo con qualsiasi tensione di riferimento (MAI al di sopra della tensione di alimentazione che sulla MINIMA e' di 4.7V circa!! ) la funzione readAref() ritorna il valore della tensione che abbiamo dato al pin AREF).
Io ho testato il programma su una R4 MINIMA originale e su una variante WeAct Studio RA4M1 con sopra caricato il bootloader della R4 MINIMA.
Se qualcuno fa delle prove sulla propria scheda mi farebbe sapere se i parametri del programma corrispondono a quelli reali (io ho confrontato la temperatura letta con un termometro ad infrarossi e la tensione con un tester...)

Non ho la R4 minima, ho fatto una prova con la wi-fi, ma sembra che lo sketch non funzioni, manda in crash la scheda, o perlomeno credo, visto che sparisce la seriale e non accade altro. Ho provato a commentare le chiamate a readTemp() e readAref() nel loop, ed in quel caso funziona, ma anche decommentadole una alla volta va in blocco. Non conosco bene l'R4, ma l'MCU non è la stessa fra minima e wi-fi?

Ciao, Ale.

Grazie per aver testato il programma @ilguargua! Io ho solo una R4 MINIMA e prima di pubblicare il programma l'ho testato li'.
Oggi, pero', mi è venuto un dubbio ... ho aggiunto delle macro per verificare che non ci siano errori nelle funzioni ...

Riepilogo
#define MODULE_NAME "r_adc"
#define EP_VERSION ("1.0")
#define RESET_VALUE (0x00)
#define NULL_CHAR '\0'

#define APP_PRINT(fn_, ...) \
  do { \
    \                                
                                 char buffer[500]; \
    sprintf(buffer, (fn_), ##__VA_ARGS__); \
    Serial.println(buffer); \
  } while (false);

#define APP_ERR_PRINT(fn_, ...) \
  do { \
    \  
                                char buffer[100]; \
    sprintf(buffer, "[ERR] In Function: %s(), %s", __FUNCTION__, (fn_), ##__VA_ARGS__); \
    Serial.println(buffer); \
  } while (false);

#define APP_ERR_TRAP(err) \
  do { \
    \  
         char buffer[10]; \
    sprintf(buffer, "\r\nReturned Error Code: 0x%x  \r\n", err); \
    Serial.println(buffer); \
  } while (false); /* trap upon the error  */

#define PRINTF_BUFFER_SIZE (32u)  // Size of buffer for Serial input to bulk-send chars via Serial
#define APP_READ(read_data) serialRead(read_data)

#define BANNER_INFO "\r\n******************************************************************" \
                    "\r\n*   Renesas FSP Example Project for " MODULE_NAME " Module                 *" \
                    "\r\n*   Example Project Version %s                                  *" \
                    "\r\n*   Flex Software Pack Version  %d.%d.%d                            *" \
                    "\r\n******************************************************************" \
                    "\r\nRefer to readme.txt file for more details on Example Project and" \
                    "\r\nFSP User's Manual for more information about " MODULE_NAME " driver\r\n"


#include "r_adc.h"
//#include "IRQManager.h"

#define PERIOD 1000    // Intervallo di lettura
#define SLOPE -0.0035  // Sensibilità del sensore di temperatura V/℃ ((vs - v1) / (24 - 125)) --> Correggere qui eventuale errore di temperatura reale/misurata (con termometro su chip)
#define T125 125       // Temperatura di calibrazione di fabbrica del microcontrollore RA4M1
#define VREF 1.46      // Tensione interna di riferimento (vedere datasheet RA4M1), correggere qui eventuale discrepanza tra la tensione letta con un tester e quella stampata su serial monitor

// Configurazione dei registri del modulo ADC per leggere la tensione sul pin aref del microcontrollore
adc_instance_ctrl_t aref_ctrl;
adc_cfg_t aref_cfg;
adc_extended_cfg_t aref_extended_cfg_t;
adc_channel_cfg_t aref_channel_cfg;

// Configurazione dei registri del modulo ADC per leggere la vCC del microcontrollore
adc_instance_ctrl_t vcc_ctrl;
adc_cfg_t vcc_cfg;
adc_extended_cfg_t vcc_extended_cfg_t;
adc_channel_cfg_t vcc_channel_cfg;

// Configurazione dei registri del modulo ADC per il sensore di temperatura
adc_instance_ctrl_t tsn_ctrl;
adc_cfg_t tsn_cfg;
adc_extended_cfg_t tsn_extended_cfg_t;
adc_channel_cfg_t tsn_channel_cfg;
adc_info_t tsn_info;  // lettura valori delle conversioni (dai registri del modulo ADC)

adc_status_t status;  // status del campionamento adc


//GenericIrqCfg_t cfg = {FSP_INVALID_VECTOR, 12, ELC_EVENT_ADC0_SCAN_END}; // Configura l'interrupt che richiama la funzione adc0_callback

float degC, vAref, vCC;  // Variabili dove memorizzare i valori letti

void setup() {
  Serial.begin(115200);
  delay(2000);
  /*print FSP version info*/
  fsp_pack_version_t version = { RESET_VALUE };
  R_FSP_VersionGet(&version);
  APP_PRINT(BANNER_INFO, EP_VERSION, version.version_id_b.major, version.version_id_b.minor, version.version_id_b.patch);
  initialize_aref_reg();  // Configura il modulo ADC per leggere la tensione AREF
  initialize_vcc_reg();   // Configura il modulo ADC per leggere la tensione Vcc
  initialize_tsn_reg();   // Configura il modulo ADC per leggere la temperatura interna del microcontrollore
  //pinMode(21,OUTPUT);    // il led TX della UNO R4 indica la lettura dell'interrupt dal modulo ADC
  //IRQManager::getInstance().addGenericInterrupt(cfg, adc0_callback);//Richiama la funzione adc0_callback ad ogni lettura della temperatura
}

void loop() {
  static uint32_t last = millis();
  uint32_t now = millis();
  if (now - last >= PERIOD) {
    last = now;
    degC = readTemp();   // Misurazione della temperatura con sensore integrato nella CPU
    vAref = readAref();  // Misurazione della tensione del pin Aref (3,3 V)
    //vCC   = readVcc();     // Misura della tensione Vcc (5V) --- Lo fa già la funzione readTemp()
    Serial.print("Temp:");
    Serial.print(degC, 2);
    Serial.print("°C");  // Temperatura di uscita su seriale
    Serial.print(", ");
    Serial.print("vAref:");
    Serial.print(vAref, 3);
    Serial.print("V");  // Uscita in tensione Aref su seriale
    Serial.print(", ");
    Serial.print("vCC:");
    Serial.print(vCC, 3);
    Serial.println("V");  // Uscita tensione Vcc su seriale
  }
}

void initialize_aref_reg() {
  aref_channel_cfg.scan_mask = ADC_MASK_VOLT;                            //ADEXICR
  aref_extended_cfg_t.adc_vref_control = ADC_VREF_CONTROL_VREFH0_AVSS0;  //ADHVREFCNT
  aref_cfg.p_extend = &aref_extended_cfg_t;
}

void initialize_vcc_reg() {
  vcc_channel_cfg.scan_mask = ADC_MASK_VOLT;                           //ADEXICR
  vcc_extended_cfg_t.adc_vref_control = ADC_VREF_CONTROL_AVCC0_AVSS0;  //ADHVREFCNT
  vcc_cfg.p_extend = &vcc_extended_cfg_t;
}

void initialize_tsn_reg() {
  tsn_channel_cfg.scan_mask = ADC_MASK_TEMPERATURE;  //ADEXICR
  tsn_cfg.p_extend = &tsn_extended_cfg_t;
}


float readTemp() {
  fsp_err_t err = FSP_SUCCESS;
  uint16_t adc_data = 0;  // R_ADC0->ADTSDR & 0xFFFF;
  float mcu_temp_c = 0;
  int16_t v125;
  float v1, vs;
  vCC = readVcc();
  //R_BSP_IrqEnable((IRQn_Type)cfg.irq); // la funzione adc0_callback viene richiamata soltanto quando viene letta la temperatura
  analogReference(AR_INTERNAL);
  err = R_ADC_Open(&tsn_ctrl, &tsn_cfg);
  if (FSP_SUCCESS != err) {
    APP_ERR_PRINT("\r\n ** R_ADC_Open for readTemp() FAILED ** \r\n");
    APP_ERR_TRAP(err);
  }
  err = R_ADC_ScanCfg(&tsn_ctrl, &tsn_channel_cfg);
  if (FSP_SUCCESS != err) {
    APP_ERR_PRINT("\r\n ** R_ADC_ScanCfg for readTemp() FAILED ** \r\n");
    APP_ERR_TRAP(err);
  }
  err = R_ADC_ScanStart(&tsn_ctrl);
  if (FSP_SUCCESS != err) {
    APP_ERR_PRINT("\r\n ** R_ADC_ScanStart for readTemp() FAILED ** \r\n");
    APP_ERR_TRAP(err);
  }
  delay(1);

  err = R_ADC_Read(&tsn_ctrl, ADC_CHANNEL_TEMPERATURE, &adc_data);
  if (FSP_SUCCESS != err) {
    APP_ERR_PRINT("\r\n ** R_ADC_Read for readTemp() FAILED ** \r\n");
    APP_ERR_TRAP(err);
  }
  while (ADC_STATE_SCAN_IN_PROGRESS == status.state) {
    err = R_ADC_StatusGet(&tsn_ctrl, &status);
    if (FSP_SUCCESS != err) {
      APP_ERR_PRINT("\r\n ** R_ADC_StatusGet for readTemp() FAILED ** \r\n");
      APP_ERR_TRAP(err);
    }
  }
  err = R_ADC_InfoGet(&tsn_ctrl, &tsn_info);
  {
    APP_ERR_PRINT("\r\n ** R_ADC_InfoGet for readTemp() FAILED ** \r\n");
    APP_ERR_TRAP(err);
  }
  v125 = (int16_t)tsn_info.calibration_data;  // v125   = (R_TSN->TSCDRH << 8) + R_TSN->TSCDRL
  v1 = 3.3f * v125 / 4096;                    // Voltage output by the TNS at 125 degreeC
  vs = vCC * adc_data / 4096;                 // Voltage output by the TNS at the time of measurement of T1 (volt)
  //Serial.print("v125: ");Serial.print(v125);Serial.print(" v1: ");Serial.print(v1);Serial.print(" vs: ");Serial.println(vs);
  mcu_temp_c = (vs - v1) / SLOPE + T125;
  //Serial.println(mcu_temp_c);
  return mcu_temp_c;
}

float readAref() {
  fsp_err_t err = FSP_SUCCESS;
  uint16_t adc_data = 0;  // R_ADC0->ADTSDR & 0xFFFF;
  err = R_ADC_Open(&aref_ctrl, &aref_cfg);
  {
    APP_ERR_PRINT("\r\n ** R_ADC_Open for readAref() FAILED ** \r\n");
    APP_ERR_TRAP(err);
  }
  err = R_ADC_ScanCfg(&aref_ctrl, &aref_channel_cfg);
  {
    APP_ERR_PRINT("\r\n ** R_ADC_ScanCfg for readAref() FAILED ** \r\n");
    APP_ERR_TRAP(err);
  }
  err = R_ADC_ScanStart(&aref_ctrl);
  {
    APP_ERR_PRINT("\r\n ** R_ADC_ScanStart for readAref() FAILED ** \r\n");
    APP_ERR_TRAP(err);
  }
  delay(1);
  err = R_ADC_Read(&aref_ctrl, ADC_CHANNEL_VOLT, &adc_data);
  {
    APP_ERR_PRINT("\r\n ** R_ADC_Read for readAref() FAILED ** \r\n");
    APP_ERR_TRAP(err);
  }
  while (ADC_STATE_SCAN_IN_PROGRESS == status.state) {
    err = R_ADC_StatusGet(&aref_ctrl, &status);
    {
      APP_ERR_PRINT("\r\n ** R_ADC_StatusGet for readAref() FAILED ** \r\n");
      APP_ERR_TRAP(err);
    }
  }
  vAref = VREF * 4096.0 / adc_data;
  //Serial.println(vCC);
  return vAref;
}

float readVcc() {
  fsp_err_t err = FSP_SUCCESS;
  uint16_t adc_data = 0;  // R_ADC0->ADTSDR & 0xFFFF;
  err = R_ADC_Open(&vcc_ctrl, &vcc_cfg);
  {
    APP_ERR_PRINT("\r\n ** R_ADC_Open for readVcc() FAILED ** \r\n");
    APP_ERR_TRAP(err);
  }
  err = R_ADC_ScanCfg(&vcc_ctrl, &vcc_channel_cfg);
  {
    APP_ERR_PRINT("\r\n ** R_ADC_ScanCfg for readVcc() FAILED ** \r\n");
    APP_ERR_TRAP(err);
  }
  err = R_ADC_ScanStart(&vcc_ctrl);
  {
    APP_ERR_PRINT("\r\n ** R_ADC_ScanStart for readVcc() FAILED ** \r\n");
    APP_ERR_TRAP(err);
  }
  delay(1);
  err = R_ADC_Read(&vcc_ctrl, ADC_CHANNEL_VOLT, &adc_data);
  {
    APP_ERR_PRINT("\r\n ** R_ADC_Read for readVcc() FAILED ** \r\n");
    APP_ERR_TRAP(err);
  }
  while (ADC_STATE_SCAN_IN_PROGRESS == status.state) {
    err = R_ADC_StatusGet(&vcc_ctrl, &status);
    {
      APP_ERR_PRINT("\r\n ** R_ADC_StatusGet for readVcc() FAILED ** \r\n");
      APP_ERR_TRAP(err);
    }
  }
  vCC = (VREF * 4096.0) / adc_data;
  delay(1);
  //Serial.println(vCC);
  return vCC;
}

/*
static void adc0_callback (){ //adc_callback_args_t * p_args
  IRQn_Type irq = R_FSP_CurrentIrqGet();
  R_BSP_IrqStatusClear(irq);
  //R_ICU->IELSR[irq] &= ~(R_ICU_IELSR_IR_Msk); // Same to R_BSP_IrqStatusClear(irq);
  digitalWrite(21, !digitalRead(21));
  R_BSP_IrqDisable((IRQn_Type)cfg.irq); // Disabilita la funzione di callback(viene abilitata soltanto per il controllo temperatura, non per vcc e vref)
}
*/

Ma stranamente, nonostante funzioni, mi riempie la schermata del serial monitor di messaggi di errore. Comunque credo di aver capito quale sia il problema ... credendo di ottimizzare il codice avevo diviso le funzioni di configurazione da quelle di lettura. Il codice qui sotto dovrebbe funzionare:

#include "r_adc.h"
#include "IRQManager.h"

#define PERIOD         1000
#define SLOPE          -0.0034  // Sensibilità del sensore di temperatura V/℃ ((vs - v1) / (24 - 125)) --> Correggere qui eventuale errore di temperatura reale/misurata (con termometro su chip)
#define T125             125     // Correggere qui eventuale differenza di temperatura reale/misurata sul RA4M1
#define VREF           1.45    // Tensione interna di riferimento (vedere datasheet)

adc_instance_ctrl_t g_adc_ctrl;
adc_cfg_t g_adc_cfg;
adc_extended_cfg_t g_adc_extended_cfg_t;
adc_status_t status;
adc_info_t adc_info;
adc_channel_cfg_t g_adc_channel_cfg;

float degC, vAref, vCC;

GenericIrqCfg_t cfg = {FSP_INVALID_VECTOR, 12, ELC_EVENT_ADC0_SCAN_END}; // Configura l'interrupt che richiama la funzione adc0_callback

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  IRQManager::getInstance().addGenericInterrupt(cfg, adc0_callback);//Richiama la funzione adc0_callback ad ogni lettura della temperatura
  Serial.begin(9600);
  delay(2000);
}

void loop() {
  static uint32_t last = millis();
  uint32_t now = millis();
  if(now - last >= 1000) {
    last = now;
  degC  = readTemp();      // Misurazione della temperatura con sensore integrato nella CPU
  vAref = readAref();      // Misurazione della tensione del pin Aref (3,3 V)
  //vCC   = readVcc();       // Misura della tensione Vcc (5V) --- Lo fa già la funzione readTemp()
   Serial.print("Temp:");Serial.print(degC, 2);Serial.print("°C");  // Temperatura di uscita in serie
  Serial.print(", ");
  Serial.print("vAref:");Serial.print(vAref, 3);Serial.print("V");  // Uscita in tensione Aref in serie
  Serial.print(", ");
  Serial.print("vCC:");Serial.print(vCC, 3);Serial.println("V");  // Uscita tensione Vcc in serie
  }
}

void initializeADC(void)
{
R_ADC_Open(&g_adc_ctrl, &g_adc_cfg);
R_ADC_ScanCfg(&g_adc_ctrl, &g_adc_channel_cfg);
R_ADC_ScanStart(&g_adc_ctrl);
}


float readTemp(){
  uint16_t adc_data = 0; // R_ADC0->ADTSDR & 0xFFFF;
  float mcu_temp_c = 0;
  int16_t v125;
  float v1,vs;
  vCC   = readVcc();
  analogReference(AR_INTERNAL);
  //g_adc_extended_cfg_t.adc_vref_control = ADC_VREF_CONTROL_AVCC0_AVSS0;
  g_adc_channel_cfg.scan_mask           = ADC_MASK_TEMPERATURE; //ADEXICR
  //g_adc_cfg.mode                        = ADC_MODE_SINGLE_SCAN;     //ADCSR
  //g_adc_cfg.trigger                     = ADC_TRIGGER_SOFTWARE; //ADCSR - ADSTRGR
  //g_adc_extended_cfg_t.clearing         = ADC_CLEAR_AFTER_READ_ON; //ADCER.ACE
  g_adc_cfg.p_extend = &g_adc_extended_cfg_t;
  R_BSP_IrqEnable((IRQn_Type)cfg.irq); // la funzione adc0_callback viene richiamata soltanto quando viene letta la temperatura
  initializeADC();
  delay(1);
    //R_ADC_ScanStart(&g_adc_ctrl);
    R_ADC_Read (&g_adc_ctrl, ADC_CHANNEL_TEMPERATURE, &adc_data);
    while( ADC_STATE_SCAN_IN_PROGRESS == status.state) {
     R_ADC_StatusGet(&g_adc_ctrl, &status);
    }
    R_ADC_InfoGet(&g_adc_ctrl, &adc_info);   
    v125 = (int16_t) adc_info.calibration_data; // v125   = (R_TSN->TSCDRH << 8) + R_TSN->TSCDRL
    v1 = 3.3f * v125 / 4096; // Voltage output by the TNS at 125 degreeC
    vs = vCC * adc_data / 4096; // Voltage output by the TNS at the time of measurement of T1 (volt)
    mcu_temp_c = (vs - v1) / SLOPE + T125;
    //Serial.println(mcu_temp_c);
    return mcu_temp_c;
}

float readAref(){
  uint16_t adc_data = 0; // R_ADC0->ADTSDR & 0xFFFF;
  g_adc_channel_cfg.scan_mask           = ADC_MASK_VOLT;//ADEXICR
  g_adc_extended_cfg_t.adc_vref_control = ADC_VREF_CONTROL_VREFH0_AVSS0;//ADHVREFCNT
  //g_adc_cfg.mode                        = ADC_MODE_SINGLE_SCAN;     //ADCSR
  //g_adc_cfg.trigger                     = ADC_TRIGGER_SOFTWARE; //ADCSR - ADSTRGR
  //g_adc_extended_cfg_t.clearing         = ADC_CLEAR_AFTER_READ_ON; //ADCER.ACE
  g_adc_cfg.p_extend = &g_adc_extended_cfg_t;
  initializeADC();
  delay(1);
    //R_ADC_ScanStart(&g_adc_ctrl);
    R_ADC_Read (&g_adc_ctrl, ADC_CHANNEL_VOLT, &adc_data);
    while( ADC_STATE_SCAN_IN_PROGRESS == status.state) {
     R_ADC_StatusGet(&g_adc_ctrl, &status);
    }
    //R_ADC_InfoGet(&g_adc_ctrl, &adc_info);
    vAref = VREF * 4096.0 / adc_data;
    //Serial.println(vCC);
    return vAref;
}

float readVcc(){
  uint16_t adc_data = 0; // R_ADC0->ADTSDR & 0xFFFF;
  g_adc_channel_cfg.scan_mask           = ADC_MASK_VOLT;//ADEXICR
  g_adc_extended_cfg_t.adc_vref_control = ADC_VREF_CONTROL_AVCC0_AVSS0; //ADHVREFCNT
  //g_adc_cfg.mode                        = ADC_MODE_SINGLE_SCAN; //ADCSR + ADSTRGR
  //g_adc_extended_cfg_t.clearing         = ADC_CLEAR_AFTER_READ_ON; //ADCER.ACE
  //g_adc_extended_cfg_t.add_average_count = ADC_ADD_AVERAGE_FOUR; //ADADC
  g_adc_cfg.p_extend = &g_adc_extended_cfg_t;
  initializeADC();
  delay(1);
    //R_ADC_ScanStart(&g_adc_ctrl);
    R_ADC_Read (&g_adc_ctrl, ADC_CHANNEL_VOLT, &adc_data);
    while( ADC_STATE_SCAN_IN_PROGRESS == status.state) {
     R_ADC_StatusGet(&g_adc_ctrl, &status);
    }
    //R_ADC_InfoGet(&g_adc_ctrl, &adc_info);
    vCC = (VREF * 4096.0) / adc_data;
    delay(1);
    //Serial.println(vCC);
    return vCC;
}

static void adc0_callback (){ //adc_callback_args_t * p_args
  IRQn_Type irq = R_FSP_CurrentIrqGet();
  R_BSP_IrqStatusClear(irq);
  //R_ICU->IELSR[irq] &= ~(R_ICU_IELSR_IR_Msk); // Same to R_BSP_IrqStatusClear(irq);
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  R_BSP_IrqDisable((IRQn_Type)cfg.irq); // Disabilita la funzione di callback(viene abilitata soltanto per il controllo temperatura, non per vcc e vref)
}

Se qualcuno ha la possibilita' di testarlo su una R4 WIFI mi potrebbe dire se quest'ultimo programma funziona?

Non ho la scheda qui a casa, e fino alla settimana prossima non rientro in laboratorio... :disappointed:
Forse Gugliemo o qualcun'altro può provare...

Ciao, Ale.

Ciao @contel87,
ho provato il tuo codice sulla mia Arduino minima R4 funziona ottimo lavoro.
Questo è quello che leggo sulla mia scheda.

Temp:25.48°C, vAref:1.450V, vCC:4.673V
Temp:25.48°C, vAref:1.450V, vCC:4.673V
Temp:26.62°C, vAref:1.450V, vCC:4.666V
Temp:25.34°C, vAref:1.450V, vCC:4.680V
Temp:26.38°C, vAref:1.450V, vCC:4.669V
Temp:26.15°C, vAref:1.450V, vCC:4.673V
Temp:25.48°C, vAref:1.450V, vCC:4.673V
Temp:25.34°C, vAref:1.450V, vCC:4.680V
Temp:26.29°C, vAref:1.450V, vCC:4.666V
Temp:25.58°C, vAref:1.450V, vCC:4.677V
Temp:25.71°C, vAref:1.450V, vCC:4.669V
Temp:25.81°C, vAref:1.450V, vCC:4.673V
Temp:25.95°C, vAref:1.450V, vCC:4.666V

Devo dire che non ciò mai capito molto delle API FSP :frowning: .
In un mio progetto mi piacerebbe inveritre il MISO e il MOSI ma avrei bisogno di qualche dritta su come poter riconfigurare il MISO su D11 e il MOSI su D12.
Grazie

Purtroppo sono via anche io tutta la settimana :confused:

Guglielmo

Ci sei quasi riuscito!!! :grin:

Guardando nel "core" di Arduino ho notato che c'è il file arduino.cpp che semplifica l'uso del modulo adc .... Se riesco a prendere il pc stasera posto qualche esempio ...

Ecco il programma per leggere il sensore di temperatura sfruttando la libreria analog.h ...

#include "analog.h"
#include "IRQManager.h"

#define PERIOD         1000
#define SLOPE          -0.0082  // Sensibilità del sensore di temperatura V/℃ ((vs - v1) / (24 - 125)) --> Correggere qui eventuale errore di temperatura reale/misurata (con termometro su chip)
#define T125            125     // Temperatura di fabbrica alla quale e' stato calibrato il sensore
#define VREF           1.43     // Tensione interna di riferimento (vedere datasheet)

float degC, vAref, vCC;


adc_status_t status;
adc_info_t adc_info;

void setup() {
  pinMode(21, OUTPUT);
  Serial.begin(115200);
  delay(2000);
}


void loop() {
  static uint32_t last = millis();
  uint32_t now = millis();
  if(now - last >= PERIOD) {
    last = now;
    degC  = readTemp();      // Misurazione della temperatura con sensore integrato nella CPU
    vAref = readAref();      // Misurazione della tensione del pin Aref
    //vCC   = readVcc();       // Misura della tensione di alimentazione --- Lo fa già la funzione readTemp() 
   Serial.print("Temp:");Serial.print(degC, 2);Serial.print("°C");  // Temperatura di uscita in serie
   Serial.print(", ");
   Serial.print("vAref:");Serial.print(vAref, 3);Serial.print("V");  // Uscita in tensione Aref in serie
   Serial.print(", ");
   Serial.print("vCC:");Serial.print(vCC, 3);Serial.println("V");  // Uscita tensione Vcc in serie
  }

}

float readTemp(){
  ADC_Container adc(0,adc0_callback);
  uint16_t adc_data = 0; // R_ADC0->ADTSDR & 0xFFFF;
  float mcu_temp_c = 0;
  int16_t v125;
  float v1,vs;
  vCC   = readVcc();
  adc.channel_cfg.scan_mask           = ADC_MASK_TEMPERATURE; //ADEXICR
  analogReference(AR_INTERNAL);
  IRQManager::getInstance().addADCScanEnd(&adc);
  R_ADC_Open(&adc.ctrl, &adc.cfg);
  R_ADC_ScanCfg(&adc.ctrl, &adc.channel_cfg);
  R_ADC_ScanStart(&adc.ctrl);
  delay(1);
    R_ADC_Read (&adc.ctrl, ADC_CHANNEL_TEMPERATURE, &adc_data);
    while( ADC_STATE_SCAN_IN_PROGRESS == status.state) {
     R_ADC_StatusGet(&adc.ctrl, &status);
    }
    R_ADC_InfoGet(&adc.ctrl, &adc_info);   
    v125 = (int16_t) adc_info.calibration_data; // v125   = (R_TSN->TSCDRH << 8) + R_TSN->TSCDRL
    v1 = 3.3f * v125 / 16383; // Voltage output by the TNS at 125 degreeC
    vs = vCC * adc_data / 16383; // Voltage output by the TNS at the time of measurement of T1 (volt)
    //Serial.print("vs: ");Serial.print(vs);Serial.print(" v1: ");Serial.println(v1);
    mcu_temp_c = (vs - v1) / SLOPE + T125;
    //Serial.println(mcu_temp_c);
    R_ADC_Close(&adc.ctrl);
    return mcu_temp_c;
}

float readVcc(){
ADC_Container adc(0,adc0_callback);
adc.channel_cfg.scan_mask           = ADC_MASK_VOLT;//ADEXICR
adc.cfg_extend.adc_vref_control      = ADC_VREF_CONTROL_AVCC0_AVSS0; //ADHVREFCNT
uint16_t adc_data = 0; // R_ADC0->ADTSDR & 0xFFFF;
float vCC;
R_ADC_Open(&adc.ctrl, &adc.cfg);
R_ADC_ScanCfg(&adc.ctrl, &adc.channel_cfg);
R_ADC_ScanStart(&adc.ctrl);
delay(1);
R_ADC_Read (&adc.ctrl, ADC_CHANNEL_VOLT, &adc_data);
    while( ADC_STATE_SCAN_IN_PROGRESS == status.state) {
     R_ADC_StatusGet(&adc.ctrl, &status);
    }
    vCC = (VREF * 16383.0) / adc_data; //4096 12bit - 16383 14bit
    //Serial.print("Vcc: ");Serial.print(vCC);Serial.println("V");
    R_ADC_Close(&adc.ctrl);
    return vCC;
}

float readAref(){
  ADC_Container adc(0,adc0_callback);
  uint16_t adc_data = 0; // R_ADC0->ADTSDR & 0xFFFF;
  adc.channel_cfg.scan_mask           = ADC_MASK_VOLT;//ADEXICR
  adc.cfg_extend.adc_vref_control     = ADC_VREF_CONTROL_VREFH0_AVSS0;//ADHVREFCNT
  R_ADC_Open(&adc.ctrl, &adc.cfg);
  R_ADC_ScanCfg(&adc.ctrl, &adc.channel_cfg);
  R_ADC_ScanStart(&adc.ctrl);
  delay(1);
    R_ADC_Read (&adc.ctrl, ADC_CHANNEL_VOLT, &adc_data);
    while( ADC_STATE_SCAN_IN_PROGRESS == status.state) {
     R_ADC_StatusGet(&adc.ctrl, &status);
    }
    vAref = VREF * 16383 / adc_data;
    //Serial.println(vCC);
    R_ADC_Close(&adc.ctrl);
    return vAref;
}

static void adc0_callback (adc_callback_args_t * p_args){
  if(p_args->event == ADC_EVENT_SCAN_COMPLETE){
  digitalWrite(21, !digitalRead(21));
  }
}

Utilizzando questa libreria (analog.h) già presente nell' IDE di arduino, sono riuscito ad utilizzare le relative funzioni dedicate appositamente al modulo adc dell'IRQManager.h (nel programma precedente associavo una funzione di callback generica e non quella dedicata al modulo adc).
P.S. ho avuto lo stesso problema di @ilguargua nel post#4 anche sulla R4 MINIMAed ho risolto inserendo il comando R_ADC_Close(&adc.ctrl); per chiudere il modulo adc prima di uscire dalla funzione di lettura.