измерить действующее значение импульсного сигнала

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1456
Зарегистрирован: Ср сен 03, 2008 21:42:17
Откуда: Ленинградская область,пос.Красный Остров

Сообщение WatchCat »

Имеется сигнал из последовательности импульсов, формируемый неким блоком, содержащим микроконтроллер, но
недоступным для реверс-инжиниринга(залит в пластмассу).
Сигнал представляет собой по всей видимости программно-сформированный ШИМ, причем сформированный весьма "неаккуратно". Меняется не только длительность импульсов, но и частота их появления(незначительно, но тем не менее). Частота близка к 500гц, импульсы раза в три-четыре короче чем пауза между ними. Исходно этот сигнал
подавался на исполнительное устройство, реагирующее приблизительно на действующее значение напряжения. А мне надо бы извлечь из этого сигнала информацию как бы о положении исполнительного устройства. То есть это самое действующее значение измерить. Для этого имеется Atmega8. В сети нашел документ от Atmel - AVR135 (файл doc8014.pdf), также у каких-то индусов скачал исходник примера к этому документу(похоже что свободно его не раздают, только на фирменных CD, но в инете как известно есть все:) ) Вопрос к присутствующим: кто что думает о применимости этого примера к моему случаю? Вроде там написано, что оно работает и при нестабильной частоте сигнала... Правда написано оно под Atmega64, но вроде как ничего сильно зависимого от нее там нет, кажется можно и на Atmega8 переделать.

P.S. Увы - кварца у меня на плате сейчас нет, Мега работает
от внутреннего генератора, как была запрограммирована из магазина - хватит ли частоты? Вроде у нее внутренний генератор на 1мгц работает?
Вложения
AVR135.zip
Тот самый пример к документу doc8014.pdf
(57.29 КБ) 288 скачиваний
Реклама
Открыл глаза
Сообщения: 41
Зарегистрирован: Пн дек 21, 2009 15:16:31

Сообщение ujin »

от внутреннего генератора, как была запрограммирована из магазина - хватит ли частоты? Вроде у нее внутренний генератор на 1мгц работает?

Вроде по даташиту так Mega настроена на внутренний RC..с частотой 1 Мгц.
Реклама
Открыл глаза
Сообщения: 41
Зарегистрирован: Пн дек 21, 2009 15:16:31

Сообщение ujin »

WatchCat писал(а):Имеется сигнал из последовательности импульсов, формируемый неким блоком, содержащим микроконтроллер, но
недоступным для реверс-инжиниринга(залит в пластмассу).
Сигнал представляет собой по всей видимости программно-сформированный ШИМ, причем сформированный весьма "неаккуратно". Меняется не только длительность импульсов, но и частота их появления(незначительно, но тем не менее). Частота близка к 500гц, импульсы раза в три-четыре короче чем пауза между ними. Исходно этот сигнал
подавался на исполнительное устройство, реагирующее приблизительно на действующее значение напряжения. А мне надо бы извлечь из этого сигнала информацию как бы о положении исполнительного устройства. То есть это самое действующее значение измерить. Для этого имеется Atmega8. В сети нашел документ от Atmel - AVR135 (файл doc8014.pdf), также у каких-то индусов скачал исходник примера к этому документу(похоже что свободно его не раздают, только на фирменных CD, но в инете как известно есть все:) ) Вопрос к присутствующим: кто что думает о применимости этого примера к моему случаю? Вроде там написано, что оно работает и при нестабильной частоте сигнала... Правда написано оно под Atmega64, но вроде как ничего сильно зависимого от нее там нет, кажется можно и на Atmega8 переделать.

P.S. Увы - кварца у меня на плате сейчас нет, Мега работает
от внутреннего генератора, как была запрограммирована из магазина - хватит ли частоты? Вроде у нее внутренний генератор на 1мгц работает?
От меги тут ничего не зависит можно и мегу8 . Это так я понимаю получаеться реализация ЦАПа......напряжение на выходе из шима за единицу времени будет прямо пропорциональна их количеству а что бы сгладить импульсы то ставять резистор и кондесатор а полученное напряжение это и есть как бы положение чего там вашего устройства вроде так, меги8 это дело подать на вход ацп от туда пересчетом напряжения получите положение.
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1456
Зарегистрирован: Ср сен 03, 2008 21:42:17
Откуда: Ленинградская область,пос.Красный Остров

Сообщение WatchCat »

Пока ходили письма я адаптировал тот исходник для Меги8 и поставил эксперимент. Оно работает, но довольно слабо реагирует на имеющиеся изменения входного сигнала. Еще порассматривал осциллографом свой сигнал - там пауза между импульсами меняется чуть ли не больше чем ширина импульса, и похоже программа это игнорирует или как-то плохо воспринимает. И действительно - коэффициент заполнения ШИМа это не совсем то, что действующее значение, особенно в случае если это не настоящий ШИМ, а последовательность импульсов с меняющимся интервалом и длительностью.

Резистор и конденсатор как было рекомендовано выше - ставить пробовал. В виде специально расчитанного НЧ-фильтра на двух ОУ. Импульсы раза в четыре короче чем пауза, на выходе или получается большая пульсация(больше чем полезные изменения) или надо совсем уж неприличную постоянную времени делать(секунды) что в моем случае весьма не желательно.

Так что продолжаю думать дальше. Надо бы найти методику измерения среднего значения методом аналого-цифрового преобразования и последующих вычислений площади под кривой. Ну и рассматривать вход контроллера как однобитный АЦП - почему бы и нет собственно...
Реклама
Эиком - электронные компоненты и радиодетали
Опытный кот
Аватара пользователя
Сообщения: 890
Зарегистрирован: Вт янв 20, 2009 14:49:08
Откуда: Гондурас, Мурманск

Сообщение DrWatson »

А посчитать длительность единицы и следующего за ней нуля (или наоборот) слабо?
- Если вы такие умные, то почему тогда строем не ходите?
ἓν οἶδα ὅτι οὐδὲν οἶδα (с) Σωκράτης
Реклама
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1456
Зарегистрирован: Ср сен 03, 2008 21:42:17
Откуда: Ленинградская область,пос.Красный Остров

Сообщение WatchCat »

DrWatson писал(а):А посчитать длительность единицы и следующего за ней нуля (или наоборот) слабо?
Вот это и попытаюсь реализовать. Нужно считать длительность нулей и единиц в заданном промежутке времени, что-нибудь около одной десятой секунды.
К сожалению готового решения похожей задачи в интернете не нашлось, придется самому придумывать. Все бы ничего, но частота сигнала высоковата, а я не настолько крутой программист чтобы хорошо код оптимизировать...
Реклама
Держит паяльник хвостом
Аватара пользователя
Сообщения: 993
Зарегистрирован: Пн сен 18, 2006 11:16:05
Откуда: Тула

Сообщение Neekeetos »

WatchCat писал(а):
DrWatson писал(а):А посчитать длительность единицы и следующего за ней нуля (или наоборот) слабо?
Вот это и попытаюсь реализовать. Нужно считать длительность нулей и единиц в заданном промежутке времени, что-нибудь около одной десятой секунды.
Может попробовать сделать ФНЧ хотя бы на RC цепочке и измерять встроеным в мегу АЦП уже осредненное значение?
Контактная информация:
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1456
Зарегистрирован: Ср сен 03, 2008 21:42:17
Откуда: Ленинградская область,пос.Красный Остров

Сообщение WatchCat »

Neekeetos писал(а): Может попробовать сделать ФНЧ хотя бы на RC цепочке
Пробовал делать ФНЧ на двух ОУ. Постоянную времени сделал максимально возможную по условиям чувствительности к изменениям сигнала. Все равно имеет место значительная пульсация выходного напряжения и показания АЦП прыгают на 5-7 единиц, что меня не устраивает. Нужен именно программный метод обработки сигнала. Придумываю, завтра буду пытаться писать.
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

WatchCat писал(а):Вроде у нее внутренний генератор на 1мгц работает?
С завода - 1, перешить можно на 2, 4, 8
WatchCat писал(а):И действительно - коэффициент заполнения ШИМа это не совсем то, что действующее значение.
Ну да, к-т заполнения это фактически среднее значение, а действующее - среднеквадратичное, корень_квадратный_из(суммы_квадратов, делённой на число_точек).
Проблема в том, что если длительности меняются мало, то как не крути - будет тяжело.
WatchCat писал(а):Пробовал делать ФНЧ на двух ОУ. Постоянную времени сделал максимально возможную по условиям чувствительности к изменениям сигнала.
ФНЧ даст среднее значение, а не действующее. Хотя, думаю, нужно всё же среднее, врядли в исполнительном устройстве стоял true-rms детектор.
WatchCat писал(а):Все равно имеет место значительная пульсация выходного напряжения и показания АЦП прыгают на 5-7 единиц, что меня не устраивает.
А дофильтровывать сигнал с АЦП с той же постоянной времени 0,1с?
WatchCat писал(а):Надо бы найти методику измерения среднего значения методом аналого-цифрового преобразования и последующих вычислений площади под кривой. Ну и рассматривать вход контроллера как однобитный АЦП - почему бы и нет собственно...
Так для этого достаточно длительностей импульса и паузы, сигнал-то однобитный ;-).
Т.е. если есть N точек амплитудой 1, то площадь всяко будет 1*N.
Так что задача всё равно сводится к измерению времён.

500Гц частота небольшая. Даже на 1МГц тактирования должно легко всё получиться.

Используем ICP таймера1 и прерывания от него.
Таймер настраиваем на такое тактирование, что самый длинный возможный период входного сигнала гарантированно меньше периода переполнения таймера, но чтобы была достаточная точность. При тактовой 1МГц и прескалере clk/1 для 500Гц период будет 2000 тактов, импульс 400-500 тактов. Віглядит неплохо, но вопрос в том, насколько меняютя эти длительности - хватит ли точности измерения изменения. Ради этого может быть нужно поднять частоту тактирования контроллера до 8МГц и иметь 16000 тактов на период, 3200-4000 тактов на импульс.

Код: Выделить всё

uint16_t prev_icr; // глобальная переменная
В прерывании от ICP инвертируем бит ICES1 в регистре TCCR1B, чтобы в следующий раз отреагировать по другому перепаду (прерывания по обеим перепадам у меги8 просто нет).

Код: Выделить всё

      uint16_t new_icr = ICR1;
      uint16_t delta = new_icr  - prev_icr;
      prev_icr = new_icr;
delta - это длительность предыдущего состояния, в зависимости от того, какое значение у бита ICES1 - длительность 0 или 1.
Видимо, это то, что написано в той апноте.

Если у нас есть две длины - len0 дя нулей и len1 для единиц, то среднее значение за период будет len1/(len0+len1), среднеквадратичное (aka действующее, эффективное) - sqrt( len1*len1/(len0+len1) );
Чтобы не уходить на плавающую точку, надо смасштабировать для вычислений с фиксированной точкой. Квадратный корень из целого числа вычисляется за время, немногим большее одного целочисленного деления соответствующей разрядности.

Я так понимаю, что проблема в дрожании, дающем шумовой эффект.

Сейчас я чайку заварю...
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев

Сообщение BCluster »

один таймер настраиваем на максимальную возможную частоту - в обработчике смотрим на состояние ноги контроллера - в зависимости нолик там или единичка инкрементируем ту или иную переменную:

Код: Выделить всё

float res;
int zero = 0, one = 0;

...Timer intrerrupt stub0()
{
if (PINB.1) 
   {
        one++;
   }
else 
   {
        zero++;
   }
}
другой таймер настраиваем на 0.1с или сколько там вы хотите

Код: Выделить всё

...Timer intrerrupt stub1()
{
asm("cli");
   if (zero) res = one/zero; 
   else res = one;
}
Таким образом у вас в res постоянно будет болтаться значение отношения времени единиц к времени нуля, по этому значению судить об измеряемой величине можно без каких бы то ни было препятствий. И на частоту вроде бы как то все равно)
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

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

Фильтрация...
Желаемое время 0,1сек - это около 50 периодов входного сигнала.
Можно попробовать просто суммы len0_sum, len1_sum за это время. Например, суммировать за 50 периодов или суммировать целыми периодами пока не пройдёт время около 0,1сек, засекая это по другому таймеру. При этом и дискретность выдачи результата будет те же 0,1сек.
Если 32 периода суммировать - получится взвешенный на степень двойки результат, с которым, возможно, будет легче работать дальше.
Хотя практически наверняка понадобится масштабирование и тогда что 50, что 32- всё уйдёт в те масштбные коэффициенты.
А масштабирование будет нужно потому, что изменение длительноти импульса "от четверти до трети периода" ведь означает 100%-ное изменение желаемого воздйствия, я правильно понимаю? Ну может не 100%, а 80%, если "края" всё равно не используются, но всё равно так. Вопрос только - где взять опорную точку, "0" для масштбирования.

Я не знаю, насколько это важно в данном случае, но может захотеться иметь результат чаще.
Тогда можно или сделать кольцевые буферы по 32 или там 50 отсчётов и делать скользящее среднее, вычитая из суммы "уходящий" отсчёт и добавляя входщий. На это уйдёт 128..200 байт ОЗУ.
При такой инерционности относительно периода можно попробовать экспоненциальный фильтр с коэффициентом рециркуляции, скажем, 15/16.

Код: Выделить всё

  average0 = (average0 * 15 / 16 + len0 / 16);
и так же для average1. Это "логика", быстрее считается в такой форме

Код: Выделить всё

  average0 = average0 + (len0 - average0) / 16;
для переменных со знаком

Код: Выделить всё

  average0 = average0 - average0 / 16 + len0 / 16 ;
для unsigned.

А лучше сразу сделать запас разрядов, при модуле 16 перейти к выходу фильтра в формате с 4 битами после фиксированной точки. Если указанной выше частоты тактирования TIMER1 достаточно, то период легко влазит в 12бит и в 16-битном слове выходит формат 12.4, дискрет усреднённого значения длительности 1/16 входного такта таймера. И вычисления даже проще :-)

Код: Выделить всё

  average0 = average0 - average0 / 16 + len0;
На расстоянии тяжело советовать какую-то конкретную фильтрацию, так как непонятны ни характер "шума", ни нчто должно получиться на выходе, ни то, важен ли сам период (ну или отношение длительности к периоду) для исполнительного устройства, которым управляет "запластмасенный ящик". Вполне может быть, что управляющим воздействием есть только длина импульса, точнее, её превышение над некоей базовой длиной, а частота 500Гц выбрана для того, чтобы воздейстиве менялось достаточно часто для случая необходимости быстрой смены. При этом дрожание периода и не важно и замерять нужно только длительность "1", вычитать из неё базовую длительность. Скажем, при изменении от 400 до 500 тактов 400 тактов означает 0% воздействия, 450 - 50%, 500 - 100%.

p.s. выше все деления желательно делать с округлением, т.е., для беззнаковых
var / 16
заменить везде на
( var + 8 ) / 16
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 6335
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Сообщение Jack_A »

WatchCat писал(а): Надо бы найти методику измерения среднего значения методом аналого-цифрового преобразования и последующих вычислений площади под кривой.
Для начала следует определиться, что хотите измерить : действующее или среднее - это, говорят в Одессе, две больших разницы. А определить коэффициент заполнения правильно советуют - разделить число отсчетов, во время которых была единица, на общее число отсчетов за период измерения. Интегрировать и затем обратно цифровать аналоговый сигнал - по моему, лишняя морока. Ведь исходный сигнал цифровой ( импульсный ), его амплитуда значения не имеет? А чтобы график функции был более гладким при приемлемом времени измерения, можно попробовать метод "скользящего окна" : хранить в массиве несколько отсчетов, при каждом новом замере удалять из массива и из суммы самое "старое" значение, заменяя его "свежим". Это и будет простейший интегратор.
А может быть, значение кодируется не коэффициентом заполнения, а частотой ( преобразователь U-F ) или того хуже - кодом ?
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

Jack_A писал(а): Для начала следует определиться, что хотите измерить : действующее или среднее - это, говорят в Одессе, две больших разницы. А определить коэффициент заполнения правильно советуют - разделить число отсчетов, во время которых была единица, на общее число отсчетов за период измерения.
Разницы-то две, но для "бинарного" сигнала рассчёт отличается одной дополнительной операцией. Действующее значение будет корнем квадратным из среднего (из коэффициента заполнения).

Среднее

Код: Выделить всё

  ave это ( len1 * 1 + len0 * 0 ) / ( len1 + len0 )
      это len1 / ( len1 + len0 )
действующее

Код: Выделить всё

  rms это  sqrt( ( len1 * 1^2 + len0 * 0^2 ) / ( len1 + len0 ) )
      это sqrt( len1 / ( len1 + len0 ) )
      это sqrt( ave )
Так что что одно, что другое - необходимо и достаточно посчитать длины 1 и 0.

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

p.s. Котоводы, ау! почему тегов [sup] [sub] нет? Ни в квадрат по-человечески не возвести, ни индексы не написать...
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1456
Зарегистрирован: Ср сен 03, 2008 21:42:17
Откуда: Ленинградская область,пос.Красный Остров

Сообщение WatchCat »

Вчера испытывал уже два варианта
программы. Для испытаний припаял Меге R2R ЦАП на ноги свободного порта и полученное значение выводил туда чтобы было удобно смотреть на изменения.

Одна программа использует в первоначальном виде исходник из вышеупомянутой аппноты, только под Atmega8 адаптированный(это оказалось не сложно), вторая программа
самописная - она также как и в аппноте ловит фронты сигнала, смотрит на значение таймера и суммирует время, в течении которого сигнал находился в состоянии "1". Раз в четверть секунды прерывание от другого таймера сумматор обнуляет, на насчитанное значение выводит в порт, туда где
я ЦАП припаял.

Работают оба варианта, мой самописный оказался более чувствительным к малым изменениям в сигнале, наверно за счет того, что он целых четверть секунды "единицы" собирает. Но проблема оказалась не в программе, а в том прискорбном факте, что сам сигнал меняется очень мало.
То есть при всех максимально возможных изменениях сигнала байт на выходе меняется от 49 до 52. Да еще и "дергается" на одну, а то и две единицы. Понятно что из этого никакой полезной информации не извлечь сколько результат ни фильтруй.

А исполнительным механизмом, который управляется тем импульсным сигналом, является большой электромагнит, который поворачивает свой рычаг градусов примерно на десять под действием столь малых изменений. Завтра попробую покормить его постоянным током от внешнего источника и посмотрю - это он действительно такой чувствительный к среднему значению сигнала или все же сигнал меняется больше, а я не могу отловить эти изменения.
Собственно мне и надо получить положение рычага, но ставить дорогущий датчик угла поворота, способный выдать на эти 10 градусов хотябы сотню шагов - мне до последнего момента не хочется. Пытаюсь вытащить информацию о положении рычага из сигнала, поступающего на электромагнит.
Вложения
pwmdecode.zip
Самодельный преобразователь сигнала,
причесывать и оптимизировать пока не пытался
(23.3 КБ) 233 скачивания
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»