Зависают часы на DS1307 и индикаторе 4-чразрядном на TM1650 плюс Arduino UNO.
- Войдите на сайт для отправки комментариев
Пнд, 28/02/2022 - 16:00
В общем собрал, написал скетч, вроде работает, но постоянно виснет. Просто останавливается работа и молчек.
Начал ковырять с нуля. Оставил вообще только основу.
#include <Wire.h> #include <TM1650.h> #define OUTR 7 //Выход на реле UNO TM1650 d; unsigned long timer1 = 0; bool dot_state = false; int n = 0; void setup() { pinMode(OUTR, OUTPUT); Wire.begin(); Wire.setClock(400000); //RTC_init(); Serial.begin(115200); d.init(); d.setBrightness(TM1650_MIN_BRIGHT); d.displayOn(); } void loop() { if (millis() - timer1 >= 1000){ char line[5]; timer1 = millis(); sprintf(line, "%u", n); d.displayString(line); dot_state = !dot_state; d.setDot(3, dot_state); digitalWrite(OUTR, !dot_state); Serial.println(n); n++; } }
Вот модуль, при включении которого происходит зависание. Это я в свое время взял какую-то библиотеку для RTC и вынул оттуда только 2 функции практически. Уже много где его использую, просто подключаю к скечу. А тут почему-то не работает.
#define I2C_ADDR 0x68 void RTC_init() { uint8_t sec; // timeClient.begin(); //get second and CH bit Wire.beginTransmission(I2C_ADDR); Wire.write(byte(0x00)); Wire.endTransmission(); Wire.requestFrom(I2C_ADDR, 1); sec = Wire.read(); Wire.read(); //set second and clear CH bit Wire.beginTransmission(I2C_ADDR); Wire.write(byte(0x00)); Wire.write(sec & 0x7F); Wire.endTransmission(); } void get_RTC(uint8_t *sec, uint8_t *min, uint8_t *hour, uint8_t *day, uint8_t *month, uint16_t *year) { Wire.beginTransmission(I2C_ADDR); Wire.write(byte(0x00)); Wire.endTransmission(); Wire.requestFrom(I2C_ADDR, 7); *sec = bcd2bin(Wire.read() & 0x7F); *min = bcd2bin(Wire.read()); *hour = bcd2bin(Wire.read()); bcd2bin(Wire.read()); //day of week *day = bcd2bin(Wire.read()); *month = bcd2bin(Wire.read()); *year = bcd2bin(Wire.read()) + 2000; return; } void set_RTC(uint8_t sec, uint8_t min, uint8_t hour, uint8_t day, uint8_t month, uint16_t year) { uint8_t ch, d; if(year >= 2000) { year -= 2000; } //get CH bit Wire.beginTransmission(I2C_ADDR); Wire.write(byte(0x00)); Wire.endTransmission(); Wire.requestFrom(I2C_ADDR, 1); ch = Wire.read(); d = Wire.read(); if(ch & 0x80) //CH set? { ch = 0x80; } else { ch = 0x00; } //set time and date Wire.beginTransmission(I2C_ADDR); Wire.write(byte(0x00)); Wire.write(bin2bcd(sec) | ch); Wire.write(bin2bcd(min)); Wire.write(bin2bcd(hour)); Wire.write(bin2bcd(0)); Wire.write(bin2bcd(day)); Wire.write(bin2bcd(month)); Wire.write(bin2bcd(year)); Wire.endTransmission(); return; } void set_RTC(int sec, int min, int hour, int day, int month, int year) { return set_RTC((uint8_t)sec, (uint8_t)min, (uint8_t)hour, (uint8_t)day, (uint8_t)month, (uint16_t)year); } uint8_t bin2bcd(uint8_t val) { return val + 6 * (val / 10); } uint8_t bcd2bin(uint8_t val) { return val - 6 * (val >> 4); }
Посмотрите мастера. Я все-таки еще очень слабый программист на таких языках.
Это схема устройства. Две Attiny на схеме для печатной платы. Просто пока буду писать скетч, буду ее в калодку на переходнике вставлять. Идея включать свет по будильнику утром, гасить когда светло станет, включать когда стемнее и выключать по будильнику вечером.
А нет. Зависло и без RTC.
Может конечно контакты... Пока на макетном бредборде собрано. Вечером уже с почти печатные платы заберу и спаяю.
Но может и не контакт, а хрень в программе.
Wire.setClock ставил и по умолчанию 100000 и 50000 и вот сейчас 400000. Не влияет. Хотя при 400000 дольше всего проработало.
Что на дисплее при зависании ?
В принципе последнее число может остаться, а могут какие-то сегменты погаснуть или загорется лишние.
Заем Вы привели два скетча и ничего не пояснили? Первый виснет или нет? В нём есть очевидная ошибка, но, может, и не одна. Та, что я сразу вижу - буфер line слишком маленький, он должен быть как минимум 6 символов, а у Вас только 5.
Первй скетч это основа, которая очень редко, но, как оказалось, таки тоже зависает. Там видите закомментировано RTC_init() - это подключается второй файл с инициализацией RTC. Я уже написал выше, что год или 2 назад бился с RTC библиотеками для DS1307, все не стабильно они работали. В итоге надергал только нужные строки из одно, убрал запуск Wire и так у меня во многих скетчах работает.
Пояснить.
Ну второй ясно - работа с DS1307.
Первый просто вывод на экран с интервалом в 1 секунду числа n, запятой в последнем разряде и мигание светодиодом через релюшку (в конце концов там будет коммутироваться 220В).
Вроде все.
А что за ошибка?
25 строка
25 строка
А что не так? Я вот с чарами никак до конца не разберусь. Но при компиляции ошибку не выдает.
Если вы о том, что может быть больше 4 символов, ну так это ясно, просто больше полутора тысяч пока не насчитывает и поэтому виснет. В конце концов то там просто время будет из 4 знаков.
А что за ошибка?
А Вы мой пост читали?
Та, что я сразу вижу - буфер line слишком маленький, он должен быть как минимум 6 символов, а у Вас только 5.
Куда заливаете скетч ?
А Вы мой пост читали?
Ой! То что ошибка увидел, а какая - нет. Я думал, что надо размер массива ставить сколько символов максимально плю 1, т.е. максимально 4 символа +1 ставим 5. Хорошо, сейчас 6 поставлю. Но не из-за этого ведь виснет?
Куда заливаете скетч ?
Пока Arduino UNO использую. Как все отработаю буду под Attiny передлывать.
А что с подтяжкой ? На схеме вроде есть, а на деле ?
А что с подтяжкой ? На схеме вроде есть, а на деле ?
На деле тоже есть. Только не 10кОм, а 4,7кОм. Это я после мучений с датчиками AHT10 решил поставить. Хотя раньше всегда 10 ставил.
На плату распаял вчера, не виснут. но часы не работают. Похоже DS1307 сдохла. 7 нога, которая в принципе никуда не идет на землю звонится на коротко. Сегодня вечером другую микруху впаяю и посмотрю.
Народ, прошу помощи. Часы запустить не удалось. Микросхему перепаял, сопротивление резисторов проверил, цепи вроде тоже все проверил. Да их там немного. Только кварц пока не трогал, но что ему будет? Само устройство Wire видит, но часы не ходют, показывают время 165:165. При этом i2c я так понимаю работает, т.к. индикатор работает и картинка на него передается правильная. Куда можно покопать?
часы не ходют, показывают время 165:165.
выложите последний код после всех правок
Основной модуль
Модуль Wire
Модуль RTC
У меня есть 1307, которая стоит с момента покупки.
У меня тоже есть. В 2 устройствах работает. А тут почему-то не пашет.
У меня сейчас два устройства в разработке. Метеостанция из соседней темы и этот включатель\выключатель. Сверил сигналы осцилографом на ногах DS1307. Одинаковые. Но одна не работает, а другая работает. Схемы копировал в EasyEDA, там же платы разводил. Делал платы у JLCPCB. Т.е. в схеме все один в один. В скетчах к стати тоже одинаковые блоки для Wire и RTC
Основной модуль
Модуль Wire
Модуль RTC
не вижу, где вы эти модули подключаете в основном коде. Как называются файлы?
Строки 16 и 17 основного кода. Это вызов инициализирующих процедур. Модули в виде файлов ino лежат в одной папке с основным файлом.
Модули в виде файлов ino лежат в одной папке с основным файлом.
а нормально, через .h файлы - сделать не судьба?
Модули в виде файлов ino лежат в одной папке с основным файлом.
а нормально, через .h файлы - сделать не судьба?
На самом деле все основные настройки и подключение библиотек в set.h файле, а в основном сверху стоит #include set.h
А по большому счету какая разница .ino или .h? Те что .ino лежат в одной папке прописывать нигде не надо. Ну и с другой стороны из-за этого ведь не может не работать время?
Может чего подскажет. Попробовал поменять местами SCL и SDA. Индикатор работать перестал. Часы так же показывают 165:165. Да, пока подключено к UNO SDA-A4, SCL-A5.
Запитал не от компьютерного USB, а от БП 2А для моего смартфона Huawei. Ситуация не изменилась.
Часы так же показывают 165:165.
вас это не удивляет? Или на двух других аналогичных проектах у вас тоже часы 165 минут показывали?
Очевидно, что проблема не в том. что "один из DS1307 не работает, а другой работает", а в кривом коде. Даже если у вас модуль RTC нерабочий и отдает неверное время или не отдает никакого - программа не должна показывать очевидную чушь на экране.
Это понятно. Я так понимаю, что для этого вы и попросили меня код выложить. Собственно я с этого и начал, спросил что не так в моем коде.
И все-таки код в устройстве где часы работают и где не работают - один. Ну код в файлах Wire.ino и RTC.ino. Я их просто копирую из проекта в проект.
И еще вопрос. Стока #define I2C_ADDR 0x68 задает адрес 0х68 для RTC? Просто если я его меняю на другой, он либо не меняется, либо Wire не видит его.
Стока #define I2C_ADDR 0x68 задает адрес 0х68 для RTC?
нет, это адрес, куда вы посылаете запросы. С адресом RTC он может и не совпадать.
Кстати, посмотрел внимательнее код - у вас вывода на дисплей нет вообще. Вы где свои 165:165 видите - в Сериал?
И еще - в вашем модуле Wire у вас. кроме Wire.begin() - целиком встроен i2c сканер. Это что. у вас и в готовых проектах так же - при каждом запуске шина будет сканироваться?
Кстати, посмотрел внимательнее код - у вас вывода на дисплей нет вообще. Вы где свои 165:165 видите - в Сериал?
Да, время на дисплей не выводится. Смотрю в Serial.
Нет. Это только во время отладки.
И да. Какая-то ошибка в коде. Нашел скетч, которым когда-то начинал разбираться с RTC. добавил туда свой индикатор и все заработало!
Но теперь еще больше непонятно где ошибка? Ведь эти файлы я действительно не трогаю, а просто копирую в новый проект.
Но теперь еще больше непонятно где ошибка? Ведь эти файлы я действительно не трогаю, а просто копирую в новый проект.
не утверждаю, что проблема в этом - но создание кода из нескольких ino файлов лично я считаю кривым колхозом. Основная проблема в том, что вы никогда не знаете, в каком порядке Ардуино ИДЕ склеит эти файлы в один и где поместит обьявления функций.
кстати. а вот эти функции вы откуда взяли?
я еще сразу обратил на них внимание - они совершенно нелогичные. Почему верхний разряд домножаем на шесть?
Сейчас глянул у вас по ссылке либу iarduino_RTC.h - и там преобразование другое, множитель 10, как и должно быть.
Я вас понял. Тогда вытекающий из этого вопрос. Я правильно понял, что .h файлы надо обязательно объявлять перед Setup?
И сейчас подробнее посмотрел и... оказывается я соврал. Рабочий вариант RTC немного другой. там время из интернета берется. Собственно я эти функции и вырезал. Сейчас попробую поподробнее посмотреть, может чего лишнее вырезал.
кстати. а вот эти функции вы откуда взяли?
я еще сразу обратил на них внимание - они совершенно нелогичные. Почему верхний разряд домножаем на шесть?
Сейчас глянул у вас по ссылке либу iarduino_RTC.h - и там преобразование другое, множитель 10, как и должно быть.
Из какой-то библиотеки по RTC. Давно было, больше года назад. Сейчас уже не вспомню из какой.
Сейчас немного работу разгребу и займусь поиском ошибки. С тестовой прогой часы уже час почти ходят и не виснут.
Может к стати в этом проблема и в другом моем скетче из другой темы?
кстати, на мой взгляд в верхней функции
вообще несколько ошибок. Мало того что множитель шесть непонятно откуда - так еще и деление на разряды неверное
должно быть как-то так:
Нашел из какой библиотеки я свою обработку RTC взял.
RTClib-1.4.1
смотрите iarduino_RTC.h - там другие формулы.
Не берусь сказать, какой из вариантов более правильный, но судя по тому. что тестовый скетч от iarduino_RTC.h работает - я бы пользовался ей.
Да, я тоже так думаю. И в другом скетче метеостанции, тоже попробую заменить. МОжет он виснуть перестанет.
Тут надо собирать на стороне макет и в отладку погружаться. Слишком странная плавающая ошибка.
В общем продолжил я разбираться с новой(старой) библиотекой и решил темы не плодить, а спросить здесь же.
Снова я проигрываю войну переменной типа char. Ну никак не победю ее. И вот сейчас. В этой библиотеке есть типа функция мигания тем разрядом, который ты менячешь. Но как это не работало год назад, так и не работает, хоть и вышла новая версия библиотеки. А где написать разработчику, так я и не нашел.
Так вот когда надо мигать вторым разрядом на дисплее (минутами) у меня все не плохо получилось. Не знаю на сколько грамотно, но работает.
А вот когда надо моргать первым разрядом - проблема. Сначала я попытался тем же путем пойти
Но вот беда, переменная mn не чистится и вытоге мы получаем длинную строку на выходе.
Тогда я попробовал так:
Но тут другая печаль. В итоге на экран должгно выдаваться " 35". В Serial так и выдается, а вот на экран выходит только минуты. Т.е. текущее время 1535, на экране мигает то 1535, то 3535. т.е. 2 первых пробела пропадают!
Пол дня уже бьюсь! Никак не понимаю.
Что вот это
что это
и это
какая-то редкостная чушь...
откуда вы эту траву берете....
В первом случае надо к двум пробелам добавить значение минут. Делаю это потом с помощью strcat(mn, mn1).
Во втором случае я где-то на просторах инета нашел, что так очищается char переменная.
mn[0] = (
char
)0;
Сначала поймите простую вешь - строка в формате char* - это просто массив байт с нулем на конце. там нет никакого шаманства, этот массив ничем не отличается от какого-нить такого
ваше время 15:35 в массиве выглядит так
а чтобы выключить часы. нужно сделать так
То есть надо ЗАМЕНЯТЬ символы, а не добавлять! Команда strcat - добавляет
Т.е.
И выводить mn на дисплей? Сейчас попробую!
Точнее mn[0] = 20 и mn[1] = 20
Точнее mn[0] = 20 и mn[1] = 20
тогда уж не mn[0] = 20, а mn[0] = 0х20 или mn[0] = 32
Но лучше пишите mn[0] = ' ' - не ошибетесь
Точнее mn[0] = 20 и mn[1] = 20
тогда уж не mn[0] = 20, а mn[0] = 0х20 или mn[0] = 32
Но лучше пишите mn[0] = ' ' - не ошибетесь
Я почему начал коды подбирать? Потому что написал mn[0] = " " и получил не пробел, а | скорее всего или 1. Оказывается есть разница в каких кавычках писать, потому что mn[0] = ' ' действительно дало пробел!
Огромное спасибо!
Но война не закончена. теперь мне предстоит преобразовывать char в int и обратно, чтобы настраивать часы, т.е. прибавлять или отнимать минуты, часы, дни, месяцы при установке часов!
Зачем? Всё должно быть в интах, чары нужны только для вывода на экран.
Зачем? Всё должно быть в интах, чары нужны только для вывода на экран.
Да, там вроде в библиотеке есть обращение к минутам, часам как к int. Ща почитаю.
Народ, подскажите, вроде со всем разобрался. Есть у меня две установки, которые хранятся в eeprom. Но собственно не важно где они хранятся. В общем есть одна переменная час включения и одна переменная минуты включения. Скажем 7 часов 0 минут. Две byte переменные 7 и 0. Мне надо вывести на экран соответственно 0700. Вот последнее мое изыскание, но не работает:
Выводит чушь на экран. Вот не складывается у меня с символьными массивами! Сегодня весь день в перерывах работы читал про работу с char. Видно не начитал.