• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Часы с кукушкой на esp 8266

vlad19950824@

New member
Добрый день, я написал скетч для esp 8266 ,часы с кукушкой.
Компоненты: esp8266, GC9A01 1,28 display, servo,mp3 Mini Player.
Работа часов такая, на дисплее отображается циферблат время часы запрашивают из интернета далее каждый час воспроизводится определённый трек для каждого часа и серво поворачивается на 90 градусов на врем проигрывания трека. Например 12 часов включается трек 12( часы кукукают 12 раз). Проблема в том что часы на esp8266 зависают в не определённый момент. Скетч компелируется без проблем вроде библиотеки тоже использовал актуальные. По питанию БП 5в 2а плюс на входе поставил конденсатор.
Программу писал через Arduino ide.

Помогите разобраться в чем проблема. Скетч есть :


#include <Wire.h>
#include "SPI.h"
#include <Adafruit_GFX.h>
#include <Adafruit_GC9A01A.h>
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
#include <NTPClient.h>
#include <DFRobotDFPlayerMini.h>
#include <Servo.h>
#include <math.h>
#include <SoftwareSerial.h>
#include <pgmspace.h>
#include <ESP8266WiFi.h>

// Параметры подключения Wi-Fi
const char* ssid = "xxxxxxxxxxxx";
const char* password = "xxxxxxxxxxxxx";

// NTP клиент для получения времени
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 7200, 60000);

// Настройки дисплея GC9A01A
#define TFT_CS D8
#define TFT_RST D1
#define TFT_DC D2

Adafruit_GC9A01A tft = Adafruit_GC9A01A(TFT_CS, TFT_DC, TFT_RST);

// Настройки MP3 плеера
SoftwareSerial mySoftwareSerial(D4, D3); // RX, TX
DFRobotDFPlayerMini myDFPlayer;

// Настройки серво
Servo myServo;
#define SERVO_PIN D6

// Центр дисплея
#define CENTER_X 120
#define CENTER_Y 120

// Предыдущие координаты стрелок
int prevHourX = CENTER_X, prevHourY = CENTER_Y;
int prevMinuteX = CENTER_X, prevMinuteY = CENTER_Y;
int prevSecondX = CENTER_X, prevSecondY = CENTER_Y;

// Переменная для отслеживания времени
unsigned long targetTime = 0;

// Программенные строки
const char connectingToWiFi[] PROGMEM = "Connecting to WiFi...";
const char connectedToWiFi[] PROGMEM = "Connected to WiFi";
const char unableToBegin[] PROGMEM = "Unable to begin:";
const char recheckConnection[] PROGMEM = "1. Please recheck the connection!";
const char insertSDCard[] PROGMEM = "2. Please insert the SD card!";

void setup() {
Serial.begin(115200);

// Подключение к Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println(FPSTR(connectingToWiFi));
}
Serial.println(FPSTR(connectedToWiFi));

// Настройка NTP клиента
timeClient.begin();

// Настройка дисплея
tft.begin();
tft.setRotation(0);
tft.fillScreen(GC9A01A_BLACK);

// Настройка MP3 плеера
mySoftwareSerial.begin(9600);
if (!myDFPlayer.begin(mySoftwareSerial)) {
Serial.println(FPSTR(unableToBegin));
Serial.println(FPSTR(recheckConnection));
Serial.println(FPSTR(insertSDCard));
while(true);
}
myDFPlayer.setTimeOut(500);
myDFPlayer.volume(29); // Установить уровень громкости от 0 до 30

// Настройка серво
myServo.attach(SERVO_PIN);
myServo.write(0); // Установка серво в начальное положение

// Рисование циферблата
drawClockFace();

// Установить начальное время для обновления
targetTime = millis() + 1000;
}

void loop() {
if (millis() >= targetTime) {
targetTime += 1000; // Обновить targetTime для следующей итерации

timeClient.update();
unsigned long epochTime = timeClient.getEpochTime();
struct tm *ptm = gmtime((time_t *)&epochTime);

int currentHour = ptm->tm_hour % 12;
int currentMinute = ptm->tm_min;
int currentSecond = ptm->tm_sec;

// Удаление старого времени и отображение нового времени
updateClock(currentHour, currentMinute, currentSecond);

// Проверка и воспроизведение трека каждый час
if (currentMinute == 0 && currentSecond == 0) {
playHourlyTrack(currentHour == 0 ? 12 : currentHour);
}
}
}

void drawClockFace() {
tft.fillScreen(GC9A01A_BLACK);

// Отметки часов
for (int i = 1; i <= 12; i++) {
float angle = (i - 3) * 30; // Каждый номер по 30 градусов
int radius = 105; // Радиус для обычных цифр

// Увеличиваем радиус для цифр
if (i == 2 || i == 3 || i == 4 || i == 5 || i == 6) {
radius = 110;
}
if (i == 3) {
radius = 114;
}

int x = CENTER_X + radius * cos(angle * M_PI / 180);
int y = CENTER_Y + radius * sin(angle * M_PI / 180);

// Определяем цвет цифры
if (i == 12 || i == 3 || i == 6 || i == 9) {
tft.setTextColor(GC9A01A_GREEN);
tft.setTextSize(2);
} else {
tft.setTextColor(GC9A01A_WHITE);
tft.setTextSize(2);
}

tft.setCursor(x - 10, y - 10); // Смещение для центрирования цифры
tft.print(i);
}

// Позиции точек
for (int i = 0; i < 12; i++) {
float startAngle = (i - 3) * 30; // Начальный угол
for (int j = 1; j <= 5; j++) {
float angle = startAngle + j * 6; // Угловое смещение для точек (6 градусов между точками)
int x = CENTER_X + 111 * cos(angle * M_PI / 180); // Уменьшенный радиус для точек
int y = CENTER_Y + 111 * sin(angle * M_PI / 180); // Уменьшенный радиус для точек
tft.drawPixel(x, y, GC9A01A_WHITE); // Рисуем точку как одиночный пиксель
}
}
}

void updateClock(int hour, int minute, int second) {
// Углы для стрелок
float hourAngle = (hour % 12 + minute / 60.0) * 30.0;
float minuteAngle = minute * 6.0;
float secondAngle = second * 6.0;

// Координаты стрелок
int hourX = CENTER_X + 50 * cos((hourAngle - 90) * M_PI / 180);
int hourY = CENTER_Y + 50 * sin((hourAngle - 90) * M_PI / 180);
int minuteX = CENTER_X + 69 * cos((minuteAngle - 90) * M_PI / 180);
int minuteY = CENTER_Y + 69 * sin((minuteAngle - 90) * M_PI / 180);
int secondX = CENTER_X + 80 * cos((secondAngle - 90) * M_PI / 180);
int secondY = CENTER_Y + 80 * sin((secondAngle - 90) * M_PI / 180);

// Удаление предыдущих стрелок
eraseLine(CENTER_X, CENTER_Y, prevHourX, prevHourY, GC9A01A_BLACK);
eraseLine(CENTER_X, CENTER_Y, prevMinuteX, prevMinuteY, GC9A01A_BLACK);
eraseLine(CENTER_X, CENTER_Y, prevSecondX, prevSecondY, GC9A01A_BLACK);

// Рисование новых стрелок
tft.drawLine(CENTER_X, CENTER_Y, hourX, hourY, GC9A01A_WHITE); // Часовая стрелка
tft.drawLine(CENTER_X, CENTER_Y, minuteX, minuteY, GC9A01A_WHITE); // Минутная стрелка
tft.drawLine(CENTER_X, CENTER_Y, secondX, secondY, GC9A01A_RED); // Секундная стрелка

// Сохранение текущих координат стрелок
prevHourX = hourX;
prevHourY = hourY;
prevMinuteX = minuteX;
prevMinuteY = minuteY;
prevSecondX = secondX;
prevSecondY = secondY;
}

void eraseLine(int x0, int y0, int x1, int y1, uint16_t color) {
tft.drawLine(x0, y0, x1, y1, color); // Стираем линию, рисуя её цветом фона
}

void playHourlyTrack(int hour) {
myDFPlayer.volume(28); // Понижаем громкость перед воспроизведением
delay(100); // Короткая задержка для стабилизации
myDFPlayer.play(hour); // Воспроизведение трека

int delayTime = 0;

switch (hour) {
case 1:
delayTime = 2500;
break;
case 2:
delayTime = 3500;
break;
case 3:
delayTime = 4500;
break;
case 4:
delayTime = 5500;
break;
case 5:
delayTime = 6500;
break;
case 6:
delayTime = 8500;
break;
case 7:
delayTime = 9500;
break;
case 8:
delayTime = 10500;
break;
case 9:
delayTime = 11500;
break;
case 10:
delayTime = 13500;
break;
case 11:
delayTime = 14500;
break;
case 12:
delayTime = 15500;
break;
}

myServo.write(90); // Выдвижение кукушки

unsigned long startTime = millis();
while (millis() - startTime < delayTime) {
// Ничего не делаем, чтобы ждать
yield(); // Вызов yield() для предотвращения watchdog перезагрузок
}

myServo.write(0); // Убираем кукушку
delay(100); // Короткая задержка для стабилизации
myDFPlayer.volume(29); // Возвращаем громкость
}
 

vlad19950824@

New member
Я думаю все таки проблема желательно в коде , так как делай такой-же проект только с lcdдисплеем там все работало. Может какие библиотеки конфликтуют?!
 

vlad19950824@

New member
Результат такой , я отключал серво , зависание все ещё есть , всетаки проблема лежит в коде ,но вот только где
 

nikolz

Well-known member
вместо этого
switch (hour) {
case 1:
delayTime = 2500;
break;
case 2:
delayTime = 3500;
break;
case 3:
delayTime = 4500;
break;
case 4:
delayTime = 5500;
break;
case 5:
delayTime = 6500;
break;
case 6:
delayTime = 8500;
break;
case 7:
delayTime = 9500;
break;
case 8:
delayTime = 10500;
break;
case 9:
delayTime = 11500;
break;
case 10:
delayTime = 13500;
break;
case 11:
delayTime = 14500;
break;
case 12:
delayTime = 15500;
break;
}
можно написать это
int T[]={0,2500,3500,4500,5500,6500,8500,9500,10500,11500,13500, 14500,15500};
....
delay_Tine=T[hour];
============
вместо этого:
targetTime += 1000; // Обновить targetTime для следующей итерации
так:
targetTime =millis() +1000; // Обновить targetTime для следующей итерации
 

nikolz

Well-known member
if (currentMinute == 0 && currentSecond == 0)
а вы уверены, что это условие будет всегда без пропусков?
 

vlad19950824@

New member
Спасибо за совет попробую исправить. Я не знаю , вроде и работает но виснет. Я всякие варианты пробую ( я новичок самоучка , так сказать методом тыка делаю)
 
Сверху Снизу