В прошлой статье, была тщательно разобрана схема стабилизатора VR V600.

Разобраны три режима стабилизации, разобраны в каком положении должны быть перемычки реле, для повышения, понижения напряжения или вообще работы без стабилизации.

Напомню схемы положения перемычек для разных режимов.

Повышающий режим:

Понижающий режим

Без стабилизации

Итог: было выяснено, что проблемы возникли в самом микроконтроллере. Поэтому было решено заменить его тем, что есть под рукой.

Наиболее близкий контроллер по ножкам - это AVR Attiny26L, который был в наличии. Но нужна была схема-переходник. Которая бы скоммутировала 20 ножек в 16, которые разведены на плате.

Плату решил не переделывать, добавить только переходник.

Вот такая схема получилась в KiCad:

На переходник кроме разводки площадок для Holtek, добавлены:

  • разъем для чтения того, что считывает микроконтроллер. По протоколу I2C
  • емкость 100 микро фарад, для сглаживания импульсо выбрасываемых реле,при переключении

Расшифровка названий разъемов:

  • TEMP ADC - вход на АЦП по считыванию температуры трансформатора
  • INL ADC - вход на АЦП с входной линии стабилизатора
  • OUT ADC - вход на АЦП с выходной линии стабилизатора
  • GND - земля
  • RL3 s/w - ножка управления реле 3
  • RL2 s/w - ножка управления реле 2
  • RL1 s/w - ножка управления реле 1
  • R/D s/w - ножка управления красным светодиодом
  • Y/D s/w - ножка управления жельым светодиодом
  • RESET - ножка сброса микроконтроллера
  • +5V - питание МК

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

Первая часть схемы - это самодиагностика. Переключая реле с выключенным выходм, производятся замеры на входной и выходной линии и сравниваются значения.

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

Немного расскажу о измерении входного напряжения. В прошлой статье в видео, было описано, что напряжение на АЦП подается с делителя напряжения, который представлеят собой: диод - резистор 940 кило ом - точка снятия напряжения - резистор 10 килоом - земля. Т.е входное напряжение понижается в 94 раза, его и считывает АЦП и перобразует в цифру.

Учитывая наличие диода, отрицательная полуволна отрезается и определить величину входного напряжения представляется возможным только на положительной полуволне:

Синяя линия - это входное напряжение.

т.е 10 миллисекунд нужно точно ждать, дожидаясь появления положительной полуволны.

Далее я сделал алгоритм нахождения максимума на положительной полуволне:

#define UNDEF 15000

uint16_t getWaveMax(uint16_t in_data){
    if (!beg){
        if (in_data>V100 && !waveMax){
            waveMax = in_data;
            } else if (in_data>V100 && prevVal<=in_data){
            if (waveMax < in_data) waveMax = in_data;
            beg = 1;
            } else {
            waveMax = 0;
        }
        } else {
        if (waveMax<in_data){
            waveMax = in_data;
            } else {
            if (in_data<=V100){
                tmpMax = waveMax;
                waveMax = 0;
                beg = 0;
                prevVal = 0;
                return tmpMax;
            }
        }
    }
    prevVal = in_data;
    return UNDEF;
}

в алгоритме запоминается старое значение и манипуляции происходят с новым значением. Реакция начинается при достижении полуволны, некоего порога V100. Т.е окончательное решение микроконтроллером о значении входного напряжения будет принято только когда положительная полуволна уйдет в значение ниже V100. Т.е это еще примерно 7 миллисекунд. Итого время реагирования стабилизатора получилось: 10 миллисекунд на отрицательную полуволну + 7 миллисекунд на вычисление максимума на положительной полуволне = 17 миллисекунд.

Во время испытаний был замечен еще один эффект. Состояния стабилизатора по алгоритму были разделены на 5 частей.

  • 0 - ниже V180
  • 1 - V180-V205
  • 2 - V205-V235
  • 3 - V235-V265
  • 4 - выше V265

0 и 4 - красня зона, когда выход стабилизатора отключен, 1,3 - желтая зона когда происходит стабилизация, 2 - зеленая зона без стабидизации.

По цвету зоны определяется какой светодиод будет гореть.

Так вот, если задать границы между зонами четко, то при достижении границы зоны, мы можем попасть в цикл переключений реле. Например:

  • было напряжение 175В - стабилизатор в красной зоне = 0
  • напряжение достигло V180, стабилизатор перешел в зону 1, переключил реле, но во время переключения возникла помеха и напряжение понизилось на 1В
  • пониженное напряжение опять перевело стабилизатор в зону 0, вновь переключилось реле
  • но помеха исчезла и напряжение опять идентифицировалось как V180 и опять реле переключилось для желтой зоны = 1

и такие события происходили циклически. Для решения проблемы была сделана таблица лимитов для каждой зоны:

COND - в таблице обозначает зону и лимиты для каждой зоны.

Можно увидеть, что в зависимости от значения COND лимиты изменяются.

Т.е при переключении из 0 в 1, лимит V180 меняется со 180 на 175, что исключает циклические переключения. Вот как выглядит график переключения для данного условия:

И описание нового алгоритма, пример:

  • было напряжение 175В - стабилизатор в красной зоне = 0
  • напряжение достигло V180, стабилизатор перешел в зону 1, переключил реле, но во время переключения возникла помеха и напряжение понизилось на 1В
  • пониженное напряжение не перевело стабилизатор в зону 0, т.к попав в зону 1 лимит V180 изменился. И теперь для перехода в зону 0 нужно понизить напряжение на 5 вольт

Вот реализация данного алгоритма:

int cond = 0; //0 < 180, 1 < 205, 2 < 235, 3 < 260, 4 > 260

uint16_t getLimit(uint16_t val){
    if (val == V180){
        if (cond == 1) return (V180 - V10);
    } else if (val == V205) {
        if (cond == 2) return (V205 - V10);
    } else if (val == V235) {
        if (cond == 3) return (V235 - V10);
    } else if (val == V260) {
        if (cond == 4) return (V260 - V10);
    }
    return val;
}

И так, программа есть, можно делать макетную плату:

и отлаживать на аппарате, описанном в этой статье

Для отладки I2C взаимодействияпришлось прибегнуть к эмуляции, как описано в статье - Видеоинструкция о том как применять stimuli файл в среде Atmel Studio. Но код питон-скрипта по генерации stimuli файлов был расширен.

https://github.com/bayrepo/embedded_avr/blob/master/attiny26l/sven_vrv600_avr/stimuli_converter/conver2.py - описание работы скрипта будет ниже.

и пришлось провести ряд тестов, при разработке функции получения значения входного напряжения.

Исходные коды

Весь проект можно найти по адресу: https://github.com/bayrepo/embedded_avr/tree/master/attiny26l/sven_vrv600_avr

В составе проекта:

main.c - исходный код программы, для МК attiny26L

stimuli_converter - в папке расположен питон скрипт, для преобразования csv файла, полученного на логическом аанализаторе LA1010 для запуска конвертера используется команда:

python3 conver2.py 8000000 2021-02-03_00-59-54_0_scl_1_sda.csv test.stim 10
где python3 conver2.py [частота в герцах] [файл csv] [выходной стимули файл] [число холостых тактов, когда начальные значения не менялись]

Пример csv файла:

Time[s],  PINB 2,  PINB 0, PINA 7
-0.012501375, 0, 1, 0
0.000000000, 1, 1, 0
0.000010250, 1, 0, 0
0.000020125, 0, 0, 0
0.000021000, 0, 1, 0
0.000028625, 0, 0, 0
0.000037875, 1, 0, 0
0.000047375, 0, 0, 1
0.000057250, 1, 0, 0
0.000066625, 0, 0, 0

Файл полученный от экспорта LA1010, в первой строке должен быть дополнен номерами пинов МК, на которые сигнал будет подан т.е PINB 2 - это PINB МК его третий бит, PINB 0 - первый бит и т.д. Пины могут быть разные.

Пример запуска:

$ python3 conver2.py 8000000 test1.csv test1_out.stim 10
F_CPU 8000000 from file test1.csv
1 cyckle size 0.000000125000

tests - папка с тестами и моделированием:

1 - моделирование функции getWaveMax, вычисление максимального значения на положительной полуволне:

$ ./sven600
Test 1. One wave 0=T(U) 10=T(U) 20=T(U) 30=T(U) 310=T(U) 320=T(U) 340=T(U) 310=T(U) 300=T(340) 100=T(U) 40=T(U) 20=T(U) 0=T(U) 0=T(U) 
Test 2. One distorted wave 0=T(U) 10=T(U) 20=T(U) 30=T(U) 310=T(U) 320=T(U) 340=T(U) 310=T(U) 320=T(U) 330=T(U) 320=T(U) 310=T(U) 100=T(340) 0=T(U) 
Test 3. One dist wave second huge 0=T(U) 10=T(U) 20=T(U) 30=T(U) 310=T(U) 320=T(U) 340=T(U) 310=T(U) 320=T(U) 330=T(U) 340=T(U) 350=T(U) 320=T(U) 310=T(U) 100=T(350) 0=T(U) 
Test 4. Two waves 0=T(U) 10=T(U) 20=T(U) 30=T(U) 310=T(U) 320=T(U) 340=T(U) 310=T(U) 290=T(340) 330=T(U) 330=T(U) 325=T(U) 320=T(U) 310=T(U) 100=T(330) 0=T(U) 
Test 5 340 == 340. One wave
Test 6 340 == 340. One distorted wave
Test 7 350 == 350. One dist wave second huge
Test 8 330 == 330. Two waves, check both
Test 9 340 == 340. Two waves, check only first
Test 10. A lot of small waves 100=T(U) 350=T(U) 100=T(U) 350=T(U) 100=T(U) 350=T(U) 100=T(U) 350=T(U) 100=T(U) 350=T(U) 100=T(U) 350=T(U) 100=T(U) 350=T(U) 100=T(U) 
Test 11. A lot of small waves 2 100=T(U) 350=T(U) 350=T(U) 100=T(350) 350=T(U) 350=T(U) 100=T(350) 350=T(U) 350=T(U) 100=T(350) 350=T(U) 350=T(U) 100=T(350)

2 - моделирование перехода между состояниями getLimit, при различных значениях на LineIn:

$ ./sven600_2
0) Volt UNDEF=63
1) Volt UNDEF=79
2) Volt UNDEF=99
3) Volt UNDEF=107
4) Volt UNDEF=158
5) Volt UNDEF=177
6) Volt UNDEF=142
7) Volt UNDEF=101
8) Volt 177 cond 0
9) Volt UNDEF=31
10) Volt UNDEF=63
11) Volt UNDEF=79
12) Volt UNDEF=99
13) Volt UNDEF=107
14) Volt UNDEF=158
15) Volt UNDEF=179
16) Volt UNDEF=142
17) Volt UNDEF=101
18) Volt 179 cond 1
19) Volt UNDEF=31
20) Volt UNDEF=63
21) Volt UNDEF=79
22) Volt UNDEF=99
23) Volt UNDEF=107
24) Volt UNDEF=158
25) Volt UNDEF=175
26) Volt UNDEF=142
27) Volt UNDEF=101
28) Volt 175 cond 1
29) Volt UNDEF=31
30) Volt UNDEF=63
31) Volt UNDEF=79
32) Volt UNDEF=99
33) Volt UNDEF=107
34) Volt UNDEF=158
35) Volt UNDEF=170
36) Volt UNDEF=142
37) Volt UNDEF=101
38) Volt 170 cond 0
39) Volt UNDEF=31
40) Volt UNDEF=63
41) Volt UNDEF=79
42) Volt UNDEF=99
43) Volt UNDEF=107
44) Volt UNDEF=158
45) Volt UNDEF=177
46) Volt UNDEF=142
47) Volt UNDEF=101
48) Volt 177 cond 0
49) Volt UNDEF=31
50) Volt UNDEF=63
51) Volt UNDEF=79
52) Volt UNDEF=99
53) Volt UNDEF=107
54) Volt UNDEF=158
55) Volt UNDEF=205
56) Volt UNDEF=142
57) Volt UNDEF=101
58) Volt 205 cond 2
59) Volt UNDEF=31
60) Volt UNDEF=63
61) Volt UNDEF=79
62) Volt UNDEF=99
63) Volt UNDEF=107
64) Volt UNDEF=158
65) Volt UNDEF=201
66) Volt UNDEF=142
67) Volt UNDEF=101
68) Volt 201 cond 2
69) Volt UNDEF=31
70) Volt UNDEF=63
71) Volt UNDEF=79
72) Volt UNDEF=99
73) Volt UNDEF=107
74) Volt UNDEF=158
75) Volt UNDEF=205
76) Volt UNDEF=142
77) Volt UNDEF=101
78) Volt 205 cond 2
79) Volt UNDEF=31
80) Volt UNDEF=63
81) Volt UNDEF=79
82) Volt UNDEF=99
83) Volt UNDEF=107
84) Volt UNDEF=158
85) Volt UNDEF=189
86) Volt UNDEF=142
87) Volt UNDEF=101
88) Volt 189 cond 1
89) Volt UNDEF=31

3 - эксперимент, когда getWaveMax возвращает не максимальное, а усредненное значение (алгоритм от которого я решил отказаться)

$ ./sven600_3
Test 1. One wave 0=T(U) 10=T(U) 20=T(U) 30=T(U) 310=T(U) 320=T(U) 340=T(U) 310=T(U) 300=T(318) 100=T(U) 40=T(U) 20=T(U) 0=T(U) 0=T(U) 
Test 2. One distorted wave 0=T(U) 10=T(U) 20=T(U) 30=T(U) 310=T(U) 320=T(U) 340=T(U) 310=T(U) 320=T(U) 330=T(U) 320=T(U) 310=T(U) 100=T(316) 0=T(U) 
Test 3. One dist wave second huge 0=T(U) 10=T(U) 20=T(U) 30=T(U) 310=T(U) 320=T(U) 340=T(U) 310=T(U) 320=T(U) 330=T(U) 340=T(U) 350=T(U) 320=T(U) 310=T(U) 100=T(320) 0=T(U) 
Test 4. Two waves 0=T(U) 10=T(U) 20=T(U) 30=T(U) 310=T(U) 320=T(U) 340=T(U) 310=T(U) 290=T(318) 330=T(U) 330=T(U) 325=T(U) 320=T(U) 310=T(U) 100=T(316) 0=T(U) 
Test 5 318 == 340. One wave
Test 6 316 == 340. One distorted wave
Test 7 320 == 350. One dist wave second huge
Test 8 316 == 330. Two waves, check both
Test 9 318 == 340. Two waves, check only first
Test 10. A lot of small waves 100=T(U) 350=T(U) 100=T(U) 350=T(U) 100=T(U) 350=T(U) 100=T(U) 350=T(U) 100=T(U) 350=T(U) 100=T(U) 350=T(U) 100=T(U) 350=T(U) 100=T(U) 
Test 11. A lot of small waves 2 100=T(U) 350=T(U) 350=T(U) 100=T(350) 350=T(U) 350=T(U) 100=T(350) 350=T(U) 350=T(U) 100=T(350) 350=T(U) 350=T(U) 100=T(350)

kicad - папка с kicad проектом схемы переходника

3models - папка с моделью крышки, для сокрытия схемы переходника. Т.к. она не поместилась в стандартный корпус.

Итог

Разрботана схема, программа для переходника, 3д модель крышечки - т.к переходник не поместился в корпус и появилась необходимость вынести его наружу корпуса и прикрыть крышечкой, напечатанной на 3д принтере.

Вот как соединен с платой сам переходник:

напаянные проводки.

Сама схема переходника на плате:

Стабилизатор работает.

Единственно, темепературные значения термодаатчика в программе не выставлены, т.к не выяснил формулу изменения сопротивления терморезистора в трансформаторе.

Видео:

Работа со stimuli файдами:

Добавить комментарий

Следующая запись Предыдущая запись