Η χρήση οθόνης σε ένα project με arduino είναι σχεδόν υποχρεωτική όταν θέλετε να έχετε επικοινωνία με τον χρήστη.
Υπάρχουν πολλών ειδών οθόνες, με τις δύο επικρατέστερες κατηγορίες να είναι αυτές των LCD και των OLED. Για τις οθόνες LCD σας έχουμε παρουσιάσει στο παρελθόν ένα project αν θέλετε να το ρίξετε μία ματιά αργότερα, είναι εδώ.
Στις οθόνες OLED, έχετε τη δυνατότητα να εμφανίσετε γραφικά με περισσότερη λεπτομέρεια καθώς οι οθόνες αυτές, αποτελούνται από pixels και η ανάλυσή τους διαφέρει. Όταν λέμε ανάλυση εννοούμε τον συνολικό αριθμό pixel που μπορούν να απεικονιστούν.
Μία οθόνη όπως αυτή που θα χρησιμοποιήσουμε, έχει 64x128 pixel άρα μπορεί να απεικονίσει σε αυτή την αναλογία έως 8192 pixel το μέγιστο.
Οθόνες OLED
Η οθόνη OLED που θα χρησιμοποιήσουμε στο project μας, είναι μία μονόχρωμη οθόνη 64x128 pixel η οποία χρησιμοποιεί το πρωτόκολλο SPI. Υπάρχει και η ίδια η οποία χρησιμοποιεί το πρωτόκολλο I2C με λιγότερα PIN.
Η οθόνη είναι ένα παραλληλόγραμμο το οποίο λειτουργεί με συντεταγμένες X, Y. Παρακάτω φαίνεται το σύστημα συντεταγμένων όπου μπορείτε να διακρίνετε που βρίσκεται το ελάχιστο και μέγιστο σημείο της οθόνης για τον σχεδιασμό των γραφικών.
PINS
PIN | Περιγραφή |
VCC | 3.3V/5V Τάση εισόδου |
GND | Γείωση / Αρνητικό |
NC | NC |
DIN | SPI Data Input |
CLK | SPI Clock input |
CS | Chip select, low active |
D/C | Command signal, low level for command, high level for data |
RES | Reset signal, low active |
Χαρακτηριστικά οθόνης
- Operating Voltage: 3.3V/5V
- Communication Interface: 3-wire SPI, 4-wire SPI, I2C
- Screen Type: OLED
- Driver Chip: SSD1306
- Resolution: 128*64 (Pixel)
- Display Size: 0.96inch
- Display Color: 1/4 yellow section, 3/4 blue section
- Operating Temp. (℃): -20°C ~ 70°C
- Storage Temp. (℃): -30°C ~ 80°C
- Visible Angle: >160°
Εντολές σχεδίασης
Drawing pixels (points)
Εντολή για σχεδιασμό ενός απλού pixel στην οθόνη σε θέση x και y με συγκεκριμένο χρώμα
void drawPixel(uint16_t x, uint16_t y, uint16_t color);
Drawing lines
Εντολή για σχεδιασμό γραμμής η οποία έχει συντεταγμένες x, y έναρξης και x, y λήξης με συγκεκριμένο χρώμα
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color);
Για οριζόντιες η κατακόρυφες γραμμές υπάρχουν και οι βελτιστοποιημένες εκδόσεις των εντολών που μπορείτε να χρησιμοποιείτε. Το length είναι το μήκος της γραμμής
void drawFastVLine(uint16_t x0, uint16_t y0, uint16_t length, uint16_t color);
void drawFastHLine(uint8_t x0, uint8_t y0, uint8_t length, uint16_t color);
Rectangles
Εντολή για σχεδιασμό παραλληλόγραμμου με σημείο έναρξης x, y και σημείο λήξης x, y και με συγκεκριμένο χρώμα. Η εντολή βγαίνει με δύο παραλλαγές. Η drawRect η οποία σχεδιάζει ένα περίγραμμα του παραλληλογράμμου και η fillRect η οποία γεμίζει με χρώμα το παραλληλόγραμμο.
void drawRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t color);
void fillRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t color);
Circles
Εντολή για σχεδιασμό κύκλων με κέντρο κύκλου τις συντεταγμένες x, y, ακτίνα r και συγκεκριμένου χρώματος. Υπάρχουν δύο παραλλαγές σχεδιασμού. η drawCircle η οποία σχεδιάζει μόνο το περίγραμμα του κύκλου και η fillCircle που σχεδιάζει έναν γεμάτο με χρώμα κύκλο.
void drawCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
void fillCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
Rounded rectangles
Εντολή για σχεδιασμό παραλληλόγραμμου με στρογγυλεμένες γωνίες με σημείο έναρξης x, y και σημείο λήξης x, y και με συγκεκριμένο χρώμα. Η εντολή βγαίνει με δύο παραλλαγές. Η drawRoundRect η οποία σχεδιάζει ένα περίγραμμα του παραλληλογράμμου και η fillRoundRect η οποία γεμίζει με χρώμα το παραλληλόγραμμο.
void drawRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color);
void fillRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color);
Triangles
Εντολή για σχεδιασμό τριγώνων. Για να σχηματιστεί το τρίγωνο χρειαζόμαστε 3 σημεία x,y με συγκεκριμένο χρώμα τα οποία είναι οι πλευρές κάθε τρίγωνο. Στη συνέχεια η εντολή ενώνει αυτά τα σημεία. Υπάρχουν δύο παραλλαγές της εντολής, η drawTriangle η οποία σχηματίζει το περίγραμμα του τριγώνου και η fillTriangle η οποία γεμίζει με το επιλεγμένο χρώμα το τρίγωνο.
void drawTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
void fillTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
Χαρακτήρες και ρυθμίσεις κειμένου
Για το κείμενο, υπάρχουν δύο βασικοί τρόποι εισαγωγής. Ο πρώτος είναι για την περίπτωση που θέλουμε να εισάγουμε έναν μόνο χαρακτήρα. Μπορείτε να τοποθετήσετε τον χαρακτήρα σε όποιο σημείο της οθόνης επιθυμείτε με ένα επιλεγμένο χρώμα. Προαιρετικά μπορείτε να δηλώσετε και το μέγεθος γραματοσειράς (1=μικρή γραμματοσειρά, 2=μεγάλη 10x16pixel ανά χαρακτήρα, 3=μεγαλύτερη...). Μοιάζει λίγο σαν να συναρμολογούμε ένα puzzle με αυτό το τρόπο αλλά είναι αποδοτικός όσον αφορά το μέγεθος του προγράμματος
Για την εκτύπωση ενός χαρακτήρα, χρειαζόμαστε το σημείο έναρξης x, y και το μέγεθος γραμματοσειράς
void drawChar(uint16_t x, uint16_t y, char c, uint16_t color, uint16_t bg, uint8_t size);
Ο δεύτερος τρόπος για να εισάγουμε κείμενο είναι να αξιοποιήσουμε τις συναρτήσεις που μας δίνει η βιβλιοθήκη και να χρησιμοποιήσουμε στο τέλος, την εντολή print που υπάρχει για να τυπώσουμε κείμενο.
setCursor: Επιλέγουμε την θέση στην οποία θέλουμε να εμφανιστεί το κείμενο
setTextColor: επιλέγουμε το χρώμα για το κείμενο, η συγκεκριμένο συνάρτηση μπορεί να χρησιμοποιηθεί και με δύο ορίσματα για να δηλώσουμε και το χρώμα του φόντου background color
setTextSize: Επιλέγουμε το μέγεθος της γραμματοσειράς 1 μικρά γράμματα και όσο ανεβαίνει τα γράμματα μεγαλώνουν.
setTextWrap: Επιλέγουμε με true ή false αν θέλουμε το κείμενο να κάνει αναδίπλωση όταν δεν φτάνει να εμφανιστεί σε μία σειρά.
void setCursor(int16_t x0, int16_t y0);
void setTextColor(uint16_t color);
void setTextColor(uint16_t color, uint16_t backgroundcolor);
void setTextSize(uint8_t size);
void setTextWrap(boolean w);
Tο project
Θα χρησιμοποιήσουμε ένα RTC module για να μετράμε τον χρόνο και να εμφανίζουμε την ώρα και ημερομηνία στην οθόνη μας.
Για να το πετύχουμε αυτό θα χρειαστούμε τα παρακάτω υλικά
- Arduino Nano
- Breadboard + καλώδια
- Real Time Clock module. Για το RTC module θα χρειαστείτε και μία μπαταρία CR2032
- OLED 0.96 SPI Display Module Arduino
Το σχέδιο
Παρακάτω η εικόνα που αποτυπώνει το σχέδιο.
Ο κώδικας
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "RTClib.h"
RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_MOSI 11
#define OLED_CLK 13
#define OLED_DC 9
#define OLED_CS 10
#define OLED_RESET 8
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
void setup() {
Serial.begin(57600);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
while (1) delay(10);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, let's set the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
if (!display.begin(SSD1306_SWITCHCAPVCC)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;)
;
}
display.clearDisplay();
}
void loop() {
DateTime now = rtc.now();
testfillrect();
prepText(5,5,1);
display.print("Date");
prepText(5,35,1);
display.print("Time");
prepText(4,15,2);
if (now.day()<10) {
display.print((String)"0"+now.day()+(String)"/");
}
else {
display.print(now.day()+ (String)"/");
}
if (now.month()<10) {
display.print((String)"0"+now.month()+(String)"/");
}
else {
display.print(now.month()+ (String)"/");
}
display.print(now.year());
prepText(4,45,2);
if (now.hour()<10) {
display.print((String)"0"+ now.hour()+ (String)":");
}
else {
display.print(now.hour()+ (String)":");
}
if (now.minute()<10) {
display.print((String)"0" + now.minute() + (String)":");
}
else {
display.print(now.minute() + (String)":");
}
if (now.second()<10) {
display.print((String)"0"+ now.second());
}
else {
display.print(now.second());
}
display.display();
display.clearDisplay();
}
void testfillrect(void) {
display.fillRect(0, 0, display.width(), display.height(), SSD1306_INVERSE);
display.fillRect(1, 1, display.width()-2, display.height()-2, SSD1306_INVERSE);
}
void prepText(int x, int y, int s) {
display.setTextSize(s); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(x, y); // Start at top-left corner
display.cp437(true); // Use full 256 char 'Code Page 437' font
}
Ο κώδικας χρησιμοποιεί αρκετές βιβλιοθήκες για την οθόνη καθώς και για το RTC. Όλες οι βιβλιοθήκες είναι από την Adafruit, δοκιμασμένες και σταθερές.
Στο βίντεο, εξηγούμε ποιες βιβλιοθήκες χρησιμοποιούμε τις οποίες μάλιστα, κατεβάζουμε μέσα από το Arduino IDE