Читайте в uint8_t. При выводе в serial используйте BIN и обозначьте где какой регистр.
К примеру:
Control 1000110
Status 10
или
0x0E бла....
0x0F лала....
P.S.
Быть может вместо "магического" значения 0x5D нагляднее использовать B1011101?
Частично разобрался. При отключении Vcc возникает низкий уровень на выводе SQW, который и вызывает прерывание. Процесс зацикливается.
Однако, если програмно с помощью флага исключить это ложное срабатывание, оказывается что прерывание по будильнику по прежнему не работает. То ли я косячу, то ли действительно ни i2c ни будильники от Vbat не работают на самом деле. Control 01011101
Подайте питание на модуль напрямую и померяйте ток, скорее всего без передачи по I2C он будет не такой большой. 250мкА - это скорей всего во время передачи данных
При отключении Vcc возникает низкий уровень на выводе SQW, который и вызывает прерывание.
При исправном питании от Vbat такого быть не должно.
Цитата:
ни i2c ни будильники от Vbat не работают
I2C, при питании от Vbat, не проверял, а Alarm2 дергает согласно настройке - от 1-й до 1440 минут
Цитата:
Control 01011101
Желательно также Status
Update
Снимите начальные состояния Control и Status сразу после включения, до всех действий с RTC, сразу после соединения по I2C и перед выключением. Они совпадают?
При исправном питании от Vbat такого быть не должно.
Батарейка 3.7в показывает.
Тут вот что нашел:
Цитата:
когда вы питаете модуль от батарейки (без внешнего источника питания), то линии SDA, SCL, INT/SQW, 32kHz не подтягиваются к положительному полюсу батарейки, так как на модуле стоит диод VD1, и соответственно передача данных не возможна.
Необходимо подтянуть эти линии через резисторы со стороны Arduino к положительному полюсу источника питания Arduino. Но при этом модуль будет подпитываться через эти резисторы и на линию питания от батарейки переключаться не будет, чтобы этого избежать надо удалить подтягивающие резисторы R1-R4 на модуле часов.
Кстати, диод я таки выпаял, без него все равно 3-4 мА получается. Правда еще LED остался.
Посыпаю голову пеплом, ввёл в заблуждение. Посмотрел свою схему. Сигнал /SQW от DS3231 поступает на компаратор MAX983ESA+, который постоянно подключен к Vcc и управляет остальными ключами питания. Моё утверждение
Feofan пишет:
При исправном питании от Vbat такого быть не должно
Можно пробовать ставить/перекидывать резистор подтяжки SQW на Vbat. Но в этом случае вполне ожидаем ток Vbat через защитные диоды MCU (соединение SQW <-> MCU).
Потребление в спящем режиме всей системы 4.5 мА. Если убрать светодиод и стабилизатор напряжения с ардуины, или использовать другой МК, должно выйти достаточно экономично. Возможно еще надо выпаять на RTC подтягивающий к земле резистор SQW.
Потребление в спящем режиме всей системы 4.5 мА. Если убрать светодиод и стабилизатор напряжения с ардуины, или использовать другой МК, должно выйти достаточно экономично. Возможно еще надо выпаять на RTC подтягивающий к земле резистор SQW.
Если уберете подтяжку SQW - оставите "в воздухе" пин на который повешены прерывания - не лучшая идея. Нужно убрать цепь подзарядки батарейки часов. Ардуину можно взять Pro Mini, она без стабилизатора напряжения. Светодиоды везде повыкусывать.
Судя по коду ардуина просыпается каждую секунду, зачем? Раз в час для вашей задачи было бы достаточно.
Да, действительно стабилизатор там есть, зато нет usb-uart микросхемы. И есть версия на 3,3 вольта, которая может питаться от двух батареек. RTC, кстати тоже.
За/против Attiny не скажу, не пробовал. ProMini, в отличие от Nano, не имеет встроенного USB-TTL - соответственно потребуется адаптер USB-TTL или программатор USBasp.
А можете подсказать, как по i2c записать/считать один бит?
В случает с портом, это PORTB |= (1 << PB5); например. А с i2c как работать? Полностью считать байт, применить маску и записать обратно? больше десятка строчек кода?
А можете подсказать, как по i2c записать/считать один бит?
В случает с портом, это PORTB |= (1 << PB5); например. А с i2c как работать? Полностью считать байт, применить маску и записать обратно? больше десятка строчек кода?
i2c рассчитан на передачу целого количества байтов. Соответственно, записать/считать один бит нельзя. Но можно трактовать считанный байт как команду на изменение бита.
"как работать?" - зависит от того, что Вам нужно. Аналогия с портом - неуместна, т.к. порт находится на том же устройстве, а i2c соединяет разные устройства.
Ладно, думал можно упростить, значит не выйдет. Не принципиально.
Есть более важный вопрос.
Итак, у меня сейчас Pro Mini, который засыпает и просыпается по прерыванию от ножки SQW c RTC. Теперь мне надо сделать 2 или 4 кнопки, чтобы можно было корректировать время в RTC без подключения к компу. И надо, чтобы нажатие на эти кнопки тоже будило МК. Как это грамотно реализовать?
В голову приходит только связать пины кнопок с пином прерывания через диоды, чтобы сигнал шел только в одну сторону. Ну и программно при пробуждении проверять, какая кнопка была нажата, или SQW сработало.
Как вариант - организовать цикл while в сетап, который будет работать при наличии единицы на каком нибудь пине. К этому пину прицепить тумблер или кнопку с фиксацией. Замыкаем тумблер и рестартим ардуино.
Ну вот, скетч работает как и хотелось. Итого, на сегодняшний момент, PRO Mini, DS3231, TM1637 ( все-таки решил, что дисплей нужен ), две кнопки для коррекции времени. В режиме простоя потребление 250 мкА, но это я еще стабилизатор не обрезал. Извиняюсь, что использовал для кнопок библиотеку Guver, но она хорошо подходит и понятно описана. PCInt отлично будят из режима PowerDown. Скетч не вышел за пределы 8кБ, но по количеству выводов я в Attiny85 не вписываюсь. Сейчас работает на ATMega88.
Можно навскидку ткнуть, где можно наиболее просто оптимизировать код? Сейчас занимает 7700 байт, а хотелось бы еще небольшой функционал прикрутить. Использование регистров вместо pinMode, digitalWrite дает 40 байт. Отказ от PCINT дает 700 байт, тогда можно повесить одну из двух кнопок на INT1, но вторая кнопка будить не будет. Некритично, но не красиво. Есть еще несложные варианты?
Ну зачем же так. Чтобы при уменьшении минут не получать отрицательные значения и можно было использовать тип byte, сначала прибавляю 10, потом отнимаю обратно. Но экономии это особо не дало.
Ну зачем же так. Чтобы при уменьшении минут не получать отрицательные значения и можно было использовать тип byte, сначала прибавляю 10, потом отнимаю обратно.
поясните, как это. Зачем вообще в коде часов отнимать что-то от минут?
если ТС расскажет мне, что он тут пытался изобразить - я думаю мы сократим эту процедуру до 3-5 строк. Вот и получится та "оптимизация", которой он жаждал
сделай кнопки аналоговыми и повесь на 1 аналоговый вход.
Так они же тогда будить не будут?
А можно ссылочку на ваш TM1637?
Конечно, код наверно не блещет. Кнопки нужны для установки/коррекции времени часов. Соответственно, если минут 00, при нажатии на кнопку (-) будет отрицательное значение. А функция с проверкой minutechange() включается только потом. Все для того чтобы использовать тип byte вместо int. Но, действительно, выигрыш копеечный, а код читается плохо.
если ТС расскажет мне, что он тут пытался изобразить - я думаю мы сократим эту процедуру до 3-5 строк. Вот и получится та "оптимизация", которой он жаждал
После установки минут, если минут больше 60 - прибавляем 1 час. минуты сбрасываем на - 60. (не на ноль, так как они могут меняться с шагом 1 и с шагом 10).
Дальше, если часов больше 23, то часы сбрасываем на 0.
Ой, сам туплю... Почему int8_t не взяли вместо int? - размер как у байта, а при этом не понадобилось бы вся эта пляска с отслеживанием перехода через ноль
Спасибо, но у меня другая задача. Дисплей не должен отображать время постоянно. Он нужен только чтобы корректировать время в RTC. Кнопки плюс и минус меняют время, потом происходит запись этого времени в RTC. Поэтому значение на дисплее меняется только кнопками. При нажатии (+), минуты начинают прибавляться, если доходит до 60, прибавляется час. При нажатии (-) в обратную сторону.
Вот, кстати, пробую вашу библиотеку. Не могу понять как правильно полностью включать и выключать дисплей ( именно полностью, чтобы не сажать батарейку). Чтобы его отключить, надо установить LOW на 5V, CLK, DIO. Чтобы включить 5V подаю обратно, но команда Display.PrintTime() включает его на долю секунды и он снова гаснет. Как включить правильно?
Библиотека 150 байт сэкономила, да и код получше читается. Спасибо.
Вот, кстати, пробую вашу библиотеку. Не могу понять как правильно полностью включать и выключать дисплей ( именно полностью, чтобы не сажать батарейку). Чтобы его отключить, надо установить LOW на 5V, CLK, DIO. Чтобы включить 5V подаю обратно, но команда Display.PrintTime() включает его на долю секунды и он снова гаснет. Как включить правильно?
Нинаю, передо мной такая задача не стояла. Ну я бы пустил 5В на дисплей через транзистор и отключал бы его, перед сном. Ну и перед сном можно сделать Display.Clear() и перевести на вход CLK и DIO. При пробуждении проделать всё не совсем в обратном порядке: снфчала подать +5 на экран, потом перевести ноги CLKи DIO на выходы, а потом уже вызывать Display.PrintTime()
Читайте в uint8_t. При выводе в serial используйте BIN и обозначьте где какой регистр.
К примеру:
Control 1000110
Status 10
или
0x0E бла....
0x0F лала....
P.S.
Быть может вместо "магического" значения 0x5D нагляднее использовать B1011101?
P.P.S.
И про задержку kost82 говорил, >=20ms.
Частично разобрался. При отключении Vcc возникает низкий уровень на выводе SQW, который и вызывает прерывание. Процесс зацикливается.
Однако, если програмно с помощью флага исключить это ложное срабатывание, оказывается что прерывание по будильнику по прежнему не работает. То ли я косячу, то ли действительно ни i2c ни будильники от Vbat не работают на самом деле. Control 01011101
Подайте питание на модуль напрямую и померяйте ток, скорее всего без передачи по I2C он будет не такой большой. 250мкА - это скорей всего во время передачи данных
Update
Снимите начальные состояния Control и Status сразу после включения, до всех действий с RTC, сразу после соединения по I2C и перед выключением. Они совпадают?
При исправном питании от Vbat такого быть не должно.
Батарейка 3.7в показывает.
Тут вот что нашел:
когда вы питаете модуль от батарейки (без внешнего источника питания), то линии SDA, SCL, INT/SQW, 32kHz не подтягиваются к положительному полюсу батарейки, так как на модуле стоит диод VD1, и соответственно передача данных не возможна.
Необходимо подтянуть эти линии через резисторы со стороны Arduino к положительному полюсу источника питания Arduino. Но при этом модуль будет подпитываться через эти резисторы и на линию питания от батарейки переключаться не будет, чтобы этого избежать надо удалить подтягивающие резисторы R1-R4 на модуле часов.
Кстати, диод я таки выпаял, без него все равно 3-4 мА получается. Правда еще LED остался.
Посыпаю голову пеплом, ввёл в заблуждение. Посмотрел свою схему. Сигнал /SQW от DS3231 поступает на компаратор MAX983ESA+, который постоянно подключен к Vcc и управляет остальными ключами питания. Моё утверждение
Фото готового изделия будет?
Пока до этого далеко. Принципиально хочу добиться, чтобы rtc работало от батарейки.
Они не будут так работать. Судя по схеме батарейка соединена только с микросхемой DS3231, вся переферия питается от vcc
Можно пробовать ставить/перекидывать резистор подтяжки SQW на Vbat. Но в этом случае вполне ожидаем ток Vbat через защитные диоды MCU (соединение SQW <-> MCU).
Совершенно точно работало от батарейки в режиме прямоугольного сигнала.
Не получается пока организовать процесс прерывание-вкл vcc-сброс бита-выкл vcc
Посмотрите схему от kost82 - без внешней подтяжки к Vcc оно не "сигналит".
Arduino должна спать и пробуждаться по прерыванию от SQW?
Вроде заработало. Сделал таки внешнюю подтяжку SQW к Vcc. Внутренней подтяжки оказалось недостаточно.
Потребление в спящем режиме всей системы 4.5 мА. Если убрать светодиод и стабилизатор напряжения с ардуины, или использовать другой МК, должно выйти достаточно экономично. Возможно еще надо выпаять на RTC подтягивающий к земле резистор SQW.
Потребление в спящем режиме всей системы 4.5 мА. Если убрать светодиод и стабилизатор напряжения с ардуины, или использовать другой МК, должно выйти достаточно экономично. Возможно еще надо выпаять на RTC подтягивающий к земле резистор SQW.
Если уберете подтяжку SQW - оставите "в воздухе" пин на который повешены прерывания - не лучшая идея. Нужно убрать цепь подзарядки батарейки часов. Ардуину можно взять Pro Mini, она без стабилизатора напряжения. Светодиоды везде повыкусывать.
Судя по коду ардуина просыпается каждую секунду, зачем? Раз в час для вашей задачи было бы достаточно.
Если уберете подтяжку SQW - оставите "в воздухе" пин на который повешены прерывания
Я же написал, что SQW подтянут резистором к Vcc ардуины. А через резистор подтяжки к земле со стороны RTC будет утекать ток на питание микросхемы RTC.
Нужно убрать цепь подзарядки батарейки часов.
Уже.
Ардуину можно взять Pro Mini, она без стабилизатора напряжения.
Таки она со стабилизатором, который к тому же потребляет ток даже при питании по Vcc.
Судя по коду ардуина просыпается каждую секунду, зачем? Раз в час для вашей задачи было бы достаточно.
Разумеется это только в отладочных целях.
Да, действительно стабилизатор там есть, зато нет usb-uart микросхемы. И есть версия на 3,3 вольта, которая может питаться от двух батареек. RTC, кстати тоже.
Сорри, к конечно резистор к Vcc.
Именно это и имел ввиду.
Как ожидаемо выяснилось, если подтянуть к Vcc ардуины SDA и SCL, то можно и вообще не подавать питание на RTC.
Как думаете лучше будет, выковыривать лишнее из Pro Mini, или взять Attiny85? Есть шанс уложиться в в 8кБ, (сейчас 3.5 кБ).
За/против Attiny не скажу, не пробовал. ProMini, в отличие от Nano, не имеет встроенного USB-TTL - соответственно потребуется адаптер USB-TTL или программатор USBasp.
Или прошить при помощи другой ардуины с USB
А можете подсказать, как по i2c записать/считать один бит?
В случает с портом, это PORTB |= (1 << PB5); например. А с i2c как работать? Полностью считать байт, применить маску и записать обратно? больше десятка строчек кода?
А можете подсказать, как по i2c записать/считать один бит?
В случает с портом, это PORTB |= (1 << PB5); например. А с i2c как работать? Полностью считать байт, применить маску и записать обратно? больше десятка строчек кода?
i2c рассчитан на передачу целого количества байтов. Соответственно, записать/считать один бит нельзя. Но можно трактовать считанный байт как команду на изменение бита.
"как работать?" - зависит от того, что Вам нужно. Аналогия с портом - неуместна, т.к. порт находится на том же устройстве, а i2c соединяет разные устройства.
Как бы, никто не мешает иметь ус-во, при адресации которого будет что то там сбрасываться: старт, запись, стоп - всё. Не?
Ладно, думал можно упростить, значит не выйдет. Не принципиально.
Есть более важный вопрос.
Итак, у меня сейчас Pro Mini, который засыпает и просыпается по прерыванию от ножки SQW c RTC. Теперь мне надо сделать 2 или 4 кнопки, чтобы можно было корректировать время в RTC без подключения к компу. И надо, чтобы нажатие на эти кнопки тоже будило МК. Как это грамотно реализовать?
В голову приходит только связать пины кнопок с пином прерывания через диоды, чтобы сигнал шел только в одну сторону. Ну и программно при пробуждении проверять, какая кнопка была нажата, или SQW сработало.
Даю на водку: PCINT.
А это работает в режиме Powerdown?
Как вариант - организовать цикл while в сетап, который будет работать при наличии единицы на каком нибудь пине. К этому пину прицепить тумблер или кнопку с фиксацией. Замыкаем тумблер и рестартим ардуино.
Ну вот, скетч работает как и хотелось. Итого, на сегодняшний момент, PRO Mini, DS3231, TM1637 ( все-таки решил, что дисплей нужен ), две кнопки для коррекции времени. В режиме простоя потребление 250 мкА, но это я еще стабилизатор не обрезал. Извиняюсь, что использовал для кнопок библиотеку Guver, но она хорошо подходит и понятно описана. PCInt отлично будят из режима PowerDown. Скетч не вышел за пределы 8кБ, но по количеству выводов я в Attiny85 не вписываюсь. Сейчас работает на ATMega88.
Можно навскидку ткнуть, где можно наиболее просто оптимизировать код? Сейчас занимает 7700 байт, а хотелось бы еще небольшой функционал прикрутить. Использование регистров вместо pinMode, digitalWrite дает 40 байт. Отказ от PCINT дает 700 байт, тогда можно повесить одну из двух кнопок на INT1, но вторая кнопка будить не будет. Некритично, но не красиво. Есть еще несложные варианты?
а зачем для PCINT отдельная библиотека? Напрямую работать не проще?
Интересные моменты у вас в коде попадаются... судя по коду, у вас в часе 70 минут :)
сделай кнопки аналоговыми и повесь на 1 аналоговый вход. я бы даже 3 сделал, Up, Set и Down.
TM1637 попробуй мой, вдруг меньше кода получица.
судя по коду, у вас в часе 70 минут :)
Ну зачем же так. Чтобы при уменьшении минут не получать отрицательные значения и можно было использовать тип byte, сначала прибавляю 10, потом отнимаю обратно. Но экономии это особо не дало.
судя по коду, у вас в часе 70 минут :)
Ну зачем же так. Чтобы при уменьшении минут не получать отрицательные значения и можно было использовать тип byte, сначала прибавляю 10, потом отнимаю обратно.
поясните, как это. Зачем вообще в коде часов отнимать что-то от минут?
Чтобы при уменьшении минут не получать отрицательные значения и можно было использовать тип byte, сначала прибавляю 10, потом отнимаю обратно.
ШО? О_О
ШО? О_О
а вот оно:
если ТС расскажет мне, что он тут пытался изобразить - я думаю мы сократим эту процедуру до 3-5 строк. Вот и получится та "оптимизация", которой он жаждал
сделай кнопки аналоговыми и повесь на 1 аналоговый вход.
Так они же тогда будить не будут?
А можно ссылочку на ваш TM1637?
Конечно, код наверно не блещет. Кнопки нужны для установки/коррекции времени часов. Соответственно, если минут 00, при нажатии на кнопку (-) будет отрицательное значение. А функция с проверкой minutechange() включается только потом. Все для того чтобы использовать тип byte вместо int. Но, действительно, выигрыш копеечный, а код читается плохо.
если ТС расскажет мне, что он тут пытался изобразить - я думаю мы сократим эту процедуру до 3-5 строк. Вот и получится та "оптимизация", которой он жаждал
После установки минут, если минут больше 60 - прибавляем 1 час. минуты сбрасываем на - 60. (не на ноль, так как они могут меняться с шагом 1 и с шагом 10).
Дальше, если часов больше 23, то часы сбрасываем на 0.
То же самое в обратную сторону.
Все для того чтобы использовать тип byte вместо int. Но, действительно, выигрыш копеечный, а код читается плохо.
причем выигрыш тут в оперативке, а в обьеме кода будет проигрыш, причем заметный
А всего лишь при нажатии кнопки "-" нужно СНАЧАЛА проверить минуты на равенство нулю и только потом отнимать или нет.
А так вы через весь код протащили какую-то бредятину с часом из 70 минут
Так конечно правильно, но эту проверку надо будет делать в каждом из четырех обработчиков кнопок. А так она одна на всех в функции minutechange().
Ой, сам туплю... Почему int8_t не взяли вместо int? - размер как у байта, а при этом не понадобилось бы вся эта пляска с отслеживанием перехода через ноль
Так конечно правильно, но эту проверку надо будет делать в каждом из четырех обработчиков кнопок. А так она одна на всех в функции minutechange().
Я изо всех сил надеюсь, што ты просто угараешь
Ok, сделал тип int8_t. Функцию переписал.
Спасибо, но у меня другая задача. Дисплей не должен отображать время постоянно. Он нужен только чтобы корректировать время в RTC. Кнопки плюс и минус меняют время, потом происходит запись этого времени в RTC. Поэтому значение на дисплее меняется только кнопками. При нажатии (+), минуты начинают прибавляться, если доходит до 60, прибавляется час. При нажатии (-) в обратную сторону.
Вот, кстати, пробую вашу библиотеку. Не могу понять как правильно полностью включать и выключать дисплей ( именно полностью, чтобы не сажать батарейку). Чтобы его отключить, надо установить LOW на 5V, CLK, DIO. Чтобы включить 5V подаю обратно, но команда Display.PrintTime() включает его на долю секунды и он снова гаснет. Как включить правильно?
Библиотека 150 байт сэкономила, да и код получше читается. Спасибо.
Вот, кстати, пробую вашу библиотеку. Не могу понять как правильно полностью включать и выключать дисплей ( именно полностью, чтобы не сажать батарейку). Чтобы его отключить, надо установить LOW на 5V, CLK, DIO. Чтобы включить 5V подаю обратно, но команда Display.PrintTime() включает его на долю секунды и он снова гаснет. Как включить правильно?
Нинаю, передо мной такая задача не стояла. Ну я бы пустил 5В на дисплей через транзистор и отключал бы его, перед сном. Ну и перед сном можно сделать Display.Clear() и перевести на вход CLK и DIO. При пробуждении проделать всё не совсем в обратном порядке: снфчала подать +5 на экран, потом перевести ноги CLKи DIO на выходы, а потом уже вызывать Display.PrintTime()
Так, все. У мня седня чота джин больно забористый, паду-ка я спать, все вопросы завтра. Кто хочет, может мня даже с 52х летием проздравить. :-)
Однозначно, поздравляю. Если б в Питере, собственного производства налить бы мог.
Кто хочет, может мня даже с 52х летием проздравить. :-)
хочет - хочет! Поздравляю!
Так, все. У мня седня чота джин больно забористый, паду-ка я спать, все вопросы завтра. Кто хочет, может мня даже с 52х летием проздравить. :-)
Поздравляю!