top of page
  • Immagine del redattoreRobNico

Arduino display OLED 128x64 orologio Digitale e Analogico

Aggiornamento: 12 dic 2020

Questo post mostra come costruire un orologio in tempo reale usando Arduino, DS1307 RTC e SSD1306 OLED.

DS1307 RTC viene utilizzato come chip di orologio in tempo reale che mantiene il tempo in esecuzione anche se l'alimentazione principale è disattivata (con l'aiuto di una batteria), l'ora e la data vengono visualizzate sull'SSD1306 128 × 64 OLED.

Il display che utilizzeremo in questo articolo ha una risoluzione di 128×64 pixel ed è molto piccolo 0,96 pollici. Vuol dire uno schermo che misura circa 2.5 cm per 1.3 cm, ha un solo colore (bianco e nero). I display OLED ci permettono di visualizzare informazioni per i nostri progetti, come abbiamo visto in un precedente post la temperatura ecc...


Hardware occorrente:


  • Scheda Arduino

  • DS1307 RTC

  • SSD1306 OLED (modalità I2C)

  • breadboard

  • Cavi jumper


Il display OLED ed anche il modulo DS1307 utilizzato in questa progetto sono del tipo con interfaccia a due fili I2C, come si vede nella foto hanno solo 4 pin, positivo (VCC) e massa (GND), e due pin dell’interfaccia seriale SCL (serial clock) e SDA serial data.

Il driver che pilota il display è un SSD1306, tensione di alimentazione dai 3,3V ai 6V circa.

Occorre scaricare queste le librerie se non le avete già disponibili nella cartella librerie di Arduino.


Colleghiamo il display OLED e il DS1307 ad Arduino UNO come da immagine:



Adesso bisogna scoprire l’indirizzo I2C del display, per farlo ci viene in aiuto un piccolo schetch chiamato I2C scanner (https://playground.arduino.cc/Main/I2cScanner). Esso cercherà gli indirizzi I2C dei dispositivi connessi tramite I2C all’Arduino e li invierà tramite seriale. Caricatelo su Arduino IDE e aprite la finestra del monitor seriale, impostate 9600 baud e dovreste avere una cosa simile a questa: (possiamo caricarlo anche dalla cartella File/esempi/wire/scanner)

Una volta terminato apriamo il monitor seriale dove ci verrà visualizzato un risultato del genere:



Quello che ci interessa è il primo indirizzo, che fà riferimento al display OLED, gli altri sono del modulo DS1307 (non servono).

In questo caso, l’indirizzo del display è “0x3C”. Prendiamone nota e proseguiamo con il prossimo passo.

Ora sarà necessario impostare nella libreria Adafruit SSD1306 il tipo di display che stiamo utilizzando (con quale risoluzione), per assicurare il corretto funzionamento del display. Per farlo abbiamo bisogno di aprire la cartella in cui sono salvate le librerie di Arduino. In Windows: apriamo l’esplora file e andiamo nella cartella libraries di Arduino.

Una volta arrivati alla lista delle librerie troviamo e clicchiamo sulla cartella “Adafruit_SSD1306” e apriamo il file “Adafruit_SSD1306.h” con Notepad++. Raggiungiamo la riga, dove vedremo le seguenti righe:


// ONE of the following three lines must be #defined:

//#define SSD1306_128_64 ///< DEPRECTAED: old way to specify 128x64 screen

#define SSD1306_128_32 ///< DEPRECATED: old way to specify 128x32 screen

//#define SSD1306_96_16 ///< DEPRECATED: old way to specify 96x16 screen


Di default la risoluzione abilitata è quella di 128×32. Per modificarla in quella utilizzata dal display che stiamo usando cioè (128×64) sarà necessario modificare la riga “#define SSD1306_128_32” e rimuovere il commento alla riga “//#define SSD1306_128_64” in questo modo:


// ONE of the following three lines must be #defined:

#define SSD1306_128_64 ///< DEPRECTAED: old way to specify 128x64 screen

//#define SSD1306_128_32 ///< DEPRECATED: old way to specify 128x32 screen

//#define SSD1306_96_16 ///< DEPRECATED: old way to specify 96x16 screen


Salviamo il file e chiudiamo il tutto, ora apriamo l'IDE di arduino, dobbiamo fare un ultimo passo, settare la scheda DS1307 per impostare la prima volta l'orario e la data, altrimenti può dare errore.

Occorre caricare e installare lo schetch SetTime.ino che possiamo trovare inserito nella cartella DS1307RTC-master/examples sempre nelle librerie dove è installato Arduino.

Perfetto ora possiamo caricare e installare il seguente codice modificando l’indirizzo I2C annotato in precedenza se necessario.

 

//OLED TIME


#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#include <Time.h>

#include <DS1307RTC.h>


#define OLED_RESET 4

Adafruit_SSD1306 display(OLED_RESET);


void setup()

{


//Serial.begin(9600);

display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //indirizzo I2C 0x3D (per il 128x64)

//display.display();

display.clearDisplay();

display.setTextSize(1);

display.setTextColor(WHITE);

display.clearDisplay();


}


void loop()

{

display.clearDisplay();

tmElements_t tm;

if (RTC.read(tm)) {

display.clearDisplay();

display.setTextSize(3); //dimensione testo orario

display.setTextColor(WHITE);

display.setCursor(5, 8); //posizione orario

print2digits(tm.Hour);

display.write(':');

print2digits(tm.Minute);

display.setTextSize(2); //dimensione testo secondi

display.setCursor(100, 8); //posizione secondi

print2digits(tm.Second);

display.setCursor(10, 40); //posizione data

display.setTextSize(2); //dimensione testo data

display.print(tm.Day);

display.write('/');

display.print(tm.Month);

display.write('/');

display.print(tmYearToCalendar(tm.Year));

display.display();


}

else

{

if (RTC.chipPresent())

{

display.setTextSize(1);

display.setTextColor(WHITE);

display.print("DS1307 stopped,run set time");

display.display();

}

else

{

display.setTextSize(1);

display.setTextColor(WHITE);

display.print("DS1307 read error,check circuit");

display.display();

}

delay(9000);

}

delay(1000);


}


void print2digits(int number) {

if (number >= 0 && number < 10) {

display.write('0');

// display.display();

}

display.print(number);

//display.display();

//display.println();

}


 

Vediamo il risultato:



 

Vediamo ora una versione con orologio digitale e analogico, più eventualmente temperatura con sensore TM36, io non ho disponibile il sensore in questo momento perciò ho sostituito false alla riga boolean useTMP36 = true; .( se vi interessa sostituite false con true alla riga 44 dello script).

Scaricare e installare la libreria:

 

/***************************************************************

OLED Clock


display IIC 128x64 OLED with SSD1306 chip

RTC DS1307

sensore temperatura opzionale TMP 36


collegamenti RTC:

VCC +5v

GND GND

SDA Analog pin 4

SCL Analog pin 5

collegamenti OLED:

VCC +5v

GND GND

SDA Analog pin 4

SCL Analog pin 5

collegamenti TMP36:

VCC +3.3v

GND GND

Out Analog pin 1


***************************************************************/

// librerie

#include <SPI.h>

#include <Wire.h>

#include "RTClib.h"

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

//

// setup OLED display

#define OLED_RESET 4

Adafruit_SSD1306 display(OLED_RESET);

#if (SSD1306_LCDHEIGHT != 64)

#error("Height incorrect, please fix Adafruit_SSD1306.h!");

//

// Setup RTC

RTC_DS1307 RTC;

char monthString[37] = {"JanFebMarAprMayJunJulAugSepOctNovDec"};

int monthIndex[122] = {0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33};

//

//TMP36 Pin Variables

boolean useTMP36 = false; // impostare questo su true se si utilizza sensore TMP36

//boolean useTMP36 = true;

#define aref_voltage 3.3

int tempPin = 1; // il pin analogico a cui è collegato il pin Vout (sense) del TMP36

//la risoluzione è di 10 mV / grado centigrado con a

//Offset 500 mV per consentire temperature negative

int tempReading; // la lettura analogica dal sensore

//


void setup() {

Serial.begin(9600);

// Se si desidera impostare aref su qualcosa di diverso da 5v

analogReference(EXTERNAL);

Wire.begin();

RTC.begin();

if (! RTC.isrunning()) {

Serial.println("RTC is NOT running!");

// la riga seguente imposta l'RTC sulla data e l'ora in cui questo schizzo è stato compilato

RTC.adjust(DateTime(__DATE__, __TIME__));

}

// Usa I2C Scanner per controllare l'indirizzo, se necessario cambia lo 0x3C nella riga sotto

display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // inizializza con l'add I2C 0x3C (per 128x64)

// imposta la dimensione del carattere

display.setTextSize(1); // font piccoli

display.setTextColor(WHITE);

display.clearDisplay();


}


void loop() {

//***** RTC **********

DateTime now = RTC.now();

display.setCursor(32, 57);

display.print(now.day(), DEC);

display.print('/');

for (int i = 0; i <= 2; i++) {

display.print(monthString[monthIndex[now.month() - 1] + i]);

}

display.print('/');

display.print(now.year(), DEC);

// *********************


// visualizzazione tempo in formato digitale

display.setCursor(2, 2);

display.print(now.hour(), DEC);

printDigits(now.minute());

printDigits(now.second());

//

// Now draw the clock face

display.drawCircle(display.width() / 2, display.height() / 2, 20, WHITE);

display.drawCircle(display.width() / 2, display.height() / 2, 2, WHITE);


for ( int z = 0; z < 360; z = z + 30 ) {

//Begin at 0° and stop at 360°

float angle = z ;

angle = (angle / 57.29577951) ; //Converti gradi in radianti

int x2 = (64 + (sin(angle) * 20));

int y2 = (32 - (cos(angle) * 20));

int x3 = (64 + (sin(angle) * (20 - 5)));

int y3 = (32 - (cos(angle) * (20 - 5)));

display.drawLine(x2, y2, x3, y3, WHITE);

}

// display second hand

float angle = now.second() * 6 ;

angle = (angle / 57.29577951) ; //Converti gradi in radianti

int x3 = (64 + (sin(angle) * (20)));

int y3 = (32 - (cos(angle) * (20)));

display.drawLine(64, 32, x3, y3, WHITE);

//

// display minute hand

angle = now.minute() * 6 ;

angle = (angle / 57.29577951) ; //Converti gradi in radianti

x3 = (64 + (sin(angle) * (20 - 3)));

y3 = (32 - (cos(angle) * (20 - 3)));

display.drawLine(64, 32, x3, y3, WHITE);

//

// display hour hand

angle = now.hour() * 30 + int((now.minute() / 12) * 6 ) ;

angle = (angle / 57.29577951) ; //Converti gradi in radianti

x3 = (64 + (sin(angle) * (20 - 11)));

y3 = (32 - (cos(angle) * (20 - 11)));

display.drawLine(64, 32, x3, y3, WHITE);

//

// ora aggiunge la temperatura se necessario

if (useTMP36 == true) {

// ottenere la lettura della tensione dal sensore di temperatura

tempReading = analogRead(tempPin);

// convert la lettura della tensione, per arduino 3.3v usare 3.3

float voltage = tempReading * aref_voltage;

voltage /= 1024.0;

// ora stampa la temperatura

int temperatureC = (voltage - 0.5) * 100 ; //conversione da 10 mv per grado con offset 500 mV

display.setCursor(100, 2);

display.print(temperatureC);

display.print("C");

}


// aggiorna il display con tutti i dati

display.display();

delay(100);

display.clearDisplay();


}


// **************** End Main Loop *****************


void printDigits(int digits) {

// funzione utility per la visualizzazione dell'orologio digitale: stampa i due punti precedenti e lo 0 iniziale

display.print(":");

if (digits < 10)

display.print('0');

display.print(digits);

}


 

Vediamo il risultato:



899 visualizzazioni0 commenti

Post recenti

Mostra tutti

Commentaires


bottom of page