РЕШЕНО Помогите разобраться что так тормозит loop?

Тема в разделе "Arduino & Shields", создана пользователем olegoriy, 14 авг 2020.

  1. olegoriy

    olegoriy Гик

    Друзья не чего не могу понять. Что так тормозит loop?
    Использую внешнее прерывание для подсчета оборотов и oled экран куда и хочу выводить обороты с неким коэффициентом.
    Для изменения коэффициента использую кнопку.
    Удерживаю кнопку, но изменения происходят раз в секунду где то.
    Да и все что пихаю в LOOP тоже исполняется раз в секунду.
    В чем проблема? Помогите плиз!!!
    Код (C++):
    #define buzz 8
      #define knopka 9  
      #define pin_SW_SDA 5                                              
      #define pin_SW_SCL 4                                              
      #include <Wire.h>
      #include <iarduino_OLED.h>                                            
    iarduino_OLED myOLED(0x3C);                                        
      extern uint8_t MediumFontRus[];
      unsigned long lastflash;
      int RPM;
      int blade = 1;                                      
                                               
                                                                         
    void setup(){
        pinMode(knopka, INPUT_PULLUP);                                                      
        myOLED.begin();                                                  
        myOLED.setFont(MediumFontRus);
        attachInterrupt(0,sens,RISING);                                      
    }    

    void sens() {
      RPM=(60/((float)(micros()-lastflash)/1000000))/blade;  //расчет
      lastflash=micros();  //запомнить время последнего оборота
    }                                                            
    void loop(){
     
         if (!digitalRead(knopka)) {
          blade=blade+1;
          if(blade>20){
            blade=1;
          }
           }                                                  
                             
        myOLED.setCursor(30,15);          
        myOLED.print(RPM);
        myOLED.print("        ");
        myOLED.setCursor(25,35);                  
        myOLED.print(" обр/м");
        myOLED.setCursor(5,55);
        myOLED.print("лопасть-");
        myOLED.print(blade);
        myOLED.print(" ");
       
        if ((micros()-lastflash)>1000000){ //если сигнала нет больше секунды
        RPM=0;  //считаем что RPM 0
      }
       
    }
     
  2. parovoZZ

    parovoZZ Гуру

    Так не делают. Необходимо ввести признак длительного удержания кнопки и изменять параметр по нему через таймер. Лучше всего это делать через конечный автомат.
     
    olegoriy нравится это.
  3. olegoriy

    olegoriy Гик

    Это понятно. В оригинале было у меня так:
    Код (C++):
    unsigned long r = millis();
         if (!digitalRead(knopka)) {
          if(r - p > i){
           blade=blade+1;
           if(blade>20)blade=1;
            p = r;
            }
            }  
    Вопрос чуть в другом, все что происходит в цикле выполняется где-то раз в 500 мл.секунд
     
  4. olegoriy

    olegoriy Гик

    Может ли все так тормозить из за библиотеки oled экрана? Или может я ее не так использую?
     
  5. parovoZZ

    parovoZZ Гуру

    как определил?
     
    olegoriy нравится это.
  6. Nekto_nikto

    Nekto_nikto Гик

    Ну мне кажется что в вашем случае все дело в выбранном алгоритме обработки, а именно в том что для подсчета вы выбрали нулевое прерывание, которое у вас судя по всему все время и вызывается, а т.к. имеет по умолчанию больший приоритет перед основной программой, сжирает почти все процессорное время и тем больше сжирает чем больше оборотов. У OLED экранов если я все правильно понимаю свой процессор на борту, который обработкой графики занимается и экран в вашем случае скорее всего ни при чем.
     
    olegoriy и arkadyf нравится это.
  7. parovoZZ

    parovoZZ Гуру

    Нет никакого процессора. Там контроллер экрана, но никакой обработкой он заниматься не способен.
    Нулевое прерывание - это ресет. У него прерывание по переднему фронту.
     
    olegoriy нравится это.
  8. olegoriy

    olegoriy Гик

    Подключил бипер и задал тон 1000 на 10 миллисекунд и за место пипипипипипи у меня пи..........пи............пи ......... :)
     
    issaom нравится это.
  9. parovoZZ

    parovoZZ Гуру

    оригинально.
    Весь код надо переписывать.
     
    olegoriy нравится это.
  10. Nekto_nikto

    Nekto_nikto Гик

    Я бы в вашем случае использовал Timer0 и Timer1.
    Timer0 запрограммировал бы на прерывание по переполнению через ну скажем 0,5с и в обработчике прерывания уже бы использовал Timer1 для определения текущего периода между двумя вращениями колеса, ну и по периоду бы уже вычислял количество оборотов в секунду и выводил бы на экран, благо у Timer1 разрешение 16 бит.
     
    olegoriy нравится это.
  11. b707

    b707 Гуру

    конечно неправильно.
    Зачем вы при каждом входе в loop() обновляете весь экран? -
    Обновляйте:
    а)только то, что меняется - RPM и blade
    и б)только тогда, когда данные реально поменялись
     
    olegoriy и Andrey12 нравится это.
  12. olegoriy

    olegoriy Гик

    Спасибо, теперь разобрался. Постоянные надписи кинул в сетап, blade вывожу на экран только при нажатии кнопки, RPM вывожу на экран раз в пол секунды. Все заработало как надо. Большое спасибо!!!