RC фильтр для аналогового входа

Тема в разделе "Микроконтроллеры AVR", создана пользователем Yerabdi, 4 ноя 2017.

  1. Yerabdi

    Yerabdi Гик

    Здравствуйте всем какое сопротивление можно подключить последовательно на аналоговый вход для атмеги328р.Пробовал ставить 10кОм и 10нФ после этого микруха гонит то видит аналоговый сигнал то не видит
     

    Вложения:

  2. Unixon

    Unixon Оракул Модератор

    Какие частоты хотите отфильтровывать?
     
  3. sslobodyan

    sslobodyan Гик

    Чем выше выходное сопротивление источника сигнала для АЦП - тем хуже. Поскольку на входе АЦП стоит (внутри кристалла) запоминающий конденсатор, который должен успеть зарядиться за очень короткий промежуток времени. Рекомендуют не более 1.5ком, желательно намного меньше. А у вас 10ком - слишком много. Уменьшайте резистор и увеличивайте конденсатор.
    Если стоит задача фильтровать высокие частоты (судя по вашей схеме) и опрос ведется регулярно, то можно сделать это и математикой:
    U=U0*K + U1*(1-K), где U - фильтрованное напряжение, U0-предыдущее значение фильтрованного напряжения, U1-считанное новое значение с АЦП, К-коеффициент от 0 до 1, причем чем он меньше, тем сильнее сглаживается сигнал.
     
    REm нравится это.
  4. Yerabdi

    Yerabdi Гик

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

    sslobodyan Гик

    нет
    кого гонит? ничего не понимаю :)
     
  6. Yerabdi

    Yerabdi Гик

    зависимости от входного значение ацп выходной сигнал ШИМ длительность импульса увеличивается или уменшается. Чем больше значение аналогово сигнала который поступает с МАП(датчик разрежение воздуха)тем больше становится длительность импульса ШИМ. Вот до того момента пока не ставил фильтр более менее работал, после того как поставил фильтр длительность импульса не увеличивается.Потом убрал фильтр не помогает
     
  7. akl

    akl Гуру

    входной сигнал постоянное напряжение? какой величины? можно сделать буфер на ОУ
     
  8. sslobodyan

    sslobodyan Гик

    А МАР-сенсор выжил? Напряжение с него меняется? Как правило, сенсоры выдают значения от 0 до + питания. В авто я сталкивался с 5-вольтовой электроникой, так что и сенсоры выдавали 0-5 вольт, что для ардуинки нормльно. Померяйте тестером выход МАРа. Вряд ли фильтр там что-то подпалит, но все же.

    И рекомендую посмотреть в сторону ардуины на базе STM32 Дешевых платок навалом. Зато там такие плюшки есть, что вам подойдут.
    1. Там есть классный 12-разрядный АЦП, причем он умеет самостоятельно последовательно с заданной скоростью опрашивать несколько входов и запоминать значения в переменных.
    2. Так как ядро 32-разрядное, то самые быстрые вычисления получаются на целых 32-разрядных числах. Есть аппаратное умножение-деление флоатов. Короче, по математике атмега и рядом не стояла.
    3. Очень навороченные таймеры.
    4. Несколько последовательных портов - для отладки просто супер.
    5. Встроенный CAN bus.
    6. 72 мегагерца тактовая в самых слабых чипах.
    Из минусов - библиотек на него относительно мало. В тонкой настройке придется оперировать регистрами ядра, что обязывает читать референс мануал. Ну и питание 3.3 вольта, соответственно придется согласовывать уровни.
    Но оно того стоит - достаточно быстро упретесь в ограничения меги.
     
  9. Yerabdi

    Yerabdi Гик

    Добрый день, выход МАП проверил тестером нормально показывает.Напруга идет с МАПа но не повышается импульс ШИМа отключаешь потом заново включаешь нормально работает атмега
     
  10. sslobodyan

    sslobodyan Гик

    А нормально это сколько? Каков диапазон напряжений с МАРа?
     
  11. Yerabdi

    Yerabdi Гик

    Когда дает газ повышается до 4,7 Вольт
     
  12. akl

    akl Гуру

    нужен даташит на датчик, полная схема подключения и скетч. вангую что ошибка в программе.
     
  13. dizzel

    dizzel Нуб

    Дико извиняюсь за поднятие темы со дна морского, но у самого сейчас подобная проблема.
    На аналоговом пине атмеги328 повесил три кнопки по схеме:
    [​IMG]
    Иногда при нажатии одной кнопки мега регистрирует нажатие соседней. Подскажите уменьшение номиналов резисторов это верный путь?
     
  14. akl

    akl Гуру

    после того как аналоговый пин зарегистрирует нажатие кнопки, надо подождать несколько миллисекунд пока напряжение установится и снова измерить его - тогда будет зарегистрировано правильное напряжение конкретной кнопки, а не какое-то случайное промежуточное. короче это примерно то же самое что дребезг контактов
     
  15. issaom

    issaom Гуру

    Есть у меня статья на эту тему - там и пример кода есть.
     
  16. dizzel

    dizzel Нуб

    Привожу отрезок кода. У меня считываются два входа на ADC3 и ADC6. Опрос происходит попеременно в прерывании. Между опросами стоит пропуск, чтобы предотвратить кашу на выходе после преобразования. Скажите может в моем случае работа с прерыванием не уместна? Ведь считывание происходит непрерывно. Не очень понимаю как внедрить антидребезг в этом случае.
    Код (C++):
    #define BUTTON_UP  690
    #define BUTTON_DOWN  180
    #define BUTTON_MENU  512
    #define DELTA  20
    #define BUT_UP_LOW  BUTTON_UP - DELTA
    #define BUT_UP_HIGH  BUTTON_UP + DELTA
    #define BUT_DOWN_LOW  BUTTON_DOWN - DELTA
    #define BUT_DOWN_HIGH  BUTTON_DOWN + DELTA
    #define BUT_MENU_LOW  BUTTON_MENU - DELTA
    #define BUT_MENU_HIGH  BUTTON_MENU + DELTA
    #define LONG_U  1
    #define SHORT_U  4
    #define LONG_M  2
    #define SHORT_M  5
    #define LONG_D  3
    #define SHORT_D  6
    #define PRESS_U  7
    #define KEYB_PIN            0x03
    #define LGHT_PIN            0x06
    uint8_t analog_ref = DEFAULT;
    volatile uint16_t keyboardSense = 0;
    volatile uint16_t lightSense = 0;
    volatile bool getADC = false;
    volatile bool selectAdcPin = false;

    void setup() {
    //Включаем АЦП
    //опорное напряжение - Vcc
    ADMUX &= ~(1 << REFS1); ADMUX |= (1 << REFS0);

    //Запоминаем состояние регистра - оно будет использоваться при смене пина входящего сигнала
    analog_ref = ADMUX;

    //Выбираем пин AC3
    ADMUX |= KEYB_PIN;

    //предделитель преобразователя 64 для ATMEGA328
    ADCSRA |= (1 << ADPS2) | (1 << ADPS1); ADCSRA &= ~(1 << ADPS0);

    //Включаем автоматическое преобразование
    ADCSRA |= (1 << ADATE);

    //Разрешаем прерывания по завершении преобразования
    ADCSRA |= (1 << ADIE);

    //Включаем АЦП
    ADCSRA |= (1 << ADEN);

    //Запускаем преобразование
    ADCSRA |= (1 << ADSC);
    }
    void loop() {
    //обрабатываем кнопку
    buttonState = getButtonState(keyboardSense, 500, 1000);
    }

    byte getButtonState (uint16_t inputData, uint16_t longDelay, uint16_t pressedDelay) {
    static uint32_t timeStamp, pressedMillis;
    static byte buttonStatus;
    static bool prevState = true, pressedDetection;

    if (inputData < 800 && prevState && (millis() - timeStamp) > 50) {
    prevState = false;
    timeStamp = millis();
    pressedMillis = timeStamp;
    if (inputData < BUT_UP_HIGH && inputData > BUT_UP_LOW) buttonStatus = 1;
    else if (inputData < BUT_MENU_HIGH && inputData > BUT_MENU_LOW) buttonStatus = 2;
    else if (inputData < BUT_DOWN_HIGH && inputData > BUT_DOWN_LOW) buttonStatus = 3;
    }

    if ((inputData < BUT_UP_HIGH && inputData > BUT_UP_LOW) && !prevState) {
    timeStamp = millis();
    if (timeStamp - pressedMillis > pressedDelay) {
    pressedDetection = true;
    return PRESS_U;
    }
    }

    if (inputData > 800 && !prevState && (millis() - timeStamp) > 50) {
    prevState = true;
    timeStamp = millis();
    if ((timeStamp - pressedMillis) > longDelay && !pressedDetection) {
    if (buttonStatus == 1) return LONG_U;
    else if (buttonStatus == 2) return LONG_M;
    else return LONG_D;
    } else if ((timeStamp - pressedMillis) < longDelay) {
    if (buttonStatus == 1) return SHORT_U;
    else if (buttonStatus == 2) return SHORT_M;
    else return SHORT_D;
    }
    pressedDetection = false;
    }

    if (inputData > 900) return 0;
    }

    ISR(ADC_vect) {
    if (getADC) {
    if (selectAdcPin) {
    lightSense = (ADCL | ADCH << 8);
    ADMUX = analog_ref | KEYB_PIN;
    } else {
    keyboardSense = (ADCL | ADCH << 8);
    ADMUX = analog_ref | LGHT_PIN;
    }
    selectAdcPin = !selectAdcPin;
    getADC = false;
    } else {
    getADC = true;
    }
    }
     
  17. asam

    asam Гик

    Что-то я не смог обнаружить упомянутый пропуск.
    А вообще, к чему такие навороты с непрерывным измерением? В чем глобальная цель?
     
  18. dizzel

    dizzel Нуб

    Пропуск реализован с помощью переменной getADC. Один цикл считали для одного входа. Пропустили. Следущий цикл для второго входа. Пропустили. Повторяем заново.
    Глобальной цели нет. Просто хотелось попробовать именно так.
     
  19. asam

    asam Гик

    А, ну да. Хотя если хочется что бы АЦП работал непрерывно, то я лучше сделал бы так.
    - Переключил канал
    - Сделал N измерений (штук 10) считая сумму и попутно находя min and max
    - Вычел из суммы мин и макс и разделил сумму на N-2. N=10 еще удобно тем, что деление заменяется сдвигом на 3 вправо
    - Переключил канал

    Кстати, если использовать автозапуск преобразования, то неплохо было бы явно прописать и триггер в ADCSRB. А еще для полной точности рекомендуют тактову. АЦП держать в диапазоне 50-200Кгц. И если у вас кварц на 16Мгц, то тогда получается 250КГц, что допустимо, но точность падает.
     
    Последнее редактирование: 1 сен 2020
  20. parovoZZ

    parovoZZ Гуру

    Нет, не допустимо. 100 кГц - самый огонь.

    в атмеге328 каналы переключаются очень медленно

    А можно всё-таки человеческую схему по ГОСТ? Потенциал на входе МК как образуется?