Управление для аквариума
- Войдите на сайт для отправки комментариев
Вс, 26/02/2017 - 20:13
Помогите новичку. Пишу простой скетч первый раз вчера и сегодня. Было много проблем на программном уровне, разобрался. Скетч работает, но есть одна непонятка.
Вот скетч
[code]
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;
const int rele_sv = 3;
const int rele_bul = 2;
const int button_bul = 9;
//int btn_bul = 0;
unsigned long nowBtn = 0;
//char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
void setup () {
while (!Serial); // for Leonardo/Micro/Zero
Serial.begin(57600);
pinMode(rele_sv, OUTPUT);
digitalWrite(rele_sv, LOW);
pinMode(rele_bul, OUTPUT);
digitalWrite(rele_bul, LOW);
pinMode (button_bul, INPUT);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
// rtc.adjust(DateTime(2017, 2, 24, 17, 32, 0));
if (! rtc.isrunning()) {
Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// This line sets the RTC with an explicit date & time, for example to set
// January 21, 2014 at 3am you would call:
//rtc.adjust(DateTime(2016, 2, 24, 17, 17, 0));
}
}
void loop () {
DateTime now = rtc.now(); //Получили текущее время
int btn_bul = digitalRead(button_bul); //Считали состояние кнопки
Serial.print(now.hour(), DEC); // Время в монитор
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
if ((now.hour() == 6) && (now.minute() == 50)) { //Если 6:50 включили реле света и компресора
digitalWrite(rele_sv, LOW);
digitalWrite(rele_bul, LOW);
};
if ((now.hour() == 21) && (now.minute() == 0)) { // Если 21:00 выключили реле света и компресора
digitalWrite(rele_sv, HIGH);
digitalWrite(rele_bul, HIGH);
};
// if (((now.hour() >= 6) && (now.minute() >= 50)) || ((now.hour() <= 21) && (now.minute() <= 0))) { // Здесь не сработала проверка нажатия кнопки только между 6:50 и 21:00
if (btn_bul == 1) { //Если нажата кнопка должны получить время в секундах с 0:0:0
nowBtn = (int(now.hour())*3600) + (now.minute()*60) + now.second(); //но получается какая то хрень в 19:54:48 получаем 6149
};
// };
if ((((int(now.hour()) * 3600) + (now.minute() * 60) + now.second())-nowBtn)<1200) { // если разница между полученным значением и текущим меньше 20 минут отключаем компрессор (кормим рыбок)
digitalWrite(rele_bul, HIGH);
}
else {
digitalWrite(rele_bul, LOW);
};
Serial.print(btn_bul); // выводим статус нажатия кнопки
Serial.println();
Serial.print(nowBtn); //выводим значение переменной nowBtn
Serial.println();
delay(3000);
}
[/code]
Непонятно как считается переменная nowBtn, в коментах описано.
вот пример
какая то хрень в 19:54:48 получаем 6149
по идее должно быть 19*3600+54*60+48=71697, а в монитор выводится 6149. Не могу понять почему.
Помогите.
Переполнение интегер , макс. 64536. Попробуйте
nowBtn =(now.hour()*3600UL) + (now.minute()*60) + now.second();//ноСпасибо помогло.
Теперь бы еще понять как такое произошло на будущее.
Я так понимаю UL преобразует к unsigned long
2Волшебник: 32767. А unsigned int 65535.
Спасибо помогло.
Теперь бы еще понять как такое произошло на будущее.
Я так понимаю UL преобразует к unsigned long
И ещё у авр-гсс есть старый хитрый баг, если сделать uint32_t proizvedenie = (uint16_t A) x (uint16_t B) то результат с больший долей вероятности будет неверный, потому что сначала произведение посчитается как 16-бит а уже потом присвоится на 32-бита. Поэтому, если есть сомнения всегда лучше указать компилёру 32-битную операцию, путём подстановки UL в названии константы, или принудителным кастингом (uint32_t) для переменной. uint32_t proizvedenie = ((uint32_t)(uint16_t A)) x (uint16_t B)
2Волшебник: 32767. А unsigned int 65535.
Волшебник, это не старый хитрый баг, это правило вычисления, принятое в языке. Другое дело, что на 32-разрядных процессорах никто специально обнулять старшие 16 битов 32-разрядного регистра не будет, поэтому с большой вероятностью вычисления приведут к желаемому результату.
Общее же правило - результат зависит от типа операндов. Правда, есть исключение: промежуточные результаты всегда не менее 16 разрядов. Поэтому, например, можно сдвинуть байт на 8 разрядов и они не пропадут.
А если баг запротоколировать то он становится принятым правилом? Я честно скажу, стндарты не читаю, там же что угодно написать витееватым пейсательским языком можно. А потом перевести неакуратно. Я сошлюсь на авр-гсс
1. Ну, как бы приведенные 9 вариантов - это как раз запротоколированное творчество программистов. А по стандарту 16х16 допускается быть 16. Т.е. если программисту нужно, чтобы было 32, он (и именно он) должен об этом позаботиться.
2. Тогда 32х32 тоже запретить.
3. Весь Си - одна большая диверсия.
А по стандарту 16х16 допускается быть 16. Т.е. если программисту нужно, чтобы было 32, он (и именно он) должен об этом позаботиться.
На фик такой стандарт, он идиотский. Язык С тут ни чего не решает, авр-гсс выбирает сам какую процедуру использовать. И какому правилу азыка С-99/ 2011 следовать а какому нет.
Кстати, там есть вторая диверсия, если принудить выполнить операцию 32 х 16 кастингом одного из 16-битных операндов, то будет выполнена 32х32 - а она как минимум в 2.5 раза более трудоёмка. На ардуино 5 микросекунд, я себе макрос на ассемблере писал 32х16 по времени 2 мксек. А то БПФ медленно очень выполнялось.
/// Я честно скажу, стндарты не читаю
))) Наш чел, понимаю, сам такой, стандарт читать - последнее дело если уже ниче не помогает, а такого пока ещё не было.. (Даже знаю какие форумчане нас заплевывать будут, но то их проблемы)
Почему такая лажа с этой разрядностью?! Так Си он кросплатформенный, должен давать одинаковый результати на 8-и и на 64-х разрядной машине. А всем не угодиш. Что скомпилится коротко на 8-и будет громоздко на 64-х и наоборот. Потому такое компромисное решение. Увы, нет идеала.
Почему такая лажа с этой разрядностью?! Так Си он кросплатформенный, должен давать одинаковый результати на 8-и и на 64-х разрядной машине.
Отнюдь.
Разработчики явно указывают, что не должен.
И в то же время указывают, что существуют средства языка, обеспечивающие кроссплатформенность, но использование именно этих средств - выбор программиста. Авторы языка явно указывают, что язык рассчитан на квалифицированного программиста, который знает, что делает. Следовательно, язык не отслеживает и не прощает глупые ошибки. В том числе и с неправильным применением типов.