Singole funzioni

Spiegazione

 

Abstract: Descrizione:

  1. sprintf
  2. Le stringhe in C
  3. setTextWrap
  4. millis
  5. Timer

sprintf

-----------------------------------------------------------------------------o-----------------------------------------------------------------------

La riga:

sprintf(newBuf, "%02d:%02d", h, m);

è una funzione del linguaggio C (o C++) che formatta una stringa e la scrive in newBuf.

Spiegazione dettagliata:

  • sprintf: sta per "string print formatted". Funziona come printf, ma invece di stampare su schermo, scrive il risultato in una stringa (in questo caso newBuf).

  • newBuf: è un array di caratteri (una stringa C) in cui verrà scritta la stringa formattata. Deve essere stato dichiarato prima, ad esempio:

    char newBuf[10];

  • "%02d:%02d": è la stringa di formato. Vediamola pezzo per pezzo:

    • %02d: stampa un intero (d) usando almeno 2 cifre, riempiendo con zeri a sinistra se necessario.

      • Esempi:

        • 5 → "05"

        • 12 → "12"

    • :: è semplicemente un carattere due punti, che separa ore e minuti.

    • Quindi, la stringa formattata sarà qualcosa tipo "08:30" o "13:05".

  • h e m: sono variabili intere che rappresentano ore e minuti.

     

    Spiegazione del formato %02d:

    • % — indica l'inizio di una specifica di formato.

    • 0 — indica che il numero deve essere riempito con zeri a sinistra se ha meno cifre del minimo specificato.

    • 2 — indica la larghezza minima del campo: in questo caso, 2 cifre.

    • d — sta per intero decimale (di tipo int).

Il simbolo % viene ripetuto due volte perché ci sono due valori da stampare: le ore (h) e i minuti (m).

 

Esempio pratico

int h = 9; int m = 5; char newBuf[6]; // Serve spazio per 5 caratteri + terminatore '\0' sprintf(newBuf, "%02d:%02d", h, m); // newBuf ora contiene "09:05".

Attenzione a rispettare le dimensioni della stinga h e m devono avere al max 2 digit ciascuno in modo che la stringa risulti lunga 6 caratteri: 09:05'\0' (6 caratteri) altrimenti sprintif scriverebbe anche oltre il terminatore creando corruzione della memoria e conseguente crash. Se non si èè sicuri usare snprintf che taglia tutto quello che eccede la dimensione es:

 

snprintf(newBuf, sizeof(newBuf), "%02d:%02d", h, m);

 

--------------------------------------------------------------------------o-----------------------------------------------------------------------

Le stringhe in C

-----------------------------------------------------------------------------o-----------------------------------------------------------------------

  • Una stringa è un array di char terminato da un carattere nullo ('\0').

  • Non esiste un tipo nativo string. Tutto è basato su array di caratteri.

    char str[] = "ciao"; // 5 byte in memoria: 'c' 'i' 'a' 'o' '\0'

La fine della stringa è indicata dal \0. È tua responsabilità assicurarti che ci sia!

Nel caso creassi un buffer più grande della stringa tipo: char s1[20] = "ciao";

 

Cosa fa il compilatore:

  • Crea un array di 20 caratteri

  • Inizializza i primi 5 elementi con: 'c', 'i', 'a', 'o', '\0' (terminatore di stringa)

  • I restanti 15 caratteri vengono inizializzati a zero ('\0') solo se sei in una variabile globale o statica.
    Se invece è una variabile locale, il resto del buffer può contenere spazzatura (valori casuali), a meno che tu non li inizializzi.

Attenzione:

Il fatto che il buffer sia grande non cambia la "lunghezza logica" della stringa:
strlen(s1) restituisce sempre il numero di caratteri prima del '\0', quindi nel tuo caso 4.

Ma se usi sizeof(s1), ottieni la dimensione totale dell'array, cioè 20.

 

--------------------------------------------------------------------------o-----------------------------------------------------------------------

setTextWrap

-----------------------------------------------------------------------------o-----------------------------------------------------------------------

Il comando:

display.setTextWrap(false);

 
      

significa disattivare il ritorno a capo automatico del testo sul display OLED.

Dettaglio:

  • Quando setTextWrap(true) (impostazione predefinita), se il testo che stai stampando con display.print() supera la larghezza del display, va automaticamente a capo sulla riga successiva.

  • Quando setTextWrap(false), invece, non va a capo: il testo prosegue orizzontalmente fuori dallo schermo, tagliandosi se supera la larghezza del display.

--------------------------------------------------------------------------o-----------------------------------------------------------------------

 

millis

-----------------------------------------------------------------------------o-----------------------------------------------------------------------

La funzione millis() restituisce il numero di millisecondi trascorsi dall'accensione della scheda. È molto utile per gestire temporizzazioni non bloccanti, cioè che non usano delay(), permettendoti di eseguire più operazioni contemporaneamente.

 

Sempice esempio:

Accendere un LED ogni secondo per un secondo:

const int ledPin = 13; // LED collegato al pin 13 (oppure cambia con il tuo)
unsigned long previousMillis = 0;
const long interval = 1000; // 1 secondo = 1000 millisecondi

bool ledState = false; // Stato attuale del LED

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();

  // Controlla se è passato un intervallo di tempo
  if (currentMillis - previousMillis >= interval) {
    // Salva il momento attuale
    previousMillis = currentMillis;

    // Inverti lo stato del LED
    ledState = !ledState;
    digitalWrite(ledPin, ledState ? HIGH : LOW);
  }
}

 

Chiaramente non si potrà rispettatre l'intervallo in modo perfetto. Tutto dipende da quanto il loop è caricato di cose da fare, esagerando per esemplificare se currentMillis = 100 millisecondi ed ogni giro di loop dura 2000 millisecondi già dopo il primo cilcp avremo 2000 - 100 = 1900 ms è >= a 1000 si accendi il led. Il les si è acceso dopo 1900 mls e non mille, Però questo è un esempio non realistico in quanto anche se oberato di cose da fare il loop impiega normalmente pochi mls e quindi a massimo ci potrà essere una dfferenza trascurabile tra l'intervallo impostato e l'effettivo intervallo di tempo trascorso

 

--------------------------------------------------------------------------o-----------------------------------------------------------------------

 

Timer

-----------------------------------------------------------------------------o-----------------------------------------------------------------------

Se si vuole avere un intervallo perfetto puoi usare i Timer Hardware, Arduino (Uno e Nano) ne hanno 3:

 

Timer0, Timer1 e Timer2 su Arduino Uno / Nano (ATmega328P)

 

Timer Bit Usato da Arduino per... Posso usarlo liberamente? Se lo uso, millis() funziona?
Timer0 8-bit millis(), micros(), delay() NO (riservato da Arduino) NO, se lo tocchi
Timer1 16-bit PWM su pin 9 e 10, usato da alcune librerie
Timer2 8-bit tone(), PWM su pin 3 e 11 (a volte) (con attenzione) , di solito

 

 

Puoi usare Timer2? Sì, ma con attenzione a…
tone() ❌ Usa Timer2 → evitalo se ti serve tone()
PWM su 3 e 11 ❌ Sarà disturbata se Timer2 viene riconfigurato
Altre libreri ❗ Controlla se lo usano internamente
Se eviti tutto ciò ✅ Nessun problema, Timer2 è tuo

 

Usa Timer1

Ecco perché è la scelta migliore:

Caratteristica Timer1
Bit 16-bit → alta risoluzione
PWM associati Solo pin 9 e 10
Usato da Arduino? ❌ No (libero!)
Interferisce con millis()? ❌ No
Interferisce con tone()? ❌ No
Può generare interrupt precisi? ✅ Sì
Supportato da librerie? ✅ TimerOne, ecc.

 

Nei Timer hardware hai solo un argomento che serve per impostare l'intervallo in microsecondi. parte da 0 quando arriva alla fine dell'intervallo scatta e torna a 0 e ricomincia a contare. Però lo devi associare ad un interrupt che eseguiràua funzione ed utilizzare la libreria <TimerOne>.

L'interrupt sono autonomi e non usano quelli classici su D2 e D3

 

Esempio con TimerOne (accende un LED ogni secondo con interrupt):

#include <TimerOne.h>

void setup() {
  pinMode(13, OUTPUT);
  Timer1.initialize(1000000);  // 1.000.000 µs = 1 secondo
  Timer1.attachInterrupt(blink);  // chiama blink() ogni secondo
}

void blink() {
  digitalWrite(13, !digitalRead(13));  // toggle LED
}

void loop() {
  // Il loop può fare qualsiasi altra cosa, o anche niente
}

--------------------------------------------------------------------------o-----------------------------------------------------------------------

 

CopiaQui

 

CopiaQui