Кopeнb:Кто подскажет, как вывести минимальное значение с датчика за последнюю допустим секунду при частоте срабатываний 20-30гц.
- какого датчика
- куда выводить
- срабатываний чего?
Кopeнb:Кто подскажет, как вывести минимальное значение с датчика за последнюю допустим секунду при частоте срабатываний 20-30гц.
- какого датчика
- куда выводить
- срабатываний чего?
Кopeнb:Всем привет. Кто подскажет, как вывести минимальное значение с датчика за последнюю допустим секунду при частоте срабатываний 20-30гц. Не очень силен в программировании.
самое простое -- массив из 30 значений и раз в секунду выбирать из этого массива минимальное значение, затем перезаполнение массива и снова выбор. Сложней, если вам надо "скользящее" окно, там надо будет динамически через сдвиг обновлять массив и выбирать минимальное значение после каждого измерения.
Панос Луридас. "Агоритмы. самый краткий и понятный курс". Почитайте ,мне кажется вы там найдете ответ на свой вопрос
Land:"скользящее" окно, там надо будет динамически через сдвиг обновлять
А зачем сдвиг, ему же не надо последовательность значений соблюдать. Заполнять массив всегда по кругу, раз в секунду пробегать и искать наименьшее.
Andy16:А зачем сдвиг, ему же не надо последовательность значений соблюдать. Заполнять массив всегда по кругу, раз в секунду пробегать и искать наименьшее.
а я не знаю, как ему надо
Land, спасибо за развернутый ответ.
Andy16, в общем нужно так - датчик показывает различные значения, от допустим 300 до 800, то больше то меньше. Вот и хотелось бы контролировать нижнюю границу показаний. Разбежка большая и заметить минимальное не всегда получается
Кopeнb:Andy16, в общем нужно так - датчик показывает различные значения, от допустим 300 до 800, то больше то меньше. Вот и хотелось бы контролировать нижнюю границу показаний. Разбежка большая и заметить минимальное не всегда получается
ну так вам тогда вполне достаточно каждое новое значение сравнивать с предыдущим. Если оно больше -- отбрасывать его. Если меньше, то присваиваете переменной min новое значение. И будет у вас минимальное значение за весь период измерения. Либо, если надо за секунду -- взводите таймер и по наступлению дедлайна обнуляйте значение min. Вернее не обнуляйте, а наоборот, загоняйте на максимум.
Land, за весь период не нужно, параметры, измеряемые датчиком, регулируются. Получается нужно вводить переменную, сравнивать ее с предыдущим и каждую секунду обновлять. Буду работать, спасибо
приветствую
столкнулся с проблемой использования функции micros() для attiny13.
использую библиотеку MicroCore, в которой эта функция реализована. опция ENABLE_MICROS включена.
вызываю эту функцию внутри while(1), чтобы обеспечить необходимые мне таймауты (всего три таймаута, на 16kHz, 3Hz, 0-1000Hz) с соответствующими обработчиками.
проблема в том, что складывается впечатление, что micros() срабатывает один раз (или вообще не срабатывает) и разница между двумя вызовами функции micros() всегда равна нулю.
посмотрел исходники функции micros()
и заметил, что она выключает все глобальные прерывания. может это как то влияет? но сколько примеров (а их совсем немного) не пересмотрел, нигда не видел, чтобы после вызова этой функции нужно было принудительно включать прерывания.
кто нибудь сталкивался с такой проблемой и как ее лечить?
zverjuga:приветствую
столкнулся с проблемой использования функции micros() для attiny13.использую библиотеку MicroCore, в которой эта функция реализована. опция ENABLE_MICROS включена.
вызываю эту функцию внутри while(1), чтобы обеспечить необходимые мне таймауты (всего три таймаута, на 16kHz, 3Hz, 0-1000Hz) с соответствующими обработчиками.
проблема в том, что складывается впечатление, что micros() срабатывает один раз (или вообще не срабатывает) и разница между двумя вызовами функции micros() всегда равна нулю.
посмотрел исходники функции micros()
и заметил, что она выключает все глобальные прерывания. может это как то влияет? но сколько примеров (а их совсем немного) не пересмотрел, нигда не видел, чтобы после вызова этой функции нужно было принудительно включать прерывания.
кто нибудь сталкивался с такой проблемой и как ее лечить?
что-то такое помниться
мелкосхему на ардуину нано с распаяным юсб заменил и забыл массу гиммороя что микрос не микрос и т.д.
я помниться несколько микросов объявлял когда-то
а потом хотелка сама отвалилась и забылась
помниться всё по ассемблерному стилем поднятием опусканием толпы флагов порешал
давно это было ничего не помню
я нашел проблему. функция micros() работает по таймеру, который нужно запустить. в исходниках есть функция init, где показан процесс запуска таймера.
но эксперименты показали, для тиньки micros() работает весьма неточно (это даже в документации написано), и вылезло кучу странных проблем, которые я так порешать и не смог. поэтому вместо micros(), для обеспечения нужных мне килогерцов, все таки перешел на прерывание таймера. а для герц мне хватит millis(), который работает с регистрами и должен работать нормально.
правда с прерыванием таймера тоже столкнулся с непонятной проблемой, а именно - с выбором прескалера для установки таймера. по документации прескалер имеет имеет значения 8, 64, 256, 1024. я перебрал все возможные варианты, и самый минимальный прескалер, который я нашел - это 64, что странно. но не критично.
zverjuga, а все потому что надо не пользовать непонятные библиотеки, а писать свои. Делаешь процедуру которая вызывается прерыванием по таймеру, а в ней накидываешь единичку в переменную, зная время прерывания, и их количество можно точно измерять временные интервалы для разных переменных, которые используются в разных событиях. Я обычно использую прерывание на 1 или 10мс. Хз как это в ардуино иде делается, но думаю можно.
SIO, ну почему же не понятные библиотеки? MicroCore - это уже чуть ли не единственная нормальная, которая написана для тиньки 13. просто нужно было исходники поизучать и поглубже вникнуть в предмет.
SIO:Делаешь процедуру которая вызывается прерыванием по таймеру, а в ней накидываешь единичку в переменную, зная время прерывания, и их количество можно точно измерять временные интервалы для разных переменных, которые используются в разных событиях
сейчас так и делаю. только вот накидывание единички в переменную - это фактически деление частоты генерируемого сигнала на 2. учитывая, что прерывание таймера можно настроить только прескалерами (8, 64, 256, 1024) и деля итоговую частоту на 2, практически невозможно получить строго нужную мне частоту. для тиньки13 нет никакой возможности получить, к примеру, частоту 8 кгц, но можно получить близкую к ней (где то около 8750, если мне не изменяет память).
когда имеешь дело с до килогерца, то тут проблем особо и нет. а вот уже если нужны килогерцы, тут и начинаются пляски, потому как миллисекунды уже не подходят. а настроить точные микросекунды не получится. и микросекунды можно получить только через прерывание таймера, что влечет большие накладные расходы. я как то даже ради интереса смотрел по осциллографу частоту сигнала, если ее генерировать из пустого бесконечного цикла. получилось где то порядка 250 кгц. а если внутри цикла просто вызывать функцию micros(), то частота падала примерно в 10 раз. чем чаще вызывать эту функцию, тем медленнее будет работать основной цикл из за того, что тинька постоянно отвлекается на прерывания.
а вообще, я научился прошивать тиньку прямо из микрочип студии, так что с arduino ide можно уже и не париться. в студии удобнее работать, как ни крути.
"прерывание таймера можно настроить только прескалерами"
А кто мешает сделать прерывание не по переполнению, а по совпадению с OCR регистром?и получить любое время с точностью до такта...
nml:а по совпадению с OCR регистром
Я именно это и мел в виду.
А если по сравнению не хочется, то во время прерывания по переполнению можно задать значение таймера TCNT регистр, и счет пойдет не с нуля, а с заданного значения, это как по сравнению только наоборот и на несколько тактов дольше.
с этой задачей я разобрался, получил ровно 8 кгц, которые мне были нужны, спасибо за подсказку. с настройками шим-таймеров пришлось повозиться, но в итоге разобрался.
но появилась другая проблема. ниже пример кода.
volatile int mr_need_ticks = 0;
ISR(TIM0_COMPA_vect)
{
PORTB ^= _BV(PB3);mr_need_ticks = mr_need_ticks - 1;
if (mr_need_ticks == 1) {
PORTB ^= (1 << PB0);
}
else if (mr_need_ticks == 0) {
PORTB ^= (1 << PB0);
mr_need_ticks = 1000000/62/6/2;
}
}
проблема в том, что блок if/else не срабатывает. в результате экспериментов выяснил, что if/else работает, если mr_need_ticks имеет типа char. а вот если уже тип short/int, то блок не работает. но мне char не подходит, так как он хранит большое число. есть идеи, как можно обойти эту проблему?
может, ты по делу что то скажешь? из твоего комментария вытекает, что подумать нужно именно тебе. под "он" в данном контексте имеется ввиду переменная mr_need_ticks с типом int. и так как число превышает 256, то отсюда и следует, что чар тут не подходит.
но если кому интересно, то проблему решил, разбив int на четыре char, и в операторе сравнения использовать уже именно чары.
char char1_tick = mr_need_ticks;
char char2_tick = ((mr_need_ticks) >> 8 );
char char3_tick = ((mr_need_ticks) >> 16);
char char4_tick = ((mr_need_ticks) >> 24);
zverjuga, в прерывании огород не городи, а то оно не успеет завершится как проц снова в прерывание уйдет не доходя до второй половины if к примеру. В прерывании минимум действий, чтобы прерывание успело завершится до наступления следующего. Все вычисления в теле программы. Ну и может способ расчета не очень подходит в данном случае. Я вообще не понял что там происходит в коде
SIO,
дело не в том, что оно не успевает завершиться. там времени вполне достаточно, я даже проверял специально. не делал никаких вычислений, а просто по IF-у менял уровень сигнала на пине. и эксперимент показал, что если IF работает с байтом (то есть чаром), то он работает нормально и условия работают нормально. а вот если в IF использовать short или int, то IF перестает работать. я если честно, нигде в доках такого не встречал
а по коду, а INT разбиваю на 4 чара (4 байта) и внутри IF уже работаю с чарами. и тогда IF работает нормально
char a = 1;
if (a == 1) {
// здесь условие срабатывает
}
short a = 1;
if (a == 1) {
// здесь условие не срабатывает
}
вычисления я и делаю внутри программы, тут ты прав. но проблема в том, что счетчик типа int, который уже нужно обработать внутри прерывания. поэтому приходится его раскладывать на 4 char.