Подскажите, как правильно посчитать частоту?

Kakmyc
Offline
Зарегистрирован: 15.01.2018

ТС тут уже решали
Я проверял, все работает как надо.
С данными параметрами таймера дискретность 4мкс
http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/chtenie-shim-5...

Zummer
Offline
Зарегистрирован: 25.11.2019

Там нет ничего подобного

gene
Offline
Зарегистрирован: 07.02.2020

Kakmyc пишет:
считать частоту через ADC это нихера не правильно. Если он не знает как это сделать правильно, то нужно ему подсказать , а не потакать ему в его заблуждениях. Если , все же ему нужно что то другое, никак не относящееся к названию темы, значит нужно исправить название темы.

Я не знаю как делать правильно. Мне предлагается компаратор (я не знаю как это вкорячить и в глаза его не видел, но прочитал описание его работы). Компаратор не подходит, так как ему нужно граница по напряжению. У меня граница плавает. Скажу не по вольтам, так как делитель напряжения выбирается под источник, а по результатам АЦП. У меня было от 0 до 24, и от 0 до 128, и от 0 до 64. Всегда 0 только потому, что я беру верхние 8 бит. Это упрощенный вариант для понимания как оно вообще работает и хватит ли буфера (один байт на отсчет позволяет сделать буфер вдвое больше, чем два байта, которые нужно для 10-битного значения). Буфер на 1024 вполне достаточен и я думаю, что 512 тоже хватит, а значит можно будет на двухбайтный (10-битный) вариант перевести. Там уже не будет от 0 до хх, а будет, например от 3 до xx, причем xx меняется просто в процессе измерения произвольно. Надежда только на до, что меняется он в зависимости от действий пользователя и поэтому получить 500-1000 значений можно успеть до момента, когда минимум и максимум изменятся. Зная минимум и максимум можно посчитать частоту, скважность и соотношение мин/макс. Если отказаться от этого соотношения мин/макс, то, наверное, можно считать частоту предложенным тут способом, и даже скважность, наверное, тоже будет доступна. Но при условии стенда какого-то, где все настроено на одно значение получаемого напряжение. А у меня портативный прибор, очень маленький, вообще без кнопок, только рубильник чтобы включить и экран, чтобы отображать полученные значения. Я когда смогу готовое что-то соорудить, выложу, покажу что оно показывает, какие есть проблемы, и тогда, наверное, найдется лучшее решение. Но пока для меня именно такой вариант самый правильный. Мегагерцовых частот у меня нет. Насколько я вижу, АЦП позволит получить примерно до 30 кГц без проблем, и этого для меня более чем достаточно. Не вижу пока причин делать измерение через другие аппаратные возможности микроконтроллера с добавлением дополнительных электронных компонентов, которых у меня нет, и в которых я вообще ничего не понимаю. Насколько я понял, компаратор не может быть динамическим, ему придется дополнительно задавать предел внешний устройством, может самой ардуиной, но для этого придется использовать тот же самый АЦП, который уже используется.

Я не ожидал, что будет такая проблема - с плавающим временем - думал, что я просто тупой и не знаю какого-то волшебного слова. Примерно понятно, что волшебное слово есть - вызов прерывания после окончания замера - в этом случае время плавает в ожидаемых пределах функции micros() (или самостоятельно настроенного таймера) и не зависит от других функций в программе - что мне и нужно было получить. Вопрос уже решен. Может быть неправильно, но это уже второй этап, который пока для меня слишком сложен. Спасибо, что участвуете в этой теме и предлагаете решения, но не все из них доступны для только-только взявшего в руки эту штуку.

sadman41
Offline
Зарегистрирован: 19.10.2016

Осциллограмма, возможно, помогла бы быстрее найти закономерности в сигнале, что поспособствовало более осмысленной разработке алгоритма детекции.

Zummer
Offline
Зарегистрирован: 25.11.2019
gene
Offline
Зарегистрирован: 07.02.2020

sadman41 пишет:
Осциллограмма, возможно, помогла бы быстрее найти закономерности в сигнале, что поспособствовало более осмысленной разработке алгоритма детекции.

Там все довольно обыденно:о.

 

 

 

Файлы для этих графиков тут.

Это я замерял на первой версии, в которой использовался вариант, выдранный из библиотеки CyberLib:

uint16_t AnRead(uint8_t An_pin)
{
  ADMUX=An_pin;   
  delay_us(10);	  
  ADCSRA=B11000110;	//B11000111-125kHz B11000110-250kHz 
  while (ADCSRA & (1 << ADSC));
  An_pin = ADCL;
  uint16_t An = ADCH; 
  return (An<<8) + An_pin;
}

Только оно было в цикле без вызова функции, с разными делителями и с левым варавниванием без младших двух битов.

gene
Offline
Зарегистрирован: 07.02.2020

Zummer пишет:

Вот что нарыл https://forum.arduino.ua/viewtopic.php?id=1071

Я это видел. Суть в целом та же самая. А в обсуждении настоятельная рекомендация выбирать правильный делитель, который "производитель рекомендует". Ну кто-то верно заметил, что там замер даже не делается. Причем там единичный замер, который, кажется, ни кого особо не волнует.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Сигнал практически голимый меандр, зачем вам использовать ADC ?
Если напряжение позволяет, то просто этот сигнал подавать на INT0/INT1. Порог перехода будет на порядок точнее всех этих ваших замеров.
Кроме этого можно ещё и аналоговый компаратор использовать.
Не изобретайте велосипед.

gene
Offline
Зарегистрирован: 07.02.2020

Kakmyc пишет:
Сигнал практически голимый меандр, зачем вам использовать ADC ? Если напряжение позволяет, то просто этот сигнал подавать на INT0/INT1. Порог перехода будет на порядок точнее всех этих ваших замеров. Кроме этого можно ещё и аналоговый компаратор использовать. Не изобретайте велосипед.

Напряжение будет от 0 до 1 вольта. Но не всегда от 0 до 1, а будет плавать. Вы наверное увидели, что по графикам максимум всегда был разный. Минимум тоже будет разный, я думаю, когда я буду использовать 10 бит. Но это просто предположение.

1. Правильно ли я понимаю, что для INT0 и INT1 должно быть напряжение строго выше определенного предела, чтобы оно сработало? То есть, например, на 0.2 вольта не будет срабатывать прерывание? Нужно будет делать какой-то повышатор? Например замерять с помощью АЦП ардуины напряжение и если какой-то порог будет превышен, то дрыгать какой-нибудь ногой, чтобы INT0/INT1 сработал?

2. Аналоговый компаратор - это оно - https://chipenable.ru/index.php/how-connection/99-analogovyy-komparator-... ? "Простейшая схема компаратора может быть построена на операционном усилителе без обратной связи. На один из входов операционного усилителя подается известное опорное напряжение, на другой -  сравниваемый аналоговый сигнал, например сигнал с датчика" - это про него? Мне нужно будет добавить в схему устройство, которое замеряет напряжение за единицу времени, потом генерирует опорное напряжение для компаратора? Я правильно понимаю, что напряжение нужно будет измерять с помощью АЦП ардуины? Или есть какой-то компаратор, который будет сам его измерять и решать, что оно будет опорным? Видимо какое-то среднее между минимумом и максимумом нужно? Если я все правильно понял, что я усложняю схему и даже не избавляюсь от замера с помощью АЦП, который я уже сейчас делаю и получаю результат. Или все совсем не так?

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Я не знаю, что вы там такое конструируете, поэтому мне сложно понять ход ваших мыслей.
Но основная суть понятна.
Что вам мешает усилить свой сигнал и ограничить его стабилитроном ?
Использовать встроенный компаратор Ардуино ?

gene
Offline
Зарегистрирован: 07.02.2020

Kakmyc пишет:
Я не знаю, что вы там такое конструируете, поэтому мне сложно понять ход ваших мыслей. Но основная суть понятна. Что вам мешает усилить свой сигнал и ограничить его стабилитроном ? Использовать встроенный компаратор Ардуино ?

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

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

Kakmyc пишет:
Я не знаю, что вы там такое конструируете, поэтому мне сложно понять ход ваших мыслей. Но основная суть понятна. Что вам мешает усилить свой сигнал и ограничить его стабилитроном ? Использовать встроенный компаратор Ардуино ?

а я по старинке LM393 вместо встроенного использовал, непорядок, надо озадачиться сокращением числа навесных деталей

Zummer
Offline
Зарегистрирован: 25.11.2019

gene пишет:

Zummer пишет:

Вот что нарыл https://forum.arduino.ua/viewtopic.php?id=1071

Я это видел. Суть в целом та же самая. А в обсуждении настоятельная рекомендация выбирать правильный делитель, который "производитель рекомендует". Ну кто-то верно заметил, что там замер даже не делается. Причем там единичный замер, который, кажется, ни кого особо не волнует.

Я не о том,кое о чем подзабыл и вспомнил когда прочитал-преобразование 27 тактов,последующие 13 тактов для непрывного преобразования,листаю Ефстигнеева,осталось разобраться с тактами

https://forum.arduino.ua/viewtopic.php?pid=23237#p23237

Zummer
Offline
Зарегистрирован: 25.11.2019

И вот еще что-в видео вы постоянно в цикле пишете

ADCSRA=B11000010;

перенесите это в setup,но так-

ADCSRA=B11100010;

Включение 6-го бита включает непрерывное преобразование,то есть ацп будет постоянно измерять автоматом после сброса 

У меня совпадает с даташитом

преобразование 13 тактов ацп

byte buffer [1024];
  unsigned long time, delta_time;
 int i;
  void setup(){
    Serial.begin(9600);
    ADMUX=B11100111;//выбор внутреннего опорного 1,1В
    ADCSRA=B11100010; // /4 
    delayMicroseconds(10);
 }
 void loop()
{   
  Serial.print( "start"  );
  TCCR1A=0;
  TCCR1B=0b00000001;// 1 тик=1/16 мксек
  TIMSK1=0; 
  i=501;
  cli();
  TCNT1   =0; 
    while (i--)
  {
    while ((ADCSRA & 0x10)==0);   // Ожидание флага окончания преобразования
    ADCSRA|=0x10;
    buffer[i] = ADCH;
  }
  delta_time =TCNT1;sei();Serial.print( "stop"  );
  Serial.print( "dt="  );Serial.print( delta_time ); Serial.println( "  " );
  //delay(1000);
  }

В UART приходит 26001-260051,то есть 13 тактов ацп как ни крути

Zummer
Offline
Зарегистрирован: 25.11.2019

Проверил на баском авр-то же 13 тактов

В итоге получается что незачем мерять время заполнения буфера-его можно рассчитать

Например ардуино уно,с кварцем 16 МГц,1000 измерений,ADCSRA=B11100010,то есть частота тактирования АЦП 16/4=4 МГц

тогда каждый цикл измерния АЦП=(1/4 Мгц)*13=3,25 мксек,а заполнение буфера 1000*3,25 мксек=3,25 мсек

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Zummer пишет:

Проверил на баском авр-то же 13 тактов

В итоге получается что незачем мерять время заполнения буфера-его можно рассчитать

Например ардуино уно,с кварцем 16 МГц,1000 измерений,ADCSRA=B11100010,то есть частота тактирования АЦП 16/4=4 МГц

тогда каждый цикл измерния АЦП=(1/4 Мгц)*13=3,25 мксек,а заполнение буфера 1000*3,25 мксек=3,25 мсек

Нельзя так рассчитать ничего.
Что бы это понять нужно изучить принцип работы АЦП. Время расчета при измерении зависит от фазы Луны и значения входного сигнала.

gene
Offline
Зарегистрирован: 07.02.2020

Zummer пишет:

И вот еще что-в видео вы постоянно в цикле пишете

ADCSRA=B11000010;

перенесите это в setup,но так-

ADCSRA=B11100010;

Так в следующем сообщение после видео  написал, что решилась проблема с помощью включения прерывания по окончанию АЦП. Время стало работать нормально.

А настройка на непрерывное получение еще до того была сделана. На видео пример из этой темы, который вы написали. У меня уже был, насколько я понял, это называется режим "free run". С ним та же самая ерунда - время произвольно меняется. В общем, так можно время пачки опросов уменьшить, но спецэффекты со временем не исчезают.
 

Zummer пишет:

У меня совпадает с даташитом

преобразование 13 тактов ацп

Я поэтому и спросил, что может только у меня такое получается. Ведь больше нигде никто о подобном не написал. У меня время меняется, вы на видео в этом убедились. Даже если другую переменную выводить после преобразования, даже если расчеты какие-то добавить-убавить.

Но проблема решилась с помощью ADIE (Кажется решилась). Вызывается прерывание, в котором в массив все складывается. Там, правда, результат полученный при опросе не всегда дает одну и ту же частоту независимо от выбора делителя. При определенном делителе частота верная, при другом - куда-то смещается, но зато держится ровно и не прыгает, как в случае прямого опроса АЦП. Теперь только остается придумать как определять "правильную" частоту на разных делителях, а делители нужны разные, так как есть частоты ниже 100 гц, которые  нужно с другим делителем получать. Но это, я надеюсь, уже дело более простое, так как показатели не зависит от вывода на экран или в порт.

 

gene
Offline
Зарегистрирован: 07.02.2020

Zummer пишет:

Проверил на баском авр-то же 13 тактов

В итоге получается что незачем мерять время заполнения буфера-его можно рассчитать

Например ардуино уно,с кварцем 16 МГц,1000 измерений,ADCSRA=B11100010,то есть частота тактирования АЦП 16/4=4 МГц

тогда каждый цикл измерния АЦП=(1/4 Мгц)*13=3,25 мксек,а заполнение буфера 1000*3,25 мксек=3,25 мсек

Я тоже думал, что можно просто посчитать. Но, как мне кажется, надо тогда писать на ассемблере. Кроме работы АЦП есть работа с буфером, сохранение регистров при входе в функцию прерывания, еще какая-нибудь ерунда. Имея давний опыт ассемблера x86, я мельком глянул на этот и понял, что пока не готов с ним разбираться )).

Еще есть "холостой" ход АЦП, который срабатывает в первый раз. И с ним тоже что-то надо делать. Его отсеивать нужно каким-то другим способом. Думаю, сочиню что-нибудь с выкидыванием из буфера на автомате, но время-то у него другое получается. То есть все равно замерять придется общее время (например, я делал от 2 до 32 полных прогонов и время micros(), которое обычно кратно 4, удавалось нормализовать, правда размер буфера крайне желательно делать степенью двойки, чтобы простым "И" выкидывать старшие биты и класть в правильные адреса - тогда время для всех измерений будет одинаковым и первое на их фоне не сильно сказывается).

gene
Offline
Зарегистрирован: 07.02.2020

Kakmyc пишет:
Нельзя так рассчитать ничего. Что бы это понять нужно изучить принцип работы АЦП. Время расчета при измерении зависит от фазы Луны и значения входного сигнала.

Вот мне тоже так показалось. Оно примерно одинаковое, если сигнал один и тот же. По логике время должно немного меняться (наверное на очень немного) в зависимости от уровня напряжения. Там же принцип деления на два, и получается, что сколько раз получится поделить на два, на столько время увеличивается. Только есть подозрение, что это настолько маленькие значения, что отловить их можно далеко не всегда.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Kakmyc пишет:

Нельзя так рассчитать ничего. Что бы это понять нужно изучить принцип работы АЦП. Время расчета при измерении зависит от фазы Луны и значения входного сигнала.

Учите матчасть! В атмеге стоит successive approximation ADC. А у таких АЦП время преобразования не зависит от величины сигнала.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

gene пишет:

Я тоже думал, что можно просто посчитать. Но, как мне кажется, надо тогда писать на ассемблере. Кроме работы АЦП есть работа с буфером, сохранение регистров при входе в функцию прерывания, еще какая-нибудь ерунда. 

При режиме FreeRunning каждое измерение занимает ровно 13 тактов АЦП и без перерыва между измерениями. Вход в прерывании и сохранение данных в буфер делается параллельно со следующим измерением. На С все прекрасно получается успевать. 

gene
Offline
Зарегистрирован: 07.02.2020

asam пишет:

Учите матчасть! В атмеге стоит successive approximation ADC. А у таких АЦП время преобразования не зависит от величины сигнала.

Не знал про "successive approximation ADC" и вообще не знал, что это такое. Но в описании все равно указано, что первое преобразование проходит дольше. Надо провести эксперимент и посмотреть действительно ли время не зависит от напряжения.

gene
Offline
Зарегистрирован: 07.02.2020

asam пишет:

При режиме FreeRunning каждое измерение занимает ровно 13 тактов АЦП и без перерыва между измерениями. Вход в прерывании и сохранение данных в буфер делается параллельно со следующим измерением. На С все прекрасно получается успевать. 

Если так, то это очень круто. Попытаюсь посчитать совпадет или нет с замеренными результатами.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

gene пишет:

Надо провести эксперимент и посмотреть действительно ли время не зависит от напряжения.

Проверял. Не зависит.

Zummer
Offline
Зарегистрирован: 25.11.2019

Kakmyc пишет:
Zummer пишет:

Проверил на баском авр-то же 13 тактов

В итоге получается что незачем мерять время заполнения буфера-его можно рассчитать

Например ардуино уно,с кварцем 16 МГц,1000 измерений,ADCSRA=B11100010,то есть частота тактирования АЦП 16/4=4 МГц

тогда каждый цикл измерния АЦП=(1/4 Мгц)*13=3,25 мксек,а заполнение буфера 1000*3,25 мксек=3,25 мсек

Нельзя так рассчитать ничего. Что бы это понять нужно изучить принцип работы АЦП. Время расчета при измерении зависит от фазы Луны и значения входного сигнала.

Если не умеете считать то учитесь,расчет правильный,читайте даташит,а фаза луны тут не при чем

 

Проверял на другом языке программирования,там все четко +-последний разряд иногда

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

gene пишет:

Надо провести эксперимент и посмотреть действительно ли время не зависит от напряжения.

Признавайтесь: Вы ежедневно экспериментально проверяете правильность таблицы умножения?