SPI issues with external ADC

Status
Not open for further replies.

Jetsream

Member
I am using SPI for the first time in a real project and I am experiencing a few issues.

- Teensy 3.2
- ADC: MCP33121-10
https://www.mouser.de/datasheet/2/268/microchip_technology_mchp-s-a0006919354-1-1749951.pdf

Project: The goal is to convert the voltage (set by potentiometer), to learn how the ADC is working (with a bigger project in mind.).

Problem: I only read 2^16 = 65535 (this should be.. 1111 1111 1111 1111) from the serial interface, despite changing (&checking with my multimeter) the analog input voltage Ain+. Below, you also find a Screenshot from my Scope, but I cant really learn whats going wrong from it. The datasheet states that 1111 .....1111 is the "error" code indicating a voltage above VRef, or VRef itself, still it occurs whichever voltage I apply on the input pin. I am quite generous with the timing, so this shouldn´t be a problem of the ADC lacking time to convert the value and present it on the SPI.

Funny thing is that I tried to see what happens, when you don´t connect DIN on the Teensy. Still, I get 2^16, no matter what. Thanks a lot guys! I am ready to learn, so please feel free to mention everything you notice.
I already tried lowering the SPI CLK, as the setup is currently on breakout/bread boards and flimsy jumper wires.

Notiz 16.08.2021.jpg
NewFile2.png
The decoded value on the scope is very unstable and jumping around all the time. The teensy serial monitor stays rock solid at 2^16, no matter what. (CLK: yellow, DIN: blue, CS: pink)

Code:
#include <SPI.h>
#define CS 10
#define CNVST 4
#define BAUDRATE 115200

const uint32_t SPI_CLK = 1E6;

uint16_t MSB;
uint16_t LSB;
uint16_t iVal;

SPISettings settingsA(SPI_CLK, MSBFIRST, SPI_MODE1); 

void Read(){
  
 SPI.beginTransaction(settingsA);
  digitalWriteFast(CS, LOW); //changed to normal digitalWrite
  MSB = SPI.transfer(0); //send  0XFF = 255, so rx only
  LSB = SPI.transfer(0); //send  0XFF = 255, so rx only
  digitalWriteFast(CS, HIGH); //changed to normal digitalWrite
    SPI.endTransaction();
  iVal = (((uint16_t)MSB << 8) | LSB);
  //iVal = iVal >> 2; //to obtain 14 bit data

  
  }

void setup(){



pinMode(CS, OUTPUT);

pinMode(CNVST, OUTPUT);
digitalWriteFast(CS, HIGH);
digitalWriteFast(CNVST, LOW);
Serial.begin(BAUDRATE);
SPI.begin(); 



}

void loop(){
delayMicroseconds(4);

digitalWriteFast(CNVST, HIGH);
delayMicroseconds(4);
digitalWriteFast(CNVST, LOW);
Read();
//Serial.println(MSB);
//Serial.println(LSB);
Serial.println(iVal);
iVal = 0;
}
 
any ideas? I tripled checked all connections and kind find a hint..

I disconnected the ADC from the breadboard, just with the cables in place. Still, the SPI interface is reading 65535, despite the ADC not being connected.
 
Last edited:
@Jetsream:
It looks to me like your A/D is putting out a signal level on the SIO pin of around 1.8 Volts which the Teensy will not recognize. The schematic you show is very difficult to read, so I have no idea why your A/D is not putting out the full 3.3v signal to the Din pin of the Teensy. The other two signals are coming from the Teensy so they look alright. I would suggest you read the data sheet again very carefully to see if there may be some error with the A/D's power input pins.
 
You misunderstood the ADC
this is not for SPI but you should I2S port
connect
clk to Teensy clk
dout to Teensy Din
cnvst to Teensy FS
din to DV+
 
@Jetsream:
It looks to me like your A/D is putting out a signal level on the SIO pin of around 1.8 Volts which the Teensy will not recognize. The schematic you show is very difficult to read, so I have no idea why your A/D is not putting out the full 3.3v signal to the Din pin of the Teensy. The other two signals are coming from the Teensy so they look alright. I would suggest you read the data sheet again very carefully to see if there may be some error with the A/D's power input pins.

Thanks for the answer @sbfreddie.
I will do so! But is it normal to have 3V to ground between DIN (Pin 12)?
 
Right, the DIN/MISO [blue] signal does not look good.
But I noticed from the schematic that you use the AGND of the Teensy as the general GND for the circuit?
You better connect all the grounds to the Teensy GND pins instead. On a Teensy 3.2, GND is not the same as AGND.

Paul
 
Thanks for the answer @sbfreddie.
I will do so! But is it normal to have 3V to ground between DIN (Pin 12)?

It depends on the A/D, some devices use a high as an idle state, and some devices use a low as an idle state. I was looking at the data sheet and you should study page 38 very carefully. I think it should clear up a few things.
@WMXZ It is an SPI device as mentioned on the front page of the data sheet, with the details on page 38. It is a very strange SPI device though.

Ed
 
@PaulS thx, I didn´t know there was a difference. I thought GND and AGND are the same, as they are connected to each other..
@Sbfreddie. I had a few errors in my setup, which I now corrected. I had a separated CNVST signal and was not using CS as a physical line (which was plain stupid from my side!). Now it´s just as in the datasheet, with CS managing CNVST, still the output is rock solid at 2^16.. could it be, that the SDO pin on the ADC changes to high-z (I suppose that´s high impedance?) when the last bit was clocked out? Why is it a strange SPI-device? Just curious to learn.
maybe its easier to read like this: (the CNVST on Teensy Pin 4 does no longer exist, I connected CNVST directly to pin 10(CS), with adapted code)
https://forum.pjrc.com/attachment.php?attachmentid=25579&d=1629208155

Edit:
Could it be the SPI sampling frequency? I just noticed, there are minima required by the adc. I increased mine to 16Mhz which should be fine for some 400ksps.. still, only getting 65535 on the readout
 
Last edited:
@Jetsream:
The CNVST timing is very critical and I don't think the Teensy's CS output from the SPI logic can be precisely controlled to get just the right timing. Make sure you read carefully the CNVST timing requirements in the data sheet. You may also have to check out the Teensy's different SPI modes to get this A/D to work correctly. You will never get anything correct out of this A/D until you cleanup the grounds, and get the Data Out pin to put out the proper logic levels (0 -> 3.3v). Perhaps use your Scope to verify the right logic levels.
All that ringing on the Data Out pin is probably caused by bad grounding.
Working with high speed A/D is a challenge.
All the best,
Ed
 
I thought GND and AGND are the same, as they are connected to each other
AGND and GND are connected by means of a small ferrite [L3 on the schematic here]
This ferrite has a certain impedance and AGND is therefor not a firm GND for digital signals.

Paul
 
@WMXZ It is an SPI device as mentioned on the front page of the data sheet, with the details on page 38. It is a very strange SPI device though.
Ed
I know it reads so, but I used a lot of similar ADC's with I2S port (in PCM mode) for years now
 
Screen Shot 2021-08-18 at 6.07.42 PM.jpg@Jetsream: I found this page at the manufactures website from their custom testing board that costs $200. It appears that the output Dout requires a pull-up resistor, check out this schematic:
 
Last edited:
I know it reads so, but I used a lot of similar ADC's with I2S port (in PCM mode) for years now
Now you got me intrigued & curious. How would that work from a software point of view? Should I use the I2S input object from Audio library?

Capture.PNG

Here is the timing diagram of the MCP33121:

Figure7-2.PNG

So the CNVST pin should be connected to the I2S LRCLK signal? [I assume you called that "FS" in message #5].
And the SCLK pin should be connected to the I2S BCLK signal?

Thanks,
Paul
 
Now you got me intrigued & curious. How would that work from a software point of view? Should I use the I2S input object from Audio library?

View attachment 25593

Here is the timing diagram of the MCP33121:

View attachment 25592

So the CNVST pin should be connected to the I2S LRCLK signal? [I assume you called that "FS" in message #5].
And the SCLK pin should be connected to the I2S BCLK signal?

Thanks,
Paul
Yes the connections are the one I'm using.
Not sure is stock I2S works, as it is tuned to codecs (setup is defined in output)
Anyhow,
key is to configure sync as short as possible
eg for a mono ADC
Code:
  I2S0_RCR4 = I2S_RCR4_FRSZ(0) | I2S_RCR4_SYWD(0) | I2S_RCR4_MF | I2S_RCR4_FSE ;
  I2S0_RCR5 = I2S_RCR5_WNW(31) | I2S_RCR5_W0W(31) | I2S_RCR5_FBT(31);
here the frame-sync is 1 clock long
so what I did, I cloned the stock i2s module and modified ir according to my needs.
critical issue is figuring out when to sample (polarity of clock) and the FramsSyncEarly (FSE)
but this can be solved by trying and reading the manuals
 
After reviewing this data sheet with a finer tooth comb, I agree with WMXZ, this A/D will not work with I2C or SPI. Perhaps some sort of bitbanging or as WMX suggests using I2S which has been customized specifically for this A/D.
Regards,
Ed
 
Last edited:
guys I just want to say thanks for your help and dedication! It really helps me out a lot. I added a pull-up on MISO and a pull-down on SC/CNVST, but with no real difference. Still, my logic level is far too small, despite checking every connection.

Any suggestions for another ADC to use, something that is slightly more beginner friendly and works with stock SPI/I2C?
I want to read the video output of a spectrometer. The spectrometer provides TRG for readout, and the data is presented at 200kHz. So I suppose (one reading per channel is enough for my needs) something at like 250ksps should be fine. Maybe something like a AD7980?
 
@MarkT its actually connected.. I was just being to lazy to paint them all into the shematic. Still, doesn´t this just influence some rippling in the analog supply?
 
looking into the timing diagram, I would simply try to use the stock Audio library I2S module.
Only one channel will get data.
Adjusting sampling frequency and clock timings for final application can be done later
 
@MarkT its actually connected.. I was just being to lazy to paint them all into the shematic. Still, doesn´t this just influence some rippling in the analog supply?

Who knows - you certainly shouldn't expect datasheet performance if you neglect analog decoupling.
 
Wait a minute, are you really expecting to get 1.8V out of a LM317 with 3.3V in? The minimum input to output differential is 3V.
 
@WMXZ is the timing really this critical? I thought the datasheet talks about the "minimum" times. So if they say, a conversion takes 1300ns, is it this critical to lower CNVST ( and subsequently start the readout) after.. 2000ns? or 2500ns?

Any suggestions for another ADC in this range? Something with like minimum 250ksps and a easy to use SPI/I2C?

@MarkT still, thanks for looking at it in detail :) very much appreciated!
 
Last edited:
@Jetsream:
In further consideration of your interesting problem, I think I have figured out why your getting all x0FFFF's back from the A/D.
If you look carefully at the MCP33121 data sheet page 38 timing diagram, you will find out why you are getting all x0FFFF's. The length of the CNVST positive cycle (rising edge to falling edge) is critical. If the CS/ signal from the Teensy is very short CS/ high state the A/D will not have time to complete the conversion when the Teensy SPI starts to shift out the data bits. As note 2 from the timing diagram says: "Any SCLK toggling events (dummy clocks) before CNVST is changed to "Low" are ignored". If you look at Timing Diagram for SDO you will see that SDO is in Hi-Z (tristate) for all the tCNV time plus tEN time, which is the convert time plus the time for enabling the SDO pin. (The convert time is set by an internal clock and cannot be changed)
As you can see you are trying to sample the DIO pin before the conversion is complete where the SDO pin is in Hi-Z which will give you a reading of x0FFFF's. Now after reviewing the LPSPI section of the RT1060 processor pages 2823-2824 you can see that the timing of the SCKPCS, PCSSCK, DBT, and SCKDIV can be set in the LPSPI Clock Configuration Register (CCR). I think if you experimented with these settings you could probably make this A/D work with the Teensy.
However if you have no idea what I am talking about with the last sentence perhaps you should consider using a more friendly A/D like the LTC2367-16, which has BUSY pin which you could use as an interrupt, thus eliminating some of these odd timing problems.
Regards,
Ed
 
Last edited:
Status
Not open for further replies.
Back
Top