Регулятор напряжения

Vladimir_955

✩✩✩✩✩✩✩
16 Мар 2023
3
0
Добрый день. Начал разработку регулятора напряжения, на основании имеющейся схемы.
Столкнулся с проблемой, как считывать данные одновременно с нескольких аналоговых портов на Arduino Nano? Нужно считать напряжение с А3 и А2 для расчета мощности. В данный момент, симистор работает, а Arduino Nano считывает с него напряжение через А1, не совсем понимаю как (программно)!
 

Вложения

poty

★★★★★★✩
19 Фев 2020
3,228
939
@Vladimir_955, а что непонятно конкретно? Вроде настройка АЦП прокомментирована:
C++:
  //====================================================== Настройка АЦП
  ADMUX = (0 << REFS1) | (1 << REFS0) | (0 << MUX2) | (0 << MUX1) | (1 << MUX0); //
  //====================================================== Включение АЦП
  ADCSRA = B11101111;
  //======================================================
  ACSR = (1 << ACD);
Значения битов MUXn определяют канал (пин), который обрабатывается. Всё это описано как в datasheet, так и в любой другой форме по запросу.
 
  • Лойс +1
Реакции: Vladimir_955

Vladimir_955

✩✩✩✩✩✩✩
16 Мар 2023
3
0
@poty, благодарю за разъяснение. А как считать информацию с нескольких аналоговых входов или есть такая возможность?
 

poty

★★★★★★✩
19 Фев 2020
3,228
939
@Vladimir_955, только последовательно. Канал преобразования один, к нему подключаются разные входы.
1678970657735.png
Время преобразования зависит от выбранной точности (в данном случае выбран делитель /128, то есть частота 16M/128 = 125кГц и время преобразования = 120мкс. (определяется последними тремя битами ADCSRA). Можно уменьшить время преобразования уменьшив делитель, но точность тоже уменьшится.
В связи с тем, что настройка сделана для постоянного измерения (free running mode) после смены канала потребуется исключить результат следующего преобразования. Чтобы не тратить попусту время лучше запускать преобразование из самого прерывания, после изменения канала и выдержки интервала переключения.
 
  • Лойс +1
Реакции: Vladimir_955

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,407
974
58
Марий-Эл
Время преобразования зависит от выбранной точности
Не совсем так.
Время преобразования выбирается в зависимости от выходного сопротивления измеряемой цепи.
Не помню зависимость для атмелов.
Но там так:
Сопротивление R1, время преобразования T1.
Сопротивление R2, время преобразования T2.

А точность в обоих случаях будет одинакова.
 
  • Лойс +1
Реакции: Vladimir_955

poty

★★★★★★✩
19 Фев 2020
3,228
939

@Эдуард Анисимов, ну, на этом принципе основана рекомендация, что всё, что ниже 200кГц будет иметь нормальную точность, а всё, что выше - уже на внутренних сопротивлениях ухудшает точность. Только по факту это такая идеализация процесса. Чем меньше импеданс подключенного источника, тем больше его шумы влияют на точность (отсутствует интегрирование). Да, это можно преодолеть буферизовав выход, но кто этим занимается?
 
  • Лойс +1
Реакции: Vladimir_955

Vladimir_955

✩✩✩✩✩✩✩
16 Мар 2023
3
0
@poty, непосредственно я, для бытовых нужд. Такой точности регулирования не требуется. Физически не получается прописать преобразование нескольких аналоговых входов из самого прерывания. Вот как это сделать?
 

poty

★★★★★★✩
19 Фев 2020
3,228
939

@Vladimir_955, ещё раз:
1. Выбираете нужный вход (биты ADMUX.MUXn).
2. У Вас есть пример настройки АЦП на начало преобразования от триггера (бит ASCSRA.ADATE = 1), Вам этот бит нужно сбросить. В этом случае произойдет 1 преобразование, которое вызовет прерывание.
3. В прерывании считываете значение по этому входу (пример прерывания в приведённом коде имеется), меняете вход (аналогично п. 1), ждёте несколько микросекунд и запускаете новое преобразование (ADCSRA.ADCS = 1).
4. По окончании преобразования оказываемся в п.3, но с другим входом.

Опрос нужно производить последовательно, по каждому нужному входу отдельно.
 

Alex_HF

★✩✩✩✩✩✩
11 Мар 2023
40
16
Ну коль взялись за bare-metall, то не пишите так ADCSRA = B11101111; - мне пришлось считать номера битов в строке и сверять с datasheet.
ADMUX = (0 << REFS1) | (1 << REFS0) | (0 << MUX2) | (0 << MUX1) | (1 << MUX0); <- наверно лучше хотя-бы так.
АЦП у вас настроен на непрерывное преобразование одного канала Free Running mode (бит 5 ADATE в ADCSRA) - отключите его и запуск ацп сделайте руками после чтения канала и там же меняйте номер канала
Например:
C++:
ISR(ADC_vect)
{
        uint16_t tmp = ADC; 
      
        // если текущий канал ADC0 - значит делаем АЦП напряжения
        if (!(ADMUX & (1 << MUX0))) {
            ADMUX |= (1 << MUX0);    // переключаем канал на ADC1
            ADCSRA |= (1 << ADSC);    // запускаем следующее преобразование
            Vtmp += ((uint32_t)tmp * tmp);
        } else { // если текущий канал ADC1 - значит делаем АЦП тока
            ADMUX &= ~(1 << MUX0);    // переключаем канал на ADC0
            ADCSRA |= (1 << ADSC);
            Itmp += ((uint32_t)tmp * tmp);
            N++;
        }
}
 
Изменено:

te238s

★★✩✩✩✩✩
14 Ноя 2021
374
97
Опрос АЦП:
include"remote_control.h"


#define ADC_RUN  (ADCSRA=(0<<ADATE)|(1<<ADEN)|(1<<ADSC)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2))

typedef enum {CH0=0,CH1,CH2,CH3,CH4,CH5,CH6,CH7} channel;

channel ch;
uint8_t*buffer_adc;
uint8_t count;
uint8_t curr_adc;


void joystick_adc_init(uint8_t*buf,uint8_t n)
{
    ch=CH6;
    buffer_adc=buf;
    ADMUX=ch;//вывод ADC0
    //запуск.одиночного преобр.Частота 1/128. Указатель на место в массиве
    ADC_RUN;

}

void joystick_read(void)
{
}

void adc_read(void)
{
    static uint8_t i;
    //"щёлкаем" по кругу каналы
    switch(ch)
    {
        case CH6:[I](buffer_adc+0)=ADCL;[/I](buffer_adc+1)=ADCH;ch=CH7;ADMUX=ch;ADC_RUN;break;
        case CH7:[I](buffer_adc+2)=ADCL;[/I](buffer_adc+3)=ADCH;ch=CH3;ADMUX=ch;ADC_RUN;break;
        case CH3:[I](buffer_adc+4)=ADCL;[/I](buffer_adc+5)=ADCH;ch=CH2;ADMUX=ch;ADC_RUN;break;
        case CH2:[I](buffer_adc+6)=ADCL;[/I](buffer_adc+7)=ADCH;ch=CH6;ADMUX=ch;ADC_RUN;break;
    }
}
Модуль из моего проекта. Функция чтения АЦП вызывается у меня каждые 5 мс. При каждом вызове сохраняется замер предидущего канала.Настраивается следующий и жмём на "время".
Ежели преобразование непрерывное,то можно канал переключать на лету. В этом случае переключение произойдет по окончанию замера старого канала,соотв. получить результат можно гарантировано через 2 цикла измерений.
 
Изменено:
  • Лойс +1
Реакции: Vladimir_955