Заголовок сообщения: Обработка значений с АЦП Мега8 не работает
Добавлено: Ср дек 07, 2022 12:34:13
Прорезались зубы
Зарегистрирован: Пн сен 03, 2012 14:46:08 Сообщений: 245 Откуда: Волгоград
Рейтинг сообщения:0
Всем привет! Делаю вольтамперметр на 8ой меге для лабораторника. Но возникла загвоздка в преобразовании значений АЦП в вольты:
Код:
uint8_t messCount = 0; // счетчик кол-во измерений АЦП uint8_t analogPin = 3; // номер входа АЦП uint8_t recMUX = 0; // переменная для сохранения исходного значения регистра ADMUX uint16_t voltADCTmp = 0; // вр. перем. для получения ср. ариф. АЦП
uint32_t voltage = 0; // напряжение uint32_t amperage = 0; // ток uint32_t wattage = 0; // мощность uint16_t uRef = 26300; // опорное напряжение для мега8а (внутренний ИОН) x10000 uint8_t rSh = 10; // сопротивление токового шунта x100 uint8_t kUr = 83; // отношение напряжений входного делителя x1000
uint16_t voltADCRes[3];
voltage = voltADCRes[2] * uRef / 1024 * 100 / kUr; // получаем напряжение типа XX.XXX
Последняя строка. voltage получается где-то 40-50. а должен получатся пятизначный результат (максимум). Если же просто выводить значение АЦП, то все в норме - до 1023. Считал на калькуляторе (режим programmer), там значения в норме. Вроде размерность переменных взял, чтобы переполнения не было... С током тоже самое - 2 других входа АЦП: amperage = voltADCRes[0] * uRef / 1024 / rSh; // ток берем до ОУ
Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
Внутренний ИОН у меги8 равен 2,56 В… а у Вас как я понял 2,63 В. Ну и хотелось бы точно знать при каком входном значении какой результат, чтобы понять где ошибка… Ещё иногда хорошо бы проверить какое значение получается у АЦП без преобразования при определённом входном напряжении…
Ну и формула ИМХО лучше когда выглядит так: ADC * Vtef / 10240… как заметили делим не на 1024, а на 10240… Vtef = 2560
Последний раз редактировалось VNS Ср дек 07, 2022 14:50:19, всего редактировалось 1 раз.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Заголовок сообщения: Re: Обработка значений с АЦП Мега8 не работает
Добавлено: Ср дек 07, 2022 14:41:33
Прорезались зубы
Зарегистрирован: Пн сен 03, 2012 14:46:08 Сообщений: 245 Откуда: Волгоград
Рейтинг сообщения:0
Значения самого АЦП в норме, от 0 до 1023 по всем трем каналам, если выводить только их (3 элемента массива), регулируя положение подстроечника. Внутренний ИОН, я измерил на AREF выводе, но сейчас все у меня на макетке. В данный момент это не принципиально. Проблема именно в математике.
Ну если с АЦП всё в порядке, то из конкретного результата можно понять где ошибка в математике… задайте в симуляторе конкретное значение ADC и посмотрите, где ошибка…
Я сейчас занят. Поднял из одного проекта. Проект не выстрелил, клиент был сельский, дорого ему было. Выдаю из наработок. Пока сами разбирайтесь. Занят. Помню, что были схожие проблемы, как у ТС, с математикой на С. Пришлось применить костыли. Результат выдал через long. А там через симулятор вычислил соответствие результата, чтобы вывести на дисплей.
В выходные попробую поднять проект, чтобы детальнее разобраться.
В проекте было измерение переменного тока (трансформаторы тока) и измерение переменного напряжения. Среднеквадратичное значение.
На тот момент я остановился на коэфициентах.
В общем, разбирайтесь, пробуйте. Работало, оставалось только допилить, чтобы более-менее соответствовало показаниям мультиметра. Особой точности в проекте не требовалось, так что...
Upd. Грубо. Суть такова. У avr плохо с float. Все упирается в ресурсы. Память, время исполнения. Переменку нужно успеть обработать. 10 мс. Поэтому нужно было успевать по максимуму работать с целочисленными значениями.
Схема измерения переменного тока была следующей. ИОН на 2,5 V. Один конец вторичной катушки на выход ИОН, второй конец через резистор 10 кОм на вход АЦП.
Схема измерения переменного напряжения. Делители напряжения. И резистор на выход ИОН для создания средней точки. Виртуальный нуль, что ли, не помню, как правильно называется эта схема.
Описание работы вкратце. Так как частота сети стабильная, детектора перехода через нуль нет. Таймер и АЦП настроены так, чтобы за 10 мс было 100 измерений. Для большей точности нужно сделать замеры нескольких периодов. Результаты измерений суммируются, затем вычисляется среднеквадратичное значение.
Так как в моем проекте было измерение трехфазной сети, каждый такт входы АЦП циклически переключаются.
Измеряю по 3м входам АЦП, сохраняю в массив (результаты измерения с нужного входа сохраняются в свою ячейку). Потом беру нужную ячейку и дальше вычисляю - мне так удобнее. Осталось только калибровку придумать...
Массив нужен для анализа, фильтрации. Если просто измерение, то достаточно суммирования при среднеарифметическое, либо возведение в квадрат результата измерения и дальнейшее суммирование и вычисление корня при среднеквадратичном.
Заголовок сообщения: Re: Обработка значений с АЦП Мега8 не работает
Добавлено: Чт дек 08, 2022 11:35:36
Прорезались зубы
Зарегистрирован: Пн сен 03, 2012 14:46:08 Сообщений: 245 Откуда: Волгоград
Рейтинг сообщения:0
Мне так удобнее. Можно и без массива, но здесь нужны будут "if" или "switch". Как нужно будет понять. с какого входа, куда данные сохранять...
Код:
void ReadADC() { uint16_t result = ADCL | ADCH << 8; // Получаем 10-битный результат
if (ADC_read) { // 10 измерений для исключения скачков if (messCount < 10) { voltADCTmp += result; // аккумулируем показания АЦП канала messCount++; // инкрементируем счетчик кол-во снятых показаний }// end if else { voltADCRes[analogPin-3] = voltADCTmp / messCount; // усредняем результат, присваиваем значения с АЦП ячейкам массива voltADCTmp = 0; // обнуляем messCount = 0; // обнуляем analogPin++; // Перебираем входные пины по кругу (А3...А5 - их может быть больше) if (analogPin > 5) { voltage = voltADCRes[2]; voltage = voltage * uRef / 1024 * 100 / kUr; // получаем напряжение типа XX.XXX
uint16_t resultTmp = voltage % 1000; // получаем тысячные
//округляем до сотых if (resultTmp % 10 < 5) resultTmp = resultTmp / 10; // если тысячные меньше 5 - просто делим на 10 else if (resultTmp < 995) resultTmp = resultTmp / 10 + 1; // если тысяные меньше 945 и тысячные больше 4, округляем сотые в большуюю сторону else { // если > 995 resultTmp = 0; // обнуляем сотые voltage += 1000; // увеличиваем целые }//end else voltage = voltage / 1000 * 100 + resultTmp; // приводим в виду XXXX (2 знака целые, 2 знака сотые)
// если напряжение после ОУ вышло из диапазона опорного (напряжение на шунте больше ~0.5V) if (voltADCRes[1] >= 1023) { amperage = voltADCRes[0]; amperage = amperage * uRef / 1024 / rSh; // ток берем до ОУ }//end if
// если напряжение после ОУ в диапазоне опорного else { amperage = voltADCRes[1]; amperage = amperage * uRef * 10 / 1024 / kOA / rSh; // ток берем с выхода ОУ (ку ОУ рассчитываем относительно друго входа без усиления) //amperage = amperage * uRef / 1024 / (voltADCRes[1] / voltADCRes[0]) / rSh; // ток берем с выхода ОУ (ку ОУ рассчитываем относительно друго входа без усиления) }//end else
resultTmp = amperage % 1000; // получаем тысячные //округляем до сотых if (resultTmp % 10 < 5) resultTmp = resultTmp / 10; // если тысячные меньше 5 - просто делим на 10 else if (resultTmp < 995) resultTmp = resultTmp / 10 + 1; // если тысяные меньше 945 и тысячные больше 4, округляем сотые в большуюю сторону else { // если > 995 resultTmp = 0; // обнуляем сотые amperage += 1000; // увеличиваем целые }//end else amperage = amperage / 1000 * 100 + resultTmp; // приводим в виду XXXX (2 знака целые, 2 знака сотые)
//if (uSw_1 && uSw_2 > uSw_1 && uSw_3 > uSw_2) SwitchRel(); // не переключаем реле, поку не установлены пороги переключения
analogPin = 3; // Все нужные перебрали...возвращаемся к первому resultReady = true; }//end if ADMUX = recMUX | (analogPin & 0x07); // Устанавливаем новый вход для преобразования ADC_read = false; // Устанавливаем флаг смены входного пина - следующее прерывание пропускаем }// end else }// end if (ADC_read) else ADC_read = true; // Первый раз пропускаем считывание и устанавливаем флаг на чтение в следующий раз }// end void ReadADC()
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 25
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения