ESP32 and MCP3201 ADC

Hi all.
I have a ESP32 and Arduino IDE.
I need a sample code (working) to read a MCP3201 ADC.
I have tried to adapt some codes intended for Arduino board, no luck.

The best code I have managed, that gives some erratic reading is below
I do not understand all of it.

Thank you.
Regards

#include <SPI.h>

const int CS_PIN = 26; // Chip Select (CS) Pin
const int CLK_PIN = 32; // Clock (CLK) Pin
const int DATA_PIN = 33; // Data (DOUT) Pin

void setup()
{
  Serial.begin(9600);
  pinMode(CS_PIN, OUTPUT);
  pinMode(CLK_PIN, OUTPUT);

  pinMode(25, OUTPUT);  //Another device Unselected
  digitalWrite(25, HIGH);//

  digitalWrite(CS_PIN, HIGH); // Set CS high initially
  // Configure SPI communication
  SPI.begin(CLK_PIN, DATA_PIN, CS_PIN);
  delay(100);
}

void loop() {
  // Start an SPI transaction
  digitalWrite(CS_PIN, LOW); // Set CS low to select MCP3201
  byte command = B11000000; // 0b11 for single-ended mode, 0b000 for channel 0
  SPISettings spiSettings(100000, MSBFIRST, SPI_MODE0); // 1MHz clock, MSB first, SPI mode 0
  SPI.beginTransaction(spiSettings);
  byte upperByte = SPI.transfer(command); // Transfer command byte
  byte lowerByte = SPI.transfer(0x00); // Transfer dummy byte to receive the data
  SPI.endTransaction();
  digitalWrite(CS_PIN, HIGH); // Set CS high to end transaction
  delay(20);
  // Combine and print the ADC value
  int adcValue = (upperByte << 8) | lowerByte;
  float ADC_FLOAT = adcValue / 4.096;

  Serial.print("ADC Float: ");
  Serial.println(ADC_FLOAT, 3);
  delay(100); 
}

I saw two libraries in the Library Manager (searching 'MCP3201').
Did you try either of those ?
(I can't say how well they mesh with ESP32.)

GitHub - labfruits/mcp320x: Arduino library for the MCP320x ADC family

GitHub - RobTillaart/MCP_ADC: Arduino library for MCP3001 MCP3002 MCP3004 MCP3008 MCP3201 MCP3202 MCP3204 MCP3208

your link didnt work so here it is

Can you show us how you have it connected please?
And examples of your RAW readings

any particular reason to use the MCP3201 whn the ESP32 has 12bit ADC

Hi all.
thank you for the replay.
I have already tried some of the suggestions.
Either do not work at all, or were meant for Arduino board.

The code I posted does read the ADC but is erratic.
The readings do change with voltage, but they are incorrect and fluctuating.

I am going to take another look at the data-sheet.

Regards

As regards a "pure" DC level ?

Hi all.
I have checked the datasheet and revised the code.
I have checked the output on the ESP32, with a scope, and the levels are correct.
I still get the incorrect results.
The voltage should read 2.1V, I get 0.015V.

I think the problem is in the section regarding the manipulation of the incoming data.
Can you please revise for me. I would be very grateful.
The relevant section about this is on page 21 of datasheet.
I found it difficult to implement the code.
https://ww1.microchip.com/downloads/en/devicedoc/21290f.pdf

Thank you and regards.

#include <SPI.h>

const int CS_PIN = 26; // Chip Select (CS) Pin
const int CLK_PIN = 32; // Clock (CLK) Pin
const int DATA_PIN = 33; // Data (DOUT) Pin
byte upperByte;
byte lowerByte;
void setup()
{
  Serial.begin(9600);
  pinMode(CS_PIN, OUTPUT);
  pinMode(CLK_PIN, OUTPUT);

  pinMode(25, OUTPUT);  //Another device Unselected
  digitalWrite(25, HIGH);//

  digitalWrite(CS_PIN, HIGH); // Set CS high initially
  // Configure SPI communication
  SPI.begin(CLK_PIN, DATA_PIN, CS_PIN);
}

void loop() {
  // Start an SPI transaction
  digitalWrite(CS_PIN, LOW); // Set CS low to select MCP3201
  byte command = B11000000; // 0b11 for single-ended mode, 0b000 for channel 0
  SPISettings spiSettings(1000000, MSBFIRST, SPI_MODE0); // 1MHz clock, MSB first, SPI mode 0
  SPI.beginTransaction(spiSettings);
  upperByte = SPI.transfer(command); // Transfer command byte
  lowerByte = SPI.transfer(0x00); // Transfer dummy byte to receive the data
  SPI.endTransaction();
  digitalWrite(CS_PIN, HIGH); // Set CS high to end transaction
  
  //******* Bytes shifting and joining *****************
   // After reading page 21 of datasheet//
  
  lowerByte = lowerByte >> 1; //Shift right to remove redandant bit B1
  byte Bit7value = (upperByte & 1) * 256; // Find if bit 0 of MSB is set (value=256)
  lowerByte=(lowerByte >> 1) + Bit7value; //Shift right to remove redandant bit B1
  //then add bit7 of upper byte
  upperByte = upperByte >> 1; // Shift rigth upper byte
  upperByte = (upperByte & 0b00011111) * 256; // clear last 3 bits and multiply
  int adcValue = upperByte  + lowerByte;//Put togheter Upper and Lower byte
//****************************************************************************
  float Vref=4.096;
  float ADC_FLOAT = adcValue*(Vref/4095);
  Serial.print("ADC: ");
  Serial.println(ADC_FLOAT,3);
  Serial.print("MSB: ");
  Serial.println(upperByte, 3);
  Serial.print("LSB: ");
  Serial.println(lowerByte, 3);
  //delay(1000);
}

Hi all.
Just to let you know.
I decided to use the I/O method to read the AD. It works.

Here is the code.

#include <SPI.h>
const int CS_PIN = 26;
const int CLK_PIN = 32;
const int DATA_PIN = 33;
int adcValue = 0;
int mydata = 0;
void setup()
{
  Serial.begin(9600);
  pinMode(CS_PIN, OUTPUT);
  delay(1);
  pinMode(CLK_PIN, OUTPUT);
  delay(1);
  pinMode(DATA_PIN, INPUT);
  delay(1);
  digitalWrite(CS_PIN, HIGH); // Set CS_PIN high initially
  delay(1); // Wait for MCP3201 to settle
  pinMode(25, OUTPUT);  //Another device, Unselected
  delay(1);
  digitalWrite(25, HIGH);//
}

void loop()
{
  adcValue = 0;
  // Start conversion by pulling CS_PIN low
  digitalWrite(CS_PIN, LOW);
  delay(1); // Wait for MCP3201 to settle
  digitalWrite(CLK_PIN, HIGH);
  delay(1);
  digitalWrite(CLK_PIN, LOW);
  delay(1);
  digitalWrite(CLK_PIN, HIGH);
  delay(1);
  digitalWrite(CLK_PIN, LOW);
  delay(1);
  digitalWrite(CLK_PIN, HIGH);
  delay(1);
  digitalWrite(CLK_PIN, LOW);
  delay(1);
  // Read 12-bit ADC value from MCP3201

  for (int i = 11; i >= 0; i--)
  {
    adcValue += digitalRead(DATA_PIN) << i;
    digitalWrite(CLK_PIN, HIGH);
    delay(1);
    digitalWrite(CLK_PIN, LOW);
    delay(1);
  }
  // End conversion by pulling CS_PIN high
  digitalWrite(CS_PIN, HIGH);
  delay(4);
  float Vout = adcValue * (4.096 / 4095);
  Serial.println(Vout, 3);
  // Print the ADC value in binary
  //Serial.print("ADC value: ");
  // for (int i = 11; i >= 0; i--)
  //{
  // bool bitValue = (adcValue >> i) & 1;
  // Serial.print(bitValue);
  delay(400);
}

Regards.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.