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 support@ccsinfo.com

MCP3208 Occasionally get odd data

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



Joined: 27 Dec 2013
Posts: 69

View user's profile Send private message

MCP3208 Occasionally get odd data
PostPosted: Tue Feb 21, 2023 10:43 am     Reply with quote

Hi All,

Have a system with a PIC24HJ256GP610 that is reading from a couple MCP3208 ADCs. It functions well for a while, and then the ADC starts to return weird data, for example, the ADC returned 0xE81F (59,423DEC) on one occasion. This seems to happen more and more as time goes on.

For now I have wrote a simple filtering function where if the returned value is greater than 4098 I ignore the value and use the previous value. This seems to work, but I would like to get to the root of the issue if possible. Code snippets below:


The erroneous data does seem to come directly from the analogReadSE function.
MCP3208 Read
Code:

unsigned int16 analogReadSE(unsigned int16 CSPIN, unsigned int8 channel)
{
   //Base address corresponds to 0b00000110 in which the two 1's denote the
   //start bit and the single/differential bit. We default to 1 for single ended
   unsigned int8 byte0 = 0x06;
   
   char addressD2 = 0;
   char addressD0D1 = 0;
   //Ensure the top 5 bits are 0
   channel = channel & 0x07;
   
   addressD0D1 = channel & 0x03;
   
   //If channel is greater than 3, then bit 0 of byte 0 is always 1
   if(channel > 3)
   {
      byte0 = 0x07;
   }
   //Put the D0D1 bits in the MSb of byte 1
   unsigned int8 byte1 = (addressD0D1 << 6) & 0xC0;
   
   output_low(CSPIN);
   delay_us(5);   
   spi_write(byte0);
   //spi_write(byte1);
   unsigned int8 highbyte = spi_read(byte1);
   unsigned int8 lowbyte  = spi_read(0x00);
   output_high(CSPIN);

   return (highbyte << 8) | lowbyte;

}


Read Analog Data


Code:

void readAnalogJoystick()
{
   //Read left joystick analog inputs
   leftAnalog.A0 = analogReadSE(leftADCCS, 0);
   delay_ms(5);
   leftAnalog.A1 = 4096-analogReadSE(leftADCCS, 1);
   delay_ms(5);
   leftAnalog.A2 = analogReadSE(leftADCCS, 2);
   delay_ms(5);
 
   //Read left joystick button inputs
   leftAnalog.BUT1 = input(L_BUT1);
   leftAnalog.BUT2 = input(L_BUT2);
   leftAnalog.BUT3 = input(L_BUT3);
   leftAnalog.BUT4 = input(L_BUT4);
   leftAnalog.BUT5 = input(L_BUT5);
   leftAnalog.BUT6 = input(L_BUT6);
   
   delay_ms(10);
   
   //Read right joystick analog inputs
   rightAnalog.A0 = analogReadSE(rightADCCS, 0);
   delay_ms(5);
   rightAnalog.A1 = analogReadSE(rightADCCS, 1);
   delay_ms(5);
   rightAnalog.A2 = analogReadSE(rightADCCS, 2);

   //Read right joystick button inputs
   rightAnalog.BUT1 = input(R_BUT1);
   rightAnalog.BUT2 = input(R_BUT2);
   rightAnalog.BUT3 = input(R_BUT3);
   rightAnalog.BUT4 = input(R_BUT4);
   rightAnalog.BUT5 = input(R_BUT5);
   rightAnalog.BUT6 = input(R_BUT6);
}


Header Setup

Code:

#include <24HJ256GP610.h>
#device ICSP=1
#use delay(crystal=20000000)

#FUSES NOWDT,NOPROTECT,HS,NOIESO,NOPR,NOCKSFSM,NOWRT,NODEBUG

#use SPI(MASTER, SPI1, BAUD=500000, MODE=0, STREAM = SPI1)
#use i2c(master, I2C1)
#use rs232(UART1, baud = 57600, ERRORS, STREAM = HID)
#use rs232 (UART2, baud = 57600, ERRORS, STREAM = PC)
#use rs232(ICD, STREAM=DEBUG)

#include <stdint.h>

void InitJ1939Address(void);
void InitJ1939Name(void);

#define __CCS_USE_TIMER_PERIPH   1
#include <tick.c>

//Following Macros used to initialize unit's J1939 Address and Name - Required
#define J1939InitAddress()    InitJ1939Address()
#define J1939InitName()       InitJ1939Name()

//Following defines/macros used to associate your tick timer to J1939 tick timer
// defines/macro's - Required
#define J1939GetTick()                 TickGet()
#define J1939GetTickDifference(a,b)    (a-b)
#define J1939_TICKS_PER_SECOND         TICKS_PER_SECOND
#define J1939_TICK_TYPE                TICK

//Include the J1939 driver
#include <j1939.c>


Any thoughts?
temtronic



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

View user's profile Send private message

PostPosted: Tue Feb 21, 2023 10:57 am     Reply with quote

general comments, haven't read you actual code,line by line.....

Does it happen to ALL of the 8 channels of the ADC or just one, or two ?

Is the power supply rock steady stable and properly filtered ?

Are you sampling too fast ?

Can you use an oscilloscope to see the actual waveforms on VDD, grounds, ADC pins ?

Is Vref of the ADC steady ??

Getting accurate, repeatable 12bit results requires GREAT PCB layout, bypass filters,shielded cables, EMI protection...

digital is easy, analog can be 'fun' !

Jay
demedeiros



Joined: 27 Dec 2013
Posts: 69

View user's profile Send private message

PostPosted: Tue Feb 21, 2023 11:57 am     Reply with quote

Thanks for the response.

It does seem to happen to all channels of the ADC. Also not specific to a single chip (I am using 2).

3.3V supply has about 60mVpp of noise on it

I don't think I'm sampling too fast, I have a 5ms delay between each read. Looks like the device can sample up to 100ksps at 5V.

VREF is steady, provided by an external precision reference, LM4132BMF-3.0.

I will probe the values with a scope to see if I can see any issues. The issue does seem to come along with increased run-time though...

For example, I sent the data to a PC via UART. I built a simple logging app to log the maximum values. Started it on Friday and it was ok, remoted in saturday morning and again was ok, with no weird values.

Came in today, and had a number of very large events as mentioned.

Thank you!
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Tue Feb 21, 2023 12:00 pm     Reply with quote

Don't get me wrong, but it's not erroneous.
If you look, the values of the last 13bits are guaranteed (a null, and then
the 12 data bits), but all the bits before this show the Dout line as
Hi-Z You are only meant to take the last 12 or 13 bits. Values
of the bits before this mean nothing. If you want them to have a guaranteed
value, you would have to apply a tiny resistive pull-up or pull-down to
the line.
What is happening is the Vih/Vil of the chip is drifting with temperature,
resulting in high levels actually being seen.
You should be simply masking off the last 12 bits.
temtronic



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

View user's profile Send private message

PostPosted: Tue Feb 21, 2023 12:10 pm     Reply with quote

Interesting... it was fine all weekend while YOU weren't there....hmmm...

As it appears to be all channels...
Look for 'silly' things, like cellphone near it, static problems, Other 'EMI' creators like motors,arc welders, Weller soldering stations, ???

Add a 'time stamp' to the data
from PIC..... time,ADC channel,rawdata,LF,CR
Use known test voltages ( A precision Vref and resistor ladder works great )
Getting analog to be 100% involves a lot of 'elimination' using the 'try this, see what happens'...... It's the 'can't happen, not according to the 'book' things ' that usually get you !
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Tue Feb 21, 2023 12:17 pm     Reply with quote

My guess would be something like LED lights, inducing noise on the Hi-Z
line when he is there.The bits are just garbage, and should not be used.
demedeiros



Joined: 27 Dec 2013
Posts: 69

View user's profile Send private message

PostPosted: Tue Feb 21, 2023 12:50 pm     Reply with quote

Thanks for the insight guys.

Ttelmah, you are absolutely correct... If I take the erroneous 0xE81F and mask out the 12 good bits, I get 2079DEC which right where I should be for midrange!

You guys are great, right to the point, I really appreciate it!!
temtronic



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

View user's profile Send private message

PostPosted: Tue Feb 21, 2023 3:36 pm     Reply with quote

DOH ! I feel silly... I should have thought of that...
looked at the ADC datasheet
maybe IT doesn't care about the ???? bits, but the PIC sure does !!

just before this...
return (highbyte << 8) | lowbyte;

'zero' the highest nibble ( 4 bits).
demedeiros



Joined: 27 Dec 2013
Posts: 69

View user's profile Send private message

PostPosted: Tue Feb 21, 2023 8:22 pm     Reply with quote

Thanks!

I ended up doing the following:

Code:

return ((highbyte << 8) | lowbyte) & 0x0FFF);


That seems to be working well.
temtronic



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

View user's profile Send private message

PostPosted: Tue Feb 21, 2023 9:26 pm     Reply with quote

It's great to hear you got an 'easy' digital SOLUTION cause analog can be 'fun' to figure out !
Worst or 'best' for me was one group of remote energy control units in a subsystem would go 'funny', ONLY on Sunday mornings,from 1 to 2 AM. Never any other time and updates were every 15 seconds.... It took 3 weeks to figure out it was 'crosstalk' on a BELL telephone 'span' cable. Had them flip the pair and trouble magically went away. Seems the crosstalk was a bank's secured phone line updating their computer, that line was ONLY used, yes, on Sunday's from 1 to 2 AM........
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Wed Feb 22, 2023 2:15 am     Reply with quote

Very Happy

Yes, I looked at the datasheet and realised in standard readout mode,
everything before the last 13bits (it does guarantee to include a null
13th bit), is '?'. The timing diagram shows the incoming line as Hi-Z
here.
It does suggest there is something in the room inducing a little noise,
when you are there, so you need to be careful that this doesn't introduce
anything into the genuine analog signal.... Caveat.
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