Хочу посмотреть во что превратят мой "код" профессионалы.

El
Offline
Зарегистрирован: 10.03.2016

Доброго времени суток уважаемые форумчане!
Собрал тут для себя устройство - автоматическая подсветка в прихожей и коридоре. В меру своих знаний и умений написал для него код. Код рабочий и работает так, как я и планировал. Просто мне стало интересно, если бы этот код писал профи, то у него он занял бы больше 5 строк?

Объясню принцип работы устройства:

Если сработл датчик движения (далее - ДД), и уровень освещенности (далее - УО) ниже определенного значения, и питание светодиодной ленты отключено, то мы включаем ленту.

Если во время работы ленты сработал ДД  и УО не привышает минимального значения, то мы продлеваем время жизненного цикла работающей подстветки.

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

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

все, что связано с LCD вводилось временно и использовалось для определения значения комфортного уровня освещенности на месте и для вывода полезной и не очень информации. После настройки уровня минимальной освещенности данные строки кода я удалил.


#include <LiquidCrystal.h> //дисплей использовался только для выяснения % освещенности на месте, чтоб не таскать с собой бук. Когда нужный процент освещенности найден, то можно удалить все упоминания об экране.
#include <EEPROM.h> //этот байт еепром используется для хранения предельного значения освещенности, просле превышения которого, лента загораться не будет. можно обойтись без него, но мне хотелось поиграться.
#define buttonPin 12 //пин датчика движения
#define ledPin 11 //пин подключения светодиодной ленты
#define lightMeterPin A0 //пин подключения датчика освещенности - фоторезистор, х/з что за марка, какой-то валялся
#define persentLight EEPROM.read(1) //чтоб каждый раз не писать этот еепром.
#define potentiometr A1 //подстроечник для настройки предела освещенности. используется для настройки уровня освещенности для включения ленты.
#define buttonValuePin 3 //пин кнопки для записи мануального значения освещенности в память устройства. можно и без нее, но я классную кнопку выпаял из старого сидюка, и мне захотелось её израсходовать.
byte manualValue; //значение подстроечника для записи в паять приведенное к %
unsigned long timer = 0; //таймер "дребезга" для датчика, с ним все понятно.
unsigned long timer1 = 0; //таймер для параметра timeToLive
boolean ledStatus = false; //статус светодиодной ленты (тру-вкл; фолс-выкл).
boolean powerOn = false; //параметр 1-лента включена, 2 - лента выключена
byte zad = 8; //задержака времени, влияющая на скорость плавного включения и плавного выключения светодиодной ленты.
unsigned long timeToLive = 5000; //время, которое должна прогореть лента, до проверки условий выхода из цыкла
unsigned long timer2 = 0; //используется для экрана, чтоб изображение не мельтешило. если от экрана отказываться, то спокойно можно удалять.
LiquidCrystal lcd(9, 8, 7, 6, 5, 4);

void setup() {
  //EEPROM.write(1, byte(50)); //Записать значение процента освещенности в память устройсва. Необходим для первого прогона, для присвоения дефолтного значения
  lcd.begin(20, 4);
  pinMode (buttonPin, INPUT); //датчик движения - вход
  pinMode (ledPin, OUTPUT); //лента - выход
  digitalWrite(ledPin, LOW); // подстраховаться и отключить подсветку при загрузке устройства.
  pinMode (lightMeterPin, INPUT); //датчик освещенности - вход
  pinMode(A1, INPUT); //подстроечный резистор для настройки минимального уровня освещенности.
  pinMode(buttonValuePin, INPUT); //кнопка для записи в память значения минимальной освещенности.
  delay(1500); //время, которое необходимо, чтоб протупил датчик движения
  lcd.setCursor(0, 0);
  lcd.print("Fotoresist."); //значение АЦП с фоторезистора/значение минимальной освещенности
  lcd.setCursor(0, 1);
  lcd.print("DD relay"); //статус датчика движения
  lcd.setCursor(0, 2);
  lcd.print("Timer"); //отсчет секунд с момента старта платы. Просто была строчка на экране лишняя.
  lcd.setCursor(0, 3);
  lcd.print("Manual val."); //значение АЦП с подстроечника установки уровня минимальной освещенности.
}

void loop() {
  if (digitalRead(buttonPin) == LOW && lightMeter() <= persentLight && powerOn == false /*&& first == false*/) { //то же, что и выше, только с выдержкой времени.
    lcd.setCursor(12, 1);
    for (byte i = 0; i <= 200; i++) { //полностью не зажигаю, и так ярко.
      analogWrite(ledPin, i);
      delay(zad);
    }
    powerOn = true;
    timer1  = millis(); //по нему отсчитывать жизненный цикл включенной ленты
  }
  if (millis() >= timer1 + timeToLive - 2000 && millis < timer1 + timeToLive && lightMeter() <= persentLight && digitalRead(buttonPin) == LOW) { //продлеваем TTL ввиду того, что люди еще шевелятся, а освещенность недостаточная.
    timer1 = millis();
  }
  if (powerOn == true && timer1 + timeToLive <= millis() && (lightMeter() > persentLight || digitalRead(buttonPin) == HIGH)) { //если питане ленты ВКЛ и ТТЛ вышел и (освещенность высокая или датчик движения молчит)
    lcd.setCursor(12, 1);
    for (byte i = 200; i > 0; i--) {
      analogWrite(ledPin, i);
      delay(zad);
    }
    digitalWrite(ledPin, LOW); //опять перестраховываюсь.
    powerOn = false;
    // first = false;
  }
  lcd.setCursor(12, 2); //вот с этого места выводим всякую инфу на экран. после настройки можно все это отключить.
  lcd.print ((millis() / 1000));
  if (timer2 + 500 <= millis()) {
    lcd.setCursor(12, 0); //АЦП фоторезистор
    lcd.print("       ");
    lcd.setCursor(12, 0);
    lcd.print(lightMeter());
    lcd.print("/");
    lcd.print(persentLight);
    manualValue = analogRead(potentiometr) / (1024 / 100);
    if (manualValue > 99) {
      manualValue = 99;
    }
    if (manualValue == 0) {
      manualValue = 1;
    }
    timer2 = millis();
    lcd.setCursor(12, 3);
    lcd.print(manualValue);
    lcd.print("  ");
    lcd.setCursor(12, 1);
    if (digitalRead(buttonPin) == HIGH) {
      lcd.print("ON ");
    } else {
      lcd.print("OFF");
    }
  }
  if (digitalRead (buttonValuePin) == HIGH) { //записываем значение минимального уровня освещенности в еепром.
    EEPROM.write(1, manualValue);
  }
}

byte lightMeter () { //функция для определения уровня освещенности в %
  byte persents = byte(analogRead(lightMeterPin) / (1024 / 100)); //не уверен, что в байте это значение считается правильно, но в данной конструкции это не играет существенной роли.
  return persents;
}

Уважаемые профи и не очень профи. Можете привести свое видение данного кода или его части? мне будет интересно на это посмотреть, может быть что-то перекачует в устройство, если я его буду повторять или существующее переделывать.

El
Offline
Зарегистрирован: 10.03.2016

Забыл сказать, если эту тему вдруг увидит Клапауций, то пусть он ее не запрещает!!!

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

El У вас неправильное представление о профессионалах программирования и их коде. Прежде всего программист не должен запутаться в своем коде, но при этом в этот код не обязан был понят постороними или же новичками.  Спросите как профессионал может запутаться в своем коде. Да легко . Если строк будет больше 1000 и при изменения внесены были не один раз и в течении не одного года. 

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

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

qwone пишет:

El У вас неправильное представление о профессионалах программирования и их коде. Прежде всего программист не должен запутаться в своем коде, но при этом в этот код не обязан был понят постороними или же новичками.  Спросите как профессионал может запутаться в своем коде. Да легко . Если строк будет больше 1000 и при изменения внесены были не один раз и в течении не одного года. 

Это у Вас неправильное представление о профессионалах программирования и их коде.

Код должен быть понятен для любого программиста, а не только для его автора.

Представьте, что из проекта уходит один программитст и приходит другой - он что, должен писать код с нуля?

Опять же, есть такое понятие, как разделение труда. Один программист (группа программистов) готовят продукт к выходу, а другой (группа) осуществляют его поддержку в то время, когда первая группа уже занята новой версией или другим проектом.

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

p19cc0r31d3ig1gb1c5unv8v0i.gif

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

andriano пишет:

Это у Вас неправильное представление о профессионалах программирования и их коде.

Код должен быть понятен для любого программиста, а не только для его автора.

Представьте, что из проекта уходит один программитст и приходит другой - он что, должен писать код с нуля?

Опять же, есть такое понятие, как разделение труда. Один программист (группа программистов) готовят продукт к выходу, а другой (группа) осуществляют его поддержку в то время, когда первая группа уже занята новой версией или другим проектом.

Ну это доброе пожелание. Делали как лучше, а получилось как всегда.  А если бы все так и было, как вы сказали, то не было понятия как "индийский код", "китайский код". И да там соблюдена буква подхода, но дух уже не тот. То есть вроде конструкции правильные, правильные и простые. А вот что делают не с первого раза разберешься.  А на вопрос: Та этот код непонятен? Идет такой же ответ: Так вы профессионал или любитель, если в "работающем" коде не разбираетесь.

Logik
Offline
Зарегистрирован: 05.08.2014

andriano пишет:

qwone пишет:

El У вас неправильное представление о профессионалах программирования и их коде. Прежде всего программист не должен запутаться в своем коде, но при этом в этот код не обязан был понят постороними или же новичками.  Спросите как профессионал может запутаться в своем коде. Да легко . Если строк будет больше 1000 и при изменения внесены были не один раз и в течении не одного года. 

Это у Вас неправильное представление о профессионалах программирования и их коде.

Код должен быть понятен для любого программиста, а не только для его автора.

А еще код должен быть без ошибок, должен быть мир во всем мире, должны смеятся дети и много чего должно быть.

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

По теме, код плотный, мне такой нравится, глубже не вникал ;)

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Просили комментарии?

1. ЕЕПРОМ не нужно читать в цикле, читайте его один раз. То есть не очень хорошо его в дефайн ставить. Пока прграмма работает - Вы пользуетесь переменной, при перезапуске - прочтете из ЕЕПРОМ, один раз, в сетапе.

2. 0-1023 от аналогового чтения не нужно пересчитывать в проценты, это портит код, да и пересчет, так как он написан - не работает.

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

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

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

вот

#define step_delay  8
#define max_val   200


int smoothOnOff (int dir, int newval)
{
  static int val=0;
  static uint32_t om=millis(); //old millis
  uint32_t nm=millis; //new millis

  // 0 используем для записи или чтения конкретного значения
  // если newval - в рамках - то запись
  // иначе функция возвращает текущее значение яркости
  // в программе, в дугих местах, нужно будет поменять
  //analodWrite на эту функцию
  if (dir == 0) 
    {
      if (0<=newval && newval<=max_val) val=newval;
      om=nm;
    }
    //step_delay вместо, простите delay(zad) ;) ;);)
  if (nm-om > step_delay) 
    {
    om=nm;
    if (dir == 1) val++; 
    if (dir == -1)val--;
    if (val < 0) val = 0;
    if (val > max_val) val=max_val;  
    analogWrite(ledPin,val);
    }
  return val;
}

указаны еще два дефайна для работы.

эту функцию нужно вызывать при входе в луп.

if (dir != 0) smoothOnOff(dir,0);

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

Logik
Offline
Зарегистрирован: 05.08.2014

wdrakula пишет:

1. ЕЕПРОМ не нужно читать в цикле, читайте его один раз. 

Да ладно, то еще мелочи по сравнению с многократной записю пока нажата кнопка - стр.90

Кстати, универсальный совет, перед записью в ЕЕПРОМ всегда считывать и побайтово сравнивать что есть и что пишется. Записывать только при различии. Экономим время и ресурс ЕЕПРОМ. Соответствующий код оформить в функцию через которую и делать все записи всегда.

А так, таки да. Согласен с написаным кроме вачдога. Там вопрос глубоко индивидуальный, надо больше знать о проекте.  

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

El пишет:
Можете привести свое видение данного кода или его части?

Код ламерский. Ошибки и полное отсутствие стиля.

timer2 + 500 <= millis()

Ошибка, нельзя к таймеру прибавлять, проделки Qwone...

if (digitalRead (buttonValuePin) == HIGH) { //записываем значение минимального уровня освещенности в еепром.
EEPROM.write(1, manualValue);
}

Теряюсь в догадках, сколько раз произойдет запись в EEPROM за время нажатия кнопки.

А это что? Особенно  / (1024 / 100);

manualValue = analogRead(potentiometr) / (1024 / 100);
    if (manualValue > 99) {
      manualValue = 99;
    }
    if (manualValue == 0) {
      manualValue = 1;
    }

так не пробовал: map(analogRead(potentiometr),0,1023,1,99)?

Если ошибки можно поправить, то стиль прививается годами.

 

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

qwone пишет:

...не было понятия как "индийский код", "китайский код".

Ну то есть по Вашим понятиям именно такой код и соответствует "правильному представлению о профессионалах программирования и их коде".

El
Offline
Зарегистрирован: 10.03.2016

wdrakula пишет:

1. ЕЕПРОМ не нужно читать в цикле, читайте его один раз. ... при перезапуске - прочтете из ЕЕПРОМ, один раз, в сетапе.

2. 0-1023 от аналогового чтения не нужно пересчитывать в проценты

3. "цикл в цикле",

4.Уж совсем для блеска, можно вочдог настроить.

5.

int smoothOnOff (int dir, int newval)

1. каюсь, даже не подумал, что читаю ЕЕПРОМ в цикле. А кнопку специально задумывал для настройки контроллера на лету,

2.  я это уже позже понял, когда устройство собрал.

3. Об этом даже не подумал ввиду того, что я представлял себе работу устройства именно так, как в коде написано. Но на будущее обязательно помечу себе этот пункт красным фламастером.

4. Я, к сожалению, не знаю, как это работает...

5. Код уже себе записал.

Logik пишет:

...то еще мелочи по сравнению с многократной записю пока нажата кнопка - стр.90

Кстати, универсальный совет, перед записью в ЕЕПРОМ всегда считывать и побайтово сравнивать что есть и что пишется...

Про запись даже не подумал во время написания программы.

Сверять ЕЕПРОМ - очень хорошая идея! учту.

Andy пишет:

Ошибка, нельзя к таймеру прибавлять

Почему?

Andy пишет:

Теряюсь в догадках, сколько раз произойдет запись в EEPROM за время нажатия кнопки.

много... (

Andy пишет:

А это что? Особенно  / (1024 / 100);

так не пробовал: map(analogRead(potentiometr),0,1023,1,99)?

А это мой код.

Не пробовал. Теперь попробую так, как показал.

Цитата:
==================================================================

Спасибо за конструктивную критику. Будем развиваться дальше.

a5021
Offline
Зарегистрирован: 07.07.2013

wdrakula пишет:
1. ЕЕПРОМ не нужно читать в цикле, читайте его один раз.

Чем плохо читать EEPROM столько раз, сколько вздумается?

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

a5021 пишет:

wdrakula пишет:
1. ЕЕПРОМ не нужно читать в цикле, читайте его один раз.

Чем плохо читать EEPROM столько раз, сколько вздумается?

плохо делать бесполезные вещи сейчас, когда мог бы делать что-то полезное сейчас

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

a5021 пишет:

wdrakula пишет:
1. ЕЕПРОМ не нужно читать в цикле, читайте его один раз.

Чем плохо читать EEPROM столько раз, сколько вздумается?

Если ты ждал фразы о том, что ЕЕПРОМ "сотрется", то ее не будет. Не сотрется, за время жизни устройства - точно "не сотрется".

Просто это плохой стиль. Тебе нравиццо - пиши так, мне - не нравится.

Или в любую дискуссию нужно свой нос засунуть?

Без тебя тут срача нет - скучновато что-то.

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

a5021 пишет:

wdrakula пишет:
1. ЕЕПРОМ не нужно читать в цикле, читайте его один раз.

Чем плохо читать EEPROM столько раз, сколько вздумается?

Вместо delay()?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

andriano пишет:

a5021 пишет:

wdrakula пишет:
1. ЕЕПРОМ не нужно читать в цикле, читайте его один раз.

Чем плохо читать EEPROM столько раз, сколько вздумается?

Вместо delay()?

Да не корми ж ты троля! не выгонишь потом его из темы. Пока модераторы не потрут.

Почитай страрые его срачи с ptr или с ОлегМ. Это ж по 10 страниц воды и газа.