Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

PIC16F676 multiple ADC reading

Status
Not open for further replies.

imranahmed

Advanced Member level 3
Joined
Dec 4, 2011
Messages
817
Helped
3
Reputation
6
Reaction score
3
Trophy points
1,298
Location
Karachi,Pakistan
Activity points
6,492
Please let me know that the code I written for PIC16F676 4Mhz internal oscillator in mikroC pro for PIC but it gives enough RAM error but it has 8-channel 10-bit ADC, how to resolve this error please let me know but same program is successfully compile in PIC16F72 and PIC16F688.
Code:
// LCD module connections
sbit LCD_RS at RC4_bit;
sbit LCD_EN at RC5_bit;
sbit LCD_D4 at RC0_bit;
sbit LCD_D5 at RC1_bit;
sbit LCD_D6 at RC2_bit;
sbit LCD_D7 at RC3_bit;
sbit LCD_RS_Direction at TRISC4_bit;
sbit LCD_EN_Direction at TRISC5_bit;
sbit LCD_D4_Direction at TRISC0_bit;
sbit LCD_D5_Direction at TRISC1_bit;
sbit LCD_D6_Direction at TRISC2_bit;
sbit LCD_D7_Direction at TRISC3_bit;
// End LCD module connections

unsigned long PV,BV,PA,BA;
unsigned char *Pvolt = "P V: 00.0V";
unsigned char *Bvolt = "BAT: 00.0V";
unsigned char *Pamp = "00.0A";
unsigned char *Bamp = "00.0A";

void main()
{
TRISC  = 0b00000000;           // PORTC All Outputs
TRISA  = 0b00001111;           // PORTA All Outputs, Except RA3 and RA2
ADC_Init();
Lcd_Init();                    // LCD display initialization
Lcd_Cmd(_LCD_CURSOR_OFF);      // LCD command (cursor off)
Lcd_Cmd(_LCD_CLEAR);           // LCD command (clear LCD)

do
{
PV = ADC_Read(0);               // Read analog value from channel 0
PA = ADC_Read(1);               // Read analog value from channel 1
BV = ADC_Read(2);               // Read analog value from channel 2
BA = ADC_Read(3);               // Read analog value from channel 3
PV = ((PV*4.89)/5)*90;           // V GOES FROM 0 TO 90 volts
BV = ((BV*4.89)/5)*30;           // V GOES FROM 0 TO 20 volts
PA = ((PA*4.89)/5)*20;           // V GOES FROM 0 TO 20 volts
BA = ((BA*4.89)/5)*35;           // V GOES FROM 0 TO 20 volts

Pvolt[5] = (PV/10000)+48;        // Extract volts (thousands of millivolts) from result
Pvolt[6] = (PV/1000)%10+48;      // Extract thousands of mv
Pvolt[8] = (PV/100)%10+48;       // Extract hundreds of mv
Lcd_Out(1,1,Pvolt);
Delay_ms(150);

Pamp[0] = (PA/10000)+48;        // Extract volts (thousands of millivolts) from result
Pamp[1] = (PA/1000)%10+48;      // Extract thousands of mv
Pamp[3] = (PA/100)%10+48;       // Extract hundreds of mv
Lcd_Out(1,12,Pamp);
Delay_ms(150);

Bvolt[5] = (BV/10000)+48;        // Extract volts (thousands of millivolts) from result
Bvolt[6] = (BV/1000)%10+48;      // Extract thousands of mv
Bvolt[8] = (BV/100)%10+48;       // Extract hundreds of mv
Lcd_Out(2,1,Bvolt);
Delay_ms(150);

Bamp[0] = (BA/10000)+48;        // Extract volts (thousands of millivolts) from result
Bamp[1] = (BA/1000)%10+48;      // Extract thousands of mv
Bamp[3] = (BA/100)%10+48;       // Extract hundreds of mv
Lcd_Out(2,12,Bamp);
Delay_ms(150);
} while(1);
}
 

Reporting the actual error messages would allow people not using mikroC to help with the problem.

According to C language rules, the below quoted code snippets will not achieve the expected result for integer variables. Don't expect that mikroC uses different type propagation rules.

Code:
PV = ((PV*4.89)/5)*90;           // V GOES FROM 0 TO 90 volts
BV = ((BV*4.89)/5)*30;           // V GOES FROM 0 TO 20 volts
PA = ((PA*4.89)/5)*20;           // V GOES FROM 0 TO 20 volts
BA = ((BA*4.89)/5)*35;           // V GOES FROM 0 TO 20 volts

You need to change the execution order

Code:
PV = (PV*(4.89*90))/5;           // V GOES FROM 0 TO 90 volts
--- Updated ---

Or simplified to

Code:
PV = PV*(4.89*90/5);           // V GOES FROM 0 TO 90 volts
 

Reporting the actual error messages would allow people not using mikroC to help with the problem.

According to C language rules, the below quoted code snippets will not achieve the expected result for integer variables. Don't expect that mikroC uses different type propagation rules.

Code:
PV = ((PV*4.89)/5)*90;           // V GOES FROM 0 TO 90 volts
BV = ((BV*4.89)/5)*30;           // V GOES FROM 0 TO 20 volts
PA = ((PA*4.89)/5)*20;           // V GOES FROM 0 TO 20 volts
BA = ((BA*4.89)/5)*35;           // V GOES FROM 0 TO 20 volts

You need to change the execution order

Code:
PV = (PV*(4.89*90))/5;           // V GOES FROM 0 TO 90 volts
--- Updated ---

Or simplified to

Code:
PV = PV*(4.89*90/5);           // V GOES FROM 0 TO 90 volts
Thank you for reply,

It is also not working same memory error occurred again.

Please do no worry about file name it is PIC16F72 but I am using PIC16F676.

1630236971398.png
 

The problem is that 16F676 has even less ROM and RAM than the other processors, only 1024 words respectively 64 Bytes. If you look sharp, you'll notice that the compiler also runs out of ROM. You can try to further slim down the code, but you probably better use a bigger PIC.
 

The problem is that 16F676 has even less ROM and RAM than the other processors, only 1024 words respectively 64 Bytes. If you look sharp, you'll notice that the compiler also runs out of ROM. You can try to further slim down the code, but you probably better use a bigger PIC.
Its ok but it has 8 channel ADC so we can use them all alternately.
 

There's in fact some redundancy in your code, e.g. by repeating the same calculation three times. As a first step, you'd analyze the memory map of sucessfully compiled code on bigger PIC16 to get an idea, if the LCD and run-time library , routines can fit the small device.
--- Updated ---

Its ok but it has 8 channel ADC so we can use them all alternately.
You can use 16F688.
 
Last edited:

There's in fact some redundancy in your code, e.g. by repeating the same calculation three times. As a first step, you'd analyze the memory map of sucessfully compiled code on bigger PIC16 to get an idea, if the LCD and run-time library , routines can fit the small device.
--- Updated ---


You can use 16F688.
Ok I am trying.
 

Also stay clear of floating point with these small memory devices. The value that you multiply PV by is 88.02 which is so close enough to 88 as makes no odds. Some of the other constant multipliers are not quite so close to an integer but you can scale the value up (even using shift instructions) and divide by a suitable integer.
Floating point requires library code to perform and that takes up a lot of your ROM. (Integer maths uses library functions as well but they are smaller and faster to execute as well.
Susan
 

    imranahmed

    Points: 2
    Helpful Answer Positive Rating
Hello!

Fully agree with Susan.
- Float requires a lot of ROM
- Division requires also ressources.
I'm aware that you want your code to be readable, and that's probably why you kept
the 4.85, 90, 5, etc... But that's what the comments are for. You can explain in a 1 line comment
how you have calculated 88.

This time for this particular coefficient, you're lucky, 88 instead of 88.02 is the same
because anyway your ADC does not have that kind of accuracy. But there are some
tricks to work only with integers, which will speedup your code or lower the memory
requirements.
Apparently you don't care about execution speed because you have lots of loop delays,
but I wouldn't be surprised if this solves your ROM problems.

NB: when your scalers don't round close enough, for example if you get a coefficient of
3.43, then you can try to do this by multiplying by 2 at each line.
You get:
0 -> 3.43
1 -> 6.86
2 -> 13.72
3 -> 27.44
4 -> 54.88
5 -> 109.76
6 -> 219.52
7 -> 439.04
When you estimate that you are close enough, then you stop and do:

Code:
#define MY_COEF 439
my_val *= MY_COEF;
my_val /= 128; // (1) see note below

(1). I used a division, which seems to be in contradiction with what I wrote. You can also
shift right by 7, which would have the same effect.
Shifting instead of dividing is the old way to write code. A long time ago, the compilers
were not smart enough to detect that some number is a power of to. Nowadays, if you divide
by 128, the compiler (most of the compilers I know) will shift the value.
This brings a personal rule:
- If the purpose is to divide, then use divide.
- If the purpose is to shift, then use shift.
But some may disagree.

Dora
 
Last edited:

    imranahmed

    Points: 2
    Helpful Answer Positive Rating
According to C-language rules, the code performs no actual float arithmetic. In so far the previous comments may be misleading.

I notice that some C-compilers are performing an automatic float conversion on a multiply with a float literal. If mikroC does it, you can shrink the code considerably by replacing the scaling operation with fixed point math, possibly even fit the small processor.
 
Last edited:

    imranahmed

    Points: 2
    Helpful Answer Positive Rating
My comments regarding floating point are based on the XC8 and XC16 compilers, and the MikroC ones may be different. Also the level of optimisation will make a difference.
However my experience is that the compilers (without any real level ofd optimisation) will not promote short integers to long ones, or integers to float until they have mixed integer/floating point operands or casts.
Therefore '5/9' always gives '0'.
This is the root cause of many questions in some of the other forums I inhabit.
Susan
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top