проблеммы с прерываниями...

flat
Offline
Зарегистрирован: 05.02.2015

Первый раз столкнулся ... вроде все понятно ... однако не работает...

Подключен 4 разрядный семисегментный индикатор. Он точно работает ... цифры выводил любые ...  

Диод моргает исправно ... но на вывод идет 0000... тоесть не растет переменная oborots. Не идет в обработчик прерывания.

Подключение

код

#include <TM1637.h>

#define CLK 10 //определим константы как номера пинов на которые будут соединены с одноименными пинами на модуле
#define DIO 9 //это нужно будет позже
int flash = 11; //порт выхода генератора
int taho=2;//вход тахометра

volatile int time1 = 0;
volatile int time2 = 0;
volatile int oborots = 0;


TM1637 tm1637(CLK, DIO); //создаем экземпляр объекта типа «TM1637», с которым будем далее работать и задаем пины.
// можно было и не определять константы, а написать проще — вместо трёх предыдущих строк одну:
// TM1637 tm1637(3,2);, но так как мы сделали наглядней
int n1, n2, n3, n4, n;
unsigned long int time;

void setup()
{
  tm1637.init();// инициализация библиотеки «TM1637.h»
  tm1637.set(BRIGHT_TYPICAL);//установка яркости указанная константа равна 2, значение по умолчанию
  pinMode (flash, OUTPUT);
  pinMode (taho, INPUT);
  attachInterrupt(2, merilka, RISING);
}

void loop()
{

    razbivka();
    printdisplay();
    miganie();

}
void printdisplay() {
  tm1637.display(0, n1); //1 цифра дисплея
  tm1637.display(1, n2); //2
  tm1637.display(2, n3); //3
  tm1637.display(3, n4); //4
}

void razbivka () {
  n4 = oborots % 10;
  oborots = oborots - n4;
  n3 = ((oborots % 100) / 10);
  oborots = oborots - n3 * 10;
  n2 = ((oborots % 1000) / 100);
  oborots = oborots - n2 * 100;
  n1 = ((oborots % 10000) / 1000);
  Serial.println(n1);
}

void miganie() {
  time = millis();
  if ((time % 1000) < 10) {
    digitalWrite (11, HIGH);
    delay(100);
  }
  digitalWrite (11, LOW);
}

void merilka () {
oborots = oborots + 1; 

}

 

flat
Offline
Зарегистрирован: 05.02.2015

возможно сигнал надо снимать до резистора? просто плату не хочу спалить .... 

nik182
Offline
Зарегистрирован: 04.05.2015

Для начала нужно посмотреть что за сигнал на ножке 2. Или подключить кнопку ко второму выходу и к + питания, вход нагрузить резистором на землю. Понажимать и посмотреть что будет. Если ничего не будет. Вот тогда разбираться. И не плохо было бы в разбивке не oborots обрабатывать, а окружив noInterrupts(); Interrupts();  присвоить значение другой переменной и уже эту переменную обрабатывать. На схеме не показан датчик. Или снимать с резистора.

flat
Offline
Зарегистрирован: 05.02.2015

за окружение спасибо ... 

по первому совету.... нет у мну осцилографа ... даж мультиметра под рукой нет ) 

но диод моргает ... знач импульс на порту должен быть

flat
Offline
Зарегистрирован: 05.02.2015

тоесть кнока идет между плюсом и 2 входом... и между ними резисор на землю? в электроннике не силен ) 

flat
Offline
Зарегистрирован: 05.02.2015

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

частота мигания диода около 1 секунды... так что проблемма не в окружении отключением прерывания.... у мну ощущение что обработчик прерывания не стартует ... 

nik182
Offline
Зарегистрирован: 04.05.2015

А как он может работать, если вы не обеспечили сигнал на входе? Резистор от входа на землю. 

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

flat пишет:

тоесть кнока идет между плюсом и 2 входом... и между ними резисор на землю? в электроннике не силен ) 

Возможно два варианта: кнопку к плюсу или к минусу. Также нужно правильно настроить фронт срабатывания прерывания: по возрастающему (rising) или по ниспадающему (falling).

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

nik182 пишет:

А как он может работать, если вы не обеспечили сигнал на входе? Резистор от входа на землю. 

О, а я уж подумал, что мне одному показалось что вход намертво заземлён :) Мало того, скечт всё равно никогда не заработает -аттач интеррапт аттачится непонятно к чему.

flat
Offline
Зарегистрирован: 05.02.2015

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

flat
Offline
Зарегистрирован: 05.02.2015

Jeka_M пишет:

flat пишет:

тоесть кнока идет между плюсом и 2 входом... и между ними резисор на землю? в электроннике не силен ) 

Возможно два варианта: кнопку к плюсу или к минусу. Также нужно правильно настроить фронт срабатывания прерывания: по возрастающему (rising) или по ниспадающему (falling).

щас получается 1 режим... тока вместо кнопки светодиод

flat
Offline
Зарегистрирован: 05.02.2015

dimax пишет:

nik182 пишет:

А как он может работать, если вы не обеспечили сигнал на входе? Резистор от входа на землю. 

О, а я уж подумал, что мне одному показалось что вход намертво заземлён :) Мало того, скечт всё равно никогда не заработает -аттач интеррапт аттачится непонятно к чему.

подробнее? вроде к мерилке атачится нет ? 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

аттачинтеррапт ( 2.... ) и вход 2 - это не одно и тоже.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

flat пишет:

подробнее? вроде к мерилке атачится нет ? 

Прочтите внимательно -  AttachInterrupt. Там нужно указывать номер прерывания, а не номер пина.

nik182
Offline
Зарегистрирован: 04.05.2015

Первый режим не очень получается. Не понятно какой у вас светодиод и сколько на нём падает вольт. Просто подключите вход 2 к любой свободной ноге и дергайте её вместе с диодом - параллельно. 100% гарантия что сработает.

flat
Offline
Зарегистрирован: 05.02.2015

dimax пишет:

аттачинтеррапт ( 2.... ) и вход 2 - это не одно и тоже.

 

перечитал еще раз Статьи ... там 0 должен стоять да ? ) ...

поправил ... таймер бежит непрерывно ... при мигании диода раз в секунду... оборотс набирает +10-15 единиц... но все равно спасибо ... 

nik182
Offline
Зарегистрирован: 04.05.2015

Да. Эх, слона то я и не приметил....

----

Т.е считает больше чем импульсов? 

flat
Offline
Зарегистрирован: 05.02.2015

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

 

диод не горит ... а счетчик бежит ) 

nik182
Offline
Зарегистрирован: 04.05.2015

Поставте параллельно резистору конденсатор на 1000 пикофарад. А ещё лучше подключить не прямо к резистору, а через другой резистор около 1кОм и между ножкой 2 и землёй поставить 10 нанофарад. Фильтр от звона поставить. Должно помочь. Если программа не очень занята, можно в прерывании организовать задержку с помощью пустого цикла for со счетом где то до 1000.       

flat
Offline
Зарегистрирован: 05.02.2015

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

flat
Offline
Зарегистрирован: 05.02.2015

Спасибо все зароаботало 

код:

#include <TM1637.h>
#define CLK 10 //определим константы как номера пинов на которые будут соединены с одноименными пинами на модуле
#define DIO 9 //это нужно будет позже

int taho = 2; //вход тахометра
volatile unsigned long int time1 = 0; // переменные для расччета оборотов
volatile unsigned long int time2 = 0;
unsigned long int time4 = 0;
volatile int time, time5, time6, time7;

int oborots = 0;

TM1637 tm1637(CLK, DIO); //создаем экземпляр объекта типа «TM1637», с которым будем далее работать и задаем пины.
// можно было и не определять константы, а написать проще — вместо трёх предыдущих строк одну:
// TM1637 tm1637(3,2);, но так как мы сделали наглядней
int n1, n2, n3, n4, n; //переменные для вывода на индикатор


void setup()
{
  tm1637.init();// инициализация библиотеки «TM1637.h»
  tm1637.set(BRIGHT_TYPICAL);//установка яркости указанная константа равна 2, значение по умолчанию
  pinMode (taho, INPUT);
  attachInterrupt(0, merilka, RISING);
  Serial.begin(9600);

}

void loop()
{
  if (time2 - time4 > 500)
  {
    printdisplay();
    time4 = millis();

  }
}

void printdisplay ()
{
  n = time;
  n4 = n % 10;
  n = n - n4;
  n3 = ((n % 100) / 10);
  n = n - n3 * 10;
  n2 = ((n % 1000) / 100);
  n = n - n2 * 100;
  n1 = ((n % 10000) / 1000);
  tm1637.display(0, n1); //1 цифра дисплея
  tm1637.display(1, n2); //2
  tm1637.display(2, n3); //3
  tm1637.display(3, n4); //4
}

void merilka () {
  time1 = time2;
  time2 = millis();
  time = ((time2 - time1)); //расчитываем обороты в секунду.
  time = (time + time5) / 2; //Усредняем значения для устранния погрешности изменений
  time5 = time;
  time = (time6 + time) / 2;
  time6 = time;
  time = time + 1; //уравниваем время между импульсами с задержкой в генераторе
  time = 60000 / time; // Получаем обороты в минуту
  time = (time - (time % 10)); //округляем значения до 10;

}

Но есть проблемма ... чем выше обороты тем больше погрешность измерений. Такак меряю функцией millis(). Почитал для функции Micros() описание .... хватает ее на 70 минут ... можно ли ее программно сбросить на 0 не перезагружая ардуино ? Чтобы повысить точнось. 

При Millis() на 6000 оборотах в секунду 1 милисекунда меняет сразу на 600 оборотов... при 3000 обортах на 143 оборота

Что как бы многовато. 

Ну и приму советы как усреднить значения проще ) я придумал пока только так ) . 

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

flat пишет:

Почитал для функции Micros() описание .... хватает ее на 70 минут ... можно ли ее программно сбросить на 0 не перезагружая ардуино ?

обязательно.

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

flat
Offline
Зарегистрирован: 05.02.2015

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

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

flat пишет:

Шутки шутками ... но я вижу использование только так... сбрасывать в 0 на каждом измерении... иначе на стыке сброса будет ошибка... 

покажи, в каком месте кода у тебя случится ошибка?

flat
Offline
Зарегистрирован: 05.02.2015

тут 

57   time2 = millis();
58   time = ((time2 - time1));

 

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

flat пишет:

тут 

57   time2 = millis();
58   time = ((time2 - time1));

ты проверял?

4294967295 - 4294967285 = 10
0          - 4294967286 = 10
...
9          - 4294967295 = 10
10         - 0          = 10

 

flat
Offline
Зарегистрирован: 05.02.2015

щас проверяю.... эта конструкция дает задержку 480 микросекунд.... хотя моргание стоит раз в 66 милисикунд .... пока хз откуда цифра... просто заменил мллис на микрос

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

flat пишет:

щас проверяю.... эта конструкция дает задержку 480 микросекунд.... хотя моргание стоит раз в 66 милисикунд .... пока хз откуда цифра... просто заменил мллис на микрос

я тебе пример привёл, который показывает, что твоя формула успешно переползает из до переполнения в переполнение

flat
Offline
Зарегистрирован: 05.02.2015

разобрался ... тип переменной тайм просто инт был ... тоесть вычитание работает норм при сбросе таймера ...  спасибо 

flat
Offline
Зарегистрирован: 05.02.2015

Всем спасибо за помошь .. работает с точностью до 10 оборотов в минуту .... устроит такая точность ... осталось мелочи... оптопару прикрутить ... есть несколько вариантов оптопар ... и модуль опторазвязки 4 канальный... буду читать как подключать )