Покритикуйте код

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

Здравствуйте, уважаемые форумчане.

Решил сделать себе маленькую домашнюю метеостанцию с часами. Посмотрите, если не сложно, код. Покритикуйте. Код собирал из примеров, честно говоря, первый раз. До этого только читал форум, учился общаться с ардуино и отдельными чипами. Буду рад любым замечаниям.

[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]

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Всякий раз, когда ТС просил покритиковать код и я, сдуру, начинал это делать внимательно и добросовестно, заканчивалось одним и тем же - я оказывался мудаком, который прикапывается к мелочам, издевается над начинающими и подкармливает своё ненасытное ЧСВ за счёт новичка :-(и

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

ну если мелочь delay, то я согласен. Их много в программе.

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

ЕвгенийП. Зря Вы так. Я всегда с удовольствием читаю все Ваши посты, стараясь почерпнуть что-то новое и интересное для себя. Поэтому буду очень рад, если Вы посмотрите и посоветуете как будет лучше. А мы с Вами тезки.

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

Спасибо, уважаемый qwone. А как это исправить?

bwn
Offline
Зарегистрирован: 25.08.2014

У Вас, все работает? Вас это устраивает? Тады зачем впустую телепонить? Будете делать следующий релиз, сами уберете ошибки опираясь на опыт и новые знания. ИМХО.
Вместо строк 18-19 лучше писать "INPUT_PULLUP", когда захотите притянуть кнопку к земле эта привычка убережет от непонятной ошибки в работе программы.

b707
Offline
Зарегистрирован: 26.05.2017

qwone пишет:

ну если мелочь delay, то я согласен. Их много в программе.

в loop всего один делей.

2 ТС - убрать его просто, см пример "блинк без делей"

Но есть еще скрытые - в библиотеке MySensors. Тут уже сложнее, придется писать работу с датчиками самому, без библиотеки

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

bwn. Спасибо.

b707. Спасибо, попробую убрать этот delay. Но работу с датчиком напрямую пока не осилил.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Изучить более современные концепции программирования. Конечно можно из свалки набрать говна и слепить себе дом. Но если Вы планируете уже на этом месте построить трехэтажный дом. Мол часть квартир сдать в аренду, то такой подход уже идет лесом.

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

qwone. Если я правильно Вас понимаю, Вы советуете не заниматься ерундой, а изучать нормальный язык программирования, правильно? Я согласен. Правда, возраст уже не тот, хотя для себя все равно интересно.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

UB3AFB пишет:

qwone. Если я правильно Вас понимаю, Вы советуете не заниматься ерундой, а изучать нормальный язык программирования, правильно? Я согласен. Правда, возраст уже не тот, хотя для себя все равно интересно.

Если не хотите-те свалится в старческий маразм , то учится надо особенно в старости. Мозг должен работать. Так что напрягайте вашу голову, это залог долголетия.

SLKH
Offline
Зарегистрирован: 17.08.2015

Сразу встречный вопрос: и как оно работает?

Ну и по коду: если кнопка без дребезга, то система, похоже, будет работать (первое впечатление, всерьёз не разбирался. Если твой индикатор нормально управляется от ШИМ, естественно).

Если с дребезгом - возможны спецэффекты. 

SLKH
Offline
Зарегистрирован: 17.08.2015

b707 пишет:

qwone пишет:

ну если мелочь delay, то я согласен. Их много в программе.

в loop всего один делей.

2 ТС - убрать его просто, см пример "блинк без делей"

Но есть еще скрытые - в библиотеке MySensors. Тут уже сложнее, придется писать работу с датчиками самому, без библиотеки

Вот на хрена их убирать-то? Чему они мешают?

Это метеостанция, а не головка самонаведения противоракеты. 

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

qwone. Спасибо.

SLKH. Работает, если честно, уже с октября. Индикатор от ШИМа работает нормально, яркость регулируется, спецэффектов пока не было. На кнопке, на контактах висит пленка 0,1 мкФ.

SLKH
Offline
Зарегистрирован: 17.08.2015

UB3AFB пишет:

qwone. Спасибо.

SLKH. Работает, если честно, уже с октября. Индикатор от ШИМа работает нормально, яркость регулируется, спецэффектов пока не было. На кнопке, на контактах висит пленка 0,1 мкФ.

ну и хорошо.

 

b707
Offline
Зарегистрирован: 26.05.2017

SLKH пишет:

 Вот на хрена их убирать-то? Чему они мешают?

Это метеостанция, а не головка самонаведения противоракеты. 

SLKH - а с чего столько эмоций-то? :))) Меня спросили - я ответил.

В лупе делей на 1 секунду, а коде измерения температуры - еще 800мс. Что там в коде датчика давления - не в курсе, но весь луп примерно занимает 2 секунды. Для программы, в которой есть кнопки - это много, реакция на нажатие будет ощутимо тормозить

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

b707. Действительно, реакция на изменение яркости тормозит. Правда, для меня это не существенно, выставил комфортную и забыл. Но для того, чтобы такого не было в дальнейшем, я и хочу это переделать. Спасибо.

SLKH
Offline
Зарегистрирован: 17.08.2015

b707 пишет:

SLKH пишет:

 Вот на хрена их убирать-то? Чему они мешают?

Это метеостанция, а не головка самонаведения противоракеты. 

SLKH - а с чего столько эмоций-то? :))) Меня спросили - я ответил.

В лупе делей на 1 секунду, а коде измерения температуры - еще 800мс. Что там в коде датчика давления - не в курсе, но весь луп примерно занимает 2 секунды. Для программы, в которой есть кнопки - это много, реакция на нажатие будет ощутимо тормозить

да не было там особенных эмоций. луповский делэй убрать несложно.

а дальше:

если обновлять инфу на дисплее раз в 5 - 10 минут (или раз в минуту, если важна индикация времени), то остального времени вполне хватит на кнопки;

которые в данной конструкции на самом деле не особо и нужны - установить один раз предпочтительное значение яркости ("выставил комфортную и забыл") или же добавить фоторезистор и изменять его в зависимости от внешнего освещения.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

b707 пишет:

2 ТС - убрать его просто, см пример "блинк без делей"

А зачем? Программе ведь всё равно в это время нечем заниматься. Какая разница, будет она циклиться в loop или в том цикле, что в delay?

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

ЕвгенийП. А поподробней?

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП пишет:

А зачем? Программе ведь всё равно в это время нечем заниматься. Какая разница, будет она циклиться в loop или в том цикле, что в delay?

Евгений, и Вы туда же?

Я уже обьяснил "зачем" - чтобы кнопки не тормозили.

Независимо от того, сколько в программе кнопок и как часто они нажимаются, хоть раз в год - я все равно писал бы луп так, чтобы его "оборот" занимал максимум 100мс, а не 2 сек. Тем более что в этом коде для этого надо - всего-то! -добавить одну переменную и две строки.

Я не понимаю, почему вы кинулись меня переубеждать? ТС хочет научиться писать правильно - так пусть учится. В этой программе может в этом и нет особого смысла, зато когда у него будет задача, действительно требующая оперативной реакции - оно получится "само"

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

b707 пишет:

Я уже обьяснил "зачем" - чтобы кнопки не тормозили.

А там чё и кнопки есть? Тогда сорри, я чёт не заметил - недостаточно внимательно смотрел :-(

Т.С,, а Вы с простейшего начните. У Вас переменные regim и flag используются только в одной функции - в loop. Так нафига, спрашивается им быть глобальными?

RG22EM
Offline
Зарегистрирован: 27.08.2016

Часики инициализировать лучше всего использованием переменных системного времени виндовс на стадии прошивки, ссылку не помню

Green
Offline
Зарегистрирован: 01.10.2015
  // наверно так? 
  if (rtc.lostPower())
     rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

b707,

Вы знаете, на что я обратил внимание (давно уже). Вот, у ТС, как он выразился, "маленькая" метеостанция с температурой, давлением, кнопками и часами. Я сейчас делаю, видимо, не просто "маленькую", а прямо-таки "нано" - в ней нет ни часов, ни давления, ни кнопок (акромя Reset) - есть только температура (правда, две - на улице и в доме). Прошивку пишет Ворота (он проспорил мне, тут в какой-то теме об этом уже говорилось).

Функциональность, как видите, намного меньше, чем у ТС. Так вот, прошивка написанная профессионалом, получилась около 800 строк (без низкоуровневой работы с экраном - считаем это "библиотекой"). И почему-то всегда так. У профи прошивки в разы больше по строкам, чем у новичков :-)

Кстати, коль скоро там нет кнопок и ничего нет вообще, он не стесняется насчёт delay там, где это нужно. Правда, между измерениями у него не delay, а глубокий power_down на 10 минут. Всё добро (atmega + nrf-PA + e-paper + даллас) вместе взятое укладывается в < 5 микроампер.

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

ЕвгенийП. Правильно?

#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 пине

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() {
  int regim=1;
  int flag=0;
   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);
}

 

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

RG22EM, Green

Если я правильно понял, это чтобы не канителиться каждый раз с выставлением времени?

RG22EM
Offline
Зарегистрирован: 27.08.2016

UB3AFB пишет:

RG22EM, Green

Если я правильно понял, это чтобы не канителиться каждый раз с выставлением времени?

да, лишь бы в компьютере шли правильно

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП пишет:

 Так вот, прошивка написанная профессионалом, получилась около 800 строк (без низкоуровневой работы с экраном - считаем это "библиотекой"). И почему-то всегда так. У профи прошивки в разы больше по строкам, чем у новичков :-)

не согласен с вами, причем категорически:) В своих программах я всегда стараюсь выкинуть повторы, написать код эффективнее, в том числе и по числу строк. По Вашей квалификации я получаюсь дремучий чайник, что может и недалеко от истины, но абидно :)

Цитата:
Правда, между измерениями у него не delay, а глубокий power_down на 10 минут. Всё добро (atmega + nrf-PA + e-paper + даллас) вместе взятое укладывается в < 5 микроампер.

у меня есть подобный проект, тини85 + HC-12 + даллас - в программе 193 строки, не считая библиотек. Среднее потребление 42 мкА - вроде в 10 раз больше, чему Ворота. Но есть нюанс - мой сенсор отсылает данные раз в минуту.

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

RG22EM Понятно, спасибо.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

b707 пишет:
В своих программах я всегда стараюсь выкинуть повторы
Так, у него тоже нет повторов и всё написано нормально. Просто "тут мелкий нюансик, там крохотный", кроме того, никаких констант, куча всяких объявлений, вот и набегает. Как закончит, может выложит в проекты. Я не хотел этот проект выкладывать, но он, похоже намылился выложить "совместную работу".

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

Вот вариант без делей.

#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 пине
long previousMillis = 0;
long interval = 1000;

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() {
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > interval) {
  previousMillis = currentMillis;
  int regim=1;
  int flag=0;
   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");
  }
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

UB3AFB пишет:

ЕвгенийП. Правильно?

Нет. Так она будет забывать значения, которые были при предыдущем вызове loop. Посмотрите подробности вот здесь.

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017
#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 пине
long previousMillis = 0;
long interval = 1000;

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() {
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > interval) {
  previousMillis = currentMillis;
  static int regim=1;
  static int flag=0;
   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");
  }
}

Значит правильно так?

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Вообще убрать delay() совсем несложно - например Вы хотите производить какое-нибудь действие раз в секунду. Тогда с помощью millis() отслеживаем эту секунду и тогда производим действие. По поводу DS датчиков - так вроде в последних библиотеках разделили запрос и ответ. Т.е. Вы послали запрос, подождали секунду (с помощью millis()) и запросили результат измерений. В остальное время контроллер должен опрашивать кнопки. Общий цикл измерение-выдача результата будет порядка 2-х секунд. На кнопки реакция мгновенная.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Проблема даже не убрать delay(), а перейти на программирование через автоматы.А вот здесь и полезет основная засада для новичков.

RG22EM
Offline
Зарегистрирован: 27.08.2016

qwone пишет:

Проблема даже не убрать delay(), а перейти на программирование через автоматы.А вот здесь и полезет основная засада для новичков.

не стращай )))

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

А что стращать. Я не зря приводил метафору про дом. Так и здесь. Пока живет семья в одном доме замечательно. Но она увеличится. Пристроим веранду. А еще больше и так до разделение на множество семей. То получится простая коммуналка. Туалет и ванна одна на кучу народу. Один засел на толчке и писец. Машину поставил и дом перекрыт. Вот что бы такой хрени и не было так развилось программирование. И все это можно рационально и удобно разместить на одном камне.

А если не учитывать это то будет так

Заходит ночью Изя в туалет и бурчит: 
— Поднял меня среди ночи и не писаешь, писай тебе говорят!
Жена из спальни: — Изя, с кем ты там разговариваешь?
— Спи, спи. Ты его уже не помнишь. 

 

Green
Offline
Зарегистрирован: 01.10.2015

Ну, это если по уму. А если есть куча чужих delay, то свою кнопку можно и в прерывании обрабатывать.)

SLKH
Offline
Зарегистрирован: 17.08.2015

UB3AFB пишет:

#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 пине
long previousMillis = 0;
long interval = 1000;

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() {
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > interval) {
  previousMillis = currentMillis;
  static int regim=1;
  static int flag=0;
   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");
  }
}

Значит правильно так?

 

Нет.

Раз в секунду (хотя зачем так часто?) нужно только измерять параметры и выводить их на экран, а кнопки следует опрашивать при каждом проходе. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

UB3AFB пишет:

Значит правильно так?

Ну, Вы, блин, даёте!

Только что убрали две переменные из глобальных и тут же засунули туда две новые, которые ТОЖЕ используются только в одной функции.

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

Если я все правильно понял, должно быть так:

#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 пине

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() {  
  static int regim=1;
  static int flag=0;
  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 ));
  
  long previousMillis = 0;
  long interval = 1000;
 unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > interval) {
  previousMillis = currentMillis;
  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");
  }
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Переменная в строке №85 будет сохранять значение между вызовами? Думайте же, что делаете-то!

UB3AFB
UB3AFB аватар
Offline
Зарегистрирован: 25.01.2017

Извините не успел ответить.

Или должно быть так:

#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 пине

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() {  
  static int regim=1;
  static int flag=0;
  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 ));
  
  static long previousMillis = 0;
  long interval = 1000;
 unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > interval) {
  previousMillis = currentMillis;
  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");
  }
}

 

NikShel
Offline
Зарегистрирован: 21.01.2018

Подписался

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

b707 пишет:

ЕвгенийП пишет:

... И почему-то всегда так. У профи прошивки в разы больше по строкам, чем у новичков :-)

не согласен с вами, причем категорически:) В своих программах я всегда стараюсь выкинуть повторы, написать код эффективнее, в том числе и по числу строк. По Вашей квалификации я получаюсь дремучий чайник, что может и недалеко от истины, но абидно :)

Вопрос на самом деле не столь очевидный.

Действительно, добрую половину публикуемых здесь программ новичков на 400 строк, можно легко свести к 30, используя массивы и циклы.

Но есть и другая сторона медали: профессионал делает гораздо больше проверок и предусматривает все варианты, в том числе и те, которые, на взгляд новичка, никогда не случатся.

Ну и простота поддержки кода (и его повторного использования) тоже немного увеличивают его объем (осмысленные (читай: длинные) названия переменных; стремление все, что можно, записать в виде предопределенных констант; комментарии; ООП ... ).

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

b707 пишет:

ЕвгенийП пишет:

 Так вот, прошивка написанная профессионалом, получилась около 800 строк (без низкоуровневой работы с экраном - считаем это "библиотекой"). И почему-то всегда так. У профи прошивки в разы больше по строкам, чем у новичков :-)

не согласен с вами, причем категорически:) В своих программах я всегда стараюсь выкинуть повторы, написать код эффективнее, в том числе и по числу строк. По Вашей квалификации я получаюсь дремучий чайник, что может и недалеко от истины, но абидно :)

Понимаешь, в чём дело: не всё так просто и очевидно. Я разумею, что Евгений вёл речь не о тупых повторах и эффективном коде, от слова "совсем". Так-то даже чайнику понятно, что если можно сделать декомпозицию и тем самым избавиться от повторяемого кода (просто как пример юзкейса) - то это надо делать.

Однако, в серьёзных рабочих проектах есть такое понятие, как архитектурный слой. А это, как минимум - обязывает. Обязывает выделять сущности, предусматривать между ними взаимодействие, и т.д. и т.п. Плюс - те же юнит-тесты, например. Плюс - отладочная информация, которую тоже надо делать настраиваемой, хотя бы по какому-нибудь условному Level (как пример - просто дефайны, по которым собирается прошивка с той или иной отладочной информацией).

Вот и получается, что рабочий код - это рабочий код. А вспомогательные вещи - они тоже строчки кода занимают, хотя на этапе продакшена в прошивку и не попадают, вообще.

Ну и, что касается примера из жизни (сейчас вожусь как раз): Android Studio, если хочешь сделать публичный enum или класс - рвёт и мечет, требует отдельного файла. Архитектурно это - очень правильно, очень. А файл лишний - есть. Ещё там можно документировать код комментариями сразу - тоже строчки кода.

Вот и имеем, что отличие прошивки любителя и профи - не в строчках кода (кто их считает) - а в подходе к работе.

Вот щас для интереса посмотрел публичный вариант проекта на гитхабе (а закрытый - поболее будет уже, за сотню тысяч строк давно), и вот что получил:

[
   {
      "language": "C++",
      "files": "87",
      "lines": "52157",
      "blanks": "8657",
      "comments": "8277",
      "linesOfCode": "35223"
   },
   {
      "language": "JavaScript",
      "files": "19",
      "lines": "33671",
      "blanks": "5202",
      "comments": "4068",
      "linesOfCode": "24401"
   },
   {
      "language": "C/C++ Header",
      "files": "115",
      "lines": "18254",
      "blanks": "3107",
      "comments": "4438",
      "linesOfCode": "10709"
   },
   {
      "language": "PHP",
      "files": "108",
      "lines": "11502",
      "blanks": "1699",
      "comments": "3399",
      "linesOfCode": "6404"
   },
   {
      "language": "C",
      "files": "10",
      "lines": "5536",
      "blanks": "19",
      "comments": "61",
      "linesOfCode": "5456"
   },
   {
      "language": "CSS",
      "files": "4",
      "lines": "3032",
      "blanks": "169",
      "comments": "160",
      "linesOfCode": "2703"
   },
   {
      "language": "Markdown",
      "files": "3",
      "lines": "271",
      "blanks": "50",
      "comments": "0",
      "linesOfCode": "221"
   },
   {
      "language": "Plain Text",
      "files": "27",
      "lines": "202",
      "blanks": "66",
      "comments": "0",
      "linesOfCode": "136"
   },
   {
      "language": "XML",
      "files": "1",
      "lines": "88",
      "blanks": "0",
      "comments": "0",
      "linesOfCode": "88"
   },
   {
      "language": "Batch",
      "files": "1",
      "lines": "1",
      "blanks": "0",
      "comments": "0",
      "linesOfCode": "1"
   },
   {
      "language": "INI",
      "files": "1",
      "lines": "0",
      "blanks": "0",
      "comments": "0",
      "linesOfCode": "0"
   },
   {
      "language": "Total",
      "files": "376",
      "lines": "124714",
      "blanks": "18969",
      "comments": "20403",
      "linesOfCode": "85342"
   }
]

На С++ - 35223 (без комментов и пустых строк), в заголовочниках: 10709 строк, всего в проекте - 85342 строк, плюс 20403 строк комментариев.

Сколько строк сможешь сэкономить, переписав? :)))))

SLKH
Offline
Зарегистрирован: 17.08.2015

А такой вариант - не?

#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);

byte const svet = 10;
byte const knopka = 4;
#define knopkaON digitalRead(knopka)==LOW // нажата
#define knopkaOFF digitalRead(knopka)==HIGH // не нажата

void brightness();
void disp();

void setup()
{
	pinMode(svet,OUTPUT);
	pinMode(knopka,INPUT_PULLUP);
	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");
	delay(5000);
	lcd.clear();
}

void loop()
{
	brightness();
	disp();
}

void brightness()
{
	static byte regim=1;
	static byte flag=0;

	if(knopkaON && flag==0)
		{
			regim++;
			flag=1;

			if(regim>5)
				{
					regim=1;
				}
		}
	if(knopkaOFF && flag==1)
		{
			flag=0;
		}

	switch (regim)
		{
		case 1:
			analogWrite(svet,255);
			break;
		case 2:
			analogWrite(svet,190);
			break;
		case 3:
			analogWrite(svet,120);
			break;
		case 4:
			analogWrite(svet,70);
			break;
		case 5:
			analogWrite(svet,0);
			break;
		}
}

void disp()
{
	const unsigned long interval = 60000;  // Раз в минуту или как нравится
	static unsigned long previousMillis = 0;

	if (millis() - previousMillis > interval)
		{
			previousMillis = millis();
			{
				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");
			}
		}
}

 

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Да уж правильно сказал ЕвгенийП.

Попросили меня как то скетч поправить для устройства отсечки оборотов двигателя.

Изначально было строк 10кода и работало, через pulseIn().

В итоге получилось такое:

Одна из вариации итоговой программы , всего их было штук 15

/*
значения таймера для разных оборотов
RPM3000_TIME=10000мкс=2500тиков
RPM4000_TIME=7500мкс=1875тиков
RPM5000_TIME=6000мкс=1500тиков
RPM6000_TIME=5000мкс=1250тиков
один тик таймера 4мкс
*/

#include <EEPROM.h>
#include <avr/interrupt.h>//библиотека прерываний по таймеру
#include <Arduino.h>
#define RPM3000_TIME 2500
#define RPM4000_TIME 1875
#define RPM5000_TIME 1500
#define RPM6000_TIME 1250

#define output 5 //выходной пин отсечки
#define modeSet 4 //пин кнопки выбор режима
#define clutchPin A0
#define switch1 6
#define switch2 7
#define switch3 8
#define switch4 9
#define switch5 10
#define switch6 11
#define modeLedPin 3
int miss_cycles=0;//переменная для отсчета поопусков цикла
#define PASSVALUE 2//количество циклов, которое будем пропускать

#define HM_rpm3000_pause1 15000
#define HM_rpm3000_pause2 4000
#define HM_rpm4000_pause1 7500
#define HM_rpm4000_pause2 3000
#define HM_rpm5000_pause1 6000
#define HM_rpm5000_pause2 2400
#define HM_rpm6000_pause1 2000
#define HM_rpm6000_pause2 1600

#define SM_rpm3000_pause1 15000
#define SM_rpm3000_pause2 4000
#define SM_rpm4000_pause1 7500
#define SM_rpm4000_pause2 3000
#define SM_rpm5000_pause1 6000
#define SM_rpm5000_pause2 2400
#define SM_rpm6000_pause1 2000
#define SM_rpm6000_pause2 1600

//#define PASS_ON
#define BUGFIX

//константы работы с кнопкой
//паузы рабочего  режима 2
long work_pause1,work_pause2;
byte work_mode_1_2;
volatile boolean cut=0;
byte pin_num=142;
enum BtnState{
RELEASE,
SHORT,
LONG};

class btn//создадим класс кнопок
{public://общие функции
 int key(int pin);
private://личные переменные и функции класса
 unsigned long start_press=0;//переменная времени нажатия кнопки
 unsigned long pressTime=0;//переменная длительности нажатия кнопки
 boolean pressFlag=0;//переменная флага нажатия
//переменные состояния/временного состояния/нажатия кнопки
 byte num=0,_num=0,button=0; 
};

uint32_t timer=0;//переменная мигания светодиода
btn Btn1;
byte MODE=1;

//=========================

//функция класса Btn(обработчик кнопок)
int btn::key(int Sb){ 
button=!digitalRead(Sb);//читаем состояние кнопки
	if(!button){num=0;}//если кнопка отпущена, выдаем результат 0
	if(button&&!pressFlag)//если кнопка нажата и флаг опущен
	{pressTime=millis()-start_press;//считаем время нажатия кнопки
		if(millis()-start_press>=2000){//если нажатие больше 2 сек
			pressFlag=1;//поднимаем флаг
num=2;//значение кнопки 2
pressTime=0;//сбрасываем длительность нажатия
		}
		}
	if(!button){//если кнопка отпущена
 start_press=millis();//сбрасываем время нажатия
pressFlag=0;//опускаем флаг
}

	if(!button&&!pressFlag){//если кнопка и флаг отпущены
		if(pressTime>50&&pressTime<2000)//а время нажатия больше 50мс, но меньше 2сек
		{pressTime=0;//сбрасываем длительность нажатия
num=1;}//значение кнопки 1
}
_num=num;
num=0;
	return _num;//возвращаем значение кнопки
}
//=========================

uint32_t now_millis=millis();
volatile bool cutoff_flag=0,check_flag;
uint16_t counter_work;
unsigned long blink_time;
enum WORKMODE{NORMAL_MODE=1,MODE_RPM3000,MODE_RPM4000,MODE_RPM5000,MODE_RPM6000};
byte KEY;

//===============ФУНКЦИИ===========

//в режиме работа функция выполняемая по достижению счетчиком значения сравнения
ISR(TIMER1_COMPA_vect){
cli();//запрещаем прерывания
TCNT1=0;//сбрасываем счетчик
check_flag=0;//опускаем флаг
sei(); //разрешаем прерывания
}

//по внешнему прерыванию
void work_count(){
cli();//отключаем прерывания
TCNT1=0;//сбрасываем значение счетчика
if(check_flag){//если флаг проверки поднят
        cutoff_flag=1;}//поднимаем флаг отсечки
check_flag=1;//поднимаем флаг проверки
/*принцип работы: при каждом сигнале с датчика, поднимаем флаг что сигнал пришел, если не успеем его сбросить прерыванием по таймеру, то тогда отсечка*/
    cut=1;
sei();//включаем прерывания
}

void check_mode(){
    switch(work_mode_1_2){
        case 0:
    if(!digitalRead(switch1)){MODE=NORMAL_MODE;}
     if(!digitalRead(switch2)){MODE=MODE_RPM3000;OCR1A=RPM3000_TIME;
   work_pause1=SM_rpm3000_pause1;
  work_pause2=SM_rpm3000_pause2;
        }
     if(!digitalRead(switch3)){MODE=MODE_RPM4000;OCR1A=RPM4000_TIME;
        work_pause1=SM_rpm4000_pause1;
  work_pause2=SM_rpm4000_pause2;}
    if(!digitalRead(switch4)){MODE=MODE_RPM5000;OCR1A=RPM5000_TIME;
        work_pause1=SM_rpm5000_pause1;
  work_pause2=SM_rpm5000_pause2;}
    if(!digitalRead(switch5)){MODE=MODE_RPM6000;OCR1A=RPM6000_TIME;
        work_pause1=SM_rpm6000_pause1;
  work_pause2=SM_rpm6000_pause2;
 }
        break;
        case 1:
        if(!digitalRead(switch1)){MODE=NORMAL_MODE;}
     if(!digitalRead(switch2)){MODE=MODE_RPM3000;OCR1A=RPM3000_TIME;
   work_pause1=HM_rpm3000_pause1;
  work_pause2=HM_rpm3000_pause2;
        }
     if(!digitalRead(switch3)){MODE=MODE_RPM4000;OCR1A=RPM4000_TIME;
        work_pause1=HM_rpm4000_pause1;
  work_pause2=HM_rpm4000_pause2;}
    if(!digitalRead(switch4)){MODE=MODE_RPM5000;OCR1A=RPM5000_TIME;
        work_pause1=HM_rpm5000_pause1;
  work_pause2=HM_rpm5000_pause2;}
    if(!digitalRead(switch5)){MODE=MODE_RPM6000;OCR1A=RPM6000_TIME;
        work_pause1=HM_rpm6000_pause1;
  work_pause2=HM_rpm6000_pause2;
 }
        break;
        }
#ifdef BUGFIX
        Serial.print("mode= ");
        Serial.println(MODE);
#endif
}

#ifdef PASS_ON
void PASS(){
    if(cut&&!cutoff_flag){
        digitalWrite(output,1);
        delayMicroseconds(work_pause2);
        digitalWrite(output,0);
        cut=0;
    }
    if(cutoff_flag){//если флаг отсечки поднят
            if(!miss_cycles){//если не надо пpопускать циклы
miss_cycles=PASSVALUE;
if(digitalRead(2)){//ждем сигнала с пина 2
digitalWrite(output,1);//включаем
delayMicroseconds(work_pause2);//даем задержку на выключение
digitalWrite(output,0);//выключаем
}
                }//опускаем флаг отсечки
            else{//если надо пропускать
            miss_cycles--;
                }       
    }       
cutoff_flag=0;cut=0;    
}//end PASS func
#else
void PASS(){
     if(cutoff_flag){//если флаг отсечки поднят
if(digitalRead(2)){//ждем сигнала с пина 2
delayMicroseconds(work_pause1);//даем задержку на включение
digitalWrite(output,1);//включаем
delayMicroseconds(work_pause2);//даем задержку на выключение
digitalWrite(output,0);//выключаем
            cut=0;
}
cutoff_flag=0;}//опускаем флаг отсечки
else{//а если флаг отсечки опущен
    if(cut&&!cutoff_flag){   digitalWrite(output,digitalRead(2));}}//то просто ретранслируем сигнал с пина 2 на пин выхода
    
}

#endif



void SHIFT(){
     if(cutoff_flag){//если флаг отсечки поднят
if(digitalRead(2)){//ждем сигнала с пина 2
delayMicroseconds(work_pause1);//даем задержку на включение
digitalWrite(output,1);//включаем
delayMicroseconds(work_pause2);//даем задержку на выключение
digitalWrite(output,0);//выключаем
            cut=0;
}
cutoff_flag=0;}//опускаем флаг отсечки
else{//а если флаг отсечки опущен
    if(cut&&!cutoff_flag){   digitalWrite(output,digitalRead(2));}}//то просто ретранслируем сигнал с пина 2 на пин выхода
    
}//end SHIFT func

void WORK_FUNC(){
if(KEY==SHORT){
work_mode_1_2=!work_mode_1_2;
        check_mode();
              }
    
if(MODE==NORMAL_MODE||!digitalRead(clutchPin)){digitalWrite(output,digitalRead(2));
        digitalWrite(modeLedPin,0);
        }else{  
    switch(work_mode_1_2){
            case 0:PASS();
            digitalWrite(modeLedPin,1);
            break;
            
            case 1:SHIFT();
            if(millis()-blink_time>=500){
                blink_time=millis();
                digitalWrite(modeLedPin,!digitalRead(modeLedPin));
            }
            break;}//end switch
        }//end else    
}//end func



//цикл настройки
void setup(){
    if(EEPROM.read(55)!=pin_num){
        while(1){
            digitalWrite(output,digitalRead(2));
            KEY=Btn1.key(modeSet);
            if(KEY==1)digitalWrite(modeLedPin,!digitalRead(modeLedPin));
        }
    }
#ifdef BUGFIX
Serial.begin(9600);
#endif
pinMode(output,OUTPUT);//настроим пин отсечки как выход
pinMode(modeSet,INPUT_PULLUP);//пин кнопки как вход с подтяжкой к +5в
    pinMode(clutchPin,INPUT_PULLUP);
pinMode(modeLedPin,OUTPUT);
    for(int i=switch1;i<=switch6;i++)
        {pinMode(i,0x2);}
attachInterrupt(0,work_count,RISING);//на внешнее прерывание назначаем функцию work_count()
TCCR1A=0;//сбрасываем настройки таймера 1А
TCCR1B=0;// сбрасыва��м настройки таймера 1В
TCNT1=0;//сбрасываем счетчик
//Устанавливаем источник тактов -> 1/(16000000/64)* 256 = 1 мс
TCCR1B =(1<<CS00)|(1<<CS01);
//check_mode();
TIMSK1|=(1<<OCIE1A);//настроим таймер на сравнение
    digitalWrite(modeLedPin,work_mode_1_2);

}//end setup

//основной цикл
void loop(){
KEY=Btn1.key(modeSet);//опросим кнопку и ее значение присвоим переменной KEY 
   if(digitalRead(MODE+5)){
check_mode() ;
        }
    
WORK_FUNC();
}//конец основного цикла



 

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Теперь по замечаниям:

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сек через миллис. Ну до кучи можно ещё разделитель использовать ":" между часами/минутами и мыргать им раз в полсекунды.

 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

UB3AFB пишет:

Покритикуйте код

Вспомнилась "критика бегуна" из из известного фильма - «Как то он не концептуально пробежал ... да пошёл ты в жопу!»