Возможно кому-то будет интересно...
По хорошему к ним надо еще корр. хода прикручивать, но по желанию.
у меня оно вот только - только "пошло".
Описание (краткое)
A4, A5 интерфейс. три кнопки для настройки, общий - минус.
НЕТ realTime, Скетч использует 18148 байт (61%) памяти устройства.
Код: Выделить всё
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDRESS 0x3C
#define BUTTON_MODE_PIN D3 // Mode button
#define BUTTON_PLUS_PIN D4
#define BUTTON_MINUS_PIN D5
struct TimeDate { // Time and Date structure
int year;
int month;
int day;
int hour;
int minute;
int second;
};
TimeDate currentTime = {2026, 4, 6, 0, 0, 0}; // Variables
bool editing = false;
int editStage = 0;
/*
Edit stages:
Line 1 (Time HH:MM:SS):
0 - Hour tens (H_)
1 - Hour units (_H)
2 - Minute tens (M_)
3 - Minute units (_M)
4 - Seconds (both digits together - SS)
Line 2 (Date YY Mon DD):
5 - Year tens (Y_)
6 - Year units (_Y)
7 - Month (full month)
8 - Day tens (D_)
9 - Day units (_D)
*/
unsigned long lastBlinkTime = 0;
bool showDigit = true;
const unsigned long blinkInterval = 500;
unsigned long lastSecondUpdate = 0;
// Month names
const char* months[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
bool lastBtnModeState = HIGH; // Button debounce
bool lastBtnPlusState = HIGH;
bool lastBtnMinusState = HIGH;
void setup() {
Serial.begin(115200);
pinMode(BUTTON_MODE_PIN, INPUT_PULLUP);
pinMode(BUTTON_PLUS_PIN, INPUT_PULLUP);
pinMode(BUTTON_MINUS_PIN, INPUT_PULLUP);
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
}
void loop() {
unsigned long now = millis();
// Update seconds every 1000ms
if (now - lastSecondUpdate >= 1000) {
lastSecondUpdate = now;
if (!editing) {
incrementSeconds();
}
}
// Read buttons
bool btnMode = digitalRead(BUTTON_MODE_PIN) == LOW;
bool btnPlus = digitalRead(BUTTON_PLUS_PIN) == LOW;
bool btnMinus = digitalRead(BUTTON_MINUS_PIN) == LOW;
// Handle Mode button press
if (btnMode && !lastBtnModeState) {
delay(50); // Debounce
if (digitalRead(BUTTON_MODE_PIN) == LOW) {
handleModeButton();
}
}
lastBtnModeState = btnMode;
// Handle + and - buttons (only in edit mode)
if (editing) {
if (btnPlus && !lastBtnPlusState) {
delay(50);
if (digitalRead(BUTTON_PLUS_PIN) == LOW) {
changeDigit(1);
}
}
if (btnMinus && !lastBtnMinusState) {
delay(50);
if (digitalRead(BUTTON_MINUS_PIN) == LOW) {
changeDigit(-1);
}
}
}
lastBtnPlusState = btnPlus;
lastBtnMinusState = btnMinus;
// Blink logic for editing
if (editing && (millis() - lastBlinkTime >= blinkInterval)) {
showDigit = !showDigit;
lastBlinkTime = millis();
}
// Update display
updateDisplay();
delay(20);
}
void handleModeButton() {
if (!editing) {
// Enter edit mode - start with first digit (hour tens)
editing = true;
editStage = 0;
showDigit = true;
lastBlinkTime = millis();
} else {
// Move to next edit stage
editStage++;
// If seconds stage (4), reset seconds to 0
if (editStage == 4) {
currentTime.second = 0;
}
// After last stage (9 = day units), exit edit mode
if (editStage > 9) {
editing = false;
editStage = 0;
}
showDigit = true;
lastBlinkTime = millis();
}
}
void changeDigit(int delta) {
switch (editStage) {
case 0: // Hour tens (0-2)
{
int tens = currentTime.hour / 10;
int units = currentTime.hour % 10;
tens = constrain(tens + delta, 0, 2);
if (tens == 2 && units > 3) units = 3;
currentTime.hour = tens * 10 + units;
}
break;
case 1: // Hour units (0-9, but max 23)
{
int tens = currentTime.hour / 10;
int units = currentTime.hour % 10;
int maxUnits = (tens == 2) ? 3 : 9;
units = constrain(units + delta, 0, maxUnits);
currentTime.hour = tens * 10 + units;
}
break;
case 2: // Minute tens (0-5)
{
int tens = currentTime.minute / 10;
int units = currentTime.minute % 10;
tens = constrain(tens + delta, 0, 5);
currentTime.minute = tens * 10 + units;
}
break;
case 3: // Minute units (0-9)
{
int tens = currentTime.minute / 10;
int units = currentTime.minute % 10;
units = constrain(units + delta, 0, 9);
currentTime.minute = tens * 10 + units;
}
break;
case 4: // Seconds (both digits - just reset to 0)
currentTime.second = 0;
break;
case 5: // Year tens
{
int yearShort = currentTime.year % 100;
int tens = yearShort / 10;
int units = yearShort % 10;
tens = constrain(tens + delta, 0, 9);
currentTime.year = 2000 + tens * 10 + units;
}
break;
case 6: // Year units
{
int yearShort = currentTime.year % 100;
int tens = yearShort / 10;
int units = yearShort % 10;
units = constrain(units + delta, 0, 9);
currentTime.year = 2000 + tens * 10 + units;
}
break;
case 7: // Month (1-12)
currentTime.month = constrain(currentTime.month + delta, 1, 12);
break;
case 8: // Day tens (0-3)
{
int tens = currentTime.day / 10;
int units = currentTime.day % 10;
tens = constrain(tens + delta, 0, 3);
int newDay = tens * 10 + units;
if (newDay < 1) newDay = 1;
if (newDay > 31) newDay = 31;
currentTime.day = newDay;
}
break;
case 9: // Day units (0-9, but valid day)
{
int tens = currentTime.day / 10;
int units = currentTime.day % 10;
units = constrain(units + delta, 0, 9);
int newDay = tens * 10 + units;
if (newDay < 1) newDay = 1;
if (newDay > 31) newDay = 31;
currentTime.day = newDay;
}
break;
}
}
void incrementSeconds() {
currentTime.second++;
if (currentTime.second >= 60) {
currentTime.second = 0;
currentTime.minute++;
if (currentTime.minute >= 60) {
currentTime.minute = 0;
currentTime.hour++;
if (currentTime.hour >= 24) {
currentTime.hour = 0;
currentTime.day++;
if (currentTime.day > 31) {
currentTime.day = 1;
currentTime.month++;
if (currentTime.month > 12) {
currentTime.month = 1;
currentTime.year++;
}
}
}
}
}
}
void drawChar(int x, int y, char c, bool inverse) {
if (inverse) {
display.fillRect(x, y, 12, 16, SSD1306_WHITE);
display.setTextColor(SSD1306_BLACK);
} else {
display.setTextColor(SSD1306_WHITE);
}
display.setCursor(x, y);
display.print(c);
display.setTextColor(SSD1306_WHITE);
}
void updateDisplay() {
display.clearDisplay();
display.setTextSize(2);
char timeBuf[9]; // LINE 1: Time HH:MM:SS
sprintf(timeBuf, "%02d:%02d:%02d", currentTime.hour, currentTime.minute, currentTime.second);
int timeX = 4;
int timeY = 8;
int charW = 12;
for (int i = 0; i < 8; i++) {
bool inverse = false;
if (editing) {
switch (editStage) {
case 0: inverse = (i == 0); break;
case 1: inverse = (i == 1); break;
case 2: inverse = (i == 3); break;
case 3: inverse = (i == 4); break;
case 4: inverse = (i == 6 || i == 7); break;
}
inverse = inverse && !showDigit;
}
drawChar(timeX + i * charW, timeY, timeBuf[i], inverse);
}
char dateBuf[12]; // LINE 2: Date YY Mon DD
sprintf(dateBuf, "%02d %s %02d", currentTime.year % 100, months[currentTime.month - 1], currentTime.day);
int dateX = 4;
int dateY = 40;
for (int i = 0; i < strlen(dateBuf); i++) {
bool inverse = false;
if (editing) {
switch (editStage) {
case 5: inverse = (i == 0); break;
case 6: inverse = (i == 1); break;
case 7: inverse = (i >= 3 && i <= 5); break;
case 8: inverse = (i == 7); break;
case 9: inverse = (i == 8); break;
}
inverse = inverse && !showDigit;
}
drawChar(dateX + i * charW, dateY, dateBuf[i], inverse);
}
display.display();
}