CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Problem in reading two channels in MAX1416 adc

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
zeeshan ahmed



Joined: 02 Dec 2010
Posts: 22

View user's profile Send private message

Problem in reading two channels in MAX1416 adc
PostPosted: Sat Dec 31, 2011 2:06 am     Reply with quote

Hi all, Happy new year,

In continuation of previous thread
http://www.ccsinfo.com/forum/viewtopic.php?t=46768

Now i am able to read Channel 1 data successfully,
I am using the following code
Code:

#include <18f26k22.h>
#fuses intrc,NOLVP,noWDT,pllen
#use delay (clock=32M)
#USE RS232(BAUD=19200, XMIT=PIN_c6, RCV=PIN_c7)
#use spi(FORCE_HW, spi2, master)

#define  SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define  SPI_MODE_1  (SPI_L_TO_H)
#define  SPI_MODE_2  (SPI_H_TO_L)
#define  SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

#define  ch_s   pin_b4
#define  rst    pin_b5
#define  drdy   pin_b0

int1  d=0;
int8  bdta[2];

#int_ext
void ext_isr(void)
{
   output_toggle(pin_c0);
   d=1;
   
   output_low(ch_s);
   delay_us(1);
   spi_write2(0x38);
   bdta[0]=spi_read2(0x00);
   bdta[1]=spi_read2(0x00);
   delay_us(1);
   output_high(ch_s); 
}


void main(void)
{
   float data=0;   
   
   ext_int_edge (0,l_to_h);
   setup_spi2(SPI_MASTER | spi_mode_3 | SPI_CLK_DIV_16);
   enable_interrupts( INT_EXT_l2h );
   enable_interrupts(GLOBAL);

   output_low(rst);        // Reset ADC for a while
   output_low(ch_s);
   delay_ms(500);
   output_high(ch_s);
   output_high(rst);
   
   delay_ms(100);

//-----------------------------------------------------------------------------
   output_low(ch_s);    // Chip Select low   
   delay_us(1); 
   
   spi_write2(0x20);    // Com Regs Chan 1, clk reg selected
   spi_write2(0xa5);    // Clk Regs, 60 HZ notch
     
   spi_write2(0x10);    // Com Regs chan 1, Setup reg selected
   spi_write2(0x44);    // Setup Regs
     
   delay_us(1);
   output_high(ch_s);   // Chip Select High
//-----------------------------------------------------------------------------

   delay_ms(1000);

   while(true)
   {
     if(d==1)
     {
         d=0;
         data=make16(bdta[0],bdta[1]);
         printf("\rWord is %f",data);
     }
  }
}


Up till now the code is working properly. Very Happy

But when i modified above program to read channel 1 and 2, problem occurs, i get wrong values.

The modified program to read 2 channels is:
Code:

#include <18f26k22.h>
#fuses intrc,NOLVP,noWDT,pllen
#use delay (clock=32M)
#USE RS232(BAUD=19200, XMIT=PIN_c6, RCV=PIN_c7)
#use spi(FORCE_HW, spi2, master)

#define  SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define  SPI_MODE_1  (SPI_L_TO_H)
#define  SPI_MODE_2  (SPI_H_TO_L)
#define  SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

#define  ch_s   pin_b4
#define  rst    pin_b5
#define  drdy   pin_b0

int1  d=0,t=0;
int8  bdta[2];


#int_ext
void ext_isr(void)
{
   int ad_data=0;
   output_toggle(pin_c0);
   d=1;
   if (t==0) ad_data=0x38;
   else if (t==1) ad_data=0x39;
   
   output_low(ch_s);
   delay_us(1);
   spi_write2(ad_data);
   bdta[0]=spi_read2(0x00);
   bdta[1]=spi_read2(0x00);
   delay_us(1);
   output_high(ch_s);
}


void main(void)
{
   float data=0;   

   ext_int_edge (0,l_to_h);
   setup_spi2(SPI_MASTER | spi_mode_3 | SPI_CLK_DIV_16);
   enable_interrupts( INT_EXT_l2h );
   enable_interrupts(GLOBAL);

   output_low(rst);
   output_low(ch_s);
   delay_ms(500);
   output_high(ch_s);
   output_high(rst);
   
   delay_ms(100);

//-----------------------------------------------------------------------------
  output_low(ch_s);
   delay_us(1); 
   
   spi_write2(0x21);  // com regs chan 2, clk reg selected
   spi_write2(0xa5);  // clk regs
     
   spi_write2(0x11);  // com regs chan 2, setup reg selected
   spi_write2(0x44);  // setup regs
   
   spi_write2(0x10);  // com regs chan 1, setup reg selected
   spi_write2(0x44);  // setup regs
   
   delay_us(1);
   output_high(ch_s);
//-----------------------------------------------------------------------------

   delay_ms(1000);
   t=0;
   while(true)
   {
      if(d==1)
      {
         d=0;
         data=make16(bdta[0],bdta[1]);
         if(t==0)
         {
            printf("ch1\r\n");
         }
         else
         {
            printf("ch2\r\n");
         }
         printf("Word is %f\r\n",data);
         
         if(t==0) t=1;
         else if(t==1) t=0;
     }     
  }
}


I think there is some thing wrong with setup or clock register setting.

Please help me and guide me if I am doing something WRONG. Confused
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Dec 31, 2011 3:51 pm     Reply with quote

I would get rid of the interrupt routine. It makes the program be
needlessly complex. You could move all that code into a driver function.
You could poll the DRDY line with an input() statement in a while() loop
until it goes ready. (Possibly with a timeout counter).

I think it would be much easier to modify and to maintain and to
understand your driver, if you re-write it and get rid of the interrupt
routine. Then you wouldn't need all those flags in the isr to synchronize
it to your main code.
temtronic



Joined: 01 Jul 2010
Posts: 9250
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Jan 01, 2012 6:37 am     Reply with quote

I agree with PCM..trash the ISR just have code in Main.

Make a simple loop
Code:

main(){
configure to read channel one
read channel one
display data channel one.
}

when that works
Code:

main(){
configure to read channel one
read channel one
save channel one data
configure to read channel two
read channel two
save channel two data
display data channel one and two
}


display data channel one.


If that doesn't read channel 2, then you've miscoded the setup 'config' for channel 2 as you know channel 1 works correctly.


Once you have it 'up and running', then create an ISR IF you can justify WHY ( speed ? code space ?so..ISR overhead is huge compared to 6-10 lines of 2nd channel 'inline')

You don't always need to use ISRs !
zeeshan ahmed



Joined: 02 Dec 2010
Posts: 22

View user's profile Send private message

Problem is still there
PostPosted: Tue Jan 03, 2012 2:19 am     Reply with quote

Thank U PCM Programmer and Temtronic,

here is the datasheet of adc
http://datasheets.maxim-ic.com/en/ds/MAX1415-MAX1416.pdf

I have modified the program, i just removed the ISR, below is the simple program, but problem is still there, i am getting wrong data. I think there is a problem with data rate selection settings.

Code:

#include <18f26k22.h>
#fuses intrc,NOLVP,noWDT,pllen
#use delay (clock=16M)
#USE RS232(BAUD=19200, XMIT=PIN_c6, RCV=PIN_c7)
#use spi(FORCE_HW, spi2, master)

#define  SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define  SPI_MODE_1  (SPI_L_TO_H)
#define  SPI_MODE_2  (SPI_H_TO_L)
#define  SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

#define  ch_s   pin_b4     // chipselect
#define  rst    pin_b5     // reset
#define  drdy   pin_b0     // data ready

int1  d=0,t=0;
int8  bdta[2];
float data=0;
int   adr=0;

void main(void)
{
   setup_spi2(SPI_MASTER | spi_mode_3 | SPI_CLK_DIV_4);
   
   output_low(rst);        // reset ADC for a while
   output_low(ch_s);
   delay_ms(500);
   output_high(ch_s);
   output_high(rst);
   
//----------------------------------------------------------------------------A
   output_low(ch_s);          // Select chip
   delay_us(1); 
     
   spi_write2(0x20);          // com regs chan 1
   spi_write2(0xa4);          // clk regs, 50 hz data rate
     
   spi_write2(0x21);          // com regs chan 2
   spi_write2(0xa4);          // clk regs, 50 hz data rate
   
   spi_write2(0x10);          // com regs chan 1
   spi_write2(0x44);          // setup regs
   
   spi_write2(0x11);          // com regs chan 2
   spi_write2(0x44);          // setup regs
   
   delay_us(1);
   output_high(ch_s);
//----------------------------------------------------------------------------A 
 

   while(true)
   {
      if(!input(drdy))                 // data register read routine
      {
         if(t==0) adr=0x38;         // chan 1
         else if (t==0) adr=0x39;   // chan 2
           
         output_low(ch_s);
         spi_write2(adr);           // channel address
         bdta[0]=spi_read2(0xff);
         bdta[1]=spi_read2(0xff);   
         output_high(ch_s);
         data=make16(bdta[0],bdta[1]);   
         d=1;
      }
     
      if(d==1)       // new data avaiable ?
      {
         if(t==0)    // data from chan 1   
         {
            printf("ch1 data is %f\r\n",data);
         }
         
         else if(t==1)
         {
            printf("ch2 data is %f\r\n",data);
         }
         
         if(t==0) t=1;        // alternate the channels
         else if (t==1) t=0;
      }
     
   }
}


Please guide me, whats wrong with above code.
Thank you very much for your time.
Best Reagrds.
temtronic



Joined: 01 Jul 2010
Posts: 9250
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Jan 03, 2012 6:59 am     Reply with quote

First , I'd make a simple loop like below.
No conditions, no 'if's, just 'hard' coding ..select channel0, read, display, select channel1, read, display, loop.
This is a test program to see if the chip is working right, not a test in 'logic' or 'main program coding'.

Second, the lines with **. It appears you're sending FF or all ones to the chip, do you really want to send this data to it ?? I admit I haven't looked at the SPI driver commands but to me these lines say 'while receiving data from the SPI device, send 0xff to it at the same time' Am I right, wrong or just confused?
Code:

while(true)
   {
      if(!input(drdy))                 // data register read routine ,ready !
      {
//read channel 1 and display data..           
         output_low(ch_s);
         spi_write2(0x38);           // channel address 0
**         bdta[0]=spi_read2(0xff);
**         bdta[1]=spi_read2(0xff);   
         output_high(ch_s);
         data=make16(bdta[0],bdta[1]);   
            printf("ch1 data is %f\r\n",data);
     
        delay_ms(100); //delay between channels for testing...
//read channel 2 and display data...
         output_low(ch_s);
         spi_write2(0x39);           // channel address 1
**         bdta[0]=spi_read2(0xff);
**         bdta[1]=spi_read2(0xff);   
         output_high(ch_s);
         data=make16(bdta[0],bdta[1]);   
            printf("ch1 data is %f\r\n",data);
       delay_ms(100); // delay after displaying channel 2 data

   }


Third.
I'd make a 'reset_ADC' function. the datasheet says how, sending a lot of 1's. It is important! You have to be able to 'synchronize' the PIC and ADC as ANY bad data on the SPI bus could/will corrupt the data stream. While 'overkill' I'd send it everytime I call the 'read channels' function just to be sure. At the very least , upon powerup and before 'main' is executed.

For test purposes I'd have fixed voltages on the channels. Say 1 volt and 4 volts. Not 0 and 5, that way you can tell if you're readings are correct.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jan 03, 2012 3:29 pm     Reply with quote

Quote:

if(!input(drdy)) // data register read routine
{
if(t==0) adr=0x38; // chan 1
else if (t==0) adr=0x39; // chan 2

This test is wrong.

Your whole 2nd program could still be written in a much more simple way,
including the above section.
zeeshan ahmed



Joined: 02 Dec 2010
Posts: 22

View user's profile Send private message

Wrong data
PostPosted: Wed Jan 04, 2012 11:40 pm     Reply with quote

Thanks alot PCM Programmer and Temtronic for the reply.
I modified the above program as you suggested, but still the result is not correct, e.g. if Voltage on channel1 analog pin is 3.3 V, then ADC shows 4.5V, sometimes 2.3 V etc. This problem arises only when I want to use 2 channels, while with one channel ADC works perfect. I think there is a problem with output data rate and filter notch setting in setup register, Because when I change the data rate(from 50 to 60 Hz), ADC values also changes.
Code:

void main(void)
{
   setup_spi2(SPI_MASTER | spi_mode_3 | SPI_CLK_DIV_4);
   
   output_low(rst);        // reset ADC for a while
   output_low(ch_s);
   delay_ms(500);
   output_high(ch_s);
   output_high(rst);
   
//----------------------------------------------------------------------------A
   output_low(ch_s);          // Select chip
   delay_us(1); 
     
   spi_write2(0x20);          // com regs chan 1
   spi_write2(0xa4);          // clk regs, 50 hz data rate
 
   spi_write2(0x10);          // com regs chan 1
   spi_write2(0x44);          // setup regs
   
 
   spi_write2(0x21);          // com regs chan 2
   spi_write2(0xa4);          // clk regs, 50 hz data rate
   
   
   spi_write2(0x11);          // com regs chan 2
   spi_write2(0x44);          // setup regs
   
   delay_us(1);
   output_high(ch_s);
//----------------------------------------------------------------------------A 
   printf("ON\r\n");

   while(true)
   {
      if(!input(drdy))       
      {
         //read channel 1 and display data..           
         output_low(ch_s);
         spi_write2(0x38);           // channel address 0
         bdta[0]=spi_read2(0xff);
         bdta[1]=spi_read2(0xff);   
         output_high(ch_s);
         data=make16(bdta[0], bdta[1]);   
         printf("ch1 data is %.2f\r\n", (data/65535)*4.96);
         
         //read channel 2 and display data...
         output_low(ch_s);
         spi_write2(0x39);           // channel address 1
         bdta[0]=spi_read2(0xff);
         bdta[1]=spi_read2(0xff);   
         output_high(ch_s);
         data=make16(bdta[0], bdta[1]);   
         printf("ch2 data is %.2f\r\n", (data/65535)*4.96);
         //delay_ms(100); // delay after displaying channel 2 data
      }   
   }
}


Temtronic said:
Quote:

Second, the lines with **. It appears you're sending FF or all ones to the chip, do you really want to send this data to it ?? I admit I haven't looked at the SPI driver commands but to me these lines say 'while receiving data from the SPI device, send 0xff to it at the same time' Am I right, wrong or just confused?

We can send any data while reading the ADC data register. I checked it with different values, it doesn't affect ADC values.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Thu Jan 05, 2012 3:35 am     Reply with quote

This is a convertor with multiplexed input, it is not a pair of convertors side by side in the same chip. This mean you cannot select one channel, read it and then immediately read the other channel. You have to set up the first channel, wait for data ready, read it then select the second channel, wait for data ready then read.

Delta-sigma convertors work by filtering over time. They are primarily intended for continuous high resolution conversion, and have a high level of noise rejection, and the filtration is optimised to reject the line/mains frequencies, i.e. 50 or 60Hz. They are especially useful to measure slowly changing small signals in the presence of mains derived noise, such as strain gauge signals. They are of limited use as single shot general purpose convertors, which is what you are trying to do. Basically every time you change anything you must wait for the convertor to go through a full acquisition cycle. So in pseudo-code its always:

Code:

while (true)
{
    set up channel or filtering settings or anything
    while (settings don't change)
    {
        wait for data ready
        read data
        do something with data just read
    }
}


RF Developer
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group