#### frahman3

##### Member
Hi,
I attached the program and changes made by considering inputs from members. Thank you so much. However, how can I avoid overflow for 12-bit ADC for voltage[value]=(ADC_value[value]/4095)*5?

Regards
FR
Hi,
CSS:
#use rs232(baud=9600,UART2)
#include <float.h>
#fuses HS, NOWDT, NOPROTECT, PUT64, BORV27
//correct - Power On Reset Timer value 64ms, Brownout reset at 2.7V
#use delay(clock=20000000)  //20 MHz crystal
#use rs232(baud=9600,UART2)
#define LED PIN_B10
//#define VSS_VDD
#define WDT_OFF=0

void main()
{

setup_adc_ports(sAN0 | sAN1 | sAN2 | sAN3 | sAN4 | sAN5 | sAN6 | sAN7 | sAN8 | sAN9 | sAN10 | sAN11 | sAN12 | sAN13 | sAN14 | sAN15, VSS_VDD);

// Built-in A/D setup function
// Built-in A/D setup function

const int8 channel_1[]=1,2,3,4,5,6,7,8,9,10,11,12,13;
int16 value;
float voltage[sizeof(channel_1)];

//I/O ports configurations(1:input, 0:output)
set_tris_a(0x0000);     //set port_a as output
set_tris_c(0x0000);     //set port_c as output
set_tris_d(0x0000);     //set port_d as output
set_tris_f(0x0000);     //set port_f as output
set_tris_g(0x0000);     //set port_g as output

output_a(0x0000);       //clear port_a to all 0s
output_c(0x0000);       //clear port_c to all 0s
output_d(0xFFFF);       //clear port_d to all 1s-portD dafault at HIGH state
output_f(0x0000);       //clear port_f to all 0s
output_g(0x0000);       //clear port_g o all 0s

while(TRUE)
{
//pair 16_1
//sample start

//Excitation_pair 16_1 (+I)
output_high(pin_G15);
output_low(pin_A15);
//excitation_pair 16_1 (-I)
output_low(pin_F0);
output_high(pin_G0);
delay_ms(2.5);

//S&H
output_d(0b1100000000000001);

for (value=0;value<sizeof(channel_1);value++)
{
}
for(value=0;value<sizeof(channel_1); value++)
{
printf("%4.3f\r\n", voltage[value]);
}
printf("9.999\r\n");

}
}

#### Pommie

##### Well-Known Member
Use a 32 bit variable.
Code:
int32 newVar;
newVar*=5000;
newVar/=4096;                    //note not 4095
voltage[value] = newVar;        //voltage = 0 to 5000 I.E. mV
Mike.
Edit, Tided up code. Just out of bed and not had coffee yet so not got code head on!!!
if you want it as a float then add float volts=voltage[n]/1000.0;

#### Pommie

##### Well-Known Member
You may need to cast some values.
Code:
int32 newVar;
newVar*=5000;
newVar/=4096;                        //note not 4095
voltage[value] = (int16) newVar;    //voltage = 0 to 5000 I.E. mV
Mike.

#### frahman3

##### Member
Thanks Mike for the code.

Regards
FR

#### frahman3

##### Member
Hi,

This morning i encountered a problem with the hyper terminal which I'm using to display ADC data from dspic. Last Friday I tried to read the data from dspic with labview using port COM3 and it was able to display on the front panel in labview. For your information, I closed and exit the hyper terminal program before I opened labview and vice versa. Now both program are unable to display the data. In hyper terminal the message displayed "Another program is using the selected telephony device. Try again after the program completes". I exit all programs and restart my laptop several times but the message remains. Can anyone guide me how to solve this problem? I'm using windows 10.

Regards

FR

#### rjenkinsgb

##### Well-Known Member
Check in device manager to make sure COM3 has no driver errors?

I've had similar errors in Realterm a couple of times when I've managed to crash it, but they can often be fixed by opening and closing the program & attempting to reconfigure the com port a couple of times, or simply rebooting.

A fault that persists through reboots and power cycling seems like a driver or hardware problem...

What is COM3? A plug-in serial card or a USB adapter?

Edit - if it is a USB device, check in device manager if the driver has auto updated. If t has, roll it back to the previous version.
There was a similar problem a few years ago with some USB serial devices..

If it's a USB serial adapter, is it a genuine FTDI type or a clone?

#### frahman3

##### Member
Hi,
Thank you for the reply. The devices i referring to is a USB serial adapter and its genuine FTDI type. What I did i clicked on control panel> hardware&sound> device and printer> FT232R usb uart> (right click) troubleshoot> follow instructions on screen. It works. Thanks for the guide.

Regards

FR

#### frahman3

##### Member
HI,

I have some other problem when read ADC data from the PIC. I created a program using for loop because I want to make sure I received all data according to how many loops i wanted. For example if I set the for loop to run 3 times (0,1,2) than on the hyper terminal I will received 3x9 data including 9.999 (marked as end of data for each iteration). But the problem is at the last iteration the data displayed less than 9. IS it because of the ADC
CSS:
#include <18F4580.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define button (PIN_B0)

void main()
{
set_TRIS_B(0x0F);

const int8 channel_1[] = 0,1,2,3,4,5,6,7;

int start;

int32 value1;
int32 voltage[sizeof(channel_1)];

//while(TRUE)
for(start=0; start<=2;start++)// acquire 8 measurements in 10 ONLY
{
LOOP1:
if(input_state(PIN_B2) ==0)//if not pres==0, LED ON/OFF 0.5sec
{
delay_ms(100);
output_b(00000000);
delay_ms(100);
output_b(11000000);

goto LOOP1;
//break;
}
else // if pressed (HIGH) start acquisition
{

for(value1 = 0; value1 < sizeof(channel_1); value1++)
{

delay_ms(500);
voltage[value1] = ADC_value1[value1] * (5 / 4096);
// Convert ADC data to mV

}

for(value1 = 0; value1 < sizeof(channel_1); value1++)
// Display 8 voltage values
{
printf("%4.3w\r\n", voltage[value1]);

}
printf("9.999\r\n");

}

}

}
buffer? First I set iteration to 10 and the problem occurs. Later, I change iteration to 3 the problem remains. Can anyone help me.

Regards
FR

#### rjenkinsgb

##### Well-Known Member
I suspect the compiler is using buffered I/O and there are a few characters still in the transmit buffer when the program quits.

Try adding a dummy printf() after the output loop that eg. prints a block of 20 space characters, just to ensure all wanted data has been flushed through the serial buffers.

#### Pommie

##### Well-Known Member
The reason you're getting zero is because, in integer maths, (5/4096)=0. Which is why I separated the calculations.

Mike.
Edit, it also needs to be 5000 (not 5) to get mV or you need to use fp variables.

#### frahman3

##### Member
Hi,

I take your advice. However I am facing error which says "Previous identifier must be a pointer" and it refers to the 'value'. I'm a bit confusing with the error statement. What does pointer mean in this situation? Sorry for my knowledge in C is bad. Pls advice.

Regards
FR

CSS:
#include <30F6014A.h>
#include <float.h>
#include <string.h>
#fuses HS, NOWDT, NOPROTECT, PUT64, BORV27
//correct - Power On Reset Timer value 64ms, Brownout reset at 2.7V
#use delay(clock=20000000)  //20 MHz crystal
//#use rs232(baud=9600,UART2)
#define LED PIN_B10
//#define VSS_VDD
#define WDT_OFF=0
#use rs232(baud=9600,UART2)
void main()
{

setup_adc_ports(sAN0 | sAN1 | sAN2 | sAN3 | sAN4 | sAN5 | sAN6 | sAN7 | sAN8 | sAN9 | sAN10 | sAN11 | sAN12 | sAN13 | sAN14 | sAN15, VSS_VDD);

// Built-in A/D setup function
// Built-in A/D setup function

const int8 channel_1[]=1,2,3,4,5,6,7,8,9,10,11,12,13;

int16 value;
int16 voltage;
int32 newVar;
newVar*=5000;
newVar/=4096;                        //note not 4095
voltage[value] = (int16) newVar;    //voltage = 0 to 5000 I.E. mV

//I/O ports configurations(1:input, 0:output)
set_tris_a(0x0000);     //set port_a as output
set_tris_c(0x0000);     //set port_c as output
set_tris_d(0x0000);     //set port_d as output
set_tris_f(0x0000);     //set port_f as output
set_tris_g(0x0000);     //set port_g as output

output_a(0x0000);       //clear port_a to all 0s
output_c(0x0000);       //clear port_c to all 0s
output_d(0xFFFF);       //clear port_d to all 1s-portD dafault at HIGH state
output_f(0x0000);       //clear port_f to all 0s
output_g(0x0000);       //clear port_g o all 0s

while(TRUE)
{
//read from chnnel 0, 0++ (1,2,3...13)
for (value=0;value<sizeof(channel_1);value++)
{
}
//display value from channels 0...7
for (value=0;value<sizeof(channel_1);value++)
{
//printf("%4.3f",voltage[value]);
printf("%4.3f\r\n",voltage[value]);

}
//printf("9.999");
printf("9.999\r\n");
}
}

#### Pommie

##### Well-Known Member
It's (I think) the * in the line newVar*=5000; Try changing it to newVar= newVar*5000;

Mike.

#### frahman3

##### Member
Hi,
Thanks Mike. But the problem remains. The errors are pointing to the term 'value' which the error says 'Previous identifier must be a pointer'.

FR

#### Pommie

##### Well-Known Member
Which line is the problem on?

Mike.
Edit, why is value sometimes blue? Is it a reserved word? I don't know or use CSS.
Edit2, why isn't voltage an array anymore? I think this is your problem

Last edited:

#### frahman3

##### Member
Hi,

I think for the time being I stick with the command voltage[value] = (ADC_value1[value]). I'll recheck it. Other options for the mv conversion I will use the labview to do it. In the time being I tried to try to read dc voltage 4.788V from multichannel ADCs but only channel AN0 seems working, others it display -16.000 Why is this happening? Does the dspic require delay to read from other ADCs? or I missed to declare/ insert include files in the code? Here is what I received in the hyper terminal. Any suggestions?

Regards
FR

4752.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
9.999

#### Nigel Goodwin

##### Super Moderator
In the time being I tried to try to read dc voltage 4.788V from multichannel ADCs but only channel AN0 seems working, others it display -16.000 Why is this happening? Does the dspic require delay to read from other ADCs?
I can't comment on your exact situation, but essentially it's a VERY common rookie mistake.

There's usually only one ADC in a microcontroller, which is switched between the different input pins. When you switch channels the capacitor in the sample and hold has to charge/discharge, and this takes time, in particular it's EXTREMELY dependent on the source impedance feeding the pins, and the specification of the ADC specifies the minimum source impedance for fast switching.

Mostly though, speed isn't an issue, so you switch channels, wait a while (dependent on source impedance), and then take the reading.

However, I wouldn't expect that to give -16 readings, the reading will normally be somewhere between the previous pin, and the one you've switched to (as the capacitor has finished charging/discharging before the reading).

#### rjenkinsgb

##### Well-Known Member
In the code with the error - this section

int16 value;
int16 voltage;
int32 newVar;
newVar*=5000;
newVar/=4096; //note not 4095
voltage[value] = (int16) newVar; //voltage = 0 to 5000 I.E. mV

You are using variables without initialising them; is that chunk of code in the wrong place, or was it intended to be a comment block?

In next example, it is as Nigel says, you need a delay for the analog input sample & hold time after each change of channel.
A 10uS delay is advised as being safe, you may be able to use less if you check the device data sheet.

#### Nigel Goodwin

##### Super Moderator
A 10uS delay is advised as being safe, you may be able to use less if you check the device data sheet.
As long as you've got a nice low source impedance 10uS is probably fine, but you need considerably longer delays if your source impedance is higher - usually 2K is the maximum suggested source impedance for most PIC's.

#### rjenkinsgb

##### Well-Known Member
As long as you've got a nice low source impedance 10uS is probably fine, but you need considerably longer delays if your source impedance is higher - usually 2K is the maximum suggested source impedance for most PIC's.
Very true; I'm thinking of my hardware designs, without allowing for other possibilities.
10uS is just the advised delay in the CCS compiler manual.

(Also, I never use inline delays so I'm not used to thinking in those terms; for ADC inputs, I use a sequencer that alternately reads the ADC result then selects a new input channel, or starts a new conversion, based on an incrementing state variable.
That's called from a regular clock interrupt at whatever frequency the project needs for that and other background functions).

#### frahman3

##### Member
Hi,

Sorry for my incompetent in c programming. I'm in learning process and asking some guidance from the experts. I have rewritten the program and now it can read from ADC (single & multi-channel). Attached are the codes for single channel ADC. I encounter problem when I pump-in dc voltage to the channel 0. The results displayed are different from what have been measured. Below are the results:-
1.03 1334
2.01 2542
3.01 3731
4.01 4981
5.01 4998

Regards
FR

CSS:
#include <30F6014A.h>
#fuses HS, NOWDT, NOPROTECT, PUT64, BORV27
//correct - Power On Reset Timer value 64ms, Brownout reset at 2.7V
#use delay(clock=20000000)  //20 MHz crystal
#use rs232(baud=9600,UART2,ERRORS)

void main()
{
setup_adc_ports(sAN0 | sAN1 | sAN2 , VSS_VDD);
// Built-in A/D setup function

// Build-in A/D setup function
signed int32 ert_voltages_0;

while(true)
{

//sample at Channel_0
delay_us(10);        //delay is required after setting channel and bef.read
}