В наших домашних электросетях иногда случаются флуктуации напряжения, которые могут привести к сбоям в работе наших домашних устройств. В связи с этим в данном проекте мы рассмотрим создание устройства отключения сети переменного тока на основе микроконтроллера PIC, которые будет отключать потребителей переменного тока от сети если напряжение в сети станет больше или меньше определенных значений. Также при этом на экран ЖК дисплея будет выдаваться предупреждающее сообщение. Основой нашего устройства станет микроконтроллер PIC, который будет производить сравнение входного напряжения с опорным и в зависимости от результатов сравнения формировать соответствующие управляющие воздействия.
Для нашего проекта мы разработали печатную плату. Также в схему нашего проекта мы добавили блок на основе операционного усилителя LM358 (необязательный элемент), который будет без участия микроконтроллера PIC также производить сравнение входного и опорного напряжений. Для демонстрационных целей мы выбрали в качестве нижнего предела напряжения величину 150v, а в качестве верхнего – 200v. Вы можете изменить эти границы на те, которые необходимы вам. Также в демонстрационных целях в нашем проекте мы не использовали реле, которое бы отключало потребителей переменного тока от сети, а просто ограничились выводом предупреждающих сообщений на экран ЖК дисплея. При необходимости вы можете добавить реле в этот проект самостоятельно.
Также на нашем сайте вы можете посмотреть другие проекты силовой электроники на основе микроконтроллеров.
Необходимые компоненты
- Микроконтроллер PIC18F2520.
- Программатор PICkit 3 (купить на AliExpress).
- Держатель микросхем на 28 контактов.
- Кварцевый генератор 12 МГц.
- Операционный усилитель LM358 (купить на AliExpress).
- 3-х пиновый коннектор (опционально).
- ЖК дисплей 16×2 (купить на AliExpress).
- Транзистор BC547 (купить на AliExpress).
- Резисторы 1 кОм и 2,2 кОм (купить на AliExpress).
- Резисторы SMD 30 кОм и 10 кОм.
- Конденсаторы 0,1 мкФ и 33 пФ (купить на AliExpress).
- Конденсаторы 10 мкФ и 1000 мкФ (купить на AliExpress).
- Регуляторы напряжения 7805 и 7812 (купить на AliExpress).
- Светодиод (купить на AliExpress).
- Диоды Зенера (стабилитроны) на 5.1v, 7.5v, 9.2v.
- Трансформатор 12-0-12.
- Соединительные провода.
Реклама: ООО «АЛИБАБА.КОМ (РУ)» ИНН: 7703380158
Внешний вид собранной конструкции проекта показан на следующем рисунке.
Общие принципы работы проекта
В нашем устройстве защиты мы будем измерять напряжение в сети переменного тока с помощью трансформатора, микроконтроллера PIC, выпрямительного моста и делителя напряжения, и отображать его на экране ЖК дисплея 16×2. Затем бы будем сравнивать это измеренное значение напряжения с установленными в нашей программе границами и отображать соответствующее сообщение на экране ЖК дисплея. Если значение напряжения будет меньше 150v мы будем отображать сообщение “Low Voltage”, а если значение напряжения будет больше 200v – мы будем отображать сообщение “High Voltage”. В демонстрационных целях мы использовали регулятор вентилятора чтобы имитировать увеличение и уменьшение напряжения в сети.
Структурная схема работы проекта показана на следующем рисунке.
В схему нашего проекта мы также добавили схему контроля напряжения на основе компаратора LM358, без использования микроконтроллера.
Итак, в схеме нашего проекта мы будем производить следующие операции:
- Измерять напряжение сети переменного тока и сравнивать его с опорным с помощью трансформатора, выпрямительного моста, делителя напряжения и микроконтроллера PIC.
- Сравнивать измеренное значение напряжения с опорным с помощью трансформатора, выпрямительного моста и компаратора LM358 (без микроконтроллера PIC).
- С выхода компаратора подавать сигнал на микроконтроллер PIC.
С помощью трансформатора мы будем понижать входное напряжение, затем с помощью моста мы будем его выпрямлять, затем будем понижать его до диапазона 5 В с помощью делителя напряжения и далее подавать его на микроконтроллер PIC.
В микроконтроллере PIC это напряжение будет подаваться на вход АЦП (аналого-цифрового преобразователя), на выходе которого мы будем получать значение в диапазоне от 0 до 1023. Чтобы получить на основе этого значения измеренное значение напряжения (в сети переменного тока) мы будем использовать формулу:
1 |
volt= ((adcValue*240)/1023) |
В качестве максимального входного напряжения схемы мы использовали значение 240v. Либо же в качестве альтернативы приведенной формулы использовать преобразование с помощью функции map:
1 |
volt = map(adcVlaue, 530, 895, 100, 240) |
Здесь 100v – минимальное нижнее значение напряжения для преобразования, 530 и 895 – значения с выхода АЦП, относительно которых мы преобразовываем.
То есть приращению в 10mV на входе АЦП будет соответствовать эквивалентное приращение входного напряжения в 2.046. Если использовать 530 в качестве минимального значения на выходе АЦП, то требуемое значение напряжения можно определить по формуле:
1 |
(((530/2.046)*10)/1000) Volt |
То есть значению напряжения 2.6v на входе микроконтроллера будет соответствовать значение напряжения в сети переменного тока равное 100V.
Более подробно про схему делителя напряжения и конвертирование напряжений с выхода АЦП можно прочитать в статье про цифровой вольтметр на основе микроконтроллера AVR.
Для тестирования работы проекта мы использовали регулятор вентилятора переменного тока, с выхода которого мы подавали напряжение на вход трансформатора нашей схемы.
После подачи питания на схему на экране ЖК дисплея будет отображаться измеряемое значение напряжения. Если напряжения будет опускаться или подниматься выше нормы, то на экране ЖК дисплея будет отображаться сообщение “HIGH Voltage Alert” или “LOW Voltage Alert”.
Для управления отключением потребителей переменного тока при недопустимых флуктуациях напряжения в сети в схему проекта необходимо добавить реле.
Схема проекта
Схема устройства отключения сети переменного тока на микроконтроллере PIC представлена на следующем рисунке.
В схеме мы использовали компаратор LM358, два выхода которого подключены к контактам 2 и 3 микроконтроллера PIC. С выхода делителя напряжения сигнал подается на контакт 4 микроконтроллера. ЖК дисплей подключен к PORTB микроконтроллера PIC и работает в 4-х битном режиме. Его контакты RS и EN подключены к контактам B0 и B1 микроконтроллера а контакты – к контактам B2, B3, B4 и B5 микроконтроллера. В схеме проекта мы использовали два регулятора напряжения – на основе микросхем 7805 и 7812. Трансформатор 12v-0-12v используется для понижения переменного напряжения.
Объяснение работы для микроконтроллера PIC
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
В коде программы нам необходимо рассчитать значение напряжения переменного тока на входе схемы на основе значения с выхода АЦП, на который подается напряжение в диапазоне 0-5v и затем сравнить его с установленными в нашей программе границами.
Первым делом в коде программе и подключим используемые библиотеки и установим биты конфигурации микроконтроллера, более подробно про установку данных бит можно прочитать в этой статье.
Для работы с ЖК дисплеем мы используем ряд ранее запрограммированных функций (их описание можно найти в этой статье), таких как lcdbegin() (инициализация ЖК дисплея), void lcdcmd(char ch) (передача команды на дисплей), void lcdwrite(char ch) (передача одного символа на дисплей), void lcdprint(char *str) (передача строки символов на дисплей).
Для преобразования значений напряжения в нашей программе запрограммируем функцию map.
1 2 3 4 |
long map(long x, long in_min, long in_max, long out_min, long out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } |
Также запрограммируем функцию для инициализации и считывания значения с АЦП.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
int analogRead(int ch) { int adcData=0; if(ch == 0) ADCON0 = 0x03; // adc channel 0 else if(ch == 1) ADCON0 = 0x0b; //select adc channel 1 else if(ch == 2) ADCON0 = 0x0b; //select adc channel 2 ADCON1 = 0b00001100; // select analog i/p 0,1 and 2 channel of ADC ADCON2 = 0b10001010; //eqisation time holding cap time while(GODONE==1); // start conversion adc value adcData = (ADRESL)+(ADRESH<<8); //Store 10-bit output ADON=0; // adc off return adcData; } |
В следующем фрагменте кода производится считывание значений с АЦП и вычисление на основе этих считанных значений их среднего. Затем на основе этого значения производится расчет напряжения переменного тока на входе схемы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
while(1) { long adcValue=0; int volt=0; for(int i=0;i<100;i++) // taking samples { adcValue+=analogRead(2); delay(1); } adcValue/=100; #if method == 1 volt= (((float)adcValue*240.0)/1023.0); #else volt = map(adcValue, 530, 895, 100, 240); #endif sprintf(result,"%d",volt); |
И, наконец, производится вывод необходимых сообщений на экран ЖК дисплея.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
if(volt > 200) { lcdcmd(1); lcdprint("High Voltage"); lcdcmd(192); lcdprint(" Alert "); delay(1000); } else if(volt < 150) { lcdcmd(1); lcdprint("Low Voltage"); lcdcmd(192); lcdprint(" Alert "); delay(1000); } |
Разработка дизайна печатной платы для нашего проекта
Для разработки схемы проекта и дизайна печатной платы для него автор проекта (ссылка на оригинал приведена в конце статьи) использовал редактор EasyEDA. Также этот онлайн редактор предоставляет услуги изготовления печатной платы и приобретения электронных компонентов.
Дизайн печатной платы нашего проекта, выполненный с помощью редактора EasyEDA, доступен по ссылке:
https://easyeda.com/circuitdigest/HIGH_LOW_Voltage_Detector-4dc240b0fde140719c2401096e2410e6
Внешний вид скриншота нашей печатной платы в редакторе EasyEDA показан на следующем рисунке.
Также в этом редакторе можно посмотреть и фото спроектированной печатной платы.
Заказ изготовления печатной платы
После того как вы закончили проектировать печатную плату в редакторе EasyEDA, вы можете нажать в нем на иконку Fabrication (изготовление), после чего вас перебросит на страницу заказа печатной платы, на которой вы можете загрузить Gerber файлы для своей платы. На данной странице вам необходимо указать число экземпляров печатной платы, ее толщину, цвет и другие параметры. После этого нажмите на кнопку “Save to Cart” и завершите свой заказ.
Доставка у сервиса EasyEDA работает быстро и уже через несколько дней после заказа автор проекта получил изготовленные экземпляры печатных плат.
Потом он припаял на них необходимые электронные компоненты.
Исходный код программы
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
#include<xc.h> //xc8 is compiler #include<stdio.h> #include<stdlib.h> // CONFIG1H #pragma config OSC = HS // Oscillator Selection bits (HS oscillator) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled) #pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled) // CONFIG2L #pragma config PWRT = ON // Power-up Timer Enable bit (PWRT disabled) #pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled)) #pragma config BORV = 3 // Brown Out Reset Voltage bits (Minimum setting) // CONFIG2H #pragma config WDT = OFF // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit)) #pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768) // CONFIG3H #pragma config CCP2MX = PORTC // CCP2 MUX bit (CCP2 input/output is multiplexed with RB1) #pragma config PBADEN = OFF // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset) #pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation) #pragma config MCLRE = ON // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled) // CONFIG4L #pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset) #pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled) #pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode)) // CONFIG5L #pragma config CP0 = OFF // Code Protection bit (Block 0 (000800-001FFFh) not code-protected) #pragma config CP1 = OFF // Code Protection bit (Block 1 (002000-003FFFh) not code-protected) #pragma config CP2 = OFF // Code Protection bit (Block 2 (004000-005FFFh) not code-protected) #pragma config CP3 = OFF // Code Protection bit (Block 3 (006000-007FFFh) not code-protected) // CONFIG5H #pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected) #pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected) // CONFIG6L #pragma config WRT0 = OFF // Write Protection bit (Block 0 (000800-001FFFh) not write-protected) #pragma config WRT1 = OFF // Write Protection bit (Block 1 (002000-003FFFh) not write-protected) #pragma config WRT2 = OFF // Write Protection bit (Block 2 (004000-005FFFh) not write-protected) #pragma config WRT3 = OFF // Write Protection bit (Block 3 (006000-007FFFh) not write-protected) // CONFIG6H #pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected) #pragma config WRTB = OFF // Boot Block Write Protection bit (Boot block (000000-0007FFh) not write-protected) #pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected) // CONFIG7L #pragma config EBTR0 = OFF // Table Read Protection bit (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks) #pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks) #pragma config EBTR2 = OFF // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks) #pragma config EBTR3 = OFF // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks) // CONFIG7H #pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) not protected from table reads executed in other blocks) #define rs RB0 #define en RB1 char result[10]; #define lcdport PORTB #define method 0 void delay(unsigned int Delay) { int i,j; for(i=0;i<Delay;i++) for(j=0;j<1000;j++); } void lcdcmd(char ch) { lcdport= (ch>>2)& 0x3C; rs=0; en=1; delay(1); en=0; lcdport= (ch<<2) & 0x3c; rs=0; en=1; delay(1); en=0; } void lcdwrite(char ch) { lcdport=(ch>>2) & 0x3c; rs=1; en=1; delay(1); en=0; lcdport=(ch<<2) & 0x3c; rs=1; en=1; delay(1); en=0; } void lcdprint(char *str) { while(*str) { lcdwrite(*str); str++; } } void lcdbegin() { lcdcmd(0x02); lcdcmd(0x28); lcdcmd(0x0e); lcdcmd(0x06); lcdcmd(0x01); } int analogRead(int ch) { int adcData=0; if(ch == 0) ADCON0 = 0x03; // adc channel 0 else if(ch == 1) ADCON0 = 0x0b; //select adc channel 1 else if(ch == 2) ADCON0 = 0x0b; //select adc channel 2 ADCON1 = 0b00001100; // select analog i/p 0,1 and 2 channel of ADC ADCON2 = 0b10001010; //eqisation time holding cap time while(GODONE==1); // start conversion adc value (начало работы АЦП) adcData = (ADRESL)+(ADRESH<<8); //сохраняем 10-битное значение с выхода АЦП ADON=0; // выключаем АЦП return adcData; } long map(long x, long in_min, long in_max, long out_min, long out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } void main() { //ADCON1 = 0b0001111; //all port is digital TRISB=0x00; TRISC=0x00; TRISA=0xff; lcdbegin(); lcdprint("HIGH/LOW Volt"); lcdcmd(192); lcdprint("Detector by PIC"); delay(1000); lcdcmd(1); lcdprint("CircuitDigest"); lcdcmd(192); lcdprint("Welcomes You"); delay(1000); while(1) { long adcValue=0; int volt=0; for(int i=0;i<100;i++) // taking samples (считываем значения с АЦП) { adcValue+=analogRead(2); delay(1); } adcValue/=100; // вычисляем их среднее #if method == 1 volt= (((float)adcValue*240.0)/1023.0); #else volt = map(adcValue, 530, 895, 100, 240); #endif sprintf(result,"%d",volt); lcdcmd(0x80); lcdprint("H>200V L<150V"); lcdcmd(0xc0); lcdprint("Voltage:"); lcdprint(result); lcdprint(" V "); delay(1000); if(volt > 200) { lcdcmd(1); lcdprint("High Voltage"); lcdcmd(192); lcdprint(" Alert "); delay(1000); } else if(volt < 150) { lcdcmd(1); lcdprint("Low Voltage"); lcdcmd(192); lcdprint(" Alert "); delay(1000); } } } |