Помогите новичку понять логику выполнения параллельных процессов
- Войдите на сайт для отправки комментариев
Всем привет. Я новичок, поэтому прошу не сильно пинать.
Решил сделать часы на 6 газоразрядных индикаторах и ардуино. Микросхема часов DS1307. При написании кода столкнулся со следующей проблемой. Если ардуина работает только с часами, то часы выдают нужную информацию без проблем. Цифры выводятся динамически, с помощью таймера MsTimer2.h тоже без проблем. Но одновременно и опрос часов раз в 1 секунду и вывод цифр не работает корректно. Проявляется проблема в том, что часть сигналов от часов приходят корректно, а часть нет. Пробовал различные варианты: в Loop делал опрос часов. Данные не всегда приходили корректные. Как я понимаю в момент общения с часами срабатывало прерывание по таймеру и данные не обрабатывались, пока выполнялось прерывание. Потом сделал опрос часов в самом прерывании, данные тоже не всегда приходят корректные.
Подскажите пожалуйста ответ на следующие вопросы:
1) Как правильно должна быть реализована логика работы микроконтроллера, который опрашивает различные датчики по различным шинам данных (SPI,I2C.1-Wire и т.д.) и при этом делает динамический вывод данных на дисплей с частотой например 100Гц каждого сегмента. То есть как обеспечить качественный опрос датчиков и одновременный вывод данных на индикаторы по прерыванию? Меня интересует именно последовательность выполнения кусков кода и в каких частях программы (Loop, прерывание) они должны быть реализованы. Скетч не прикладываю, потому-что пока необходимо понять саму логику и последовательность опроса датчиков.
2) Как понять сколько времени необходимо на опрос какого либо датчика по какой либо шине. То есть как называется параметр в даташите на датчик, который указывает величину времени необходимого на опрос датчика.
3) Как определить величину времени, необходимого на вывод информации в СОМ порт. То есть например есть строка Serial.println(unitsecond); СОМ порт работает на скорости 9600. Сколько времени потратит микроконтроллер на вывод int-ой переменной unitsecond? Как определить это время?
Очень буду рад ссылкам на соответствующие темы.
нечем дуино делать параллельные процессы - у контроллера одно ядро.
поэтому принцип работы программы следующий - бегаешь по кругу вечного цикла loop и что-то делаешь. пока делаешь что-то одно - остальное мирно ждёт своей очереди.
1. если критично точное исполнение, то народ привязывается к прерываниям на аппаратных таймерах, если нет - то лепишь программный таймер на миллис.
2. если сложно найти все слова time в документации на датчик, то зачем понимать - спросил датчик, датчик ответил, сохранил значение в переменную.
3. стоять с секундомером.
ты точно хоть один скетч написал сам?
а сами переменные модифицировать при помощи volatile
Пробовал
1noInterrupts();2// Ваш код3interrupts();и переменные которые используются в прерывании у меня volatile не помогает.
Согласен, что ардуина может выполнять только один процесс в один момент времени. Но под параллельными процессами я имел в виду, что например ардуина делает какие-то вычисления, потом происходит прерывание, она откладывает этот процесс и выполняет код в прерывании, потом возвращается и продолжает вычисления. То есть микроконтроллер не выполняет последовательно одну задачу пока ее не выполнит и переходит к следующей, а прыгает между задачами "как-бы" параллельно выполняя их. Согласен, что в терминологии я не очень подкован.
не помогает.
публикуй код с комментариями, в каком месте кода у тебя не помогает.
*Вставка программного кода в тему/комментарий
1. если критично точное исполнение, то народ привязывается к прерываниям на аппаратных таймерах, если нет - то лепишь программный таймер на миллис.
3. стоять с секундомером.
ты точно хоть один скетч написал сам?
1. Я и пытаюсь привязаться к таймеру 2, чтобы стабильно выводить цифры. Но что-то делаю неправильно. Поэтому и пытаюсь уточнить у специалистов, какая же последовательность кусков кода позволит корректно опрашивать датчиков.
3. Очень дельный совет :-)
скетчи писал, но очень простые. Проблема появилась именно с динамическим выводом с помощью прерываний
ну есть один вариант. http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-chainikov разберетесь, будет вам и решение. А нет, то не будет.
1. если критично точное исполнение, то народ привязывается к прерываниям на аппаратных таймерах, если нет - то лепишь программный таймер на миллис.
3. стоять с секундомером.
ты точно хоть один скетч написал сам?
1. Я и пытаюсь привязаться к таймеру 2, чтобы стабильно выводить цифры. Но что-то делаю неправильно. Поэтому и пытаюсь уточнить у специалистов, какая же последовательность кусков кода позволит корректно опрашивать датчиков.
3. Очень дельный совет :-)
скетчи писал, но очень простые. Проблема появилась именно с динамическим выводом с помощью прерываний
1. Например:
loop() {
1. Например:
loop() {
#include <iarduino_RTC.h> #include <MsTimer2.h> iarduino_RTC time(RTC_DS1307); #define clock 13 #define data 11 #define latch 8 #define DIG1 2 //анод А1 #define DIG2 3 //анод А2 #define DIG3 7 //анод А3 #define DIG4 6 //анод А4 #define DIG5 5 //анод А5 #define DIG6 4 //анод А6 byte hour = 0; byte dechour = 0; byte unithour = 0; byte minut = 0; byte decminut = 0; byte unitminut = 0; byte second = 0; byte decsecond = 0; byte unitsecond = 0; volatile short counterTime = 0; volatile byte cifra1 = 0; //значение выводимое на 1-й индикатор volatile byte cifra2 = 0; //значение выводимое на 2-й индикатор volatile byte cifra3 = 0; //значение выводимое на 3-й индикатор volatile byte cifra4 = 0; //значение выводимое на 4-й индикатор volatile byte cifra5 = 0; //значение выводимое на 5-й индикатор volatile byte cifra6 = 0; //значение выводимое на 6-й индикатор byte flagdig = 3; // флаг определяющий, какая цифра зажигается в данный момент byte flagtime = 1; // флаг определяющий, что на индикаторы выводится время byte flagtemp = 0; // флаг определяющий, что на индикаторы выводится температура byte flaghumidity = 0; // флаг определяющий, что на индикаторы выводится влажность byte g_digits[] = {0b01000000, 0b10000000, 0b01000000, 0b00100000, 0b00010000, 0b00001000, 0b00000100, 0b00000010, 0b00000001, 0b10000000, 0b00100000 }; // 0 1 2 3 4 5 6 7 8 9 DP void setup() { pinMode(clock, OUTPUT); pinMode(data, OUTPUT); pinMode(latch, OUTPUT); pinMode(DIG1, OUTPUT); pinMode(DIG2, OUTPUT); pinMode(DIG3, OUTPUT); pinMode(DIG4, OUTPUT); pinMode(DIG5, OUTPUT); pinMode(DIG6, OUTPUT); digitalWrite(latch, HIGH); digitalWrite(DIG1, LOW); digitalWrite(DIG2, LOW); digitalWrite(DIG3, LOW); digitalWrite(DIG4, LOW); digitalWrite(DIG5, LOW); digitalWrite(DIG6, LOW); Serial.begin(9600); // открываем последовательный порт, задаем скорость передачи данных 9600 бод time.begin(); shiftOut(data, clock, LSBFIRST, 0b00000000); shiftOut(data, clock, LSBFIRST, 0b00000000); shiftOut(data, clock, LSBFIRST, 0b00000000); shiftOut(data, clock, LSBFIRST, 0b00000000); digitalWrite(latch, HIGH); //"защелкиваем" регистр, тем самым устанавливая значения на выходах MsTimer2::set(5, SistemTimer); // 1000ms period MsTimer2::start(); Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время } void loop() { if (millis() % 1000 == 0) { // если прошла 1 секунда // Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время MsTimer2::stop(); time.gettime(); hour = time.Hours; Serial.print(hour); // выводим время minut = time.minutes; Serial.print(minut); // выводим время second = time.seconds; Serial.println(second); // выводим время dechour = hour / 10; Serial.print(dechour); // выводим десятки часов unithour = hour % 10; Serial.print(unithour); // выводим единицы часов decminut = minut / 10; Serial.print(decminut); // выводим десятки минут unitminut = minut % 10; Serial.print(unitminut); // выводим единицы минут decsecond = second / 10; Serial.print(decsecond); // выводим десятки секунд unitsecond = second % 10; Serial.println(unitsecond); // выводим единицы секунд Serial.println(g_digits[0]); // выводим единицы секунд MsTimer2::start(); } } void SistemTimer (void){ if (flagtime == 1){ cifra1 = dechour; cifra2 = unithour; cifra3 = decminut; cifra4 = unitminut; cifra5 = decsecond; cifra6 = unitsecond; } if (flagdig == 3){ //вывод по 2 цифры одновременно digitalWrite(DIG1, LOW);// выключаем анод DIG1 digitalWrite(DIG2, LOW);// выключаем анод DIG2 digitalWrite(DIG3, HIGH);// включаем анод DIG3 digitalWrite(DIG4, LOW);// выключаем анод DIG4 digitalWrite(DIG5, LOW);// выключаем анод DIG5 digitalWrite(DIG6, HIGH);// включаем анод DIG6 digitalWrite(latch, LOW); // устанавливаем синхронизацию "защелки" на LOW if ((cifra6 == 0)|| (cifra6 == 9)) { shiftOut(data, clock, LSBFIRST, g_digits[cifra6]); // Записываем информацию в регистр (сдвигаем данные на один регистр) shiftOut(data, clock, LSBFIRST, 0b00000000); // Записываем информацию в регистр (сдвигаем данные на один регистр) } if ((cifra6 > 0)& (cifra6 < 9)) { shiftOut(data, clock, LSBFIRST, 0b00000000); // Записываем информацию в регистр (сдвигаем данные на один регистр) shiftOut(data, clock, LSBFIRST, g_digits[cifra6]); // Записываем информацию в регистр (сдвигаем данные на один регистр) } shiftOut(data, clock, LSBFIRST, 0b00000000); // Записываем информацию в регистр (сдвигаем данные на один регистр) shiftOut(data, clock, LSBFIRST, 0b00000000); // Записываем информацию в регистр digitalWrite(latch, HIGH); //"защелкиваем" регистр, тем самым устанавливая значения на выходах } }если закомментировать вывод в сериал должно заработать стабильней
если закомментировать вывод в сериал должно заработать стабильней
Это понятно. Но во первых - вывод в сом порт я использую для отладки. То есть он мне необходим как воздух. А во вторых и это самое главное - это не решит саму проблему, а просто поможет приблизиться к результату. Но мне необходимо понять именно суть проблемы. Исходя из логики кода я не вижу что мешает делать качественный опрос часов. Прерывания остановили, опросили часы и вывели в сом монитр. Но ведь что-то же мешает. Значит что-то происходит. Но что именно я не могу понять.
Если я пойму что происходит, то я смогу попробовать решить эту проблему. А пока я не понимаю, что это за глюк то и устранить его не смогу.
если закомментировать вывод в сериал должно заработать стабильней
Это понятно. Но во первых - вывод в сом порт я использую для отладки. То есть он мне необходим как воздух. А во вторых и это самое главное - это не решит саму проблему, а просто поможет приблизиться к результату. Но мне необходимо понять именно суть проблемы. Исходя из логики кода я не вижу что мешает делать качественный опрос часов. Прерывания остановили, опросили часы и вывели в сом монитр. Но ведь что-то же мешает. Значит что-то происходит. Но что именно я не могу понять.
мне так и не удалось заставить Timer2 работать стабильно, разбираться пока не стал, обошёлся другими методами, но где пробегало, при вызове кода таймера надо запретить прерывания
мне так и не удалось заставить Timer2 работать стабильно, разбираться пока не стал, обошёлся другими методами, но где пробегало, при вызове кода таймера надо запретить прерывания
Скорее всего имелось в виду, что при опросе часов необходимо запретить прерывания по таймеру, чтобы полностью отработать опрос часов без всякого вмешательства из вне.
1. Например:
loop() {
Я бы по другому действия распределил.
Библиотеку таймера выкинуть - лишняя сущность здесь, по-моему. Настроить аппаратное прерывание каждую секунду от DS1307. В этом прерывании получать от неё время и запоминать его, больше ничего. В основном цикле выводить время с нужной периодичностью на индикаторы и в сериал.
И Ваше определение того, что "прошла секунда" (77 строка), мне кажется несколько некорректным.
1. если отключить всю индикацию, оставить только вывод в сериал - часы работают/читаются правильно?
2. я бы выкинул из
SistemTimer() всё, кроме установки какого-то флага - мол, очередной тик пришел.всю остальную работу с индикаторами вынес бы в луп.Я бы по другому действия распределил.
Библиотеку таймера выкинуть - лишняя сущность здесь, по-моему. Настроить аппаратное прерывание каждую секунду от DS1307. В этом прерывании получать от неё время и запоминать его, больше ничего. В основном цикле выводить время с нужной периодичностью на индикаторы и в сериал.
И Ваше определение того, что "прошла секунда" (77 строка), мне кажется несколько некорректным.
Аппаратное прерывание - хорошая идея. Но к сожалению реальность такова, что уже изготовлена и собрана плата. И к сожалению вывод с часов заведен на ногу без аппаратного прерывания. Поэтому необходимо попытаться программно решить проблему.
По поводу 77 строки - это стандартный скетч и комментарий из него же. Понятно что с millis() точно измерить секунду в обычном цикле не получится.
1. если отключить всю индикацию, оставить только вывод в сериал - часы работают/читаются правильно?
2. я бы выкинул из
SistemTimer() всё, кроме установки какого-то флага - мол, очередной тик пришел.всю остальную работу с индикаторами вынес бы в луп.1. Да часы работают как часы (без проблем). Извините за тавтологию.
2. Идея интересная. Буду пробовать. Но по логике ничего не будет мешать таймеру срабатывать во время опроса часов, что повлечет за собой битые данные. Также в Loop невозможно будет обеспечить стабильную частоту вывода на индикаторы.
Также в Loop невозможно будет обеспечить стабильную частоту вывода на индикаторы.
А зачем она Вам нужна? В прерывании должны выполняться действительно критичные действия. Отображение информации к этому совсем не относится. Ну неужели можно заметить, если один раз информация обновится не через 5, а через 8 миллисекунд? Я именно из таких же соображений предложил не размещать индикацию в прерывании.
Я бы по другому действия распределил.
Библиотеку таймера выкинуть - лишняя сущность здесь, по-моему. Настроить аппаратное прерывание каждую секунду от DS1307. В этом прерывании получать от неё время и запоминать его, больше ничего. В основном цикле выводить время с нужной периодичностью на индикаторы и в сериал.
И Ваше определение того, что "прошла секунда" (77 строка), мне кажется несколько некорректным.
скорее, изрядно некорректное.
стандартное millis()-prevmillis > 1000 было бы ладнее.
в теле программы много длинных сериалпринтов. вполне возможно, что программа точную секунду проскакивает.
А зачем она Вам нужна? В прерывании должны выполняться действительно критичные действия. Отображение информации к этому совсем не относится. Ну неужели можно заметить, если один раз информация обновится не через 5, а через 8 миллисекунд? Я именно из таких же соображений предложил не размещать индикацию в прерывании.
Код в Loop будет очень разрастаться. И не известно сколько вемени понадобится на один проход Loop. Если взять например 8 мс, то частота вывода каждого символа будет 1000/(8*3) = 42 Гц. А с учетом времени задержки на запись в сдвиговых регистрах и того меньше. Это уже возможно кто-то сможет заметить. Таймер же позволял не беспокоиться о такой проблеме.
Kinder, в Вашем случае можно обоитись без прерываний.
Попробуйте реализовать очередность событий как в скетче ниже
const word interval = 10;// 1 сек = 100 х 10 void setup(){ } void loop(){ //нам не нужно измерять интервалы > 1 мин. //поэтому достаточно word вместо unsigned long static word carrMillis = 0, prevMillis = 0; static byte counter = 0; carrMillis = word(millis()); if(carrMillis - prevMillis >= interval){ prevMillis += interval; printDispl();//каждые 10 мс switch (counter){ case 0: readRTC();//читаем RTC раз в сек break; case 1: //что-то делаем раз в сек break; case 2: //что-то делаем раз в сек break; // и так далее до 19 } counter ++; if(counter >= 100) counter = 0; } }//END loop() //========================= void printDispl(){ //обновляем инфу на одном индикаторе (по очереди) } //======================== void readRTC(){ }И отключать-включать прерывания правильней так
Попробовал вариант предложенный Pyotr. К сожалению стало хуже. И опять таже проблема. согласно этого кода я и близко не вижу что может влиять на опрос часов. Снова проверил часы. Работают четко.
Код покажите и что значит хуже?
#include <iarduino_RTC.h> #include <MsTimer2.h> iarduino_RTC time(RTC_DS1307); #define clock 13 #define data 11 #define latch 8 #define DIG1 2 //анод А1 #define DIG2 3 //анод А2 #define DIG3 7 //анод А3 #define DIG4 6 //анод А4 #define DIG5 5 //анод А5 #define DIG6 4 //анод А6 byte hour = 0; byte dechour = 0; byte unithour = 0; byte minut = 0; byte decminut = 0; byte unitminut = 0; byte second = 0; byte decsecond = 0; byte unitsecond = 0; volatile short counterTime = 0; volatile byte cifra1 = 0; //значение выводимое на 1-й индикатор volatile byte cifra2 = 0; //значение выводимое на 2-й индикатор volatile byte cifra3 = 0; //значение выводимое на 3-й индикатор volatile byte cifra4 = 0; //значение выводимое на 4-й индикатор volatile byte cifra5 = 0; //значение выводимое на 5-й индикатор volatile byte cifra6 = 0; //значение выводимое на 6-й индикатор byte flagdig = 3; // флаг определяющий, какая цифра зажигается в данный момент byte flagtime = 1; // флаг определяющий, что на индикаторы выводится время byte flagtemp = 0; // флаг определяющий, что на индикаторы выводится температура byte flaghumidity = 0; // флаг определяющий, что на индикаторы выводится влажность byte g_digits[] = {0b01000000, 0b10000000, 0b01000000, 0b00100000, 0b00010000, 0b00001000, 0b00000100, 0b00000010, 0b00000001, 0b10000000, 0b00100000 }; // 0 1 2 3 4 5 6 7 8 9 DP const word interval = 10;// 1 сек = 100 х 10 void setup() { pinMode(clock, OUTPUT); pinMode(data, OUTPUT); pinMode(latch, OUTPUT); pinMode(DIG1, OUTPUT); pinMode(DIG2, OUTPUT); pinMode(DIG3, OUTPUT); pinMode(DIG4, OUTPUT); pinMode(DIG5, OUTPUT); pinMode(DIG6, OUTPUT); digitalWrite(latch, HIGH); digitalWrite(DIG1, LOW); digitalWrite(DIG2, LOW); digitalWrite(DIG3, LOW); digitalWrite(DIG4, LOW); digitalWrite(DIG5, LOW); digitalWrite(DIG6, LOW); Serial.begin(9600); // открываем последовательный порт, задаем скорость передачи данных 9600 бод time.begin(); shiftOut(data, clock, LSBFIRST, 0b00000000); shiftOut(data, clock, LSBFIRST, 0b00000000); shiftOut(data, clock, LSBFIRST, 0b00000000); shiftOut(data, clock, LSBFIRST, 0b00000000); digitalWrite(latch, HIGH); //"защелкиваем" регистр, тем самым устанавливая значения на выходах // MsTimer2::set(5, SistemTimer); // 1000ms period // MsTimer2::start(); Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время } void loop() { //нам не нужно измерять интервалы > 1 мин. //поэтому достаточно word вместо unsigned long static word carrMillis = 0, prevMillis = 0; static byte counter = 0; carrMillis = word(millis()); if(carrMillis - prevMillis >= interval){ prevMillis += interval; printDispl();//каждые 10 мс switch (counter){ case 0: readRTC();//читаем RTC раз в сек break; case 1: //что-то делаем раз в сек break; case 2: //что-то делаем раз в сек break; // и так далее до 19 } counter ++; if(counter >= 100) counter = 0; } }//END loop() //========================= void printDispl(){ //обновляем инфу на одном индикаторе (по очереди) if (flagtime == 1){ cifra1 = dechour; cifra2 = unithour; cifra3 = decminut; cifra4 = unitminut; cifra5 = decsecond; cifra6 = unitsecond; } if (flagdig == 3){ //вывод по 2 цифры одновременно digitalWrite(DIG1, LOW);// выключаем анод DIG1 digitalWrite(DIG2, LOW);// выключаем анод DIG2 digitalWrite(DIG3, HIGH);// включаем анод DIG3 digitalWrite(DIG4, LOW);// выключаем анод DIG4 digitalWrite(DIG5, LOW);// выключаем анод DIG5 digitalWrite(DIG6, HIGH);// включаем анод DIG6 digitalWrite(latch, LOW); // устанавливаем синхронизацию "защелки" на LOW if ((cifra6 == 0)|| (cifra6 == 9)) { shiftOut(data, clock, LSBFIRST, g_digits[cifra6]); // Записываем информацию в регистр (сдвигаем данные на один регистр) shiftOut(data, clock, LSBFIRST, 0b00000000); // Записываем информацию в регистр (сдвигаем данные на один регистр) } if ((cifra6 > 0)& (cifra6 < 9)) { shiftOut(data, clock, LSBFIRST, 0b00000000); // Записываем информацию в регистр (сдвигаем данные на один регистр) shiftOut(data, clock, LSBFIRST, g_digits[cifra6]); // Записываем информацию в регистр (сдвигаем данные на один регистр) } shiftOut(data, clock, LSBFIRST, 0b00000000); // Записываем информацию в регистр (сдвигаем данные на один регистр) shiftOut(data, clock, LSBFIRST, 0b00000000); // Записываем информацию в регистр digitalWrite(latch, HIGH); //"защелкиваем" регистр, тем самым устанавливая значения на выходах } } //======================== void readRTC(){ time.gettime(); hour = time.Hours; Serial.print(hour); // выводим время minut = time.minutes; Serial.print(minut); // выводим время second = time.seconds; Serial.println(second); // выводим время dechour = hour / 10; Serial.print(dechour); // выводим десятки часов unithour = hour % 10; Serial.print(unithour); // выводим единицы часов decminut = minut / 10; Serial.print(decminut); // выводим десятки минут unitminut = minut % 10; Serial.print(unitminut); // выводим единицы минут decsecond = second / 10; Serial.print(decsecond); // выводим десятки секунд unitsecond = second % 10; Serial.println(unitsecond); // выводим единицы секунд Serial.println(g_digits[0]); // выводим единицы секунд }красными прямоугольниками выделено не корректное время. И они чаще, чем при использовании таймера2.
Строки 15-23 не нужны.
hour = time.Hours; ?? - есть time.Hours зачем ещё hour
25-31 уберите volatile
Со стандартной библиотекой RTC пробовали?
Строки 15-23 не нужны.
hour = time.Hours; ?? - есть time.Hours зачем ещё hour
25-31 уберите volatile
Со стандартной библиотекой RTC пробовали?
Строки 15-23 нужны. Потому что в этих переменных храню значение цифры, которую вывожу на индикатор. Для того чтобы зажечь например цифру 5 отправляется определенная комбинация битов в сдвиговый регистр и включается соответствующий катод индикатора. При этом цифре пять соответствует комбинация битов, которые находятся в таблице g_digits[] под номером пять. Таким образом, чтобы вывести определенную цифру мне необходимо определить эту цифру из данных полученных от часов. Для чего и служат переменные в строках 15-23.
hour - это переменная, которая хранит количество целых часов полученное от DS1307dechour =- это переменная, которая хранит количество десятков часовunithour =- это переменная, которая хранит количество единиц часови т.д.
volatile осталось от работы с таймером2. Не уверен, что это может влиять на работу часов.
Для работы с часами использовал только библиотеку iarduino_RTC.h. Подскажите пожалуйста название стандартной, а еще лучше проверенной библиотекой. С которой не было проблем.
"Снова проверил часы. Работают четко. " - меня терзают смутные сомненья...
Предлагаю:
loop() {
readRTC();Serial.println("==================");Serial.println();delay(200);
}
voidreadRTC(){// из #27
}Для проверки часов использую следующий код #include <iarduino_RTC.h> iarduino_RTC time(RTC_DS1307); void setup() { delay(300); Serial.begin(9600); time.begin(); } void loop(){ if(millis()%1000==0){ // если прошла 1 секунда Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время delay(1); // }результат меня устраивает. Нет ни пропущенных секунд, ни испорченных данных.
результат меня устраивает. Нет ни пропущенных секунд, ни испорченных данных.
при этом испорченные данные откуда-то появляются при разборе полученной от часов информации?
вот я и предлагаю проверить, без прерываний, индикации и т.п.
не нравится вариант из #32 - можно к скетчу из #33 после строки 13 добавить, например, строки 80 - 102 из #10.
и при нормальной нагрузке в цикле и пропущенные секунды появятся.
я бы выкинул из
SistemTimer() всё, кроме установки какого-то флага - мол, очередной тик пришел.всю остальную работу с индикаторами вынес бы в луп.А цветом Вы выделили специально, чтоб все видели - это вредный совет? Наверно так.
Почему вредный? Смотрим и сравниваем 2 варианта реализации.
1. Как у Вас, прерывание установка флага в лупе - вся остальная работа.
2. Просто в лупе проверяем аппаратный флаг переполнения соответствующего таймера (или просто, на миллисе отмеряем ) и выполняем всю работу если он установлен.
Что в них общего - что вся работа будет выполнена только тогда, когда луп докрутится до этого мест. Ни как не раньше. А худший прогноз - это максимальное время выполнения лупа.
Чем они различаются - в первом варианте время выполнения лупа еще и увеличилось на время обработки прерывания. Ну и код сложней разумеется в первом. А преимуществ перед 2 нет вобще.
ПС. Не помню кто на форуме продвигал эту дурь несусветную с установкой флажка в прерывании и обработкой в лупе, но практически всегда это просто глупость. За исключением случая, когда событие вызвавшее прерывание очень быстротечно, тогда флажок просто продлевает его, на время пока луп сможет активизироватся. Правильный стиль - обработчик прерывания выполняет работу быстро и завершается, если же ему нужно формировать временные интервалы, то он настраивает и запускает таймер и тоже завершается. А у таймера будет свой обработчик и он продолжит в том же стиле. Но это если луп неуспевает. В примере он все успевает, прерывания трогать не надо вобще.
результат меня устраивает. Нет ни пропущенных секунд, ни испорченных данных.
при этом испорченные данные откуда-то появляются при разборе полученной от часов информации?
вот я и предлагаю проверить, без прерываний, индикации и т.п.
не нравится вариант из #32 - можно к скетчу из #33 после строки 13 добавить, например, строки 80 - 102 из #10.
и при нормальной нагрузке в цикле и пропущенные секунды появятся.
Пробовал и такой вариант
прилагаю код
#include <iarduino_RTC.h> iarduino_RTC time(RTC_DS1307); byte hour = 0; byte dechour = 0; byte unithour = 0; byte minut = 0; byte decminut = 0; byte unitminut = 0; byte second = 0; byte decsecond = 0; byte unitsecond = 0; void setup() { delay(300); Serial.begin(9600); time.begin(); } void loop(){ if(millis()%1000==0){ // если прошла 1 секунда Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время time.gettime(); hour = time.Hours; Serial.print(hour); // выводим время minut = time.minutes; Serial.print(minut); // выводим время second = time.seconds; Serial.println(second); // выводим время dechour = hour / 10; Serial.print(dechour); // выводим десятки часов unithour = hour % 10; Serial.print(unithour); // выводим единицы часов decminut = minut / 10; Serial.print(decminut); // выводим десятки минут unitminut = minut % 10; Serial.print(unitminut); // выводим единицы минут decsecond = second / 10; Serial.print(decsecond); // выводим десятки секунд unitsecond = second % 10; Serial.println(unitsecond); // выводим единицы секунд delay(1); // } }Данные получаются корректные.
Я пользуюсь библиотекой DS1307new. Проблем не было. В IDE конечно не включена библа для RTC.
Можно ещё попробовать вывод через аппаратный SPI.