Вольтамперметр, 7 сегментные индикаторы, SPI

Автор zenon, 29 Сен., 2020, 22:18

« предыдущая - следующая »

zenon

Без сглаживания у меня последняя цифра дребезжит с вероятностью 50/50, попадешь - стоит, нет болтается например 8-9, или 4-5.
Хотя бы если сдвиги делаю на 1 - то уже воспринимается лучше.
Ну и 0,02 никуда не девается, если я убираю эту "хрень".
Завтра уже осциллографом гляну.
https://github.com/minamonra/

Slabovik

Ну тогда убери эту 8. Мистика какая-то. Потому что не может 8, поделённая на 16 в бинарном виде стать двойкой. Также не могут быть одновременно все озвученные наблюдения.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Без дизера.
На ноге АЦП МК, земля на Agnd - DS1Z_QuickPrint8.png
На первой ноге 6002 (out), земля щупа на 4-ой ноге  - DS1Z_QuickPrint9.png
V+ закорочен на Out-.
https://github.com/minamonra/

zenon

Ну как мистика-то - я же не придумываю, абсолютно не зачем... что вижу то есть.
Подожду как макет соберёшь.  ;)
https://github.com/minamonra/

Slabovik

Нифига ж себе колбасит-то там... По частоте - тактовая. Размах огромен. Да, надо дождаться макета...
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Тут я наверное зря соединил все земляные пины 3, 5, 21 под корпусом меги. (Хотя в элементе кикада эти выводы вместе).
Если пин 1 вверху.
3, 5 надо соединить и вывести слева, рядом повесив 0,1 мКф.
Пин 21 справа, он рядом с Agnd и Aref, его вправо, тоже на ёмкость. И потом объеденив их соединить внизу (или вверху) с Gnd.
Приблизительно изобразил... переделать надо.
https://github.com/minamonra/

Slabovik

Тут важно, чтобы точки минусового питания ОУ были  выведены вот на толстую площадку GND внизу, а точка, куда подключаются резисторы на входах и выходах этих ОУ была выведена под процик, оптимально к C2 при таком расположении как сейчас или к C1, если C1 и C2 под проциком не соединяются (Gnd от C1 идёт тоже на толстую Gnd, не проходя через C2)

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

zenon

Было бы интересно залить твой hex конечно, но и сам могу.
У меня atmega328p U-TH, вот что про них нашёл (https://hamster.in.ua/viewtopic.php?f=40&t=236).
Про ногу ОУ - понадеялся на полигоны земляные, они и вверху и внизу почти сплошной.
Меня больше интересует 21-ая нага gnd, она рядом с aref, и по идее под корпусом соединять не надо, а с двух сторон, а ботом на полигон..
https://github.com/minamonra/

Slabovik

#158
У меня из DIP (а на макетке DIP, для QFP надо плату делать, а мне неохота) есть Mega8A и Mega48-20PU. У них у обоих код отличается от 328-й (и друг от друга тоже, у 48-88-168-328 ресурсы хотя бы одинаковые, а у 8А ресурсы на других адресах). Но в принципе, мне ничто не мешает сходить в чип-дип да прикупить 328-е. Но они тоже будут DIP. Это значит, что 6 и 7 каналов АЦП у них нет (на кристалле есть, а на ногах нет). Я присоединю какие-нибудь другие.
А вот по поводу аппаратного SPI ещё не решил. Можно задействовать, можно не задействовать - просто другие ноги порта.

Я это к тому, что схему надо синхронизировать, чтобы код подходил...

зы: на ALI можно брать только их, китайские контроллеры. В остальном подделок дофига. Я пару раз обжёглся на PIC'ах, более не экспериментирую - то было 100% попадание на перепиленый хлам...
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

У меня в DIP китайские, а тот, который сейчас atmega328p U-TH куплен в "нормальном" магазине, не с али, поставщик вроде  промэлектроника.
https://github.com/minamonra/

Slabovik

#160
Не, я не к тому, что надо обязательно в DIP или QFN, надо просто чтобы тип совпадал. Если не совпадает, значит, просто перекомпилировать надо будет с другими установками, готовый бинарник не подойдёт.

Возьму сегодня 328-е...

Взял
Mega328P.jpg

зы: а не посадить ли тебя на asm?
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Не знаю на счёт асма, не готов пока. Мне бы C получше изучить.
Сегодня психанул - переделал плату, только вытравил.
На установку поставил переходники на камеру (пятак 0,8 теперь 75% кадра занимает), теперь совмещение сторон вроде лучше.
Хотя пока только первый раз, посмотрю как с повторяемостью.
https://github.com/minamonra/

zenon

Цитата: Slabovik от 28 Окт., 2020, 13:55готовый бинарник не подойдёт.
Ну откомпилировать наверное и сам смогу, и поправить где надо.
ы. С AT90USB162 не имел дела?
https://github.com/minamonra/

Slabovik

#163
Не, я больше со старьём... с USB надо конкретно отдельно разбираться - там протокол обмена замороченный... А так само ядро такое же, как в Меге.

зы: в качестве совета: на макете предусматривай возможность переподсоединения линий на другие ноги портов. Часто пригождается, когда вдруг по макету готовишь релиз, а разводка не идёт и удобнее переподсоединить оборудование куда-нибудь в другое место. Позволяет сделать это на макете, не дожидаясь платы, и поправить-отладить программу.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

Slabovik

Сегодня целый день (благо спокойствие на работе позволяло) упражнялся с Цэ. Нет, ребяты, это не моё. Хочется иметь предсказуемый и прогнозируемый результат, но однако с Цэ это не так. Не спорю, часто решающим является стиль написания, но всё-таки многие моменты совершенно не ясны, например, почему он из-за незначительной перестановки порядка обработки переменных корёжит получающийся бинарник до неузнаваемости. Непонятно...

Кстати, вот один очень простой пример, скорее относящийся к тому, как надо делать, а как делать разве что от лени.
Коротенький обработчик прерываний. Картинка. В картинке показаны код на Си и бинарный код, ему соответствующий.
Конкретно, в прерывании обрабатываются две переменные. Одна инкрементируется, вторая декрементируется с условием.

Вариант первый, вполне логичный для пишущего на Си.

Короткий-в-Цэ---длинный-в-байтах.png

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

Длинный-в-Цэ---короткий-в-байтах.png

Однако смотрите, что происходит.
Короткая на Си запись приводит к гораздо более затратному и бессмысленному с точки зрения кода "гонянию" память-регистр и обратно.

Собственно, к чему это я? К тому, что не нужно уповать на глобальность переменных и работать только с ними. Передача их значений для обработки в локальные переменные функций часто приводит к улучшению получающегося кода. На asm'е это логично и естественно: грузим данные в регистры - крутим - выгружаем. На Си совершенно не очевидно. И гоняться за наиболее компактной записью выражения часто бессмысленно и даже вредно.

зы: а ещё я расстроен тем, что не могу добиться правильного возврата из прерываний с установкой флага "Interrupts Enable". Дело в том, что код SEI необходимо давать непосредственно перед кодом RETI, что в Си мне сделать не удаётся - там на входе и на выходе "push-pop'ная" безусловная заглушка, имеющаяся даже при абсолютно пустой процедуре обработки прерывания, из-за чего SEI вставляется перед гуртом POP'ов, задолго до RETI, что в принципе неправильно и при "лавине" запросов на прерывания приведёт к переполнению стека.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Ну я не знаток Цэ. Но тут (https://habr.com/ru/post/309796/).
(поискав чуть-чуть) Про это есть:
Цитата: undefined...нужно искать возможность ввести временную локальную переменную, в которую производить запись, и только через какое-то время произвести запись из этой переменной в память....
Тут бы сесть и разобраться, кстати это указателей тоже касается.
А то статью эту по-диагонали просмотрел... :) :o
https://github.com/minamonra/

Slabovik

Просто оставлю ссылку здесь. Полезная инфа про стандартные библиотеки GNU AVR Lib C
https://www.nongnu.org/avr-libc/user-manual/index.html
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

Slabovik

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

Из приятного: оно работает. И дизер работает тоже. Причём работает как надо. При выключенном дизере (просто микросхемку вынимаю) показания дискретны с шагом 4 (предел 4096, либо ступенька 6 с пределом 6144). С дизером я могу поставить любое, так что все четыре знака (десятичных) в деле.

Из неприятного. Ты оказался прав, когда говорил, что у тебя всё прыгает на прерываниях. Суть в том, что код на Си весьма медленный и банально не успевает. Мне, переползшего с ассемблера, на такое непонятно как смотреть, потому что, как я уже говорил, за один тик я успеваю окучить 8 (восемь!) каналов и ещё время остаётся на "покурить". На Си у меня даже один не проходит без того, чтобы не занизить скорость отображения дисплея. Если поставить номинальную скорость, начинаются пропуски отсчётов. А поскольку не успевший закончить работу ADC возвращает нули (потому что прибегает "чужое" прерывание от таймера), то и начинается расколбас показаний. Что делать я пока не представляю. Попробую погонять программу на выяснение, какие процедуры сколько времени отнимают.
Варианты лечения. Первый - перейти на статическое отображение и тупо гонять программу по кругу без всяких таймеров, останавливаясь только на ожидание показания от АЦП. В этом случае уже ничто не будет мешать, а с какой скоростью будет идти измерения - с такой и ладно.
Второй - попробовать написать то же самое, но на асме, посмотреть, велик ли выигрыш. Займёт время.

Недоделка-на-макетке-заработала.jpg

зы: я конечно тактовую взял не 16 и даже не 14, а 12 МГц, но это из расчёта поставить частоту АЦП 187 кГц - немного выше, чем это получается при 16 МГц. Хотя, при 16 МГц можно было бы 250 кГц выставить на тиктирование АЦП и, думаю, ему хуже бы от этого не стало. Но аппноты говорят, что для точности надо ориентироваться на ~150 кГц плюс-минус...
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Воот, только я не понял, мы же, когда запускаем преобразование ADC разве проснуться можем в прерывании таймера? Вроде нет.
Макет получился что надо, выглядит брутально!
Я пробовал также примерно делать, - не, не хочу так больше, трудоёмко.
У меня плату получается сделать быстрее.
ы. Пробовал и пластиковые макетки штыревые - мат стоял в 33 этажа...
https://github.com/minamonra/

Slabovik

#169
Я поковырялся сегодня и нахожусь немного в тупоре (именно так, без буквы 'c').
Осциллограф мне показал, что таймер исправно тикает, но вот... сведения на индикатор (по SPI) идут в 1000 раз чаще, чем нужно по таймеру. Возможно, опрос ADC вместе с ними (это предстоит выяснить). Ну т.е. почти непрерывно, но... чётко зависят от настроек таймера (который тикает в 1000 раз реже!).  Явно ошибка в логике кода, но... пока её не вижу - тормоза стоят где надо...

А со штыревыми макетками, которые BreadBord, довольно весело. Но мне их вечно не хватает т.к. они не предполагают плотный монтаж. Плюс тянется проблема контактов - частенько он то есть, то где-то его нет.
На фото макетка 15x18 см, но и то я ещё не приступал к аналоговому узлу. С другой стороны, на ней сделана куча ошибок в расположении, из-за чего хочется переделать, но уже плотнее. Благо, выводно-проводной монтаж это позволяет.

Когда мы запускаем преобразование ADC в режиме Noise Reduction, мы не ожидаем никаких прерываний кроме прерывания от ADC. Таймер и сама программа специально настроены так, чтобы в это время ничего "лишнего" не прилетало. Это раз. Контрольный здесь - это сам механизм. В режиме Noise Reduction приостанавливается тактирование всех (!) таймеров, кроме RTC (если он есть) и возможна работа таймера N2, но только если тактовая на него поступает извне. У нас ни одного из этих "кроме" нет. Поэтому когда мы останавливаемся на ожидание ADC, то первым придёт именно прерывание от ADC. Ну типа это как проснулся утром по таймеру (солнышку), и до следующего тика (восхода солнышка), успеваешь приготовить завтрак да сходить отлить (вывести данные в индикатор), поработать (опросить ADC), книжку почитать (посчитать результаты), да поужинав пойти спать до следующего восхода.

ps. Разобрался, в чём проблема. Она одинаковая в наших случаях. Заключается в том, что ADC не останавливается по окончании преобразования. Либо (предположение №2), снова запускается, как, только режим переключается (регистр SMCR) из ADC Noise Reduction. В итоге, когда случается Idle для ожидания таймера, весело отрабатывает прерывание от ADC, выводя проц из режима ожидания в нормальную работу.

Выход из положения по-красивому пока не придумал как сделать, но просто отключение ADC на время, когда он не используется, работает. Из минусов такого подхода - это то, что на преобразование тратится не 13, а все 26 тактов (на частоте работы ADC), что при моих настройках (12 МГц, коэф.деления 64) даёт 140 микросекунд на преобразование. Но в принципе, это не является какой-то проблемой (такое долгое время) - в запасе остаётся ещё как минимум 700 мкс (именно столько проц находится в режиме Idle в ожидании прерывания от таймера).
↓ спойлер ↓
ADC-капризничает.png
[свернуть]
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

Slabovik

Ссылка на образовательную статью, где есть формула, по которой "немец" считал сглаживание.
Use Software Filters To Reduce ADC Noise (https://www.electronicdesign.com/technologies/analog/article/21778422/use-software-filters-to-reduce-adc-noise)
↓ спойлер ↓
вообще-то я хотел, чтобы ты сам попробовал - та формула на бумажке за пару проходов понимается, ну а в статье она "A Filter with Feedback"
[свернуть]
И вот ещё по следам, но по-русски http://we.easyelectronics.ru/Theory/chestno-prostoy-cifrovoy-filtr.html

А вообще здорово помогает колупание то там, то сям. В голове какие-то следы остаются.
А я сам пока что несколько проредил работу с кольцевым буфером, сделав ячеечки накопительными. Это значит, что в ячеечку (она двубайтовая) кладу не один отсчёт АЦП, а много, штуки четыре или восемь (максимально можно 64 - у нас АЦП десятибитный). Соответственно, обновление данных для индикатора в это количество раз становятся реже, что приятно сказывается на постоянстве цифр. Сейчас я могу выставить (регулируя ручечкой напряжение на входе АЦП) любую цифру с дискретностью 1. Перемаргивания конечно есть (особенно досаждает, когда перемаргивают сразу три или даже 4 цифры, типа 2999-3000, но уж таков недостаток цифровой индикации), но из-за более редкого обновления индикатора воспринимаются гораздо лучше.

И такие накопительные ячейки кольцевого буфера здорово сокращают потребую память под сам буфер. В 200 байт легко уложиться.

Не совсем пойму, нужна ли схема моего макета. Она немного отличается от той, что я показывал (ну хотя бы кузов другой), соответственно, программа привязана к схеме, хотя всё возможно переделать.

Всё-таки сделал я 4 канала измерений исходя из двух вариантов логики.
Первый: два канала измеряют традиционное напряжение на выходе блока. Они выводятся на индикатор по умолчанию.
Вторые два канала измеряют опорные напряжения для ограничителей тока и задатчика напряжения и по-умолчанию они не показываются на индикаторе. Но индикатор переключается на их показ (каждый индивидуально) если только опорное напряжение начинает изменяться (человек крутит ручку). Как только напряжение перестаёт изменяться, происходит переключение (через некоторое время) на показ выходного напряжения.
Таким образом, применяя индикатор можно не задействовать (т.е. не подключать) входы этих каналов, показания по ним будут нулевые, и автопереключения на них не будет происходить и пользователь вообще может не знать о их существовании.

Второй вариант - дополнительные каналы используются традиционно для автоматического переключения диапазона измерения.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

Ну тогда я не понял, почему ты против цифровой фильтрации?
ы. Ноль есть на макете (я про 0,02)?
https://github.com/minamonra/

Slabovik

#172
Когда я был против?  :o
Я против применения без понимания, и тем более против применения в качестве "розовых очков"  :) Ну это когда последующими обработками пытаешься буквально скрыть косяки в работе (аппаратуры или программы) на предыдущих стадиях. Касаемо этого фильтра - скрыть иногда неверно прочитанные отсчёты АЦП.

Ноль безпроблемный, но масштабирующие ОУ аналоговой части пока ещё не распаяны. Что будет с ОУ - посмотрим в ближайшие дни.

зы: думаю, что добавлю конфигурационные перемычки для того, чтобы можно было выбирать режим работы не прибегая к всяким "конфигурационным зажатиям кнопок".
Кнопки можно две - принудительное гашение младшего разряда  у каждого индикатора в том случае, если имеющих значение знаков становится четыре
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.

zenon

#173
Тут же как получается, - разбираю примеры и на этом учусь, но некоторые вещи пропускаю, в надежде на разобраться потом, всё-равно сразу всего не охватить, а возвращаться приходиться, вот и повод на ещё один подход...
За ссылку на изиэелектроникс спасибо, из любопытсва надо бы попробовать ещё и с БИХ фильтром, что там упоминается.

+++
Ноль именно с таким же как у меня способом подсчёта?
sum[adc_channel] += ADC;
if (++counter[1] > 16 - 1) {
        adc_oversampled[1] = (sum[1] + X) >> 2;
        sum[1] = 0;
        counter[1] = 0;
}
Потому, что у меня даже при замыкании каналов АЦП при X=8 ноля не было.
Новую плату правда ещё не собрал. Надо ещё в первый мой макет попробовать залить эту прошивку.
ы. Мне тут белые индикаторы подоспели на TM1637 подоспели.
Не пойму как их лучше задействовать, софтовый i2c или железный? Применять тут их наверное не буду, к stm уже.
ыы. Запустил их - яркие сильно, даже на яркости установленной в 0 отлично. Фильтр сверху им нужен из какого нибудь платика.
https://github.com/minamonra/

Slabovik

#174
Гм, я же показал формулу расчёта немного выше (https://anklab.ru/forum/index.php?msg=455). Она в самом низу на картинке. Но буфер у меня устроен по кольцевому принципу. Это значит, что предыдущие отсчёты вплоть до (-n) учитываются автоматически. В формуле "немца" примерно похоже, толко кольца нет. Принцип работы той формулы - новое значение имеет вес только на 25%, остальные 75% - вес старых значений. Это и хорошо и плохо. Хорошо тем, что приближение происходит по экспоненте. В первый проход - 25% новой инфы. Второй проход - 44 процента новой инфы, третий проход - 62 процента новой инфы и т.д. Плохо тем, что 100% новой инфы не бывает никогда и время установления рассчитывается, когда "остаток" старой инфы не будет приводить к изменению самого младшего разряда. А это довольно долго.

Кольцевой буфер "выкидывает" всегда чётко ровное количество старой инфы, поэтому приближение у него линейное, а не по экспоненте. Возвращаясь к тому же примеру, в первый проход 25 новой инфы, второй проход - 50%, третий 75, четвёртый - вся инфа новая.

25% я взял ради примера, поскольку у "немца" было столько.

Индикатор можно применять любой, только процедуру вывода для него написать соответствующую. I2C программный или аппаратный - в данном применении значения не имеет т.к. для использования преимуществ аппаратного нужно придумать, где он может работать параллельно основному ходу программы.

TM - микросхема удобная тем, что там всё внутри есть. Туда "плюнул и забыл". Но I2C подразумевает передачу не только "голой даты", но и предварительных управляющих команд. А максимальная частота Clock у ней ограничивается 500 кГц (типовая для I2C считается 400 кГц). Соответственно, вывод будет длиннее по времени. Вывод: как всегда, смотрим по месту и выбираем, что больше нравится :) Лично мне не трудно на пригоршне ТМ2, приправленных  ЛА3 подобное сколхозить :) А сюда я её вставлять не буду - пусть традиционные 595-е остаются.

зы: поправлю схему в соответствии со своим макетом - поделюсь и схемой и исходником. Надо-всё-таки решать, куда дальше двигаться.
зызы: Выяснил, что REF198 надо хоть немножко нагружать. Сочетание "без нагрузки" (вход AREF нагрузкой не является) и керамический конденсатор на выходе иногда приводят к генерации (после касания рукой, пинцетом и т.п.). Добавление буквально 47 кОм (ток 9 мкА) избавляют от этого свойства.
Генерацию цифровым осциллографом не видно (был как-то спор, мне упирались, мол цифровым всё можно посмотреть). Выявил, когда смотрел аналоговым, по утолщению линии. Частота - несколько МГц, вид - спадающая пила, размах - несколько милливольт. Проявлялось как некоторое увеличение показаний АЦП, буквально на несколько отсчётов в пределах величины дизера, после касания пинцетом или рукой вывода выхода REF198.
Вот такая вот закавыка. Кстати, в даташите указывается на наличие электролитического алюминиевого конденсатора на выходе - похоже, это связано с этим явлением.
Общением на форуме подпитываю свою эгоистичную, склонную к самолюбованию сущность.