Millis() или МК, кто тормозит?

StasOn
Offline
Зарегистрирован: 10.05.2017

Прошу меня сильно не пинать, в программировании не силен. В общем ситуация следующая:

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

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

Т. е. если скетч голый то светодиоды включаются на 10 секунд, между включениями пауза 5 секунд, а если скетч содержит другие функции (вывод на дисплей, обработка кнопок и др.) то светодиоды включаются уже на 50 секунд а пауза составляет 25 секунд. 

Я понимаю, что обработка digitalRead и digitalWrite занимает какое-то время, и сейчас буду изучать тему управления портами, но не могла ведь программа замедлится в 5 раз из-за 4 операторов?

#include <OLED_I2C.h>

class Button {
    byte pin, prev_state;
    bool _clicked, _held, _dblclicked;
    unsigned long pressed_time, uct, clct;
    static const unsigned int jtime = 10;
    static const unsigned int htime = 100;
    static const unsigned int dbltime = 300;
public:
    void process_button() {
        byte val = digitalRead(pin);
        _clicked = false;
        _dblclicked = false;
        if (val == 0 && prev_state == 1) {
            uct = 0;
            unsigned long now = millis();
            if (pressed_time == 0)
                pressed_time = now;
            if (now > pressed_time + jtime) {
                prev_state = val;
                _clicked = true;
                if (clct != 0 && now < clct + dbltime) {
                    _dblclicked = true;
                }
                clct = pressed_time;
            }
        } else if (val == 1 && prev_state == 0) {
            pressed_time = 0;
            if (uct == 0)
                uct = millis();
            if (millis() > uct + jtime) {
                prev_state = val;
                _held = false;
                uct = millis();
            }
        }
        if (val == 0 && prev_state == 0 && millis() > clct + htime) {
            _held = true;
        } else {
            _held = false;
        }
    }
    Button(byte _pin) :
            pin(_pin) {
        prev_state = 1;
        _dblclicked = _held = _clicked = false;
        clct = uct = pressed_time = 0;
    }
    bool is_clicked() {
        return _clicked;
    }
    unsigned long held_time() {
        if (_held)
            return millis() - clct;
        return 0;
    }
    bool is_dblclicked() {
        return _dblclicked;
    }
};

OLED  myOLED(SDA, SCL, 8);
extern uint8_t SmallFont[]; //подключаем шрифт
int Zar; //время заряда
int Raz; //время разряда
int Paz = 5; //время паузы
bool start; //переменная включения и выключения зарядки 
 
  bool mode_zar = 1; // 1 заряд / 0 разряд
  Button bZarUp(2);
  Button bZarDw(4);
  Button bRazUp(7);
  Button bRazDw(8); 
  Button bStart(12);
  
void setup() {
  Serial.begin(9600);
  myOLED.begin();
  myOLED.setFont(SmallFont);
  pinMode (2,INPUT_PULLUP);
  pinMode (4,INPUT_PULLUP);
  pinMode (7,INPUT_PULLUP);
  pinMode (8,INPUT_PULLUP);
  pinMode (12,INPUT_PULLUP);
  pinMode (3,OUTPUT);
  pinMode (5,OUTPUT);
  digitalWrite(3, LOW);
  digitalWrite(5, LOW);
  Zar=10;
  Raz=10;
  start=false;
  chargeLCD();
  dischargeLCD();
}

void correction()
{
  bZarUp.process_button();
  bZarDw.process_button();
  bRazUp.process_button();
  bRazDw.process_button();
    if (bZarUp.is_clicked()) { //обработка кнопки + время заряда
        Zar=Zar+5;
        myOLED.clrScr();
        chargeLCD();
        dischargeLCD();
    }
    if (bZarDw.is_clicked()) { //обработка кнопки - время заряда
        if (Zar >= 10){
          Zar=Zar-5;
          chargeLCD();
          myOLED.clrScr();
          chargeLCD();
          dischargeLCD();
        }
    }
    if (bRazUp.is_clicked()) { //обработка кнопки + время разряда
        Raz=Raz+5;
        myOLED.clrScr();
        chargeLCD();
        dischargeLCD();
    }
    if (bRazDw.is_clicked()) { //обработка кнопки - время разряда
        if (Raz >= 10){
          Raz=Raz-5;
          chargeLCD();
          myOLED.clrScr();
          chargeLCD();
          dischargeLCD();
        }
    }
}
void chargeLCD() //отображение на экране времени заряда
{
    if (Zar <=59)
    {
      myOLED.printNumI((Zar), 40, 0);
      myOLED.print("S", 55, 0);
      myOLED.update();
    }
  else
    {
      myOLED.printNumF((Zar)/60, 0, 40, 0);
      myOLED.print("M", 55, 0);
      myOLED.printNumF((Zar) % 60, 0, 65, 0);
      myOLED.print("S", 80, 0);
      myOLED.update();
    }
}

void dischargeLCD() //отображение на экране времени разряда
{
  if (Raz <=59)
    {
      myOLED.printNumI((Raz), 40, 20);
      myOLED.print("S", 55, 20);
      myOLED.update();
    }
    
  else
    {
      myOLED.printNumF((Raz)/60, 0, 40, 20);
      myOLED.print("M", 55, 20);
      myOLED.printNumF((Raz) % 60, 0, 65, 20);
      myOLED.print("S", 80, 20);
      myOLED.update();
    }
}

void relay() //функция работы реле
{
  static unsigned long past = 0;
  static unsigned long tZar = Zar * 1000UL;
  static unsigned long tRaz = Raz * 1000UL;
  static unsigned long tPaz = Paz * 1000UL;
  static byte mode = 0; // 0 заряд  /  1 пауза1 / 2 разряд / 3 пауза2
  
   if ((mode == 0) && millis() - past >= tPaz) { // Кончилась первая пауза начался разряд
    past = millis();
    mode = 1;
    digitalWrite(3, LOW);
    digitalWrite(5, HIGH);
  }
  if ((mode == 1) && millis() - past >= tRaz) { // Кончился разряд началась вторая пауза
    past = millis();
    mode = 2;
    digitalWrite(3, LOW);
    digitalWrite(5, LOW);
  }
  if ((mode == 2) && millis() - past >= tPaz) { // Кончилась вторая пауза начался заряд
    past = millis();
    mode = 3;
    digitalWrite(3, HIGH);
    digitalWrite(5, LOW);
  }
  if ((mode == 3) && millis() - past >= tZar) { // Кончился заряд началась первая пауза
    past = millis();
    mode = 0;
    digitalWrite(3, LOW);
    digitalWrite(5, LOW);
  }
}

void loop(){

  myOLED.print("T.Zar=", LEFT, 0);
  myOLED.print("T.Raz=", LEFT, 20);
   

  bStart.process_button();
  myOLED.update();

  if (bStart.is_clicked()) { //обработка кнопки Старт
      if (start==false){start=true;}
      else {start=false;}
    }
  if (start==false)
  {
    correction();
  }
  else
  {
    relay();
  }
}

Буду благодарен если объясните, как это можно починить.

Ардуинка у меня старенькая, китайская, МК - Atmega 328P-PU

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

StasOn пишет:

кто тормозит?

StasOn

StasOn
Offline
Зарегистрирован: 10.05.2017

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

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

Вы шуток и иронии совсем не воспринимаете? Или просто решили поиграть в обиженную гимназистку? Ну-ну, играйте ... А ответ на Ваш вопрос был абсолютно точен. Вы спросили, кто тормозит, Вам ответили.

А сглупили Вы или нет, то неизвестно. Вы же не указали какой именно библиотекой Вы пользуетесь. Попробуйте набрать в гугле "OLED_I2C.h github" и  посчитайте сколько их там разных. Ну и как Вам можно помочь, даже если у кого-то есть такое желание?

StasOn
Offline
Зарегистрирован: 10.05.2017

web: http://www.RinkyDinkElectronics.com/ - библиотека оттуда

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

Вы считаете что проблема может быть с библиотекой OLED? Может заменить на другую?

 

 

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

Мил-человек, в больнице и автосервисе вы платите деньги и получаете право "качать права" прости за каламбур.

Тут же, или идите в "Ищу исполнителя и предлагайте деньги за консультацию, или просите объяснить, без болтовни о высокомерии.

Да, мы - высокомерны, не нравится - скатертью по жопе. Вам никто ничего тут не должен. Новичек - никому не интересен. Что-то объяснять - наша добрая воля.

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

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

Вы ведь, наверняка, не полный кретин? Должны понимать, что любому из нас написать новый код в 10 раз проще, чем читать чужой и безграмотный.

Если Вы хотите, чтобы  Вам помогали править именно ваш код, то следует показать заинтересованность.

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

StasOn
Offline
Зарегистрирован: 10.05.2017

Мил-человек, я против высокомерия ничего не имею :-) Мне тут никто и ничего как вы выразились не должен. Все дело в том, что нормальный человек на вопрос ответит по нормальному, или пожмет плечами и отвернется, а извините "м * дак" будет выеживатся, ухмылятся и указывать на вашу несостоятельность. Я не боюсь ошибатся, не боюсь спрашивать. 

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/*to_StasOn.ino
  кнопки
*/
// устройство
int Zar; //время заряда
int Raz; //время разряда
int Paz = 5; //время паузы
unsigned long tZar = Zar * 1000UL;
unsigned long tRaz = Raz * 1000UL;
unsigned long tPaz = Paz * 1000UL;
bool start; //0 предустановка /1 работа
byte mode = 0; // 0 заряд  /  1 пауза1 / 2 разряд / 3 пауза2
// экран
#include <OLED_I2C.h>
OLED  myOLED(SDA, SCL, 8);
extern uint8_t SmallFont[]; //подключаем шрифт
void viev() { //отображение на экране времени заряда
  static uint32_t past = 0;
  if (millis() - past >= 500) {
    past = millis();
    myOLED.print("T.Zar=", LEFT, 0);
    myOLED.print("T.Raz=", LEFT, 20);
    myOLED.clrScr();
    if (Zar <= 59) {
      myOLED.printNumI((Zar), 40, 0);
      myOLED.print("S", 55, 0);
      myOLED.update();
    } else {
      myOLED.printNumF((Zar) / 60, 0, 40, 0);
      myOLED.print("M", 55, 0);
      myOLED.printNumF((Zar) % 60, 0, 65, 0);
      myOLED.print("S", 80, 0);
      myOLED.update();
    }
    if (Raz <= 59) {
      myOLED.printNumI((Raz), 40, 20);
      myOLED.print("S", 55, 20);
      myOLED.update();
    } else {
      myOLED.printNumF((Raz) / 60, 0, 40, 20);
      myOLED.print("M", 55, 20);
      myOLED.printNumF((Raz) % 60, 0, 65, 20);
      myOLED.print("S", 80, 20);
      myOLED.update();
    }
  }
}

//светодиод
class Cl_Led {
  private:
    byte pin;
  public:
    Cl_Led(byte _pin): pin(_pin) {};
    setup() {
      pinMode (pin, OUTPUT);
      digitalWrite(pin, LOW);
    };
    ON() {
      digitalWrite(pin, HIGH);
    };
    OFF() {
      digitalWrite(pin, LOW);
    };
};
Cl_Led Led_Zar(3);
Cl_Led Led_Raz(5);
// кнопки
class Cl_Btn {
  private:
    byte pin ; // номер ноги на кнопке
    void (* Do_Btn)();
    bool btn, btn_old;
    bool bounce_btn = 0; // антидребезговый флаг
    uint32_t past = 0 ;
  public:
    Cl_Btn(byte _pin, void (* _Do_Btn)()): pin(_pin), Do_Btn(_Do_Btn) {};
    void setup() {
      pinMode(pin, INPUT_PULLUP);// подключить кнопку 1 с подтяжкой
      btn = digitalRead(pin); // прочитать реальное значение на выводе};
    }
    void loop() {
      if (! bounce_btn && btn != digitalRead(pin)) { // если прошел фронт изм на выводн
        bounce_btn = 1;                                 // выставить флаг
        past = millis();                         // сделать временую засветку
      }
      else if ( bounce_btn && millis() - past >= 5 ) { // если прошло антидребезговое время
        bounce_btn = 0;      // то снять флаг
        btn_old = btn ;
        btn = digitalRead(pin) ; // прочитать реальное значение на выводе
        if (btn_old && ! btn)  Do_Btn();
      }
    };
};
void Do_Btn_Zar_plus() { //обработка кнопки + время заряда
  if (start ) return;
  Zar = Zar + 5;
}
void Do_Btn_Zar_minus() { //обработка кнопки - время заряда
  if (start ) return;
  if (Zar >= 10) Zar = Zar - 5;
}
void Do_Btn_Raz_plus() { //обработка кнопки + время разряда
  if (start ) return;
  Raz = Raz + 5;
}
void Do_Btn_Raz_minus() { //обработка кнопки - время разряда
  if (start ) return;
  if (Raz >= 10) Raz = Raz - 5;
}
void Do_Btn_Start() { //обработка кнопки Старт
  if (start ) return;
  start = 1;
  mode = 0;
  tZar = Zar * 1000UL;
  tRaz = Raz * 1000UL;
  tPaz = Paz * 1000UL;
}
Cl_Btn Btn_Zar_plus (2  , Do_Btn_Zar_plus );
Cl_Btn Btn_Zar_minus(4  , Do_Btn_Zar_minus);
Cl_Btn Btn_Raz_plus (7  , Do_Btn_Raz_plus );
Cl_Btn Btn_Raz_minus(8  , Do_Btn_Raz_minus);
Cl_Btn Btn_Start    (12 , Do_Btn_Start    );

void relay_work() {   //функция работы реле
  if   (!start) return;
  static unsigned long past = 0;
  if ((mode == 0) && millis() - past >= tPaz) { // Кончилась первая пауза начался разряд
    past = millis();
    mode = 1;
    Led_Zar.OFF();
    Led_Raz.ON();
  }
  if ((mode == 1) && millis() - past >= tRaz) { // Кончился разряд началась вторая пауза
    past = millis();
    mode = 2;
    Led_Zar.OFF();
    Led_Raz.OFF();
  }
  if ((mode == 2) && millis() - past >= tPaz) { // Кончилась вторая пауза начался заряд
    past = millis();
    mode = 3;
    Led_Zar.ON();
    Led_Raz.OFF();
  }
  if ((mode == 3) && millis() - past >= tZar) { // Кончился заряд началась первая пауза
    past = millis();
    mode = 0;
    Led_Zar.OFF();
    Led_Raz.OFF();
  }
}
void setup() {
  // устройство
  Zar = 10;
  Raz = 10;
  start = false;
  // светодиоды
  Led_Zar.setup();
  Led_Raz.setup();
  // экран
  myOLED.begin();
  myOLED.setFont(SmallFont);
  // кнопки
  Btn_Start.setup();
  Btn_Zar_plus.setup();
  Btn_Zar_minus.setup();
  Btn_Raz_plus.setup();
  Btn_Raz_minus.setup();
}
void loop() {
  // экран
  viev();
  // кнопки
  Btn_Start.loop();
  Btn_Zar_plus.loop();
  Btn_Zar_minus.loop();
  Btn_Raz_plus.loop();
  Btn_Raz_minus.loop();
  // устройство
  relay_work();
}

ПС: люди высказавшие выше правы.

StasOn
Offline
Зарегистрирован: 10.05.2017

Спасибо Евгению. Как оказалось библиотека экрана видимо влияла на частоту МК. Переделал экран для работы по SPI протоколу, подключил, теперь все работает как надо. Осталось снова оформить красивый вывод. ))

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

StasOn пишет:

Как оказалось библиотека экрана видимо влияла на частоту МК. 

Только не на частоту, а просто загружала его по полной за счёт кривой реализации. Были б Вы менее обоидчивым и не называли бы меня как в посте №6, я бы Вам вчера ещё про это сказал.

StasOn
Offline
Зарегистрирован: 10.05.2017

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

Если вы восприняли мои слова на свой счет, то извините меня, я лично никого в виду не имел. 

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

Вот смотрите,

1. В той библиотеке используется программная реализация I2C (ни разу не аппаратная)

2. Вы зачем-то обновляете дисплей при каждом проходе loop (строки 207, 208, 212) (это не менее 50 кГц!) 

Зачем п.2  так часто? Максимальная скорость обновления дисплея, при которой человек успеет разглядеть обновления - раз в 20 миллисекунд, т.е. 50 раз в секунду. Быстрее обновлять нет смысла, человек всё равно ничего не увидит. Вы же обновляете примерно 50 тысяч раз в секунду. Зачем?

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

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

Обновляёте экран через каждые 20 мс (при помощи того же моллис) и у Вас будет огромный запас быстродействия на другие дела.

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

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

2. Вы зачем-то обновляете дисплей при каждом проходе loop (строки 207, 208, 212) (это не менее 50 кГц!) 

Зачем п.2  так часто? Максимальная скорость обновления дисплея, при которой человек успеет разглядеть обновления - раз в 20 миллисекунд, т.е. 50 раз в секунду. Быстрее обновлять нет смысла, человек всё равно ничего не увидит. Вы же обновляете примерно 50 тысяч раз в секунду. Зачем?

Евгений, зачем вводить человека в заблуждение?

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

Текстовый дисплей 1602 на вывод одного символа более или менее стандартной библиотекой тратит порядка 2 мс. Т.е. не то, что дисплей одновить 50000 раз в секунду, а один стмвол обновить 500 раз в секунду - это предел. Я тут создавал специально посвященную скорости вывода на этот дисплей тему, там совместными усилиями пришли к выводу, что если разогнать i2c до предела (880 кГц) и применить нестандартный протокол обмена при вылизанном по скорости коде можно добиться времени вывода одного символа примерно 110-120 мкс, т.е. все равно далеко до 50000 экранов в секунду. Но, как показывает преактка, хотя микросхема при указанных в дэйташите 100 кГц реально может работать на более высоких частотах, на 880 кГц она работает неустойчиво. Поэтому реальный предел скорости - это 180 мкс на символ.

С графичекими дисплеями - гораздо хуже. Опять же, при стандартной реализации дисплей можно обновлять всего единицы раз в секунду. В моей версии библиотеки для 0.96" OLED I2C мне удалось добиться вывода строк и битмэпа (не отдельных символов!) в темпе до 20 раз в секунду, но это уже близко к пределу. Где там 50000!

Единственное, в чем Вы правы, - это в том, что вывод на дисплей запросто может сожрать все процессорное время, и что частоту обновления экрана нужно ограничивать (т.е. по сути верные выводы при неверной посылке, что, впрочем, не противоречит логике).

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

andriano не придирайтесь. Он обновляет дисплей с частотой loop и в этом его проблема. Вы с этим не согласны? Именно это я и написал - сообщение было об этом. А 50 килогерц с потолка взятая "типичная" частот loop.

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

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

А 50 килогерц с потолка взятая "типичная" частот loop.

Если в loop стоит вывод на экран, эта величина сразу перестает быть "типичной". 

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

Особенно, если мы беремся делать оцеки интервалов времени или частот выполнения тех или иных фрагментов кода.

StasOn
Offline
Зарегистрирован: 10.05.2017

Нашел интересный ролик про дисплеи https://www.youtube.com/watch?v=lkWZuAnHa2Y там показана зависимость скорости вывода и размера скетча от используемой библиотеки. Я думаю так-же есть влияние на загруженность МК.

Вот решил подобным методом увеличить скорость и освободить память. С обновлением тоже нужно работать, обновлятся в функции loop дисплей больше не будет.  Или будет но реже. Хочу реализовать управление портами через регистры и применить максимально легкую библиотеку для ОЛЕД (либо без нее как в видеоролике).

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

Рука-лицо.

StasOn
Offline
Зарегистрирован: 10.05.2017

Если я буду обновлять экран отдельной функцией, например так: 

void updateLCD(){ myOLED.update();}

Или же я сразу напишу:

void loop()
{
.....
 myOLED.update();
}

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

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

А если данные будут меняться хотя 1000 раз в секунду, вы тоже будете с такой частотой обновлять экран.

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

andriano,

да прекратите Вы придираться - я указал человеку на проблему - попытка перерисовывать экран в каждом лупе. Указал правильно - Вы согласны? ну, и хватит об этом. Я уже сказал никаких оцено я не делал, 50 кгц сказано от бвылды. Давайте заменим 50 на 100500 - ничего не изменится. Проблема указана правильно. Давайте прекращать.

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

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

я указал человеку на проблему - попытка перерисовывать экран в каждом лупе. Указал правильно - Вы согласны?

По поводу того, с чем я согласен, а с чем - нет, я уже писал в посте №14.

Но если для Вас это важно, я еще раз с Вами соглашусь.

Цитата:

Давайте заменим 50 на 100500 - ничего не изменится.

Напомню, что 50 - это на самом деле 50 тысяч проходов цикла loop() в секунду. 

100500 тысяч проходов цикла loop() в секунду на 16-МГц процессоре это круто!

Снимаю шляпу!

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

andriano пишет:

Снимаю шляпу!

Напрасно, весна нынче поздняя. Наденьте! :)

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

Раньше надо было говорить, а сейчас уже потеплело.

StasOn
Offline
Зарегистрирован: 10.05.2017

Ребята, я понял, что обновление дисплея желательно обрабатывать по событию, а не помтоянно.Сейчас пытаюсь разобраться, как тот чувак упралял дисплеем без библиотеки.. Может и бесперспективно, зато зарядка для ума ))

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

StasOn пишет:

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

Независимо от появления новых результатов измерений обновлять алфавитно-цифровую информацию на дисплее разумно 5 - 10 раз в секунду. Чаще 10 нет смысла - глаза/мозги всё равно не обработают это мельтешение.

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

SLKH пишет:

обновлять алфавитно-цифровую информацию на дисплее разумно 5 - 10 раз в секунду.

Присоединяюсь. А 20 - уже просто физиологический предел.

А у ТС ненужное обновление всё процессорное время сжирает.

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

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

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

SLKH пишет:

StasOn пишет:

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

Независимо от появления новых результатов измерений обновлять алфавитно-цифровую информацию на дисплее разумно 5 - 10 раз в секунду. Чаще 10 нет смысла - глаза/мозги всё равно не обработают это мельтешение.

Разумнее 2-5 (или любое другое удобное число) раз в секунду проверять, нет ли данных для обновления, и обновлять показания, только если данные реально изменились.

StasOn
Offline
Зарегистрирован: 10.05.2017

Теперь во время ввода данных экран обновляется через каждые 200 миллисекунд, а во время работы вместе с реле. Убрав из программы библиотеки OLED использование динамической памяти снизилось с 66% до 9%, по крайней мере так пишет Arduino IDE.

Убрал одну кнопку.

Теперь хочу прикрутить обратный отсчет времени и автоматическое выключение экрана (говорят они выгорают). Ну и до кучи отказатся от digitalWrite/digitalRead.

Думаю, может стоит записывать последние введенные значения в EEPROM.