Как обработать сигнал с компаратора

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

Знаете, Вы бы удаляли, а не комментировали, а то читать невозможно.

Вы из сетапа удалили attachInterrupt, а как же она у Вас первый LOW-то поймает?

DmitryR
Offline
Зарегистрирован: 12.05.2017

Я там запутался, комментировал, когда код разбирал
Если рассматривать тот код, который вы прислали, то по моим соображениям: 
Удаляем 6 строку, 57 надо изменить, 65 и 66 тоже 
Использование функций detachInterrupt и attachInterrupt мне не совсем понятно

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

Так в них то вся и суть. Прочитайте их описание здесь на сайте в разделе справки.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

так как  CONTROL_PERIOD величина для конкретного контура постоянная, красиво было бы его вычислять
к примеру по тау между вторым и третьим срабатыванием компаратора

 

DmitryR
Offline
Зарегистрирован: 12.05.2017

Длительность состояний LOW у компаратора в течении времени уменьшается, а длительность HIGH наоборот, поэтому за CONTROL PERIOD можно принимать длительность предыдущего LOW

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DmitryR пишет:

Длительность состояний LOW у компаратора в течении времени уменьшается, а длительность HIGH наоборот, поэтому за CONTROL PERIOD можно принимать длительность предыдущего LOW

да это без разницы, частота же неизменна, полупериод и измеряем

DmitryR
Offline
Зарегистрирован: 12.05.2017

Вроде разобрался, вот что получилось
 

///////////////////////////////////
//
//  Пины копки и сигнала
// должны быть 2 и 3 в любом порядке
//

#define SIGNAL_PIN  3

///////////////////////////////////
//
//  Время ожидания продолжения сигнала в миллисекундах
// Если за это время уровень ни разу не стал LOW, 
// то считаем, что сигнал прекратился
//
#define CONTROL_PERIOD  50ul

///////////////////////////////////
//
// Возможные состояния измерителя
//
enum METER_STATES {
  WAITING_FOR_SIGNAL = 0, // Ждём LOW на сигнальный пин
  MEASURING,  // Измеряем
  READY // Закончили, результат готов
};

//////////////////////////////////
//
//  Переменная для хранени текущего состояния измерителя
// Изначальное состояние - ожидание нажатия кнопки
//
static volatile METER_STATES meterState = WAITING_FOR_SIGNAL;

//////////////////////////////////
//
// Переменные для хранения времени начала отсчёта
// и времени окончания отсчёта (пропадания сигнала)
//
static volatile unsigned long startSignalTime = 0, endSignalTime = 0;

//////////////////////////////////
//
// Функция - обработчик поступающего во 
// время измерения сигнала. Выполняется,
// когда на сигнальном пине появляется HIGH
//
void measureISR(void) {
  endSignalTime = millis(); // просто запоминем время
}

//////////////////////////////////
//
// Функция - обработки поступления на сигнальный пин LOW
//
void waitingISR(void) {
  startSignalTime = endSignalTime = millis(); // запоминаем время
  pinMode(SIGNAL_PIN, INPUT);
  attachInterrupt(SIGNAL_PIN - 3, measureISR, FALLING);
  meterState = MEASURING; // Изменяем состояние на "измеряем"
}

void setup(void) {
  Serial.begin(115200);
  pinMode(SIGNAL_PIN, INPUT);
  attachInterrupt(SIGNAL_PIN - 3, waitingISR, RISING);
}

void loop(void) {
  if (meterState == MEASURING) {
      //
      // Проверяем, что с момент последнего HIGH 
      // прошло >= CONTROL_PERIOD миллисекунд
      //
      if (millis() - endSignalTime >= CONTROL_PERIOD) {
        //
        // если прошло, то заканчиваем измерения
        //
        detachInterrupt(SIGNAL_PIN - 3);
      meterState = READY; // закончили
      Serial.print("Result is: ");
      Serial.print(endSignalTime - startSignalTime);
      Serial.println(" milliseconds");
      }
  }
}

 

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

1.
Откуда в строке 65 "-3"? Должно быть "-2". Третий пин - это прерывание 1, а второй пин - прерывание 0. Отсюда эта "-2" и вылазит, чтобы из номера пина сделать номер прерывания. Тоже касается и строк 58 и 78

2.
Возможно я уже запутался, но мне кажется RISING в строке 65 неверно (хотя, я уж дейтсвительно запутался). Проверьте сами. Если Вы в качестве сигнала к началу отсчёта ожидаете высокий уровень, то у Вас правильно. Если ожидаете низкий, то ставьте FALLING.

3.
В функции waitingISR Вы правильно включаете новое прерывание. В принципе, всё там нормально, но я бы всё же для начала выключил бы старое (detachInterrupt), а потом бы включал новое. Хотя, и так должно работать.  

4.
А вот в строке 58, думаю, точно нужен RISING. Вы же там отлавливаете именно появление высокого уровня, разве нет?

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DmitryR пишет:

Вроде разобрался, вот что получилось
 

///////////////////////////////////
//
//  Пины копки и сигнала
// должны быть 2 и 3 в любом порядке
//

#define SIGNAL_PIN  3

///////////////////////////////////
//
//  Время ожидания продолжения сигнала в миллисекундах
// Если за это время уровень ни разу не стал LOW, 
// то считаем, что сигнал прекратился
//
#define CONTROL_PERIOD  50ul

///////////////////////////////////
//
// Возможные состояния измерителя
//
enum METER_STATES {
  WAITING_FOR_SIGNAL = 0, // Ждём LOW на сигнальный пин
  MEASURING,  // Измеряем
  READY // Закончили, результат готов
};

//////////////////////////////////
//
//  Переменная для хранени текущего состояния измерителя
// Изначальное состояние - ожидание нажатия кнопки
//
static volatile METER_STATES meterState = WAITING_FOR_SIGNAL;

//////////////////////////////////
//
// Переменные для хранения времени начала отсчёта
// и времени окончания отсчёта (пропадания сигнала)
//
static volatile unsigned long startSignalTime = 0, endSignalTime = 0;

//////////////////////////////////
//
// Функция - обработчик поступающего во 
// время измерения сигнала. Выполняется,
// когда на сигнальном пине появляется HIGH
//
void measureISR(void) {
  endSignalTime = millis(); // просто запоминем время
}

//////////////////////////////////
//
// Функция - обработки поступления на сигнальный пин LOW
//
void waitingISR(void) {
  startSignalTime = endSignalTime = millis(); // запоминаем время
  pinMode(SIGNAL_PIN, INPUT);
  attachInterrupt(SIGNAL_PIN - 3, measureISR, FALLING);
  meterState = MEASURING; // Изменяем состояние на "измеряем"
}

void setup(void) {
  Serial.begin(115200);
  pinMode(SIGNAL_PIN, INPUT);
  attachInterrupt(SIGNAL_PIN - 3, waitingISR, RISING);
}

void loop(void) {
  if (meterState == MEASURING) {
      //
      // Проверяем, что с момент последнего HIGH 
      // прошло >= CONTROL_PERIOD миллисекунд
      //
      if (millis() - endSignalTime >= CONTROL_PERIOD) {
        //
        // если прошло, то заканчиваем измерения
        //
        detachInterrupt(SIGNAL_PIN - 3);
      meterState = READY; // закончили
      Serial.print("Result is: ");
      Serial.print(endSignalTime - startSignalTime);
      Serial.println(" milliseconds");
      }
  }
}

 

Проверяли? А то у меня сомнения, особенно в правильности измерения

DmitryR
Offline
Зарегистрирован: 12.05.2017

1. С пинами напутал, исправил. А на плате arduino nano к какому пину подключать выход компаратора?

2. Сигнал к началу отсчёта является низкий уровень. Сигнал к концу - высокий. Согласен, перепутал высокий и низкий уровни местами

3. Добавил межуду 56 и 57 строкой: detachInterrupt(SIGNAL_PIN - 2);

 

DmitryR
Offline
Зарегистрирован: 12.05.2017

//Проверяли? А то у меня сомнения
 

Ну я если честно не могу судить о правильности кода. Только начал понимать что к чему. Скоро хочу проверить на компонентах. А сомнения в чём именно? 

DmitryR
Offline
Зарегистрирован: 12.05.2017

Хотя, если сигнал к началу изменение c HIGH на LOW, к концу - наоборот

Вот эта часть кода ждёт изменения на сигнальном пине для конца отсчёта?

void waitingISR(void) {
  startSignalTime = endSignalTime = millis(); // запоминаем время
  detachInterrupt(SIGNAL_PIN - 2);
  pinMode(SIGNAL_PIN, INPUT);
  attachInterrupt(SIGNAL_PIN - 2, measureISR, RISING);
  meterState = MEASURING; // Изменяем состояние на "измеряем"
 
А эта часть кода ждёт изменения для начала отсчёта?
 
void setup(void) {
  Serial.begin(115200);
  pinMode(SIGNAL_PIN, INPUT);
  attachInterrupt(SIGNAL_PIN - 2, waitingISR, FALLING);

Я правильно понимаю? 

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

DmitryR пишет:

Хотя, если сигнал к началу изменение c HIGH на LOW, к концу - наоборот

Я ж писал что надо прерывание настроить на изменение состояния (спад+наростание). Онож в подробностях дофени нам в плане определения длительности процесса, чуть шото шелохнулось - начинаемфиксируем время начала, потом просто время каждого шевеления запоминаем, как затихло -нужное время уже есть.

DmitryR
Offline
Зарегистрирован: 12.05.2017

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

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

Так даффйайте спорит ;) 

У Вас же известен момент, с которого стоит ожидать начало процесса? Вот и инициализируйте все в этот момент, вплоть до разрешения прерывания только с этого момента. Если после этого момента начнутся шумы импульсы и прочее дерьмо с выхода компаратора, то как его отличать от самого процесса? Не то, чтоб я не знал как можна пробовать это делать, я просто понимаю что если все так плохо - то ну его нафиг ;)
И опять же если с компаратара лезит кака - нет разницы как её ловить, по спаду, росту или обоюдно. 

А то, что надо пробовать на реальном - ни возражаю, пробуйте.

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

DmitryR пишет:

Я правильно понимаю? 

Да

DmitryR
Offline
Зарегистрирован: 12.05.2017

Тогда должно быть всё правильно

DmitryR
Offline
Зарегистрирован: 12.05.2017

А на плате arduino nano к какому пину подключать выход компаратора?

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

Ну, так Вы ж вроде третий выбрали? Или я что-то пропустил?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Фуф! Разобрался, как это работает!
Идеология понятна. где можно применить тоже, в том же ватчдоге к примеру!
Интересно, Вам это зачем, цель какова?

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

Вот странно, за 70 постов никто словом не обмолвился что в МК есть свой встроенный компаратор с полнофункциональным прерыванием..

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

dimax пишет:

Вот странно, за 70 постов никто словом не обмолвился что в МК есть свой встроенный компаратор с полнофункциональным прерыванием..

ну я то этого и знать не мог )))

DmitryR
Offline
Зарегистрирован: 12.05.2017

//Ну, так Вы ж вроде третий выбрали? Или я что-то пропустил?
 

Ну да, вроде к 3

DmitryR
Offline
Зарегистрирован: 12.05.2017

//Вам это зачем, цель какова?
 

Измерение добротности контура

negavoid
Offline
Зарегистрирован: 09.07.2016

DmitryR

Попробуйте почитать вот это http://www.electronoobs.com/eng_arduino_tut10_3.php правда там измеряется индуктивность, но можно намерить и Q.

DmitryR
Offline
Зарегистрирован: 12.05.2017

negavoid
 

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

DmitryR
Offline
Зарегистрирован: 12.05.2017
void loop(void) {
69   if (meterState == MEASURING) {
70       //
71       // Проверяем, что с момент последнего HIGH
72       // прошло >= CONTROL_PERIOD миллисекунд
73       //
74       if (millis() - endSignalTime >= CONTROL_PERIOD) {
75         //
76         // если прошло, то заканчиваем измерения
77         //
78         detachInterrupt(SIGNAL_PIN - 3);
79       meterState = READY; // закончили

 

 
80       Serial.print("Result is: ");
81       Serial.print(endSignalTime - startSignalTime);
82       Serial.println(" milliseconds");

Такой вопрос по этому участку кода: когда мы считаем разность в 81 строчке, там учитывается CONTROL_PERIOD или он идёт как постоянная добавка к полученному времени и его надо вычитать дополнительно?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

вроде ничего вычитать не нужно я так считаю, уже всё подсчитано, в endSignalTime время последнего прерывания по спаду

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

DmitryR, а какой частоты ваша синусоида?

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

DmitryR пишет:

 

Такой вопрос по этому участку кода: когда мы считаем разность в 81 строчке, там учитывается CONTROL_PERIOD или он идёт как постоянная добавка к полученному времени и его надо вычитать дополнительно?

А Вы сами посмотрите когда endSignalTime запоминается. Только при отлове уровня! Так какой же там нафиг CONTROL_PERIOD, чистое время.

DmitryR
Offline
Зарегистрирован: 12.05.2017

//DmitryR, а какой частоты ваша синусоида?

Экспериментально 4 кГц, но опять же уточню, что частота меняется в зависимости от параметров

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

DmitryR пишет:

Экспериментально 4 кГц, но опять же уточню, что частота меняется в зависимости от параметров

А вас не смущает, что период сигнала 250µS , а измерять вы будете миллисекундами?

DmitryR
Offline
Зарегистрирован: 12.05.2017

Смущает, просто моделировал сигнал с периодом в миллисекундах, и совсем забыл про экспериментальное значение частоты

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

dimax пишет:

DmitryR, а какой частоты ваша синусоида?

Вот умеешь ты Дмитрий каверзные (область применения) вопросы задавать )))
...и спускалися мы с покорённых вершин, что поделать и Боги опускались на землю...

PS перевести на микрос, но там точность не лучше 5-10 мксек

DmitryR
Offline
Зарегистрирован: 12.05.2017

#define CONTROL_PERIOD  50ul

Мне интересно как эту строчку перевести? В остальных я так понимаю заменится millis на micros

 

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

DmitryR пишет:

#define CONTROL_PERIOD  50ul

Мне интересно как эту строчку перевести? В остальных я так понимаю заменится millis на micros

Эту строчку переводить никак не надо. А вот с остальным - не всё так просто.

Теперь Вы оценили мою дотошность в выспрашивании у Вас всего и вся? 

Как оказалось, я был недостаточно дотошным.

DmitryR
Offline
Зарегистрирован: 12.05.2017

Да я Вас понимаю, просто все ньюансы сложно рассказать, тем более пока всё это в отработке.
Ну чисто теоритически, control period можно и оставить таким, главное чтобы он был больше периода сигнала. Просто самому теперь интересно, как изменить его, казалось бы поменять названия и одну строчку

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

DmitryR пишет:

Просто самому теперь интересно, как изменить его

Так а чего сложного его менять? Там число 50. Буковки ul всего лишь означают, что оно unsigned long. Хотите сделать не 50, а 51, ну, так и пишите 51ul.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

DmitryR пишет:

Просто самому теперь интересно, как изменить его

Так а чего сложного его менять? Там число 50. Буковки ul всего лишь означают, что оно unsigned long. Хотите сделать не 50, а 51, ну, так и пишите 51ul.

а я предлагал её рассчитать, она же для каждого контура константа и, Вы Евгений Петрович это можете )))

оно конечно может и смысла нет, если нижняя граничная частота исследуемых контуров известна )))

Сейчас она 20 герц

 

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

ua6em пишет:

а я предлагал её рассчитать, она же для каждого контура константа и, Вы Евгений Петрович это можете )))

оно конечно может и смысла нет, если нижняя граничная частота исследуемых контуров известна )))

Сейчас она 20 герц

Вы напрасно считаете, что я в этом разбираюсь. Я программист, но ни грамма не электронщик. Школьный курс физики и односеместровый курс ТОР 30 лет назад, вот и всё. В простых цифровых схемах, выручает здравый смысл и общеинженерная эрудиция но этого кое-как со скрипом хватает на цифровые дела и то не сложные, а когда дело доходит до аналоговых схем ... "ой, мама"!

Если ТС внятно объяснит, что ему надо, я могу помочь в программировании, а вот в определении что же всё-таки надо - это уж Вы ему помогайте :)

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

1. В посте №1 я задал вопрос насчёт частоты.
2. В посте №2 получил ответ
3. А в посте №81 ТС передумал и оказалось, что частота известна

Если бы он мне сразу сказал про такую частоту, я бы не писал ему пример с подсчётом в миллисекундах и он бы не потерял два дня времени на изначально неверный подход! (ТС, надеюсь, Вы это тоже читаете).

Т.е. я готов помочь в программировании, но поймите, когда Вы начинаете меж собой говорить о сигналах, компараторах и прочих фронтах, мне часто хочется выдать шариковское "неприличными словами не выражаться!". Разберитесь чего Вам надо, господа электронщики, а с программой я помогу :)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

на уровне логики измерения уже устаканилось жеж )))
Надо опробовать электронику на низких частотах с этим скетчем, а далее видно будет
 

DmitryR
Offline
Зарегистрирован: 12.05.2017

Я опишу подробно устройство и задачу:

1) Имеется колебательный контур (конденсатор и катушка индуктивности, в роли которой сердечник с обмоткой). В данном контуре конденсатор всегда имеет постоянные параметры, а у катушки их можно менять, но не в пределах одного измерения. Т.е. установили одни параметры, производим измерение, получаем результат. Опять поменяли, опять производим измерение. Ввиду того, что параметры катушки можно менять, меняется и период колебаний, следовательно частота. 

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

3) Задача измерения - определение добротности катушки. Добротность можно определить по скорости затухания синусоиды. Для этого надо замерить время от появления сигнала (в начальный момент он максимален), до его затухания до определённого значения (как правило равняющимся примерно 1/23 от начальной амплитуды).

4) Для фиксации момента достижения амплитуды затухающей синусоиды значений 1/23 от начального, используется компаратор, опорное напряжение котрого как раз и равняется этой 1/23, следовательно он будет срабатывать пока сигнал идёт и как только он дойдёт до нужного значения, компаратор сработает последний раз. Это будет конец отсчёта. 

5) Итог - разность времени конца и начала отсчёта. Данная величина времени покажет скорость затхания, а следовательно и добротность, т.к. они пропорциональны. 

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

7) Частота. Частота, как я упомянул выше, меняется. Единственное, что можно сказать - это экспериментаьно полученно, что период будет около 250 мкс, следовательно частота = 4кГц. Т.е. можно сказать, что это сотни герц - десятки киллогерц.  Пршу заметить, что частоту я считаю выпрямленного сигнала (она в 2 раза больше частоты синусоиды).

8) Задача микроконтроллера - обработать сигнал, идущий с компаратора, т.е. понять - когда наступило начало отсчёта, когда его конец и выдать разность.

DmitryR
Offline
Зарегистрирован: 12.05.2017

Красный сигнал - сигнал с катушки (колебания контура)

Зелёный сигнал - выпрямленный сигнал (после преобразований), он идёт на вход компаратора

Фиолетовый - сигнал с компаратора, идёт на вход микроконтроллера. У данного сигнала 2 уровня: высокий 5В, низкий 0,5В. 
Вся электроника быстродействующая

Т.к. период около 250 мкс, то подсчитанное время будет в миллисекундах ( за время затухания таких периодов будет несколько десятков)

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

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

DmitryR
Offline
Зарегистрирован: 12.05.2017

Я просто собрал всю информацию в кучу, для общего представления

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

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

DmitryR
Offline
Зарегистрирован: 12.05.2017

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

Гриша
Offline
Зарегистрирован: 27.04.2014

DmitryR пишет:

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

перетоки и петли от БП??? подключитесь с АКБ ноута - развяжитесь по питанию. Тут недавно обсуждали трупик контроллера из-зи проблем с БП . Ну или опторазвязку на компаратор.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Гриша пишет:

DmitryR пишет:

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

перетоки и петли от БП??? подключитесь с АКБ ноута - развяжитесь по питанию. Тут недавно обсуждали трупик контроллера из-зи проблем с БП . Ну или опторазвязку на компаратор.

скорее всего отсутствие защиты по входу компаратора с LC контура

DmitryR
Offline
Зарегистрирован: 12.05.2017

//скорее всего отсутствие защиты по входу компаратора с LC контура

Какую защиту вы имеете ввиду? Между компаратром и LC резистивный делитель был

ИспользуЮ компаратор AD8561: на in- сигнал, на in+ землю, обратную свзять с R = 1кОм от out к in+, положительное однополярное питание