В прошлой статье, была тщательно разобрана схема стабилизатора 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 файдами: