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

ads8331 - help

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



Joined: 26 Apr 2010
Posts: 56

View user's profile Send private message

ads8331 - help
PostPosted: Fri Dec 07, 2012 10:17 pm     Reply with quote

Hi,

Any one has experience or driver code of ads8331 ADC converter with 24EP512GU810 or any PIC?

This is chip is not easy to nail down.

Thanks,
Howard
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sat Dec 08, 2012 4:53 am     Reply with quote

Quote:
This is chip is not easy to nail down.

Which chip?

Google took me straight to the TI ADS8331, and its data sheet.

A search on microchip's web site yielded the appropriate PIC data sheet.

What more do you need?

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19516

View user's profile Send private message

PostPosted: Sat Dec 08, 2012 8:40 am     Reply with quote

The interface is standard SPI. Like many other TI chips, they use a format that only requires less than a multiple of eight clocks, but then accept extra clocks to allow standard 8bit formats to be used. So if you study table 7, you have the clocks required for one mode as >=19, with up to five trailing zeros, allowing 24 clocks to be used and normal SPI.
Like many chips driving is not going to be 'generic', is has several different modes, dependant on whether you have acquisition continuous, or only when you read, which channel(s) you want to. read, whether you want sleep, etc. etc.. Draw a table of which features you want to use, then what commands you think are needed. Then try to code these. When you find this works, cheer, or if it doesn't, then post this here, and we will try to help. Keep the test 'environment' in the code simple. Just read values for the channels you want, don't try to attach this to your main code, till this is working.

Best Wishes
kongfu1



Joined: 26 Apr 2010
Posts: 56

View user's profile Send private message

ads8331 - help
PostPosted: Sat Dec 08, 2012 1:42 pm     Reply with quote

Hi,

Thanks for everyone's help. This project was done long time ago when a controller board is available but sensors circuit not.

Now everything is here. The problem is that, the ads8331 does not switch between two channels in a manual mode. CFR is set with manual channel select mode and everything else - 0x7fd. See SetFRC(), SetCh1() and SetCh2(). Testing code is attached below. Thanks.
Howard



Code:


#include <24EP512GU810.h>

#device *=16
#fuses NOWDT, NOIESO, NODEBUG, NOJTAG
#use delay(crystal=8Mhz, clock=120Mhz, AUX:clock=48Mhz) 

#pin_select SDI3     = PIN_D14
#pin_select SDO3     = PIN_D15
#pin_select SCK3IN  = PIN_B13
#pin_select SS3IN    = PIN_B14

#use spi(SLAVE, FORCE_HW, DI=PIN_D14, DO=PIN_D15, CLK=PIN_B13, BITS=8, SPI3, stream=SPI_RCB)

#define CCB_CHANNEL_ONE      1
#define CCB_CHANNEL_TWO      2

void SetCFR(void)
{
   
   output_low(ADC_SPI_CS);
   
   spi_write2(0xe7);
   spi_write2(0xfd);

   output_high(ADC_SPI_CS);
}

void SetCh1(void)
{
   output_low(ADC_SPI_CS);
   spi_write2(0x00);   //select INT0 input
   spi_write2(0x00);
   output_high(ADC_SPI_CS);
}

void SetCh2(void)
{
   output_low(ADC_SPI_CS);
   spi_write2(0x01);   //select INT1 input
   spi_write2(0x00);
   output_high(ADC_SPI_CS);
}

void ResetADC(void)
{
   output_low(ADC_SPI_CS);
   spi_write2(0xf0);
   spi_write2(0x00);
   output_high(ADC_SPI_CS);
}

//----------------------------------------------
void initADC(void)
//----------------------------------------------
{
   output_high(ADC_SPI_CS);
   setup_spi2(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_512);

   delay_us(30);
   ResetADC();
   delay_ms(500);
   SetCFR();
   delay_ms(10);
   SetCh1();      //set to next channel
   SW_ON(ADC_START);
}

//use spi call to set and read data back from adc
unsigned int16 readPhotoCh(void)
{
   unsigned int16 adcResult = 0, theInt16 = 0;
   unsigned int8 i = 0, theInt0 = 0, theInt1 = 0;
   

   
   while(!input(ADC_READY) && i < 1000)
   {
      delay_us(10);
      i++;
   }
   if(i < 10)
   {
      delay_us(1);
      output_low(ADC_SPI_CS);
      delay_us(1);
     
      theInt0 = spi_read2(0);
      theInt1 = spi_read2(0);
      output_high(ADC_SPI_CS);
     
      theInt16 = theInt0;
      theInt16 = theInt16 << 8;
      adcResult = theInt16 | theInt1;
   }
   
   return adcResult;


void enableADC1(void)
{
 
   SW_OFF(ADC_START);   //convert analog to ADC SPI chip
   spi_write2(0xd0);   //read command 0x0d
   spi_write2(0x00);

}

void enableADC2(void)
{

   SW_OFF(ADC_START);   //convert analog to ADC SPI chip
   spi_write2(0xd0);   ////read command 0x0d
   spi_write2(0x00);
 
}

int16 ReadCh1(void)
{
   uint16 volA;

   enableADC1();   //convert analog to ADC SPI chip
   volA = readPhotoCh();
   SW_ON(ADC_START);
   SetCh2();   //set to next channel
   return volA;
}

int16 ReadCh2(void)
{
   uint16 volA;

   enableADC2();   //convert analog to ADC SPI chip
   volA = readPhotoCh();
   SW_ON(ADC_START);
   SetCh1();   //set to next channel
   return volA;
}

int16 ReadCh(void)
{
   if(currentChannel == CCB_CHANNEL_ONE)
      return ReadCh1();
   else
      return ReadCh2();

}


void main(void)
{
   int16 theValue;

   initADC();
   
   currentChannel = CCB_CHANNEL_ONE;
   theValue = ReadCh();
   currentChannel = CCB_CHANNEL_TWO;
   theValue = ReadCh();


}

PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Dec 08, 2012 1:58 pm     Reply with quote

Quote:
unsigned int8 i = 0, theInt0 = 0, theInt1 = 0;

while(!input(ADC_READY) && i < 1000)

Your data type is too small.

Also, some of these variable names are not very good. You should
use better names like 'lsb' and 'msb'. The first byte to come out is
the msb, and the next byte is the lsb. Much better names than "theInt".
temtronic



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

View user's profile Send private message

PostPosted: Sat Dec 08, 2012 1:59 pm     Reply with quote

Are you're telling us the only problem is selecting the channel ? That everything else works fine ?

What were the ADC values tested and the results ?

Your 'main' program isn't complete and runs off......
It initalizes the ADC then captures 2 readings but nowhere does it display the results to us humans, then stops.well sleeps actually...
at least no that I can see.

Perhaps others see it differently ?
kongfu1



Joined: 26 Apr 2010
Posts: 56

View user's profile Send private message

PostPosted: Sat Dec 08, 2012 2:19 pm     Reply with quote

temtronic wrote:
Are you're telling us the only problem is selecting the channel ? That everything else works fine ?

What were the ADC values tested and the results ?

Your 'main' program isn't complete and runs off......
It initalizes the ADC then captures 2 readings but nowhere does it display the results to us humans, then stops.well sleeps actually...
at least no that I can see.

Perhaps others see it differently ?


Yes. the value was read back from ads8331 with sensor attached. The reading from ads8331 matches with sensor output. But it is always same value from channel 1 regardless SetCh1/SetCh2 were called or not.

USB communication was used with the board here. It is going to be too long to add USB driver with the testing code.

In debug mode, it shall be OK to test and see the problem.
Thanks.
Howard
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sat Dec 08, 2012 2:52 pm     Reply with quote

How do you KNOW the ADC values?

Mike
kongfu1



Joined: 26 Apr 2010
Posts: 56

View user's profile Send private message

PostPosted: Sat Dec 08, 2012 3:20 pm     Reply with quote

Mike Walne wrote:
How do you KNOW the ADC values?

Mike


The ADC values were measured from pin IN0 (channel 1) and IN1 (channel2) of ads8331. Also sensor output could be set in a rough range such as 0, 1,2..6V. For a testing purpose, have channel 1 set on 0 or 3 and channel 2 on 5V, readings from ads8331 are always same on both channels that matches with channel 1 settings.

Thanks,
Howard
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sat Dec 08, 2012 6:02 pm     Reply with quote

Code:
void enableADC1(void)
{
 
   SW_OFF(ADC_START);   //convert analog to ADC SPI chip
   spi_write2(0xd0);   //read command 0x0d
   spi_write2(0x00);

}

void enableADC2(void)
{

   SW_OFF(ADC_START);   //convert analog to ADC SPI chip
   spi_write2(0xd0);   ////read command 0x0d
   spi_write2(0x00);
 
}


I don't find your code easy to analyse.

I can't see much difference between your two functions 'void enableADC2(void)' and 'void enableADC1(void)'.

Is this significant?

Mike

EDIT And I still don't see how KNOW what your ADC output is.
temtronic



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

View user's profile Send private message

PostPosted: Sat Dec 08, 2012 6:22 pm     Reply with quote

I have to agree with Mike.
You should start with simple linear coding. Get ONE channel working correctly (showing the result either on and LCD or to a PC terminal program). Currently there is NO way to see the ADC results.

MANUALLY change the ADC channel and observe the results.

Once this is working, duplicate the 'read adc and display' code segment and add to 'main', with a small delay(say 500ms), so that you can observe the results, again on either LCD or PC, looping between the channels.

Once ALL this works, then, you can 'make it fancy', if you want. Really though, unless you're working on a very, very tight memory budget, it's NOT worth the effort to make it overly complicated.

hth
jay
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Dec 10, 2012 3:57 pm     Reply with quote

Quote:
void SetCh1(void)
{
output_low(ADC_SPI_CS);
spi_write2(0x00); //select INT0 input
spi_write2(0x00);
output_high(ADC_SPI_CS);
}

void SetCh2(void)
{
output_low(ADC_SPI_CS);
spi_write2(0x01); //select INT1 input
spi_write2(0x00);
output_high(ADC_SPI_CS);
}

The ADC values were measured from pin IN0 (channel 1) and IN1 (channel2) of ads8331

But it is always same value from channel 1 regardless SetCh1/SetCh2 were called or not.

1. The channel numbers for IN0 and IN1 are not ch 1 and ch 2.
They are ch 0 and ch 1. They are the same as the INx number.
It's just a naming convention, but you shouldn't mentally rename the
channels to something different than the data sheet says.

2. Your method of selecting the channels is wrong. Look on page 27
of the ads8331 data sheet:
http://www.ti.com/lit/ds/symlink/ads8331.pdf
It has a table which shows the CMR values required to select channels
0 and 1. It shows clearly that the 4-bit CMR value is in bits 15:12 of
the of the 16-bit word. But your code, shown above, doesn't do that.
You have the channel in bits 11:8. That's not correct.
Download the sample C code from TI for interfacing to the ads8331.
http://www.ti.com/litv/zip/slaa551
Look in the main.c file. I have posted their channel select routine below.
Notice how they left-shift the channel into the upper 4 bits (bits 15:12).
This is a confirmation of the ads8331 data sheet.
Quote:

// Write CMR register to select channel if Manual channel select is enabled
void ADS833x_Channel_Select(Uint16 Data)
{
Data = Data << 12;
while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG !=0) { } // Wait until SPITXBUF is free
SpiaRegs.SPITXBUF = Data;
}

So your channel select code should be changed as shown in bold below:
Quote:

void SetCh1(void)
{
output_low(ADC_SPI_CS);
spi_write2(0x00); //select INT0 input
spi_write2(0x00);
output_high(ADC_SPI_CS);
}

void SetCh2(void)
{
output_low(ADC_SPI_CS);
spi_write2(0x10); //select INT1 input
spi_write2(0x00);
output_high(ADC_SPI_CS);
}


Please see bkamen's comments in the PIC101 thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=47549&start=1
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Mon Dec 10, 2012 7:49 pm     Reply with quote

BTW: whats the reason for the 24EP512GU810
in your post. ?
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