Друзья не чего не могу понять. Что так тормозит 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 } }
Так не делают. Необходимо ввести признак длительного удержания кнопки и изменять параметр по нему через таймер. Лучше всего это делать через конечный автомат.
Это понятно. В оригинале было у меня так: Код (C++): unsigned long r = millis(); if (!digitalRead(knopka)) { if(r - p > i){ blade=blade+1; if(blade>20)blade=1; p = r; } } Вопрос чуть в другом, все что происходит в цикле выполняется где-то раз в 500 мл.секунд
Ну мне кажется что в вашем случае все дело в выбранном алгоритме обработки, а именно в том что для подсчета вы выбрали нулевое прерывание, которое у вас судя по всему все время и вызывается, а т.к. имеет по умолчанию больший приоритет перед основной программой, сжирает почти все процессорное время и тем больше сжирает чем больше оборотов. У OLED экранов если я все правильно понимаю свой процессор на борту, который обработкой графики занимается и экран в вашем случае скорее всего ни при чем.
Нет никакого процессора. Там контроллер экрана, но никакой обработкой он заниматься не способен. Нулевое прерывание - это ресет. У него прерывание по переднему фронту.
Подключил бипер и задал тон 1000 на 10 миллисекунд и за место пипипипипипи у меня пи..........пи............пи .........
Я бы в вашем случае использовал Timer0 и Timer1. Timer0 запрограммировал бы на прерывание по переполнению через ну скажем 0,5с и в обработчике прерывания уже бы использовал Timer1 для определения текущего периода между двумя вращениями колеса, ну и по периоду бы уже вычислял количество оборотов в секунду и выводил бы на экран, благо у Timer1 разрешение 16 бит.
конечно неправильно. Зачем вы при каждом входе в loop() обновляете весь экран? - Обновляйте: а)только то, что меняется - RPM и blade и б)только тогда, когда данные реально поменялись
Спасибо, теперь разобрался. Постоянные надписи кинул в сетап, blade вывожу на экран только при нажатии кнопки, RPM вывожу на экран раз в пол секунды. Все заработало как надо. Большое спасибо!!!