[SOLVED] I am gonna make a Voltmeter using pic16f716 and I need some advice about the code

Status
Not open for further replies.

long0900

Newbie level 6
Joined
Jul 6, 2017
Messages
13
Helped
1
Reputation
2
Reaction score
0
Trophy points
1
Activity points
106
Hi!!
PIC16F716 has 13 I/O pins ( 5 for PORTA, 8 for PORTB),I am using PORTB for driving each segment of 7 segment LED, 4 pins of PORTA for driving each digit and pin RA0 for input voltage.
I am using mikroC because I dont have to worry much about the configuration but I quite not sure about how to config the ADCON1 register of the PIC.
About the code, should I use array or a Switch..case function to store the bits of the numbers?
Why I keep getting 0000 when I use "/","%" to get each digit of the voltage?

Here is the datasheet : https://ww1.microchip.com/downloads/en/DeviceDoc/41206B.pdf

Please help me!
Thanks in advance
 

Please post your code.

What kind of voltage range do you try to measure?

Basically you have two tasks:
1. 7 segment display
2. ADC read (voltage measurement)

First you should check if 7 segment display is working, then start working on ADC (voltage measurement).


Here is an example of LCD volt/amp meter with mikroC:


Code C - [expand]
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
// LCD module connections
sbit LCD_RS at RB5_bit;
sbit LCD_EN at RB7_bit;
sbit LCD_D4 at RC4_bit;
sbit LCD_D5 at RC5_bit;
sbit LCD_D6 at RC6_bit;
sbit LCD_D7 at RC7_bit;
 
sbit LCD_RS_Direction at TRISB5_bit;
sbit LCD_EN_Direction at TRISB7_bit;
sbit LCD_D4_Direction at TRISC4_bit;
sbit LCD_D5_Direction at TRISC5_bit;
sbit LCD_D6_Direction at TRISC6_bit;
sbit LCD_D7_Direction at TRISC7_bit;
// End LCD module connections
 
char look(int a)
{
  switch(a)
  {
    case 0:
      return '0';
    case 1:
      return '1';
    case 2:
      return '2';
    case 3:
      return '3';
    case 4:
      return '4';
    case 5:
      return '5';
    case 6:
      return '6';
    case 7:
      return '7';
    case 8:
      return '8';
    case 9:
      return '9';
    default:
      return '.';
  }
}
 
void main()
{
  unsigned int v,vp,ip,i;
  char *volt = "00.0";
  char *current = "0.00";
  CMCON = 0x07;
  TRISA = 0xFF;
  ADCON1 = 0x00;
  Lcd_Init();
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Cmd(_LCD_CURSOR_OFF);
 
  do
  {
    v = ADC_Read(2);
    i = ADC_Read(3);
    i = (i*4.89)/0.47;
    v = ((v*4.89)/20)*120;
    if(v!=vp || i!=ip )
      Lcd_Cmd(_LCD_CLEAR);
    vp = v;
    ip = i;
    volt[0] = look(v/10000);
    volt[1] = look((v/1000)%10);
    volt[3] = look((v/100)%10);
    Lcd_Out(1,1,"Voltage = ");
    Lcd_Out(1,11,volt);
    Lcd_Out(1,16,"V");
 
    current[0] = look(i/1000);
    current[2] = look((i/100)%10);
    current[3] = look((i/10)%10);
    Lcd_Out(2,1,"Current = ");
    Lcd_Out(2,11,current);
    Lcd_Out(2,16,"A");
    Delay_ms(250);
  } while(1);
}

 

hello,


4 pins of PORTA for driving each digit
so 4 digits :
5000
or 5.00


this ADC is 8 bits wide only !.. resolution maximum +-20mV (if range is 5V) display 5000 mV



Code:
unsigned int v,vp,ip,i;
....
  v = ((v*4.89)/20)*120;

not so good to use floating point calculation with an integer value ..
nead to cast V into float
v=(int) ((float)V*29,34); // could be better

and with this PIC
ADC value on 8 bits only..
 

Yes! I know that 2 things but please look at the ADC section of the datasheet, I dont understand how to configure ADCON1 register
And, I think it isnt neccesary to use the "look" function in your example.
 

    cloud6447

    Points: 2
    Helpful Answer Positive Rating
ADC value on 8 bits only..
I know that, I dont need so much precision

- - - Updated - - -

Here is the code:
Code:
 short digit(short a){
  switch(a){
    case 0 : return 0x3F;
    case 1 : return 0x06;
    case 2 : return 0x5B;
    case 3 : return 0x4F;
    case 4 : return 0x66;
    case 5 : return 0x6D;
    case 6 : return 0x7D;
    case 7 : return 0x07;
    case 8 : return 0x7F;
    case 9 : return 0x6F;
  }
}
void main(){
  int v;
  short tmp;
  TRISA = 1;
  TRISB = 0;
  ADCON1.PCFG2 = 0;
  ADCON1.PCFG0 = 0;
  do{
    v = (int)(ADC_Read(0)*500/255);
    PORTA = 0x03;
        PORTB = digit(0) ;
        delay_ms(100);
    PORTA = 0x05;
        PORTB = digit(v/100);
        delay_ms(100);
    PORTA = 0x09;
        PORTB = digit((v%100)/10);
        delay_ms(100);
    PORTA = 0x11;
        PORTB = digit(v%10);
        delay_ms(100);
  }
  while(1);
}
I have tested it with proteus but it keeps displaying weird number when I measure voltage greater than about 2.6 v
 

I have tested it with proteus but it keeps displaying weird number when I measure voltage greater than about 2.6 v

I haven't checked the code and I do not have Proteus but usually when the ADC works up to 8 bit resolution (2.55v) then gives a strange reading, it means the result is justified the wrong way (right to left or left to right) or you haven't cast the variable sizes so it can return the extra two bits of the value.

Brian.
 

Overflow probleme !
1 byte => max 255 * 500 = 127500 !
Code:
  v = (int) ((long)ADC_Read(0) * 500 /255);
 
Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…