0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何使用PIC16F877A和ACS712-5A制作数字电流表

科技观察员 来源:circuitdigest 作者:阿斯文斯·拉吉 2023-01-25 16:24 次阅读

在制作或调试任何电气系统时,测量电压和电流总是有帮助的。在这个项目中,我们将 使用PIC16F877A微控制器和电流传感器ACS712-5A制作自己的数字电流表 。该项目可以测量0-30A范围内的交流和直流电流,精度为0.3A。只需对代码进行少量修改,您也可以使用此电路测量高达30A的电流。

所需材料:

  1. PIC16F877A
  2. 7805 稳压器
  3. ACS712 电流传感器
  4. 16*2液晶显示屏
  5. 接线盒和负载(仅用于测试)
  6. 连接线
  7. 电容器
  8. 面包板。
  9. 电源 – 12V

ACS712电流传感器的工作原理

在我们开始构建项目之前,了解 ACS712 电流传感器的工作原理对我们来说非常重要,因为它是项目的关键组件。测量电流,尤其是交流电流始终是一项艰巨的任务,因为噪声加上不正确的隔离问题等。但是,借助由Allegro设计的ACS712模块,事情变得容易多了。

该模块的工作原理是霍尔效应,这是由埃德温·霍尔博士发现的。根据他的原理,当载流导体被放入磁场中时,在其边缘垂直于电流和磁场方向产生电压。让我们不要太深入这个概念,简单地说,我们使用霍尔传感器来测量载流导体周围的磁场。该测量将以毫伏为单位,我们称之为霍尔电压。该测量的霍尔电压与流过导体的电流成正比。

使用 ACS712 电流传感器的主要优点是可以测量交流和直流电流,它还在负载(交流/直流负载)和测量单元(微控制器部分)之间提供隔离。如图所示,模块上有三个引脚,分别是Vcc,Vout和接地。

电流传感器模块 ACS712-5A

2 针接线端子是载流线应穿过的位置。模块工作在+5V,因此Vcc应由5V供电,接地应连接到系统的地。Vout引脚的失调电压为2500mV,这意味着当没有电流流过导线时,输出电压将为2500mV,当电流为正时,电压将大于2500mV,当电流为负时,电压将小于2500mV。

我们将使用 PIC 微控制器的 ADC 模块来读取模块的输出电压 (Vout),当没有电流流过导线时,输出电压为 512(2500mV)。当电流以负方向流动时,该值将减小,当电流沿正方向流动时,该值将增加。下表将帮助您了解输出电压和ADC值如何根据流过导线的电流而变化。

数字电流表输出电流和 ADC 值

这些值是根据 ACS712 数据表中给出的信息计算得出的。您也可以使用以下公式计算它们:

Vout Voltage(mV) = (ADC Value/  1023)*5000
Current Through the Wire (A) = (Vout(mv)-2500)/185

现在,我们知道了ACS712传感器的工作原理以及我们可以从中得到什么。让我们继续看电路图。

电路图:

下图显示了该数字电流表项目的完整电路图。

1.png

完整的数字电流计电路工作在+5V电压下,由7805稳压器调节。我们使用 16X2 LCD 来显示电流值。电流传感器 (Vout) 的输出引脚连接到 7^千^PIC的引脚,即AN4,用于读取模拟电压。

此外,PIC 的引脚连接如下表所示

S.No: 引脚编号 引脚名称 已连接到
1 21 RD2 液晶显示器的 RS
2 22 RD3 液晶显示器的E
3 27 RD4 液晶屏D4
4 28 RD5 液晶屏D5
5 29 RD6 液晶屏D6
6 30 RD7 液晶屏D7
7 7 AN4 当前塞斯诺的沃特

您可以在面包板上构建此数字电流表电路或使用性能板。如果您一直遵循PIC教程,那么您还可以重用我们用于学习PIC微控制器的硬件。在这里,我们使用了与PIC微控制器一起为LED闪烁构建的相同 性能板 ,如下所示:

用于PIC微控制器的PERF包教程

注意: 构建此板不是强制性的,您可以简单地按照电路图在面包板上构建电路,并使用任何转储器套件将程序转储到 PIC 微控制器中。

模拟:

在您实际使用硬件之前,也可以使用 Proteus 模拟此 电流表电路 。分配本教程末尾给出的代码的十六进制文件,然后单击播放按钮。您应该能够注意到LCD显示屏上的电流。我使用灯作为交流负载,您可以通过单击它来改变灯的内阻以改变流过它的电流。

PIC数字电流表项目模拟

如上图所示,电流表显示流过灯的实际电流约为 3.52 A,LCD 显示电流约为 3.6 A。但是,在实际情况下, 我们可能会得到高达0.2A的误差 。ADC值和电压(mV)也显示在LCD上,供您理解。

PIC微控制器编程

如前所述,完整的代码可以在本文末尾找到。该代码是用注释行自我解释的,只涉及将LCD与PIC微控制器连接的概念,以及在PIC微控制器中使用ADC模块的概念,我们已经在之前的PIC微控制器学习教程中介绍过。

从传感器读取的值将不准确,因为电流是交流的并且还受到噪声的影响。因此,我们读取ADC值20次并将其平均以获得适当的电流值,如下面的代码所示。

我们使用上面解释的相同公式来计算电压和电流值。

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

由于该项目也可以读取交流电流,因此电流也将是负的和正的。也就是说,输出电压值将高于和低于2500mV。因此,如下图所示,我们更改了负电流和正电流的公式,以便我们不会得到负值。

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);

使用 30A 电流传感器:

如果您需要测量超过 5A 的电流,您可以简单地购买 ACS712-30A 模块并以相同的方式连接它,并通过将 18.5 替换为 0.66 来更改以下代码行,如下所示:

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);

如果要测量低电流,还可以使用AVR微控制器检查100mA电流表

加工:

一旦您对PIC微控制器进行了编程并准备好了硬件。只需打开负载和PIC微控制器的电源,您应该能够看到电流通过LCD屏幕上显示的电线。

注意: 如果您使用的是 ASC7125A 模块,请确保您的负载消耗不超过 5A,同时使用更高规格的导线作为载流导体。

使用 PIC 和 ACS712 的数字电流表

/*

Digital Ammeter for PIC16F877A

 * Code by: B.Aswinth Raj

 * Dated: 27-07-2017

 * More details at: www.CircuitDigest.com

 */

 

#define _XTAL_FREQ 20000000

#define RS RD2

#define EN RD3

#define D4 RD4

#define D5 RD5

#define D6 RD6

#define D7 RD7

 

#include 

 

#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;

}
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 微控制器
    +关注

    关注

    48

    文章

    6813

    浏览量

    147671
  • PIC16F877A
    +关注

    关注

    2

    文章

    43

    浏览量

    21689
  • 电流传感器
    +关注

    关注

    9

    文章

    764

    浏览量

    40532
  • 数字电流表
    +关注

    关注

    0

    文章

    6

    浏览量

    7433
收藏 人收藏

    评论

    相关推荐

    谁有pic16f877a中文资料?

    谁有pic16f877a中文资料? 
    发表于 07-15 13:22

    PIC16F877A

    菜鸟想问下各位,我想用PIC16F877A做个流水灯,所有端口输出高电平1S,然后输出低电平1s 。 单片机放在学习板上测试的时候是正常的,用prpteus仿真也正常,可是放到电路板上就不正常了,低电平时间很短,Led只是闪了一下。  哪位高手指点一下是什么原因,还是要怎样测试找出问题?
    发表于 07-28 14:32

    PIC16F877A在proteus中读写AT24C512

    此时把I2C DEBUGGER的SCL线连接到PIC16F877A和AT24C512的SCL线上,这样PIC16F877A可以正常的写AT24C512。当PIC16F877A发送启动信号且正常启动
    发表于 12-30 16:09

    PIC16F877A使用宏定义读写FlashROM

    MPLAB IDE v8.80PICC9.83读写PIC16F877A内部的EEPROM时可以使用头文件中的两个宏定义EEPROM_READ(unsigned char addr
    发表于 12-31 14:01

    新手求助,求PIC16F877A测频率的程序!

    想用PIC16F877A的CCP1模块做一个简易的频率计,但是自己的程序总是测不准,希望得到大神的帮助~
    发表于 04-29 21:38

    PIC16F877A的中断优先级问题

    现在我需要通过串口来接收指令控制PIC16F877A的捕获脉冲行为,可以做到的是:接收到开捕获指令后,能正常开始捕获脉冲,但是再发送关闭指令却不能让它停下来,通过KIT3发现,在捕获的时候,串口不能
    发表于 06-06 21:18

    PIC16f877a的配置位怎么配置?在程序里该怎么描述???

    PIC16f877a的配置位怎么配置?在程序里该怎么描述???最好能发一份中文版的手册
    发表于 11-07 11:42

    PIC16F877A万年历程序

    为了把KS0108系列的液晶吃透,特别制作了这款万年历,感觉效果还是不错的.希望大家分享我的喜悦,毕竟有了更多志同道合的朋友支持,我才能更进一步提高. 全文下载: PIC16F877A万年历程序.doc
    发表于 07-03 05:39

    PIC16F877A复位问题

    嗨,我还是新手,但是我有一个使用PIC16F877a的倒计时计划,而不是运行一个4位数的7段显示,并有5个按钮来选择倒计时的时间。在倒计时结束时,它发出3次哔哔声。它运行得很完美,但是会产生随机
    发表于 04-01 09:39

    基于pic16f877a模拟交通灯设计,请各各位指导

    请各位大神帮忙看看这个pic16f877a模拟交通灯
    发表于 10-14 20:27

    PIC16F877A单片机相关资料下载

    PIC16F877A单片机(配置字)1 MPLAB X V5.0,编译器为XC8(V2.0)2MPLAB V5.0,编译器为PICC1 MPLAB X V5.0,编译器为XC8(V2.0)单击
    发表于 11-24 08:22

    PIC16F877A看门狗定时器实验的相关资料推荐

    //*******************PIC16F877A 看门狗定时器实验*******************// //PORTA,PORTB,PORTC,PORTD,PORTE复位时为输入
    发表于 11-25 07:52

    PIC16F877A和TB6612FNG电机驱动的微型电路

    描述格柏OK用PIC16F877A和TB6612FNG电机驱动的微型电路
    发表于 09-05 06:12

    pic16f877a中文资料pdf

    pic16f877a中文资料
    发表于 07-15 13:20 4542次下载
    <b class='flag-5'>pic16f877a</b>中文资料pdf

    基于PIC16F877A的4位密码电子锁的制作

    电子发烧友网站提供《基于PIC16F877A的4位密码电子锁的制作.pdf》资料免费下载
    发表于 10-10 09:19 0次下载
    基于<b class='flag-5'>PIC16F877A</b>的4位密码电子锁的<b class='flag-5'>制作</b>