Arduino UNO R4 - trigger di Schmitt sugli INPUT

Il tutto prende spunto da QUESTO mio post in cui si parlava degli INPUT degli AVR classici, in cui, nello schema, è presente un trigger di Schmitt e mi stavo chiedendo come fosse la situazione sulla nuova UNO R4 basata sul Renesas Ra4M1 ...

Il datasheet è piuttosto misterioso e non parla dettagliatamente della cosa (salvo che io non l'abbia trovato ... cosa che su 1454 pagine è possibile :grin:) ed anche lo schema degli I/O non da molte informazioni sulla cosa:

... per cui mi sono messo a fare alcune ricerche ed ho trovato delle informazioni più dettagliate per la serie RA2E1. Dato che ciò che viene descritto (registri e bits) è presente ed applicabile anche per la serie RA4M1, ho pensato che potesse essere utile fare un confronto e magari applicare la stessa tecnica ...

Guglielmo

Il documento che ho trovato è il seguente: Usage of Schmitt Trigger Input Pins .pdf (1.2 MB)

... ed è appunto dedicato all'uso dei pin di INPUT con Schmitt Trigger. A pagina 4/6, in blu, ho aggiunto sul lato destro due riferimenti alla documentazione relativa al RA4M1 per ritrovare i vari registri ed i bits da impostare.

C'è un altra mia discussione che spiega come manipolare porte e pins su RA4M1 e, facendo riferimento a quella, dovrebbe essere possibile scrivere un programmino di prova che implementa la sequenza necessaria. Appena ho un po' di tempo provo ... nel frattempo, se qualcuno si vuole divertire e riportare i risultati, ben venga :slight_smile:

Guglielmo

Con la pi-pico sono abilitati di default, ma non so se lo fa la skd o la MCU è così di fabbricazione.

void gpio_set_input_hysteresis_enabled(uint gpio, bool enabled) {
    check_gpio_param(gpio);
    if (enabled)
        hw_set_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_SCHMITT_BITS);
    else
        hw_clear_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_SCHMITT_BITS);
}

Ciao.

1 Like

Mmmm ... in questo documento: RA4 Quick Design Guide.pdf (1.4 MB), che è specifico per gli RA4, a pagina 40/50 ho trovato la seguente frase:

Normal GPIO ports typically require CMOS level inputs (High ≥ 0.8 * VCC, Low ≤ 0.2 * VCC). Some GPIO ports have Schmitt Trigger inputs, which have slightly different input requirements. See the Hardware User’s Manual section Electrical Characteristics for more information.

... quindi sembrerebbe che sulla seria RA4 le cose siano diverse e NON valga quanto ho prima scritto, se non, FORSE, per abilitare il Trigger di Schmitt per specifici pin di specifiche periferiche :roll_eyes:

Per i normali pin di GPIO occorre fare riferimento all'indicato "Hardware User’s Manual" cercando nella sezione "Electrical Characteristics" per avere i dettagli.

Ora, facendo riferimento al già citato datasheet, la sezione "Electrical Characteristics" si trova a pagina 1310 ed è la sezione 48.

In tale sezione, nella sottosezione 48.2.2 sono elencati, in funzione della tensione di alimentazione, i vari VIH e VIL per i pin che hanno o non hanno il trigger di Schmitt.

Devo dire che, almeno ad una prima lettura, NON mi è ben chiaro quali siano i pin che hanno il trigger di Schmitt e quali no ... se ne frattempo qualcuno da una letta anche lui ai documenti indicati ... magari ne veniamo a capo prima :roll_eyes:

Grazie,

Guglielmo

Ah ... per confondere ancora di più le idee ho trovato anche questo documento:

Usage of Schmitt Trigger Input Pins on RA4M3.pdf (424.3 KB)

... che come vedere è per RA4M3, mentre noi, su Arduino UNO R4, abbiamo RA4M1 per la cui serie NON trovo un documento equivalente :confused:

Guglielmo

Non vorrei sbagliarmi ma ...
... sulla serie RA4M1 mi sembra che SOLO pin di specifiche periferiche (come UART, I2C o SPI e pin di interrupt) abbiano la possibilità di avere il trigger di Schmitt.

Gli altri pin di GPIO funzionano con livelli di input CMOS standard, e non forniscono la caratteristica di isteresi di un trigger di Schmitt.

Ovviamente, in questo modo, questi pin sono più sensibili al rumore e alle fluttuazioni del segnale. :roll_eyes:

Almeno così sembra leggendo e facendo un po' di ricerche ...

Guglielmo

Che tipo di segnale devi campionare? Potrebbe tornare utile il modulo ADC ... A pagina 312 del manuale sulle fsp 4.0 a cui fanno riferimento le librerie della UNO R4 c'è la descrizione della Window compare function. Forse c'è qualche funzione utile nella libreria Analog.cpp

No, no, nessuna necessità ... sto studiando ... ricordavo come funzionavano gli I/O degli AVR e speravo che anche sul Renesas, sugli I/O digitali, ci fossero i trigger di Schmitt, ma ... credo che la risposta sia purtroppo negativa ...

Grazie :slight_smile:

Guglielmo

Oppure vai alla vecchia maniera, la verifica pratica! In laboratorio alzi lentamente la tensione all' ingresso con un trimmer finché cambia stato, poi se abbassandola lo stato permane allora lo ST è presente, così misuri pure soglia e isteresi

:grin: ... difatti era quello che volevo fare ....

Guglielmo

Lo sto giusto facendo, un attimo di pazienza e posto i risultati...

Ciao, Ale.

... poi bisognerebbe provare effettivamente, ad esempio per i pin INT (interrupt) ad attivare il trigger (come descritto in quelle AN) e vedere l'effetto su tali periferiche :roll_eyes:

Guglielmo

Allora, ce l'ho fatta, dopo attimi di panico perchè non trovavo un cavetto usb C funzionante...
Ho usato un dac MCP4725, ed ho scritto questo sketch:

#include <Wire.h>
#include <MCP4725.h>

MCP4725 dac(0x61);

byte pin = 2;
uint16_t set = 2048;
uint16_t alto = 0;
uint16_t basso = 0;
uint16_t diff = 0;

void setup(){
    Serial.begin(115200);
    Serial.println("Program begin...");
    
    Wire.begin();
    dac.begin();
    pinMode(pin,INPUT);
    
    Serial.print("dac.begin() -> ");
    Serial.println(dac.isConnected());
    dac.setValue(set);

}


void loop(){
    Serial.println("Test begin...");
    set = 2048;
    while(digitalRead(pin) == LOW){
        set++;
        dac.setValue(set);
        delay(50);
    }
    alto = set;
    while(digitalRead(pin) == HIGH){
        set--;
        dac.setValue(set);
        delay(50);
    }
    basso = set;
    Serial.print("Soglia alta dac: ");
    Serial.print(alto);
    Serial.print(" , volt: ");
    dac.setValue(alto);
    Serial.println(dac.getVoltage(),2);
    Serial.print("Soglia bassa dac: ");
    Serial.print(basso);
    Serial.print(" , volt: ");
    dac.setValue(basso);
    Serial.println(dac.getVoltage(),2);
    Serial.print("Isteresi ");
    Serial.print((alto-basso)*(5.0/4096),2);
    Serial.println(" volt");
    delay(1000);
}

L'ho fatto girare su un Uno R3 e su un Uno R4 wifi, questo è il risultato:

Test Isteresi 
Arduino Uno R3

Program begin...
dac.begin() -> 1
Test begin...
Soglia alta dac: 2048 , volt: 2.50
Soglia bassa dac: 1850 , volt: 2.26
Isteresi 0.24 volt
Test begin...
Soglia alta dac: 2097 , volt: 2.56
Soglia bassa dac: 1857 , volt: 2.27
Isteresi 0.29 volt
Test begin...
Soglia alta dac: 2094 , volt: 2.56
Soglia bassa dac: 1853 , volt: 2.26
Isteresi 0.29 volt
Test begin...
Soglia alta dac: 2090 , volt: 2.55
Soglia bassa dac: 1859 , volt: 2.27
Isteresi 0.28 volt

Arduino Uno R4 wifi

Program begin...
dac.begin() -> 1
Test begin...
Soglia alta dac: 2650 , volt: 3.24
Soglia bassa dac: 2650 , volt: 3.24
Isteresi 0.00 volt
Test begin...
Soglia alta dac: 2048 , volt: 2.50
Soglia bassa dac: 2047 , volt: 2.50
Isteresi 0.00 volt
Test begin...
Soglia alta dac: 2647 , volt: 3.23
Soglia bassa dac: 2647 , volt: 3.23
Isteresi 0.00 volt
Test begin...
Soglia alta dac: 2649 , volt: 3.23
Soglia bassa dac: 2649 , volt: 3.23
Isteresi 0.00 volt
Test begin...
Soglia alta dac: 2048 , volt: 2.50
Soglia bassa dac: 2047 , volt: 2.50
Isteresi 0.00 volt

Quindi sembra confermato, l'R4 non ha isteresi sugli input digitali.
Visto che ho il setup montato a disposizione, dimmi se vuoi che provi con altri pin.

Ciao, Ale.

3 Likes

Bel lavoro ! Grazie per tutta la prova !

Ora devo mettere assieme due righe per attivare il trigger su un pin INT e poi, magari, visto che hai tutto pronto, si può rifare la prova :slight_smile:

Ancora grazie per il tempo che hai dedicato alla cosa.

Guglielmo

Grazie, per me è un piacere, mi diverto...
Se ce la fai in giornata sarebbe meglio, perchè da domani sono a lavorare altrove, e fino alla prossima settimana non torno in laboratorio.

Ciao, Ale.

1 Like

Sai che mi sa tanto che per i pin INT non c'è nulla da fare? Nel senso che, se si attiva l'interrupt su un pin automaticamente dovrebbe essere abilitato il trigger di schmitt ...

... infatti, se si controlla la parte della documentazione relativa a "Register settings for input/output pin function (PORTn)", si vede che i bit PSEL[4:0] sono selezionabili SOLO per i pin di vere periferiche (SPI, I2C, AGT, GPT, ecc), mentre per gli interrupts c'è un bit dedicato che non fa parte di PSEL[4:0], ma è a parte ... ISEL.

Anche nei due esempi forniti, se si guarda quello relativo al INT si ha:

Alternatively: if a pin has an IRQ capability, the Schmitt Trigger functionality will be also available once enabling the IRQ, like shown in the following code example:

R_IOPORT_PinCfg(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_00, (uint32_t)(IOPORT_CFG_IRQ_ENABLE));

Potresti quindi semplicemente provare adbilitare l'interrupt con la classica chiamata del framework attachInterrupt( digitalPinToInterrupt(pin) ); magari usando come pin il pin 2.

Fammi sapere :wink:

Guglielmo

Eccomi!
Programma modificato:

#include <Wire.h>
#include <MCP4725.h>

MCP4725 dac(0x61);

byte pin = 2;
uint16_t set = 1500;
uint16_t alto = 0;
uint16_t basso = 0;
uint16_t diff = 0;
volatile byte state = LOW;

void setup(){
    Serial.begin(115200);
    Serial.println("Program begin...");
    
    Wire.begin();
    dac.begin();
    pinMode(pin,INPUT);
    attachInterrupt(digitalPinToInterrupt(pin),isr,RISING);
    
    Serial.print("dac.begin() -> ");
    Serial.println(dac.isConnected());
    dac.setValue(set);

}


void loop(){
    Serial.println("Test begin...");
    set = 1500;
    dac.setValue(set);
    while(digitalRead(pin) == LOW){
        set++;
        dac.setValue(set);
        delay(10);
    }
    alto = set;
    while(digitalRead(pin) == HIGH){
        set--;
        dac.setValue(set);
        delay(10);
    }
    basso = set;
    Serial.print("Soglia alta dac: ");
    Serial.print(alto);
    Serial.print(" , volt: ");
    dac.setValue(alto);
    Serial.println(dac.getVoltage(),2);
    Serial.print("Soglia bassa dac: ");
    Serial.print(basso);
    Serial.print(" , volt: ");
    dac.setValue(basso);
    Serial.println(dac.getVoltage(),2);
    Serial.print("Isteresi ");
    Serial.print((alto-basso)*(5.0/4096),2);
    Serial.println(" volt");
    delay(1000);
}

void isr(){
    state = !state;
}

Risultato:

Program begin...
dac.begin() -> 1
Test begin...
Soglia alta dac: 2448 , volt: 2.99
Soglia bassa dac: 2052 , volt: 2.51
Isteresi 0.48 volt
Test begin...
Soglia alta dac: 2453 , volt: 3.00
Soglia bassa dac: 2051 , volt: 2.50
Isteresi 0.49 volt
Test begin...
Soglia alta dac: 2453 , volt: 3.00
Soglia bassa dac: 2050 , volt: 2.50
Isteresi 0.49 volt
Test begin...
Soglia alta dac: 2452 , volt: 2.99
Soglia bassa dac: 2047 , volt: 2.50
Isteresi 0.49 volt
Test begin...

Quindi confermo, abilitando l'interrupt l'isteresi appare.
Rimango perplesso sul fatto che non sia abilitata di default... :roll_eyes:

Ciao, Ale.

2 Likes

Mah ... scelte di disegno dell'architettura ... :roll_eyes:

Sui vecchi AVR era proprio presente e fisso in hardware sui pin di INPUT, su Arduino UNO R4 occorre ricordarsi che non è così ... :confused:

Ancora grazie per tutte le prove ... almeno ora abbiamo delle conferme :slight_smile:

Guglielmo

Vabbè, devo dire che questa MCU non mi ha mai entusiasmato, il fatto poi che abbia gli input digitali di Schrödinger me la fa amare ancora meno.

Ciao, Ale.

2 Likes

:joy: :joy: :joy:

Guglielmo