Foudation và power line sẽ luôn có ích khi tạo hoặc gỡ bỏ bất kỳ hệ thống điện nào. Trong dự án này, chúng tôi sẽ chế tạo Ampe kế hoạch kỹ thuật số của riêng mình bằng cách sử dụng Vi điều khiển PIC16F877A và dòng ACS712-5A cảm biến. This project can may đo cả dòng điện AC và DC với dải từ 0-30A với 0,3A chính xác. Với một số sửa đổi trên mã, bạn cũng có thể sử dụng mạch này để đo lên đến 30A. Vì vậy, chúng ta hãy bắt đầu !!!
Materials Required:
- PIC16F877A
- 7805 Voltage Regulator
- ACS712 current Sensor
- 16*2 LCD display
- A junction box and load (Just for testing)
- Connecting wires
- Capacitors
- Breadboard.
- Power supply – 12V
Working of ACS712 Current Sensor:
Trước khi chúng tôi bắt đầu xây dựng dự án, điều rất quan trọng là chúng tôi phải hiểu hoạt động của cảm biến dòng ACS712 vì nó là thành phần quan trọng của dự án. Đo dòng điện, đặc biệt là dòng điện AC luôn là một nhiệm vụ khó khăn do tiếng ồn cùng với vấn đề cách ly không phù hợp, v.v. Nhưng, với sự trợ giúp của mô-đun ACS712 được chế tạo bởi Allegro, mọi thứ đã trở nên dễ dàng hơn rất nhiều.
Mô-đun này hoạt động dựa trên nguyên lý hiệu ứng Hall, được phát hiện bởi Tiến sĩ Edwin Hall. Theo nguyên lý của ông, khi đặt một dây dẫn mang dòng điện vào từ trường, một điện áp được tạo ra trên các cạnh của nó vuông góc với hướng của cả dòng điện và từ trường. Chúng ta đừng đi sâu vào khái niệm này, nhưng hãy nói một cách đơn giản, chúng ta sử dụng một cảm biến Hall để đo từ trường xung quanh một vật dẫn mang dòng điện. Phép đo này sẽ tính theo milivôn mà chúng tôi gọi là điện áp hội trường. Điện áp hội trường đo được này tỷ lệ với dòng điện chạy qua dây dẫn.
Ưu điểm chính của việc sử dụng Cảm biến dòng ACS712 là có thể đo cả dòng AC và DC và nó cũng cung cấp sự cách ly giữa Tải (tải AC / DC) và Đơn vị đo (phần Vi điều khiển). Như trong hình, chúng ta có ba chân trên mô-đun lần lượt là Vcc, Vout và Ground.
Current Sensor Module ACS712-5A
Khối đầu cuối 2 chân là nơi có dây dẫn dòng điện đi qua. Mô-đun hoạt động trên + 5V nên Vcc phải được cấp nguồn 5V và nối đất với Đất của hệ thống. Chân Vout có điện áp bù là 2500mV, nghĩa là khi không có dòng điện chạy qua dây thì điện áp đầu ra sẽ là 2500mV và khi có dòng điện dương thì điện áp sẽ lớn hơn 2500mV và khi dòng điện chạy qua là điện áp âm thì điện áp sẽ nhỏ hơn 2500mV.
Chúng tôi sẽ sử dụng mô-đun ADC của vi điều khiển PIC để đọc điện áp đầu ra (Vout) của mô-đun, sẽ là 512 (2500mV) khi không có dòng điện chạy qua dây. Giá trị này sẽ giảm khi dòng điện chạy theo chiều âm và sẽ tăng khi dòng điện chạy theo chiều dương. Bảng dưới đây sẽ giúp bạn hiểu điện áp đầu ra và giá trị ADC thay đổi như thế nào dựa trên cường độ dòng điện chạy qua dây dẫn.
Các giá trị này được tính toán dựa trên thông tin được cung cấp trong Datasheet của ACS712. Bạn cũng có thể tính toán chúng bằng cách sử dụng các công thức dưới đây:
Vout Voltage(mV) = (ADC Value/ 1023)*5000
Current Through the Wire (A) = (Vout(mv)-2500)/185
Bây giờ, chúng ta đã biết cách hoạt động của Cảm biến ACS712 và những gì chúng ta có thể mong đợi từ nó. Chúng ta hãy tiến hành sơ đồ mạch.
Circuit Diagram:
Sơ đồ mạch hoàn chỉnh của Dự án Ampe kế kỹ thuật số này được hiển thị trong hình ảnh bên dưới.
Mạch đo dòng điện kỹ thuật số hoàn chỉnh hoạt động trên + 5V được điều chỉnh bởi bộ điều chỉnh điện áp 7805. Chúng tôi đã sử dụng màn hình LCD 16X2 để hiển thị giá trị của dòng điện. Chân đầu ra của Cảm biến hiện tại (Vout) được kết nối với chân thứ 7 của PIC là AN4 để đọc điện áp Analog.
Hơn nữa kết nối chân cho PIC được hiển thị trong bảng bên dưới
S.No: | Pin Number | Pin Name | Connected to |
1 | 21 | RD2 | RS of LCD |
2 | 22 | RD3 | E of LCD |
3 | 27 | RD4 | D4 of LCD |
4 | 28 | RD5 | D5 of LCD |
5 | 29 | RD6 | D6 of LCD |
6 | 30 | RD7 | D7 of LCD |
7 | 7 | AN4 | Vout of Current Sesnor |
Lưu ý: Bạn không bắt buộc phải xây dựng bảng này, bạn có thể chỉ cần làm theo sơ đồ mạch và xây dựng mạch của bạn trên bảng mạch bánh mì và sử dụng bất kỳ bộ kết xuất nào để kết xuất chương trình của bạn vào Vi điều khiển PIC.
Simulation:
Mạch đo dòng điện này cũng có thể được mô phỏng bằng Proteus trước khi bạn thực sự tiến hành với Phần cứng của mình. Gán tệp hex của mã được đưa ra ở cuối hướng dẫn này và nhấp vào nút phát. Bạn sẽ có thể nhận thấy dòng điện trên màn hình LCD. Tôi đã sử dụng Đèn làm tải xoay chiều, bạn có thể thay đổi điện trở bên trong của Đèn bằng cách nhấp vào nó để thay đổi dòng điện chạy qua nó.
Như bạn có thể thấy trong hình trên, Ampe kế hiển thị dòng điện thực tế chạy qua Đèn là khoảng 3,52 A và màn hình LCD hiển thị dòng điện là khoảng 3,6A. Tuy nhiên, trong trường hợp thực tế, chúng tôi có thể nhận được Lỗi lên đến 0,2A. Giá trị ADC và điện áp tính bằng (mV) cũng được hiển thị trên màn hình LCD để bạn hiểu.
Programming the PIC Microcontroller:
Như đã nói trước đó, mã hoàn chỉnh có thể được tìm thấy ở cuối bài viết này. Mã tự giải thích bằng các dòng chú thích và chỉ liên quan đến khái niệm giao tiếp màn hình LCD với Vi điều khiển PIC và Sử dụng mô-đun ADC trong Vi điều khiển PIC mà chúng tôi đã trình bày trong các bài hướng dẫn học Vi điều khiển PIC trước đây của chúng tôi.
Giá trị đọc từ cảm biến sẽ không chính xác vì dòng điện xoay chiều và cũng có thể bị nhiễu. Do đó, chúng tôi đọc giá trị ADC trong 20 lần và lấy giá trị trung bình để có được Giá trị hiện tại thích hợp như được hiển thị trong đoạn mã bên dưới.
Chúng tôi đã sử dụng các công thức tương tự đã được giải thích ở trên để tính giá trị điện áp và dòng điện.
for (int i=0; i<20;i++) //Read value for 20 Times
{
adc=0;
adc=ADC_Read(4); //Read ADC
Voltage = adc*4.8828; //Calculate the Voltage
if (Voltage>=2500) //If the current is positive
Amps += ((Voltage-2500)/18.5);
else if (Voltage<=2500) //If the current is negative
Amps += ((2500-Voltage)/18.5);
}
Amps/=20; //Average the value that was read for 20 times
Vì dự án này cũng có thể đọc dòng điện xoay chiều nên dòng điện hiện tại sẽ là âm và dương. Đó là giá trị của điện áp đầu ra sẽ ở trên và dưới 2500mV. Do đó, như hình dưới đây, chúng tôi thay đổi công thức cho dòng điện âm và dương để chúng tôi không nhận được giá trị âm.
if (Voltage>=2500) //If the current is positive
Amps += ((Voltage-2500)/18.5);
else if (Voltage<=2500) //If the current is negative
Amps += ((2500-Voltage)/18.5);
Sử dụng cảm biến dòng 30A:
Nếu bạn cần đo dòng điện hơn 5A, bạn có thể chỉ cần mua một mô-đun ACS712-30A và giao diện nó theo cách tương tự và thay đổi dòng mã bên dưới bằng cách thay thế 18,5 bằng 0,66 như hình dưới đây:
if (Voltage>=2500) //If the current is positive
Amps += ((Voltage-2500)/0.66);
else if (Voltage<=2500) //If the current is negative
Amps += ((2500-Voltage)/0.66);
Working:
Khi bạn đã lập trình Vi điều khiển PIC và chuẩn bị xong phần cứng. Chỉ cần bật nguồn cho tải và bộ vi điều khiển PIC của bạn, bạn sẽ có thể thấy dòng điện đi qua dây dẫn được hiển thị trên màn hình LCD của bạn.
LƯU Ý: NẾU bạn đang sử dụng mô-đun ASC7125A, hãy đảm bảo tải của bạn không tiêu thụ nhiều hơn 5A, đồng thời sử dụng dây đo cao hơn cho dây dẫn mang dòng điện.
Hoạt động hoàn chỉnh của dự án ampe kế dựa trên vi điều khiển PIC được hiển thị trong Video bên dưới. Hy vọng bạn có dự án hoạt động và thích làm nó. Nếu bạn có bất kỳ nghi ngờ nào, bạn có thể viết chúng trong phần bình luận bên dưới hoặc đăng chúng trên diễn đàn của chúng tôi.
#define _XTAL_FREQ 20000000
#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
#include <xc.h>
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//LCD Functions Developed by Circuit Digest.
void Lcd_SetBit(char data_bit) //Based on the Hex value Set the Bits of the Data Lines
{
if(data_bit& 1)
D4 = 1;
else
D4 = 0;
if(data_bit& 2)
D5 = 1;
else
D5 = 0;
if(data_bit& 4)
D6 = 1;
else
D6 = 0;
if(data_bit& 8)
D7 = 1;
else
D7 = 0;
}
void Lcd_Cmd(char a)
{
RS = 0;
Lcd_SetBit(a); //Incoming Hex value
EN = 1;
__delay_ms(4);
EN = 0;
}
void Lcd_Clear()
{
Lcd_Cmd(0); //Clear the LCD
Lcd_Cmd(1); //Move the curser to first position
}
void Lcd_Set_Cursor(char a, char b)
{
char temp,z,y;
if(a== 1)
{
temp = 0x80 + b - 1; //80H is used to move the curser
z = temp>>4; //Lower 8-bits
y = temp & 0x0F; //Upper 8-bits
Lcd_Cmd(z); //Set Row
Lcd_Cmd(y); //Set Column
}
else if(a== 2)
{
temp = 0xC0 + b - 1;
z = temp>>4; //Lower 8-bits
y = temp & 0x0F; //Upper 8-bits
Lcd_Cmd(z); //Set Row
Lcd_Cmd(y); //Set Column
}
}
void Lcd_Start()
{
Lcd_SetBit(0x00);
for(int i=1065244; i<=0; i--) NOP();
Lcd_Cmd(0x03);
__delay_ms(5);
Lcd_Cmd(0x03);
__delay_ms(11);
Lcd_Cmd(0x03);
Lcd_Cmd(0x02); //02H is used for Return home -> Clears the RAM and initializes the LCD
Lcd_Cmd(0x02); //02H is used for Return home -> Clears the RAM and initializes the LCD
Lcd_Cmd(0x08); //Select Row 1
Lcd_Cmd(0x00); //Clear Row 1 Display
Lcd_Cmd(0x0C); //Select Row 2
Lcd_Cmd(0x00); //Clear Row 2 Display
Lcd_Cmd(0x06);
}
void Lcd_Print_Char(char data) //Send 8-bits through 4-bit mode
{
char Lower_Nibble,Upper_Nibble;
Lower_Nibble = data&0x0F;
Upper_Nibble = data&0xF0;
RS = 1; // => RS = 1
Lcd_SetBit(Upper_Nibble>>4); //Send upper half by shifting by 4
EN = 1;
for(int i=2130483; i<=0; i--) NOP();
EN = 0;
Lcd_SetBit(Lower_Nibble); //Send Lower half
EN = 1;
for(int i=2130483; i<=0; i--) NOP();
EN = 0;
}
void Lcd_Print_String(char *a)
{
int i;
for(i=0;a[i]!='\0';i++)
Lcd_Print_Char(a[i]); //Split the string using pointers and call the Char function
}
/*****End of LCD Functions*****/
//**ADC FUnctions***//
void ADC_Initialize()
{
ADCON0 = 0b01000001; //ADC ON and Fosc/16 is selected
ADCON1 = 0b11000000; // Internal reference voltage is selected
}
unsigned int ADC_Read(unsigned char channel)
{
ADCON0 &= 0x11000101; //Clearing the Channel Selection Bits
ADCON0 |= channel<<3; //Setting the required Bits
__delay_ms(2); //Acquisition time to charge hold capacitor
GO_nDONE = 1; //Initializes A/D Conversion
while(GO_nDONE); //Wait for A/D Conversion to complete
return ((ADRESH<<8)+ADRESL); //Returns Result
}
//***End of ADC Functions***//
int main()
{
int adc=0; //Variable to read ADC value
int a1,a2,a3,a4; //Variable to split ADC value into char
int Voltage; //Variable to store voltage
int vl1,vl2,vl3,vl4; //Variable to split Voltage value into char
int Amps; //Variable to store Amps value
int Am1,Am2,Am3,Am4; //Variable to split Amps value into char
TRISD = 0x00; //PORTD declared as output for interfacing LCD
TRISA4 =1; //AN4 declared as input
ADC_Initialize();
Lcd_Start();
Lcd_Clear();
while(1)
{
/***Current Calculation*****/
for (int i=0; i<20;i++) //Read value for 20 Times
{
adc=0;
adc=ADC_Read(4); //Read ADC
Voltage = adc*4.8828; //Calculate the Voltage
if (Voltage>=2500) //If the current is positive
Amps += ((Voltage-2500)/18.5);
else if (Voltage<=2500) //If the current is negative
Amps += ((2500-Voltage)/18.5);
}
Amps/=20; //Average the value that was read for 20 times
/******Current Calculation******/
//**Display current**//
Am1 = (Amps/100)%10;
Am2 = (Amps/10)%10;
Am3 = (Amps/1)%10;
Lcd_Set_Cursor(1,1);
Lcd_Print_String("Current: ");
Lcd_Print_Char(Am1+'0');
Lcd_Print_Char(Am2+'0');
Lcd_Print_Char('.');
Lcd_Print_Char(Am3+'0');
//**Display ADC**//
a1 = (adc/1000)%10;
a2 = (adc/100)%10;
a3 = (adc/10)%10;
a4 = (adc/1)%10;
Lcd_Set_Cursor(2,1);
Lcd_Print_String("ADC:");
Lcd_Print_Char(a1+'0');
Lcd_Print_Char(a2+'0');
Lcd_Print_Char(a3+'0');
Lcd_Print_Char(a4+'0');
//**Display Voltage**//
vl1 = (Voltage/1000)%10;
vl2 = (Voltage/100)%10;
vl3 = (Voltage/10)%10;
vl4 = (Voltage/1)%10;
Lcd_Print_String(" V:");
Lcd_Print_Char(vl1+'0');
Lcd_Print_Char(vl2+'0');
Lcd_Print_Char(vl3+'0');
Lcd_Print_Char(vl4+'0');
}
return 0;
}