Ищу человека который напишет код настройки времени для часов
- Войдите на сайт для отправки комментариев
Втр, 08/06/2021 - 23:12
Есть часы-метеостанция к ним припаяно 3 кнопки нужно настраивать время через них.
За пример была взята метеостанция от Алекса Гивера https://alexgyver.ru/meteoclock/
Моя схема и уже имеющийся код приведены ниже.

Основной код:
/*
Время и дата устанавливаются атвоматически при загрузке прошивки (такие как на компьютере)
График всех величин за час и за сутки (усреднённые за каждый час)
В модуле реального времени стоит батарейка, которая продолжает отсчёт времени после выключения/сброса питания
Как настроить время на часах. У нас есть возможность автоматически установить время на время загрузки прошивки, поэтому:
- Ставим настройку RESET_CLOCK на 1
- Прошиваемся
- Сразу ставим RESET_CLOCK 0
- И прошиваемся ещё раз
- Всё
*/
// ------------------------- НАСТРОЙКИ --------------------
#define RESET_CLOCK 0 // сброс часов на время загрузки прошивки (для модуля с несъёмной батарейкой). Не забудь поставить 0 и прошить ещё раз!
#define SENS_TIME 30000 // время обновления показаний сенсоров на экране, миллисекунд
#define DISP_MODE 1 // в правом верхнем углу отображать: 0 - год, 1 - день недели, 2 - секундо
#define WEEK_LANG 0 // язык дня недели: 0 - английский, 1 - русский (транслит)
#define DEBUG 0 // вывод на дисплей лог инициализации датчиков при запуске. Для дисплея 1602 не работает! Но дублируется через порт!
#define DISPLAY_ADDR 0x27 // адрес платы дисплея: 0x27 или 0x3f. Если дисплей не работает - смени адрес! На самом дисплее адрес не указан
// адрес BME280 жёстко задан в файле библиотеки Adafruit_BME280.h
// стоковый адрес был 0x77, у китайского модуля адрес 0x76.
// Так что если юзаете не библиотеку из архива - не забудьте поменять
// если дисплей не заводится - поменяйте адрес (строка 54)
// библиотеки
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(DISPLAY_ADDR, 20, 4);
#include "RTClib.h"
RTC_DS3231 rtc;
DateTime now;
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme;
#include <GyverTimer.h>
GTimer_ms sensorsTimer(SENS_TIME);
GTimer_ms drawSensorsTimer(SENS_TIME);
GTimer_ms clockTimer(1000);
int8_t hrs, mins, secs;
// переменные для вывода
float dispTemp;
byte dispHum;
int dispPres;
// символы
// цифры
uint8_t LT[8] = {0b00111, 0b01111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
uint8_t UB[8] = {0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000};
uint8_t RT[8] = {0b11100, 0b11110, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111};
uint8_t LL[8] = {0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b01111, 0b00111};
uint8_t LB[8] = {0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111};
uint8_t LR[8] = {0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11110, 0b11100};
uint8_t UMB[8] = {0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111};
uint8_t LMB[8] = {0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111};
void drawDig(byte dig, byte x, byte y) {
switch (dig) {
case 0:
lcd.setCursor(x, y); // set cursor to column 0, line 0 (first row)
lcd.write(0); // call each segment to create
lcd.write(1); // top half of the number
lcd.write(2);
lcd.setCursor(x, y + 1); // set cursor to colum 0, line 1 (second row)
lcd.write(3); // call each segment to create
lcd.write(4); // bottom half of the number
lcd.write(5);
break;
case 1:
lcd.setCursor(x + 1, y);
lcd.write(2);
lcd.setCursor(x + 1, y + 1);
lcd.write(3);
break;
case 2:
lcd.setCursor(x, y);
lcd.write(6);
lcd.write(6);
lcd.write(2);
lcd.setCursor(x, y + 1);
lcd.write(3);
lcd.write(7);
lcd.write(7);
break;
case 3:
lcd.setCursor(x, y);
lcd.write(1);
lcd.write(6);
lcd.write(5);
lcd.setCursor(x, y + 1);
lcd.write(4);
lcd.write(7);
lcd.write(5);
break;
case 4:
lcd.setCursor(x, y);
lcd.write(3);
lcd.write(4);
lcd.write(2);
lcd.setCursor(x + 2, y + 1);
lcd.write(3);
break;
case 5:
lcd.setCursor(x, y);
lcd.write(0);
lcd.write(6);
lcd.write(6);
lcd.setCursor(x, y + 1);
lcd.write(7);
lcd.write(7);
lcd.write(5);
break;
case 6:
lcd.setCursor(x, y);
lcd.write(0);
lcd.write(6);
lcd.write(6);
lcd.setCursor(x, y + 1);
lcd.write(3);
lcd.write(7);
lcd.write(5);
break;
case 7:
lcd.setCursor(x, y);
lcd.write(1);
lcd.write(1);
lcd.write(5);
lcd.setCursor(x + 1, y + 1);
lcd.write(0);
break;
case 8:
lcd.setCursor(x, y);
lcd.write(0);
lcd.write(6);
lcd.write(2);
lcd.setCursor(x, y + 1);
lcd.write(3);
lcd.write(7);
lcd.write(5);
break;
case 9:
lcd.setCursor(x, y);
lcd.write(0);
lcd.write(1);
lcd.write(2);
lcd.setCursor(x + 1, y + 1);
lcd.write(7);
lcd.write(5);
break;
case 10:
lcd.setCursor(x, y);
lcd.write(32);
lcd.write(32);
lcd.write(32);
lcd.setCursor(x, y + 1);
lcd.write(32);
lcd.write(32);
lcd.write(32);
break;
}
}
void drawdots(byte x, byte y, boolean state) {
byte code;
if (state) code = 165;
else code = 32;
lcd.setCursor(x, y);
lcd.write(code);
lcd.setCursor(x, y + 1);
lcd.write(code);
}
void drawClock(byte hours, byte minutes, byte x, byte y, boolean dotState) {
// чисти чисти!
lcd.setCursor(x, y);
lcd.print(" ");
lcd.setCursor(x, y + 1);
lcd.print(" ");
//if (hours > 23 || minutes > 59) return;
if (hours / 10 == 0) drawDig(10, x, y);
else drawDig(hours / 10, x, y);
drawDig(hours % 10, x + 4, y);
// тут должны быть точки. Отдельной функцией
drawDig(minutes / 10, x + 8, y);
drawDig(minutes % 10, x + 12, y);
}
#if (WEEK_LANG == 0)
static const char *dayNames[] = {
"Sund",
"Mond",
"Tues",
"Wedn",
"Thur",
"Frid",
"Satu",
};
#else
static const char *dayNames[] = {
"BOCK",
"POND",
"BTOP",
"CPED",
"4ETB",
"5YAT",
"CYBB",
};
#endif
void drawData() {
lcd.setCursor(15, 0);
if (now.day() < 10) lcd.print(0);
lcd.print(now.day());
lcd.print(".");
if (now.month() < 10) lcd.print(0);
lcd.print(now.month());
if (DISP_MODE == 0) {
lcd.setCursor(16, 1);
lcd.print(now.year());
} else if (DISP_MODE == 1) {
lcd.setCursor(16, 1);
int dayofweek = now.dayOfTheWeek();
lcd.print(dayNames[dayofweek]);
}
}
void loadClock() {
lcd.createChar(0, LT);
lcd.createChar(1, UB);
lcd.createChar(2, RT);
lcd.createChar(3, LL);
lcd.createChar(4, LB);
lcd.createChar(5, LR);
lcd.createChar(6, UMB);
lcd.createChar(7, LMB);
}
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
lcd.clear();
#if (DEBUG == 1)
boolean status = true;
lcd.setCursor(0, 1);
lcd.print(F("RTC... "));
Serial.print(F("RTC... "));
delay(50);
if (rtc.begin()) {
lcd.print(F("OK"));
Serial.println(F("OK"));
} else {
lcd.print(F("ERROR"));
Serial.println(F("ERROR"));
status = false;
}
lcd.setCursor(0, 2);
lcd.print(F("BME280... "));
Serial.print(F("BME280... "));
delay(50);
if (bme.begin(&Wire)) {
lcd.print(F("OK"));
Serial.println(F("OK"));
} else {
lcd.print(F("ERROR"));
Serial.println(F("ERROR"));
status = false;
}
lcd.setCursor(0, 3);
if (status) {
lcd.print(F("All good"));
Serial.println(F("All good"));
delay(1000);
lcd.clear();
} else {
lcd.print(F("Check wires!"));
Serial.println(F("Check wires!"));
delay(1000);
while (1);
}
#else
rtc.begin();
bme.begin(&Wire);
#endif
bme.setSampling(Adafruit_BME280::MODE_FORCED,
Adafruit_BME280::SAMPLING_X1, // temperature
Adafruit_BME280::SAMPLING_X1, // pressure
Adafruit_BME280::SAMPLING_X1, // humidity
Adafruit_BME280::FILTER_OFF );
if (RESET_CLOCK || rtc.lostPower())
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
now = rtc.now();
secs = now.second();
mins = now.minute();
hrs = now.hour();
bme.takeForcedMeasurement();
uint32_t Pressure = bme.readPressure();
loadClock();
drawClock(hrs, mins, 0, 0, 1);
drawData();
readSensors();
drawSensors();
}
void loop() {
if (sensorsTimer.isReady()) readSensors(); // читаем показания датчиков с периодом SENS_TIME
if (clockTimer.isReady()) clockTick(); // два раза в секунду пересчитываем время и мигаем точками
if (drawSensorsTimer.isReady()) drawSensors(); // обновляем показания датчиков на дисплее с периодом SENS_TIME
}
Код с функциями:
void readSensors() {
bme.takeForcedMeasurement();
dispTemp = bme.readTemperature();
dispHum = bme.readHumidity();
dispPres = (float)bme.readPressure() * 0.00750062;
}
void drawSensors() {
lcd.setCursor(0, 2);
lcd.print(String(dispTemp, 1));
lcd.write(223);
lcd.setCursor(6, 2);
lcd.print(" " + String(dispHum) + "% ");
lcd.setCursor(13, 2);
lcd.print(String(dispPres) + " mm");
lcd.setCursor(13, 3);
}
boolean dotFlag;
void clockTick() {
dotFlag = !dotFlag;
if (dotFlag) { // каждую секунду пересчёт времени
secs++;
if (secs > 59) { // каждую минуту
secs = 0;
mins++;
if (mins <= 59) drawClock(hrs, mins, 0, 0, 1);
}
if (mins > 59) { // каждый час
now = rtc.now();
secs = now.second();
mins = now.minute();
hrs = now.hour();
drawClock(hrs, mins, 0, 0, 1);
if (hrs > 23) {
hrs = 0;
}
drawData();
}
if (DISP_MODE == 2) {
lcd.setCursor(16, 1);
if (secs < 10) lcd.print(" ");
lcd.print(secs);
}
}
drawdots(7, 0, dotFlag);
}
Если есть wifi, замените ардуину на esp8266 и получайте наиточнейшее время с NTP. Не думаю, что заказ станет от этого сильно дороже, но станет сильно удобнее
...все равно кнопки неправильно пририсованы.
Но тогда придётся как-то вводить SSID, passphrase и адрес NTP.
Даже не знаю, что лучше.
Проблема как раз таки в том, что требования чтобы часы были как обычные настольные но на Arduino, с настройкой кнопками и без дополнительных деталей. :(
NTP не надо вводить, их достаточно штук 20 проверенных прописать в цикл перебора. Могу скинуть свои топ-20. Вэб-морду писать придется, это да! Еще и кэш логин-пароль.. Но, что-то мне подсказывает, что для вас это не сильно обременительно)) И это решение будет всяко удобнее кнопок
Проблема как раз таки в том, что требования чтобы часы были как обычные настольные но на Arduino, с настройкой кнопками и без дополнительных деталей. :(
А так они еще и с телефона будут управляться! Годнота, да и только!
Для меня - нет, для заказчика - скорее всего.
Ну он же не сам собирается делать, он хочет решение готовое оплатить.
Ну он же не сам собирается делать, он хочет решение готовое оплатить.
Это и есть его бремя ))
У меня просто требование сделать с кнопками.
В принципе, я би уже давно всё сделал бы, но есть проблема, я уже нашел неплохой код настройки на https://lesson.iarduino.ru/page/urok-17-podklyuchenie-rtc-chasy-realnogo...
Но проблема в том что там другая библиотека, и при простом переносе - функции не работают, а при замене библиотеки - не работает пол кода.
Это и есть его бремя ))
Это не бремя, Это рыночные отношения. Вот вам ведь тоже знания и опыт даром не достались? И он, возможно, в чем-то профессионал. Теория вмененных издержек советует заниматься за деньги профильным делом, а непрофильные задачи отдавать на аутсорсинг.
Ну, это ваши личные проблемы. Решайте их с исполнителем
Возможно я начал тему не в том разделе, просто меня немного напрягло то, что я брал за основу чужой проект, а на форуме написано что "Здесь помогают тем, кто пытается что-то сделать сам, имеет самописный скетч и задает вопросы по нему. Если вас не устраивают требования, есть чудесный раздел: "Ищу исполнителя"."
Вы все сделали правильно. С разделом не ошиблись. Гайвера тут не очень уважают, но я уверен - это не помешает вам найти потенциального исполнителя для вашего проекта. Если ваши конкретизированные формулировки задачи совпадут с суммой, которую вы готовы отдать за работу
UPD: 74 это регион, или другое?))
Bogdan74, огласите бюджет, пожалуйста
Бюджет неважен. Напишите мне на почту barmaley2m@yandex.ru