Ещё одни часы без RTS
- Войдите на сайт для отправки комментариев
Пт, 19/02/2016 - 18:06
Всем привет, я начинающий, в программировании чють больше нуля, решил я сделать себе наручные часы с 7ми сигментым индикатором, наковырял скеч с часиками, залил, показывают всё время 0012(точки как разделить часы-минуты пока не использую) упёрся в какое то глобльное незнание(( тыкните в место где что-то не так?
#include "SevSeg.h"
SevSeg myDisplay;
unsigned long timer;
int deciSecond = 0;
void setup()
{
int displayType = COMMON_CATHODE; //
int digit1 = 8; //Pin 1
int digit2 = 5; //Pin 10
int digit3 = 11; //Pin 4
int digit4 = 13; //Pin 6
int segA = 7; //Pin 12
int segB = 6; //Pin 11
int segC = 10; //Pin 3
int segD = 3; //Pin 8
int segE = 9; //Pin 2
int segF = 4; //Pin 9
int segG = 2; //Pin 7
int segDP= 12; //Pin 5
int numberOfDigits = 4;
myDisplay.Begin(displayType, numberOfDigits, digit1, digit2, digit3, digit4, segA, segB, segC, segD, segE, segF, segG, segDP);
myDisplay.SetBrightness(100);
timer = millis();
}
void loop() {
int n = 0;
int hours = 00;
int minutes = 00;
int elapsedMinutes = 0;
int seconds = 0;
char timeString[10];
sprintf(timeString, "%02d%02d", n);
myDisplay.DisplayString(timeString, 0);
unsigned long time = millis() - (elapsedMinutes * 60000);
seconds = ((time / 1000) % 60);
if (seconds > 60) {
seconds = 0;
minutes++;
elapsedMinutes++;
if (minutes >= 60) {
minutes = 0;
hours++;
if (hours > 23) {
hours = 0;
}
}
}
n = (hours * 100) + minutes;
}
Ну в странной логике вычисления часов минут секунд разбираться не охота, а вот для начала вынести переменные
40intn = 0;41inthours = 00;42intminutes = 00;43intelapsedMinutes = 0;44intseconds = 0;следует в глобальную секцию до loop() или сделать их static
После этого если и будет показывать хрень - то будем разбираться уже в странной логике.
Может кому пригодится, вот проверенное решение для данной задачи. Замечу, что у меня этот кусок кода задействован в скетчах периферийных устройств, которые периодически синхронизируются со временем основного устройства, которое имеет модуль RTC, который периодически синхронизируется с NTP-сервером, (в доме, который построил Джек ))) ). Также замечу, что часы без RTC - плохая идея, точность их не порадует. Впрочем, код :
// Имеем ряд глобальных переменных byte CurTimeHour = 0; byte CurTimeMin = 0; byte CurTimeSec = 0; unsigned long setClockpreviousMillis; // unsigned long Every1SecondTimer = 0; void loop() { // с периодичностью в секунду вызывается некая функция, которая, в том числе, контролирует переменные времени. if ( (millis() - Every1SecondTimer) > 1000 ) { RunEverySecond(); Every1SecondTimer = millis(); } } void RunEverySecond() { unsigned long setClockcurrentMillis = millis(); unsigned long setClockelapsedMillis += setClockcurrentMillis - setClockpreviousMillis; while ( setClockelapsedMillis > 999 ) { CurTimeSec++; if ( CurTimeSec > 59 ) { CurTimeMin++; CurTimeSec = 0; } if ( CurTimeMin > 59 ) { CurTimeHour++; CurTimeMin = 0; } if ( CurTimeHour > 23 ) { CurTimeHour = 0; } setClockelapsedMillis -= 1000; } setClockpreviousMillis = setClockcurrentMillis - setClockelapsedMillis; }Огоромное спасибо за код.
Я осознаю, что часы без RTС не точны, я хочу сделать наручные часы, о обойтись минимальной схемой... и паралельно попытатся разобратся в прогарммировании.
Так пусть же все Ваши попытки будут успешными (звучит как тост))).
P.S. Всё-таки RTC - Real Time Clock.
Здравствуйте Sr.FatCat, спасибо за совет, вынес переменные за loop(), но реакция прежняя статичная картинка 0012. Есле не трудно то подскадите код с паривльной логикой хотябы для отсчёта секунд, а я попробую разобратся с минутми и часами...
Так пусть же все Ваши попытки будут успешными (звучит как тост))).
P.S. Всё-таки RTC - Real Time Clock.
Спасибо, исправил.
Вот такой вариант на 16 битном таймере будет работать ещё более точно:
volatile uint8_t minut=0; volatile uint8_t chas=0; volatile uint8_t sec=0; void setup(){ Serial.begin(9600); TCCR1A=(1<<WGM11); //режим14 FAST PWM TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256 ICR1=62499; // (16000000MHz /div256) -1 = 1 раз в секунду TIMSK1=(1<<TOIE1); //разрешить прерывание } ISR (TIMER1_OVF_vect) { sec++ ; //инкремент переменной каждую секунду if (sec>59){sec=0; minut++; } if (minut>59){minut=0; chas++; } if (chas>23){chas=0;} } void loop(){ Serial.print(chas); Serial.write(':'); Serial.print(minut); Serial.write(':'); Serial.print(sec); Serial.println(); }...
Красивый у вас код, прям как из даташита к МК :)
Но по-моему, это несколько противоречит тому, что хочет ТС. Он хочет осмысленно написать простую программу.
Пока у него с осмысленностью простейших операций не очень. А тут одно деление на 256 чего стоит :)
2c0smo
выложите новый скетч с вынесенными переменными и с комментариями к строкам.
начиная со строки
timer = millis();
которые вы не используете ниже :)
и вставьте в 49 строку Serial.println(timeString); -посмотрите в мониторе тоже "0012"?
Sr.FatCat
#include "SevSeg.h" SevSeg myDisplay; //Cоздаём объект //Глобальные переменные unsigned long timer; int deciSecond = 0; void setup() { int displayType = COMMON_CATHODE; // Тип дисплея катод //декларируем пины подключения индикатора int digit1 = 8; //Pin 1 int digit2 = 5; //Pin 10 int digit3 = 11; //Pin 4 int digit4 = 13; //Pin 6 int segA = 7; //Pin 12 int segB = 6; //Pin 11 int segC = 10; //Pin 3 int segD = 3; //Pin 8 int segE = 9; //Pin 2 int segF = 4; //Pin 9 int segG = 2; //Pin 7 int segDP= 12; //Pin 5 int numberOfDigits = 4; //Количество сегментов индикатора 4 //что то для работы индикатора myDisplay.Begin(displayType, numberOfDigits, digit1, digit2, digit3, digit4, segA, segB, segC, segD, segE, segF, segG, segDP); myDisplay.SetBrightness(100);//100% яркость timer = millis(); //Возвращает количество миллисекунд с момента начала выполнения текущей программы } //Переменные для часов тоже из примера int n = 0; int hours = 00; int minutes = 00; int elapsedMinutes = 0; int seconds = 0; void loop() { char timeString[100]; //Используется для sprintf sprintf(timeString, "%02d%02d", seconds); //Запись значеия в строку с 2-мя лидирующими нулями myDisplay.DisplayString(timeString, 0); //Вывод значения на индиактор? Serial.println(timeString); //здесь странная логика вычисления временя из примера unsigned long time = millis() - (elapsedMinutes * 60000); seconds = ((time / 1000) % 60); if (seconds > 60) { seconds = 0; minutes++; elapsedMinutes++; if (minutes >= 60) { minutes = 0; hours++; if (hours > 23) { hours = 0; } } } n = (hours * 100) + minutes; }после добавления строки Serial.println(timeString); , что то стало вычистятся(не корректно конечно) но это уже прорыв!) см.видео ( https://yadi.sk/i/AqEbOD6PpApnz )
c0smo, в 54
должно быть
sprintf(timeString,"%02i%02i", hours, minutes);и все-таки не ясна конечная цель. Если вы хотите хоть как-то поизучать с/с++ то стоит как-то внимательнее, что ли примерыпосмотреть, книжки проглядеть от начала, хотя бы до середины.
А каждую строчку исправлять он-лайн как-то не очень эффективно. Я написал, что timer не используете, но вы так и не используете.
Да и дальше такой бред....
Спасибо, Sr.FatCat ,.... осознал что я ничо не понимаю )
Продолжил ковырять скеч и теперь всё работает. Хотя видно что примерно пару раз за 10 секунд, эти секунды перескакивают быстрее чем положенно, и думаю что время будет сильно улетать вперед. Думаю над коррекцией, вроде как можно сделать относительно частоты кварца, но сначала я прикручу к скечу кнопки настройки. А пока вот рабочий вариант.
#include "SevSeg.h" SevSeg myDisplay; void setup() { int displayType = COMMON_CATHODE; int digit1 = 8; //Pin 1 int digit2 = 5; //Pin 10 int digit3 = 11; //Pin 4 int digit4 = 13; //Pin 6 int segA = 7; //Pin 12 int segB = 6; //Pin 11 int segC = 10; //Pin 3 int segD = 3; //Pin 8 int segE = 9; //Pin 2 int segF = 4; //Pin 9 int segG = 2; //Pin 7 int segDP= 12; //Pin 5 int numberOfDigits = 4; myDisplay.Begin(displayType, numberOfDigits, digit1, digit2, digit3, digit4, segA, segB, segC, segD, segE, segF, segG, segDP); myDisplay.SetBrightness(100); } unsigned long lastTick = 0; unsigned int seconds = 1; unsigned int minutes = 0; unsigned int hours = 0; void loop() { char timeString[10]; sprintf(timeString, "%02d%02d", minutes, seconds); myDisplay.DisplayString(timeString, 0); if (millis() - lastTick >= 1000) { seconds++; if (seconds==60) {minutes++; seconds=0; } if(minutes==60) { hours++; minutes=0; } lastTick = millis(); } }маленькая подсказка: инициализировать время в setupможно через время компиляции скетча: системная константа __TIME__
Типа
RTC успешно реализуется на атмега8 - ставим тактирование от внутреннего осциллятора и подключаем часовой кварц.
здесь теория, даже с усыплением камня http://microcontrollerov.net/microcontrolleri/mega/AVR134-Chasy-Realnogo-Vremeni-na-osnove-Asinhronnogo-Tajmera
а, это то, что я использую для атмега8. где t - секунды
// volatile unsigned long t = 0; ISR (TIMER2_OVF_vect) {++t;} // обработка событий по прерыванию счётчика void setup() { /////////////////////////////////////////////////////////////////// cli(); // запрет прерываний глобально TIMSK &= ~(_BV(TOIE2) | _BV(OCIE2)); // отключение прерывания Таймера 2 ASSR |= _BV(AS2); // перевод Таймера 2 в асинхронный режим тактирования от кварцевого резонатора 32768Гц TCNT2 = 0x00; // начальная инициализация счётчика TCCR2 = 0x05; // установка коэффициента деления 128 OCR2 = 0x00; // совпадение с частотой 1 Гц while (ASSR & (_BV(TCN2UB) | _BV(OCR2UB) | _BV(TCR2UB))); // ждём готовности таймера TIMSK |= _BV(TOIE2); // разрешаем прерывание от Таймера 2 sei(); // разрешаем прерывания глобально /////////////////////////////////////////////////////////////////// } void loop() {}и, вдогонку, если не желается считать часы, минуты программно - ставим стрелочные индикаторы на PWM и радуемся тёплому ламповому времени
Спасибо примеры без RTC часов.