Тема: Стабилизатор мощности на бытовом электрическом счетчике
К сожалению, а может к счастью выгорел контакт на много тарифном счетчике. Счетчик заменили, сгоревший я забрал на работу на опыты. При дальнейшем рассмотрении было установлено, что счетчик кроме счета вытаскивания из моего кармана денег, считает мгновенную мощность, напряжение, ток, косинус, и частоту. Стабилизаторы напряжения и тока я делал более простыми методами, поэтому меня заинтересовала только мощность, ну и еще возможность обнулять накопленные данные. Так, как счетчик имел оптическую головку для считывания, оставалось только сделать такую же и прикрутить к COM порту. Для опытов есть такая софтина AdminTools с помощью ее были определены команды на чтение мощности и обнуление накопленных данных. Осталось только загнать в контроллер. Контроллер собран на базе PIC628A для регулировки я использовал энкодер с внешним кольцом, которое работает как кнопки, вправо смена режимов, влево обнуление данных. Сам энкодер прибавляет или вычитает периоды для регулировки симистором BTA 40-800. Всего периодов около 350 поэтому каждый прибавляет или убавляет около 0,7 вольта в среднем. Режима два, ручной и автоматический. Алгоритм простой, при ручном режиме выставляется необходимая мощность по дисплею электросчетчика, при включении автоматического режима, значение сохраняется в EEPROM и далее каждые полсекунды считывается значение мощности полученное из электросчетчика с сохраненным значением. Если значения не совпадают подстраивается на один шаг в ту или другую сторону. При автоматической регулировке значение мощности изменяется на 3-4 процента, из за задержки чтения и подстройки, но всегда в обе стороны симметрично, поэтому общая стабильность высокая.
Вопрос для чего стабилизатор мощности когда есть недорогие стабилизаторы напряжения и тока. Во первых жалко выбрасывать электросчетчик, ва во вторых можно например на куб поставить 2 или более тэнов и при сгорании одного нагрузку на себя возьмет другой или другие. Ни стабилизатор напряжения ни стабилизатор тока на такое не способны.
А, еще печатка
Код для контроллера:
/*
* Project name:
RegPower (Стабилизированный регулятор мощности на CE102M)
* Copyright:
(c) Волков Александр, 2018.
* RegPower configuration:
MCU: PIC16F628A
Oscillator: HS, 20.0000 MHz
SW: mikroC v6.2.1.0
* NOTES: Переменные массивы работают только в первом или втором банке
void Init();
//const char OutUart[]="\xAF\x3F\x21\x8D\x0A\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x06\x30\x35\xB1\x8D\x0A\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x81\xD2\xB1\x82\x56\xCF\xCC\xD4\x41\x28\xA9\x03\x5F\x0\x0\x0\x0\x0\x0\x0\x81\xD2\xB1\x82\xC3\x55\xD2\xD2\xC5\x28\xA9\x03\x5A\x0\x0\x0\x0\x0\x0\x0\x81\xD2\xB1\x82\x50\xCF\xD7\xC5\x50\x28\xA9\x03\xE4\x0\x0\x0\x0\x0\x0\x0\x81\x42\x30\x03\xF5";
const char OutUart0[]="\xAF\x3F\x21\x8D\x0A";// Запрос модели
const char OutUart1[]="\x06\x30\x35\xB1\x8D\x0A";
const char OutUart2[]="\x81\xD2\xB1\x82\x50\xCF\xD7\xC5\x50\x28\xA9\x03\xE4";// Запрос мощности
const char OutUart3[]="\x81\x50\xB1\x82\x28\x33\xB1\xB4\xB1\x35\x39\xB2\x36\xA9\x03\xF6";//запрос пароля
const char OutUart4[]="\x81\xD7\xB1\x82\xC5\x4E\xC3\xCC\xD2\x28\x30\xB1\x30\x35\x35\x36\x30\x39\x36\x33\x35\xB1\xB2\xB1\x35\xA9\x03\x53";// Обнуление
const char OutUart5[]="\x81\x42\x30\x03\xF5";
unsigned PowerNagr; //Мощность нагрузки
unsigned PowerStab; //Мощность стабилизации
char ModeStab;//Режим стабилизаци (0-нет стабилизации, 1-по мощности)
char InUartVolt;
unsigned InUartCurre;
unsigned InUartPower;
char CountBait; // Счетчик байт
char InUsBait; //Принимаемый байт с порта
char FEncod;//Флаг состояния энкодера
char FMode;//Флаг режима (0-кнопка нажата, 1-кнопка отпущена, 2-Запись в память
char FUsWr;// Флаг выдачи данных в порт (0-запрс данных, 1-обнуление данных)
char FWrEEpr;//Флаг записи EEprom
char SchUsWr;// Счетчик выдачи данных в порт
char cir;
char ValCorr; //Значение коррекции мощности
char MaxCikl; //Максимальное количество сетьевых периодов
unsigned SchEncod; // Счетчик енкодера
unsigned SchTmr1; // Счетчик импульсов таймера
unsigned CountImp;//Количество импульсов таймера за полупериод сетьевого напряжения
unsigned TmpCnImp;
//***********************ГЛАВНАЯ ПРОГРАММА**************************************
void main() {
Init();
do { // главный цикл
} while (1);
} //~!
//********************ИНИЦИАЛИЗАЦИЯ*********************************************
void Init(){
STATUS=0b00000000;
OPTION_REG=0b10000100; //коэффициент деления TMR0 1:32
INTCON =0b11110000; //Разрешить прерывания от TMR0,RB0/INT и от переферийных модулей
RCSTA=0b10010000; // Модуль USART включен
PIE1 =0b00100001; //Разрешить прерывания от TMR1 от приемника EUSART
T1CON=0b00000001; //модуль Т1 включен предделитель 1:1
T2CON=0b00000000; //модуль Т2 выключен
CMCON=0b00000111; //Компараторы выключены
VRCON =0b00000000; //источник опорного напряжения выключен
TRISA=0b11101111;
TRISB=0b00011011;
PORTB=0;
PORTA.F4=1;
Usart_Init(9600); // Инициализация модуля USART (8 бит, скорость обмена 9600 бод, без паритета..)
SchTmr1=0;
SchEncod=350;
ModeStab=Eeprom_Read(0);
Delay_ms(50);
PowerStab=Eeprom_Read(1);
PowerStab=PowerStab<<8;
Delay_ms(50);
PowerStab=PowerStab+Eeprom_Read(2);
CountBait=0;
FUsWr=0;
FMode=0;
FWrEEpr=0;
MaxCikl=50;//Максимальное количество сетьевых периодов
}//~!
// //****************ПРЕРЫВАНИЯ****************************************************
//
void interrupt() {
INTCON.F7=0; //Запретить все прерывания
//прерывание по ТМР0
if (INTCON.F2){
if(ModeStab==0) { //Ручной режим
PORTB.F7=0;
// Обработка вращения энкодера
if(PORTB.F3) if(PORTB.F4){
FEncod=0; //Флаг сбрасывается когда на обоих контактах энкодера высокий уровень
PORTB.F6=1; //Светодиод автоматического режима
}
if(PORTB.F4==0){ // Определяется направление вращения
if(PORTB.F3){
if(FEncod==0){
PORTB.F6=0; //Светодиод автоматического режима
if(SchEncod>15) SchEncod=--SchEncod;// вычитает из счетчика увеличивая напряжение
FEncod=1; // и устанавливается флаг
}
}
}
if(PORTB.F3==0){ // Определяется направление вращения
if(PORTB.F4){
if(FEncod==0){
PORTB.F6=0; //Светодиод автоматического режима
if(SchEncod<(CountImp/2)-15) SchEncod=++SchEncod; // прибавляет к счетчику уменьшая напряжение
FEncod=1; // и устанавливается флаг
}
}
}
}
INTCON.F2=0;
}
//прерывание по ТМР1
if (PIR1.F0) {
T1CON.TMR1ON=0; //Таймер выключаем
TMR1H=255;
TMR1L=160;
T1CON.TMR1ON=1; //Таймер включаем
SchTmr1=++SchTmr1; // За сетьевой период проходит 763 отсчета
TmpCnImp=CountImp/2;
if(SchTmr1==SchEncod) PORTB.F5=1;//Включение семистора в 1 полупериоде
if(SchTmr1==SchEncod+1) PORTB.F5=0;//Выключение семистора в 1 полупериоде
if(SchTmr1==TmpCnImp+SchEncod) PORTB.F5=1; //Включение семистора во 2 полупериоде
if(SchTmr1==TmpCnImp+SchEncod+1) PORTB.F5=0;//Выключение семистора в 1 полупериоде
PIR1.F0=0;
}
//прерывание по RB0
if (INTCON.F1){
CountImp=SchTmr1;
SchTmr1=0;
if(ModeStab>1) ModeStab=0;
//Отправка в порт команд на выдачу мощности
if (SchUsWr==0) CountBait=0; //Обнуляем счетчик принимаемых байт
if (SchUsWr<5) Usart_Write(OutUart0[SchUsWr]);
if (SchUsWr>9) if (SchUsWr<16) Usart_Write(OutUart1[SchUsWr-10]);
if (FUsWr==0){
if (SchUsWr>19) if (SchUsWr<33) Usart_Write(OutUart2[SchUsWr-20]);// Запрос мощности
}
else {
if (SchUsWr>49) if (SchUsWr<67) Usart_Write(OutUart3[SchUsWr-50]);// Запрос пароля
if (SchUsWr>69) if (SchUsWr<98) Usart_Write(OutUart4[SchUsWr-70]);// Обнуление
}
if(PORTA.F1) if (SchUsWr>39) if (SchUsWr<45) Usart_Write(OutUart5[SchUsWr-40]);// Окончание пакета запроса мощности
if(PORTA.F1==0) if (SchUsWr>99) if (SchUsWr<105) Usart_Write(OutUart5[SchUsWr-100]);// Окончание пакета обнуления
//Преключение режимов стабилизации
if (SchUsWr==7){
PORTB.F7=0; //Светодиод автоматического режима
if (PORTA.F2==0){
if (PORTA.F1){
if (FMode==0){
FMode=1; // установка флага нажатия кнопки
ModeStab=++ModeStab;
if(ModeStab>1)ModeStab=0;
switch (ModeStab) {
case 0: {
PORTB.F6=1;//Светодиод ручного режима
PORTB.F7=0; //Светодиод автоматического режима
EEprom_Write(0, ModeStab);
break; //Запись в память EEPROM режима
}
case 1:{ // Запоминание значения мощности
PORTB.F6=0;//Светодиод ручного режима
PORTB.F7=1; //Светодиод автоматического режима
PowerStab=PowerNagr;
EEprom_Write(0, ModeStab);//Запись в память EEPROM режима
break;
}
}
}
}
}
}
if (SchUsWr==18){ //Установка флага отпускания кнопки
if (PORTA.F2){
if (PORTA.F1){
if (FMode>0){
FMode=0;
FWrEEpr=1;
EEprom_Write(1,PowerStab>>8);//Запись в память EEPROM старшего байта значения мощности
}
}
}
}
if (SchUsWr==35) {
if (FWrEEpr){
PORTA.F4=~PORTA.F4;
FWrEEpr=0;
EEprom_Write(2,PowerStab); //Запись в память EEPROM младшего байта значения мощности
}
}
//Автоматический режим стабилизация по мощности
if (SchUsWr==38){
if (ModeStab==1) {
PORTB.F6=0; //Светодиод ручного режима
PORTB.F7=1; //Светодиод автоматического режима
if(PowerNagr>PowerStab){
if(PowerNagr>PowerStab+30) ValCorr=5;
else ValCorr=1;
if(SchEncod<(CountImp/2)-20) SchEncod=++SchEncod;
}
if(PowerNagr<PowerStab){
if(PowerNagr+30<PowerStab) ValCorr=5;
else ValCorr=1;
if(SchEncod>20) SchEncod=SchEncod-ValCorr;
}
}
}
//Обнуление
if (SchUsWr==5){
if(PORTA.F1){
FUsWr=0;
MaxCikl=50;
}
else { //Отправление запроса на обнуление
FUsWr=1;
MaxCikl=254;
}
}
SchUsWr=++SchUsWr;
if( SchUsWr>MaxCikl) SchUsWr=0; //Опредаление времени запроса данных из эл.счетчика
INTCON.F1=0;
}
//прерывание от приемника USART
if (PIR1.RCIF){
if (Usart_Data_Ready()){
InUsBait=Usart_Read();//Принимаем байт из порта
InUsBait=InUsBait & 0b01111111; // Удаляем бит четности
InUsBait=InUsBait-48;//Конвертируем код числа в число
switch (CountBait) {
// Мощность
case 40: InUartPower=InUartPower+InUsBait*1000;break;
case 42: InUartPower=InUartPower+InUsBait*100;break;
case 43: InUartPower=InUartPower+InUsBait*10;break;
case 44: {
InUartPower=InUartPower+InUsBait;
PowerNagr=InUartPower;
InUartPower=0;
break;
}
}
CountBait=++CountBait;
}
PIR1.RCIF=0;
}
INTCON.F7=1; //Разрешить прерывания
return;
}//~
Контроллер программируется любым программатором поддерживающим PIC контроллеры, например "мастер кит", либо сделать самому, схем полно.
Но еще можно перенести все в Ардуино, я думаю не сложно (хотя я сам на Ардуино не работаю, когда начинал его еще не было), поэтому и выставил код, а не прошивку. Могу выставить и прошивку, но не нашел где файлы пристегиваются.
PS
Если кто заинтересуется расскажу все до мелочей