Покритикуйте код
- Войдите на сайт для отправки комментариев
Вс, 16/02/2020 - 12:16
Здравствуйте, уважаемые форумчане.
Решил сделать себе маленькую домашнюю метеостанцию с часами. Посмотрите, если не сложно, код. Покритикуйте. Код собирал из примеров, честно говоря, первый раз. До этого только читал форум, учился общаться с ардуино и отдельными чипами. Буду рад любым замечаниям.
[code] #include <stdint.h> #include <Wire.h> #include "SPI.h" #include "SparkFunBME280.h" #include <DS3231.h> #include <LiquidCrystal_I2C.h> BME280 mySensor; DS3231 rtc(SDA, SCL); LiquidCrystal_I2C lcd(0x27,16,2); //Кнопка на 4 пине, подсветка на 10 пине int regim=1; int flag=0; void setup() { pinMode(10,OUTPUT); pinMode(4,INPUT); digitalWrite(4,HIGH); Wire.begin(); lcd.init(); rtc.begin(); lcd.backlight(); mySensor.settings.commInterface = I2C_MODE; mySensor.settings.I2CAddress = 0x76; mySensor.settings.runMode = 3; mySensor.settings.tStandby = 5; mySensor.settings.filter = 0; mySensor.settings.tempOverSample = 1; mySensor.settings.pressOverSample = 1; mySensor.settings.humidOverSample = 1; mySensor.begin(); lcd.setCursor(0,0); lcd.print(" MeteoChasy"); lcd.setCursor(0,1); lcd.print(" Evgeniy v.03"); // The following lines can be commented out to use the values already stored in the DS1307 // rtc.setDOW(TUESDAY); // Set Day-of-Week to SUNDAY // rtc.setTime(14,31, 0); // Set the time to 12:00:00 (24hr format) // rtc.setDate(27, 03, 2018); // Set the date to October 3th, 2010 delay(5000); lcd.clear(); } void loop() { if(digitalRead(4)==LOW&&flag==0) { regim++; flag=1; if(regim>5) { regim=1; } } if(digitalRead(4)==HIGH&&flag==1) { flag=0; } if(regim==1) { analogWrite(10,255); } if(regim==2) { analogWrite(10,190); } if(regim==3) { analogWrite(10,120); } if(regim==4) { analogWrite(10,70); } if(regim==5) { analogWrite(10,0); } lcd.setCursor(0,0); lcd.print(rtc.getTimeStr(FORMAT_SHORT )); lcd.setCursor(8,0); lcd.print(rtc.getDateStr(FORMAT_SHORT )); lcd.setCursor(0,1); float temp=mySensor.readTempC()-1.5; lcd.print(temp,1); lcd.print("'C"); lcd.setCursor(7,1); lcd.print((uint8_t)mySensor.readFloatHumidity()); lcd.print("%"); lcd.setCursor(11,1); int mmH=mySensor.readFloatPressure()/133; lcd.print(mmH); lcd.print("mm"); delay(1000); } [/code]
Всякий раз, когда ТС просил покритиковать код и я, сдуру, начинал это делать внимательно и добросовестно, заканчивалось одним и тем же - я оказывался мудаком, который прикапывается к мелочам, издевается над начинающими и подкармливает своё ненасытное ЧСВ за счёт новичка :-(и
ну если мелочь delay, то я согласен. Их много в программе.
ЕвгенийП. Зря Вы так. Я всегда с удовольствием читаю все Ваши посты, стараясь почерпнуть что-то новое и интересное для себя. Поэтому буду очень рад, если Вы посмотрите и посоветуете как будет лучше. А мы с Вами тезки.
Спасибо, уважаемый qwone. А как это исправить?
У Вас, все работает? Вас это устраивает? Тады зачем впустую телепонить? Будете делать следующий релиз, сами уберете ошибки опираясь на опыт и новые знания. ИМХО.
Вместо строк 18-19 лучше писать "INPUT_PULLUP", когда захотите притянуть кнопку к земле эта привычка убережет от непонятной ошибки в работе программы.
ну если мелочь delay, то я согласен. Их много в программе.
в loop всего один делей.
2 ТС - убрать его просто, см пример "блинк без делей"
Но есть еще скрытые - в библиотеке MySensors. Тут уже сложнее, придется писать работу с датчиками самому, без библиотеки
bwn. Спасибо.
b707. Спасибо, попробую убрать этот delay. Но работу с датчиком напрямую пока не осилил.
Изучить более современные концепции программирования. Конечно можно из свалки набрать говна и слепить себе дом. Но если Вы планируете уже на этом месте построить трехэтажный дом. Мол часть квартир сдать в аренду, то такой подход уже идет лесом.
qwone. Если я правильно Вас понимаю, Вы советуете не заниматься ерундой, а изучать нормальный язык программирования, правильно? Я согласен. Правда, возраст уже не тот, хотя для себя все равно интересно.
qwone. Если я правильно Вас понимаю, Вы советуете не заниматься ерундой, а изучать нормальный язык программирования, правильно? Я согласен. Правда, возраст уже не тот, хотя для себя все равно интересно.
Сразу встречный вопрос: и как оно работает?
Ну и по коду: если кнопка без дребезга, то система, похоже, будет работать (первое впечатление, всерьёз не разбирался. Если твой индикатор нормально управляется от ШИМ, естественно).
Если с дребезгом - возможны спецэффекты.
ну если мелочь delay, то я согласен. Их много в программе.
в loop всего один делей.
2 ТС - убрать его просто, см пример "блинк без делей"
Но есть еще скрытые - в библиотеке MySensors. Тут уже сложнее, придется писать работу с датчиками самому, без библиотеки
Это метеостанция, а не головка самонаведения противоракеты.
qwone. Спасибо.
SLKH. Работает, если честно, уже с октября. Индикатор от ШИМа работает нормально, яркость регулируется, спецэффектов пока не было. На кнопке, на контактах висит пленка 0,1 мкФ.
qwone. Спасибо.
SLKH. Работает, если честно, уже с октября. Индикатор от ШИМа работает нормально, яркость регулируется, спецэффектов пока не было. На кнопке, на контактах висит пленка 0,1 мкФ.
Вот на хрена их убирать-то? Чему они мешают?
Это метеостанция, а не головка самонаведения противоракеты.
SLKH - а с чего столько эмоций-то? :))) Меня спросили - я ответил.
В лупе делей на 1 секунду, а коде измерения температуры - еще 800мс. Что там в коде датчика давления - не в курсе, но весь луп примерно занимает 2 секунды. Для программы, в которой есть кнопки - это много, реакция на нажатие будет ощутимо тормозить
b707. Действительно, реакция на изменение яркости тормозит. Правда, для меня это не существенно, выставил комфортную и забыл. Но для того, чтобы такого не было в дальнейшем, я и хочу это переделать. Спасибо.
Вот на хрена их убирать-то? Чему они мешают?
Это метеостанция, а не головка самонаведения противоракеты.
SLKH - а с чего столько эмоций-то? :))) Меня спросили - я ответил.
В лупе делей на 1 секунду, а коде измерения температуры - еще 800мс. Что там в коде датчика давления - не в курсе, но весь луп примерно занимает 2 секунды. Для программы, в которой есть кнопки - это много, реакция на нажатие будет ощутимо тормозить
а дальше:
если обновлять инфу на дисплее раз в 5 - 10 минут (или раз в минуту, если важна индикация времени), то остального времени вполне хватит на кнопки;
которые в данной конструкции на самом деле не особо и нужны - установить один раз предпочтительное значение яркости ("выставил комфортную и забыл") или же добавить фоторезистор и изменять его в зависимости от внешнего освещения.
2 ТС - убрать его просто, см пример "блинк без делей"
А зачем? Программе ведь всё равно в это время нечем заниматься. Какая разница, будет она циклиться в loop или в том цикле, что в delay?
ЕвгенийП. А поподробней?
А зачем? Программе ведь всё равно в это время нечем заниматься. Какая разница, будет она циклиться в loop или в том цикле, что в delay?
Евгений, и Вы туда же?
Я уже обьяснил "зачем" - чтобы кнопки не тормозили.
Независимо от того, сколько в программе кнопок и как часто они нажимаются, хоть раз в год - я все равно писал бы луп так, чтобы его "оборот" занимал максимум 100мс, а не 2 сек. Тем более что в этом коде для этого надо - всего-то! -добавить одну переменную и две строки.
Я не понимаю, почему вы кинулись меня переубеждать? ТС хочет научиться писать правильно - так пусть учится. В этой программе может в этом и нет особого смысла, зато когда у него будет задача, действительно требующая оперативной реакции - оно получится "само"
Я уже обьяснил "зачем" - чтобы кнопки не тормозили.
А там чё и кнопки есть? Тогда сорри, я чёт не заметил - недостаточно внимательно смотрел :-(
Т.С,, а Вы с простейшего начните. У Вас переменные regim и flag используются только в одной функции - в loop. Так нафига, спрашивается им быть глобальными?
Часики инициализировать лучше всего использованием переменных системного времени виндовс на стадии прошивки, ссылку не помню
b707,
Вы знаете, на что я обратил внимание (давно уже). Вот, у ТС, как он выразился, "маленькая" метеостанция с температурой, давлением, кнопками и часами. Я сейчас делаю, видимо, не просто "маленькую", а прямо-таки "нано" - в ней нет ни часов, ни давления, ни кнопок (акромя Reset) - есть только температура (правда, две - на улице и в доме). Прошивку пишет Ворота (он проспорил мне, тут в какой-то теме об этом уже говорилось).
Функциональность, как видите, намного меньше, чем у ТС. Так вот, прошивка написанная профессионалом, получилась около 800 строк (без низкоуровневой работы с экраном - считаем это "библиотекой"). И почему-то всегда так. У профи прошивки в разы больше по строкам, чем у новичков :-)
Кстати, коль скоро там нет кнопок и ничего нет вообще, он не стесняется насчёт delay там, где это нужно. Правда, между измерениями у него не delay, а глубокий power_down на 10 минут. Всё добро (atmega + nrf-PA + e-paper + даллас) вместе взятое укладывается в < 5 микроампер.
ЕвгенийП. Правильно?
RG22EM, Green
Если я правильно понял, это чтобы не канителиться каждый раз с выставлением времени?
RG22EM, Green
Если я правильно понял, это чтобы не канителиться каждый раз с выставлением времени?
да, лишь бы в компьютере шли правильно
Так вот, прошивка написанная профессионалом, получилась около 800 строк (без низкоуровневой работы с экраном - считаем это "библиотекой"). И почему-то всегда так. У профи прошивки в разы больше по строкам, чем у новичков :-)
не согласен с вами, причем категорически:) В своих программах я всегда стараюсь выкинуть повторы, написать код эффективнее, в том числе и по числу строк. По Вашей квалификации я получаюсь дремучий чайник, что может и недалеко от истины, но абидно :)
у меня есть подобный проект, тини85 + HC-12 + даллас - в программе 193 строки, не считая библиотек. Среднее потребление 42 мкА - вроде в 10 раз больше, чему Ворота. Но есть нюанс - мой сенсор отсылает данные раз в минуту.
RG22EM Понятно, спасибо.
Вот вариант без делей.
ЕвгенийП. Правильно?
Нет. Так она будет забывать значения, которые были при предыдущем вызове loop. Посмотрите подробности вот здесь.
Значит правильно так?
Вообще убрать delay() совсем несложно - например Вы хотите производить какое-нибудь действие раз в секунду. Тогда с помощью millis() отслеживаем эту секунду и тогда производим действие. По поводу DS датчиков - так вроде в последних библиотеках разделили запрос и ответ. Т.е. Вы послали запрос, подождали секунду (с помощью millis()) и запросили результат измерений. В остальное время контроллер должен опрашивать кнопки. Общий цикл измерение-выдача результата будет порядка 2-х секунд. На кнопки реакция мгновенная.
Проблема даже не убрать delay(), а перейти на программирование через автоматы.А вот здесь и полезет основная засада для новичков.
Проблема даже не убрать delay(), а перейти на программирование через автоматы.А вот здесь и полезет основная засада для новичков.
не стращай )))
А что стращать. Я не зря приводил метафору про дом. Так и здесь. Пока живет семья в одном доме замечательно. Но она увеличится. Пристроим веранду. А еще больше и так до разделение на множество семей. То получится простая коммуналка. Туалет и ванна одна на кучу народу. Один засел на толчке и писец. Машину поставил и дом перекрыт. Вот что бы такой хрени и не было так развилось программирование. И все это можно рационально и удобно разместить на одном камне.
А если не учитывать это то будет так
Ну, это если по уму. А если есть куча чужих delay, то свою кнопку можно и в прерывании обрабатывать.)
Значит правильно так?
Раз в секунду (хотя зачем так часто?) нужно только измерять параметры и выводить их на экран, а кнопки следует опрашивать при каждом проходе.
Значит правильно так?
Ну, Вы, блин, даёте!
Только что убрали две переменные из глобальных и тут же засунули туда две новые, которые ТОЖЕ используются только в одной функции.
Если я все правильно понял, должно быть так:
Переменная в строке №85 будет сохранять значение между вызовами? Думайте же, что делаете-то!
Извините не успел ответить.
Или должно быть так:
Подписался
... И почему-то всегда так. У профи прошивки в разы больше по строкам, чем у новичков :-)
не согласен с вами, причем категорически:) В своих программах я всегда стараюсь выкинуть повторы, написать код эффективнее, в том числе и по числу строк. По Вашей квалификации я получаюсь дремучий чайник, что может и недалеко от истины, но абидно :)
Вопрос на самом деле не столь очевидный.
Действительно, добрую половину публикуемых здесь программ новичков на 400 строк, можно легко свести к 30, используя массивы и циклы.
Но есть и другая сторона медали: профессионал делает гораздо больше проверок и предусматривает все варианты, в том числе и те, которые, на взгляд новичка, никогда не случатся.
Ну и простота поддержки кода (и его повторного использования) тоже немного увеличивают его объем (осмысленные (читай: длинные) названия переменных; стремление все, что можно, записать в виде предопределенных констант; комментарии; ООП ... ).
Так вот, прошивка написанная профессионалом, получилась около 800 строк (без низкоуровневой работы с экраном - считаем это "библиотекой"). И почему-то всегда так. У профи прошивки в разы больше по строкам, чем у новичков :-)
не согласен с вами, причем категорически:) В своих программах я всегда стараюсь выкинуть повторы, написать код эффективнее, в том числе и по числу строк. По Вашей квалификации я получаюсь дремучий чайник, что может и недалеко от истины, но абидно :)
Понимаешь, в чём дело: не всё так просто и очевидно. Я разумею, что Евгений вёл речь не о тупых повторах и эффективном коде, от слова "совсем". Так-то даже чайнику понятно, что если можно сделать декомпозицию и тем самым избавиться от повторяемого кода (просто как пример юзкейса) - то это надо делать.
Однако, в серьёзных рабочих проектах есть такое понятие, как архитектурный слой. А это, как минимум - обязывает. Обязывает выделять сущности, предусматривать между ними взаимодействие, и т.д. и т.п. Плюс - те же юнит-тесты, например. Плюс - отладочная информация, которую тоже надо делать настраиваемой, хотя бы по какому-нибудь условному Level (как пример - просто дефайны, по которым собирается прошивка с той или иной отладочной информацией).
Вот и получается, что рабочий код - это рабочий код. А вспомогательные вещи - они тоже строчки кода занимают, хотя на этапе продакшена в прошивку и не попадают, вообще.
Ну и, что касается примера из жизни (сейчас вожусь как раз): Android Studio, если хочешь сделать публичный enum или класс - рвёт и мечет, требует отдельного файла. Архитектурно это - очень правильно, очень. А файл лишний - есть. Ещё там можно документировать код комментариями сразу - тоже строчки кода.
Вот и имеем, что отличие прошивки любителя и профи - не в строчках кода (кто их считает) - а в подходе к работе.
Вот щас для интереса посмотрел публичный вариант проекта на гитхабе (а закрытый - поболее будет уже, за сотню тысяч строк давно), и вот что получил:
На С++ - 35223 (без комментов и пустых строк), в заголовочниках: 10709 строк, всего в проекте - 85342 строк, плюс 20403 строк комментариев.
Сколько строк сможешь сэкономить, переписав? :)))))
А такой вариант - не?
Да уж правильно сказал ЕвгенийП.
Попросили меня как то скетч поправить для устройства отсечки оборотов двигателя.
Изначально было строк 10кода и работало, через pulseIn().
В итоге получилось такое:
Одна из вариации итоговой программы , всего их было штук 15
Теперь по замечаниям:
1.ТС изучай типы данных. А не тупо из примеров Недалеких, а-ля гивер копируй. Не нужен однобайтовой переменной flag тип int, а вот boolean самое оно. То же самое с regim, byte сгодится вполне.
2. При конфигурации пинов можно сразу указать что нужна подтяжка по высокому уровню, указав в качестве второго аргумента функции pinMode, значение INPUT_PULLUP.
3. Все значения режимов поместить в один массив и скважность задавать обращаясь к нужному элементу массива:
byte pwm_regim[5]={20,50,100,150,255};
AnalogWrite(pin,pwm_regim[regim]);
Половина портянки сразу свернётся до одной строки.
4. delay() убирать тут в принципе необязательно, достаточно сократить до 50мс, будет в качестве дребезга выступать.
5.обновление информации на экране выполнять либо когда данные изменились, либо раз в 0.5-1сек через миллис. Ну до кучи можно ещё разделитель использовать ":" между часами/минутами и мыргать им раз в полсекунды.
Покритикуйте код
Вспомнилась "критика бегуна" из из известного фильма - «Как то он не концептуально пробежал ... да пошёл ты в жопу!»