Kali ini kita akan membuat tutorial cara membuat jam tampilan analog menggunakan Arduino dan layar OLED kecil.
Komponen yang Dibutuhkan
Untuk proyek ini kita hanya membutuhkan tiga komponen:
- Arduino Uno (Anda dapat menggunakan Papan Arduino lainnya)
- Layar OLED I2C 128×64
- Modul DS1302 Real Time Clock (RTC)
Perakitan Komponen
Mari kita hubungkan komponen ke Arduino terlebih dahulu.
- VCC dan ground modul OLED dan RTC ke VCC dan GND arduino
- Pin SCL dan SDA layar OLED disambungkan ke A5 & A4 pada Arduino
- PIN CLK DAT RST dari RTC ke Arduino pin A1 A2 dan A3
Desain Tampilan Jam
Sekarang kita merencanakan desain jam yang akan ditampilkan pada layar OLED 128×64. Kita akan membuat tampilan sebagai berikut:
- Lingkaran dengan jari-jari 32 pixel (dari titik tengah memiliki koordinat 64 horizontal dan 32 vertikal)
- Nomor 12 di atas Petunjuk jam 12
- Tampilan detik kita akan memiliki lingkaran kecil bergerak memutar
- Jarum menit dibuat dengan satu baris dan jarum jam yang lebih tebal (dibuat dengan dua garis berdampingan)
Menghitung Posisi Jarum Jam
Bagian paling rumit dari proyek ini adalah menghitung posisi masing-masing jarum. Memiliki lingkaran dengan jari-jari R dan sudut yang diketahui α yang menunjukkan posisi yang tepat dimana titik pada lingkaran ditampilkan. Kita dapat menghitung koordinat titik itu dengan rumus berikut.
X= R*sin(α)
Y= R*cos(α)
dimana α=0…2π
Full Source Code
Source Code ini membutuhkan beberapa library yang bisa didownload di bawah ini:
- GitHub – adafruit/Adafruit_SSD1306: Arduino library for SSD1306 monochrome 128×64 and 128×32 OLEDs
- GitHub – adafruit/Adafruit-GFX-Library: Adafruit GFX graphics core library, this is the ‘core’ class that all our other graphics libraries derive from
- ArduinoRTClibrary/virtuabotixRTC.h at master · chrisfryer78/ArduinoRTClibrary · GitHub
#define SCREEN_HEIGHT 64 // Definisikan ukuran tinggi layar OLED dalam satuan pixel
// Deklarasi koneksi layar SSD1306 dengan I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (atau -1 jikan membagi pin reset Arduino )
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const float pi = 3.14159267 ;
const int clock_center_x=64;
const int clock_center_y=32;
int o=1;
// variabel digunakan untuk menentukan posisi dalam lingkaran
int x;
int y;
int x1;
int y1;
// variabel waktu RTC
int seconds=0;
int minutes;
int hours;
void setup() {
Serial.begin(9600);
//myRTC.setDS1302Time(10, 00,13, 4, 18, 06, 2020);
// SSD1306_SWITCHCAPVCC = menghasilkan tegangan tampilan 3.3V secara internal
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D untuk 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;); // ulangi terus menerus
}
// buffer tampilan awal di layar --
// library menginisialisasi ini dengan layar splash Adafruit.
display.display();
delay(2000); // Pause selama 2 detik
// hapus buffer
display.clearDisplay();
draw_clock_face();
display.display();
}
void draw_second(int second, int mode){
y= (24*cos(pi-(2*pi)/60*second))+clock_center_y;
x =(24*sin(pi-(2*pi)/60*second))+clock_center_x;
if (mode==1) display.drawCircle(x, y, 2, SSD1306_WHITE);
else display.drawCircle(x, y, 2, SSD1306_BLACK);
}
void draw_hour(int hour, int minute, int mode){
y= (18*cos(pi-(2*pi)/12*hour-(2*PI)/720*minute))+clock_center_y;
x =(18*sin(pi-(2*pi)/12*hour-(2*PI)/720*minute))+clock_center_x;
y1=(18*cos(pi-(2*pi)/12*hour-(2*PI)/720*minute))+clock_center_y+1;
x1=(18*sin(pi-(2*pi)/12*hour-(2*PI)/720*minute))+clock_center_x+1;
if (mode==1){
display.drawLine(clock_center_x,clock_center_y,x,y,SSD1306_WHITE);
display.drawLine(clock_center_x+1,clock_center_y+1,x1,y1,SSD1306_WHITE);
}
else{
display.drawLine(clock_center_x,clock_center_y,x,y,SSD1306_BLACK);
display.drawLine(clock_center_x+1,clock_center_y+1,x1,y1,SSD1306_BLACK);
}
}
void draw_minute(int minute, int mode){
y= (24*cos(pi-(2*pi)/60*minute))+clock_center_y;
x =(24*sin(pi-(2*pi)/60*minute))+clock_center_x;
if (mode==1)display.drawLine(clock_center_x,clock_center_y,x,y,SSD1306_WHITE); else display.drawLine(clock_center_x,clock_center_y,x,y,SSD1306_BLACK);
}
void draw_clock_face(void){
// menampilkan bagian tengah jam
display.drawCircle(clock_center_x, clock_center_y,3, SSD1306_WHITE);
display.fillCircle(clock_center_x, clock_center_y,3, SSD1306_WHITE);
// menampilkan jarum jam
for (int i=0;i<12;i++){
y= (32*cos(pi-(2*pi)/12*i))+clock_center_y;
x =(32*sin(pi-(2*pi)/12*i))+clock_center_x;
y1= (28*cos(pi-(2*pi)/12*i))+clock_center_y;
x1 =(28*sin(pi-(2*pi)/12*i))+clock_center_x;
display.drawLine(x1,y1,x,y,SSD1306_WHITE);
}
//
display.drawCircle(26*sin(pi)+clock_center_x, (26*cos(pi))+clock_center_y, 6, SSD1306_BLACK);
display.fillCircle(26*sin(pi)+clock_center_x, (26*cos(pi))+clock_center_y, 5, SSD1306_BLACK);
display.setTextSize(1); // Skala Normal 1:1 pixel
display.setTextColor(SSD1306_WHITE); // menampilkan text
display.setCursor(clock_center_x-3,0); //
display.println(F("12"));
}
void redraw_clock_face_elements(void){
display.drawCircle(clock_center_x, clock_center_y,3, SSD1306_WHITE);
display.fillCircle(clock_center_x, clock_center_y,3, SSD1306_WHITE);
display.setCursor(clock_center_x-3,0);
display.println(F("12"));
}
void loop() {
myRTC.updateTime();
if (myRTC.seconds!=seconds){
draw_second(seconds,0);
draw_minute(minutes,0);
draw_hour(hours,minutes,0);
draw_second(myRTC.seconds,1);
draw_minute(myRTC.minutes,1);
draw_hour(myRTC.hours,myRTC.minutes,1);
display.display();
seconds=myRTC.seconds;
minutes=myRTC.minutes;
hours=myRTC.hours;
redraw_clock_face_elements();
}
}