Giter VIP home page Giter VIP logo

arduino_mcp3x6x_library's Introduction

Arduino MCP3x6x Library build

Supports Microchip 16bit MCP3461/MCP3462/MCP3464/ and 24bit MCP3561/MCP3562/MCP3564/ Analog Digital Converters.

Supported Boards

This project is set up to be build with different MCUs, but I am not able the test each of them. Personally I use the SAMD21, so this should be the most stable code.

Introduction

This lib does not (yet) support all features of these ADCs, but should help to get you started. Depending on which constructor is called the ADC will be configuerd in two different mode:

Mux Mode

MCP3x6x(const uint8_t pinCS = SS,SPIClass *theSPI = &SPI,
const uint8_t pinMOSI = MOSI, const uint8_t pinMISO = MISO, const uint8_t pinCLK = SCK)

Scan Mode

MCP3x6x(const uint8_t pinIRQ, const uint8_t pinMCLK, const uint8_t pinCS = SS, SPIClass *theSPI = &SPI,
const uint8_t pinMOSI = MOSI, const uint8_t pinMISO = MISO, const uint8_t pinCLK = SCK)

So scan mode requieres two additional pins, pinIQR for the conversion interrupt flag and pinMCLK (which is not implemented at all).

Both constructors fall back to default definitions which are common in the Arduino world. So if no pins is explicit specified the default SPI pinout will be used. Therefor it boils down to something simple as MCP3561 mcp(2, 3, 10); or even MCP3561 mcp(10);.

Please take a look at the examples how to configure these different modes.

Further documentation is available here.


see also:

arduino_mcp3x6x_library's People

Contributors

nerdyscout avatar pre-commit-ci[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

arduino_mcp3x6x_library's Issues

Strange issue with MCP3561

Hello,
I know the question is not directly related to the library, but I still want to give it a shot, since I am a bit stuck there.

I have a MCP3561 with a MAX4208 amplifier to measure the voltage at the output of a strain gauge. The MCP3561 is drived by an ESP32 using this library. I would like the system to work in continuous mode in MUX mode (differential).
Everything is working well (config settings, continuous mode, irq pin) but I have very strange steps showing in the output signal. It seems to be related to some specific ADC count values, and I can't find anything similar on the web too. After some digging I found out that sometimes, somehow, a group of samples has missing ADCDATA bytes, always the less significant ones. So data like 0x3Cxxxx becomes 0x3C0000 and it stays like this until a high/low enough sample appears and change the current value.

image
Like you can see on this picture (values are calibrated values for my use), there are somes value-based steps appearing at 11.27-21.68-31.04, on the ascent and the descent of the curve.

There is a small antialiasing filter consisting of two RC (1k/100n) filters in between, like in the schematics of the weight scale example application provided by microchip

I have tried with a signal generator directly on the input of the antialiasing filter and it still the same.

If you have any clue or something I could check/test/do to know what's causing this issue...

How do I add license in my source code ?

Hi,

I noticed that you have two licenses: CC0 and MIT. However, they seem pretty identical to me. Is it legal to include just one of the licenses?

Also, this is my first time adding a license. I don't know what the typical approach is for doing this. Should I add the full text of MIT/CC0 in the specific library, or should I create another folder to hold all the licenses?

Some questions about the SPI

Recently I run in to some issue that got me good : that is the timming of CS pin pulldown

MCP3x6x::status_t MCP3x6x::_transfer(uint8_t *data, uint8_t addr, size_t size) {
_spi->beginTransaction(SPISettings(MCP3x6x_SPI_SPEED, MCP3x6x_SPI_ORDER, MCP3x6x_SPI_MODE));
noInterrupts();
digitalWrite(_pinCS, LOW);
_status.raw = _spi->transfer(addr);
_spi->transfer(data, size);
digitalWrite(_pinCS, HIGH);
interrupts();
_spi->endTransaction();
return _status;
}

As above in your code CS pin is pulldowned after beginTransaction function been called , and it works! But when i'm using another adc (Texas Instrument's ads8691) it have to pulldown before it
So my question is how do I know when do I need to place it before or after beginTransaction function call ?

Another question: does the noInterrupts(); effect on the Interrupts that was pinned to another esp32 core?

Problems with SDO on MCP3464

Hi,
first of all thank you very much for the code. I was very happy to find something for this ADC family.
Unfortunately the code does not run on my MCP3464 yet. The signals from the CLK, CS and SDI look good but unfortunately the ADC at the SDO gives nothing out. Only a small ripple from the CLK is visible on the Scope. Do you have an idea where the problem could be?

I would be very grateful for any information.
Thanks a lot

Difficulty with compiling for RP2040 using earlephilhower core

Hi!
I'm having some trouble compiling my code after adding this library.
Most likely I'm doing something dumb, but would appreciate any input.

I include and initialise it like this:

#include "lib/MCP3x6x/MCP3x6x.h"
MCP3464 ext_mcp_adc(ADC_CS_PIN, &SPI, ADC_MOSI_PIN, ADC_MISO_PIN, ADC_SCK_PIN);

Then I get the following errors:

Linking .pio/build/PicoADK/firmware.elf
/Users/hallwrk/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/10.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/PicoADK/src/main.cpp.o: in function `_GLOBAL__sub_I_tft':
main.cpp:(.text.startup._GLOBAL__sub_I_tft+0x42): undefined reference to `_ZN7MCP3x6xC2EhhthPN7arduino11HardwareSPIEhhh'
/Users/hallwrk/.platformio/packages/toolchain-rp2040-earlephilhower/bin/../lib/gcc/arm-none-eabi/10.3.0/../../../../arm-none-eabi/bin/ld: .pio/build/PicoADK/src/main.cpp.o: in function `loop':
main.cpp:(.text.loop+0x98): undefined reference to `_ZN7MCP3x6x20analogReadContinuousENS_3MuxE'

(and so on)

I have some other peripherals on the two SPI channels which are working fine, an OLED and a DAC.

Not really an issue :)

Last year you discovered my repo for this chip and even helped out.
https://github.com/fhnw-ise-qcrypt/mcp3564

I just wanted to let you know that my library is now at a point where it is working in a product that I am still developing.
https://github.com/fhnw-ise-qcrypt/stm32-wiggly-pointy

And I came up with a conf.h file to have various configuration examples because this chip is just so damn adaptable.
So feel free to cheat by looking through my code. This is how I handle the "streaming" mode via GPIO interrupts. It actually works according to the timing from the Excel sheet:
https://github.com/fhnw-ise-qcrypt/stm32-wiggly-pointy/blob/main/Core/Src/stm32f3xx_it.c#L225

I am really curious how you implement the Stream class as I have seen in the example that you want to achieve.

mcp 3462 with Arduino Zero definition-question not issue!

Not really an issue, more of a question so apologies...

I'm attempting to read from channel 0 in mux mode but having issues even entering the setup and loop sections. I'm assuming it's something to do with my mcp definition since I've tested the println function and it seems to work. I'm using an Arduino Zero which is SAMD21. I added a lot of print statements to try and figure out where the program is/isn't making it to. If I go by these statements, the setup and loop aren't being read. Assuming that I've done something really dumb since I'm quite new to this.

MCP3462 mcp(10); //the problem?

void setup() {
Serial.begin(115200);
while (!Serial)
;
Serial.println(FILE);
if (!mcp.begin()) {
Serial.println("failed to initialize MCP");
while (1)
;
}
}

// the loop routine runs over and over again forever:
void loop() {
// read the input on default analog channel:
int32_t adcdata = mcp.analogRead(MCP_CH0);

// Convert the analog reading
double voltage = adcdata * mcp.getReference() / mcp.getMaxValue();
Serial.println("converted voltage");

// print out the value you read:
Serial.println("voltage: ");
Serial.print(voltage, 10);
Serial.println("printed voltage");

// pause program for one second
delay(1000);
}

Function: _getValue(uint32_t raw) wrong return

Hi, it's me again

I found out while the value should be negative number returns a very large positive number when I'm in data_format::SGN_DATA (int24)mode. For example, when the ADCDATA REGISTER have value FFFE2F, _getValue(raw) will return 16776751 while it should return -465;

The problem happend here:

case (data_format::SGN_DATA):
bitWrite(raw, 31, bitRead(raw, 24));
bitClear(raw, 24);
return raw;

I can't figure out what when wrong so I modified it like this:

case (data_format::SGN_DATA):  
  if(bitRead(raw, 23)){
    return (((~raw+1) & 0x7FFFFF)*-1);  // OR return((0x1000000 - raw & 0x7FFFFF)*-1);
  }else{
    return raw & 0x7FFFFF;
  }

if MSB==1(Negative Number), turn it to nergative number by two's complement, but we don't need to consider bytes greater then 22(0~22). So we & 0x007FFFFFF, but we still needs the negative sign so *-1.

I think there is some way to simplify this but this will work for me.



side note: I decided to write the whole register at once in the begin function like this
void MCP3x6x::setConfig0(){
  settings.config0.vref_sel=1;
  settings.config0.cfg0=1;
  settings.config0.clk=clk_sel::INTERN;
  settings.config0.bias=cs_sel::BIAS_0UA;
  settings.config0.adc=adc_mode::STANDBY;
  _status = write(settings.config0);
}
void MCP3x6x::setConfig1(){
  settings.config1.pre=pre::MCLK_0;
  settings.config1.osr=osr::OSR_256;
  _status = write(settings.config1);
}
void MCP3x6x::setConfig2(){
  settings.config2.boost=boost::BOOST_1;
  settings.config2.gain=gain::GAIN_32;
  settings.config2.az_mu=0;
  settings.config2.az_ref=1;
  settings.config2.reserved=1;
  _status = write(settings.config2);
}
void MCP3x6x::setConfig3(){
  settings.config3.conv_mode=conv_mode::CONTINUOUS;
  settings.config3.data_format=data_format::SGN_DATA;
  settings.config3.crc_format=0;
  settings.config3.en_crccom=0;
  settings.config3.en_offcal=1;
  settings.config3.en_gaincal=1;
  _status = write(settings.config3);
}
bool MCP3x6x::begin(uint16_t channelmask, float vref) {
  pinMode(_pinCS, OUTPUT);
  digitalWrite(_pinCS, HIGH);
  
  _spi->begin(_pinCLK,_pinMISO,_pinMOSI,_pinCS);
  _status = reset();

  setConfig0();
  setConfig1();
  setConfig2();
  setConfig3();
  return true;
}

to check if the counfigurations actually apply to MCP3X6X

void MCP3x6x:: readBuffer(){  
  uint8_t buffer[1];
  _transfer(buffer, MCP3x6x_CMD_IREAD | MCP3x6x_ADR_CONFIG0);
  Serial.printf("CONFIG0: %02X\n",buffer[0]);

  _transfer(buffer, MCP3x6x_CMD_IREAD | MCP3x6x_ADR_CONFIG1);
  Serial.printf("CONFIG1: %02X\n",buffer[0]);

  _transfer(buffer, MCP3x6x_CMD_IREAD | MCP3x6x_ADR_CONFIG2);
  Serial.printf("CONFIG2: %02X\n",buffer[0]);
  
  _transfer(buffer, MCP3x6x_CMD_IREAD | MCP3x6x_ADR_CONFIG3);
  Serial.printf("CONFIG3: %02X\n",buffer[0]);
}

Best,

Get stuck in mcp.analogRead loop

Hi,
Thank you for making this ADC library. It's one of the few library that support MCP3562.

But when I'm implement this code to my ESP32 S3 it seems to stuck in analogread infinite loop.
The differences are I make the MCP3562 instance aka mcp a global instance by adding extern MCP3562 mcp; in MCP3x6x.h and MCP3562 mcp=MCP3562(); in MCP3x6x.cpp .
Also dude to the layout error I swap the pin definition of MISO & MOSI in the class Constructor .

MCP3x6x::MCP3x6x(const uint16_t MCP3x6x_DEVICE_TYPE, const uint8_t pinCS, SPIClass *theSPI,
                 const uint8_t pinMOSI, const uint8_t pinMISO, const uint8_t pinCLK) {
  switch (MCP3x6x_DEVICE_TYPE) {
    case MCP3461_DEVICE_TYPE:
      _resolution_max = 16;
      _channels_max   = 2;
      break;
    case MCP3462_DEVICE_TYPE:
      _resolution_max = 16;
      _channels_max   = 4;
      break;
    case MCP3464_DEVICE_TYPE:
      _resolution_max = 16;
      _channels_max   = 8;
      break;
    case MCP3561_DEVICE_TYPE:
      _resolution_max = 24;
      _channels_max   = 2;
      break;
    case MCP3562_DEVICE_TYPE:
      _resolution_max = 24;
      _channels_max   = 4;
      break;
    case MCP3564_DEVICE_TYPE:
      _resolution_max = 24;
      _channels_max   = 8;
      break;
    default:
#warning "undefined MCP3x6x_DEVICE_TYPE"
      break;
  }

  //  settings.id = MCP3x6x_DEVICE_TYPE;
/* ========================================= */

  _spi        = theSPI;
  _pinMISO    = pinMOSI;//SWAP DUE TO LAYOUT ERROR
  _pinMOSI    = pinMISO;//SWAP DUE TO LAYOUT ERROR
  _pinCLK     = pinCLK;
  _pinCS      = pinCS;

  Serial.print("_pinMISO: ");
  Serial.println(_pinMISO);
  Serial.print("_pinMOSI: ");
  Serial.println(_pinMOSI);
  Serial.print("_pinCLK: ");
  Serial.println(_pinCLK);
  Serial.print("_pinCS: ");
  Serial.println(_pinCS);

/* ========================================= */

  _resolution = _resolution_max;
  _channel_mask |= 0xff << _channels_max;  // todo use this one
};

And this is my main task

#include <SPI.h>
#include "MCP3x6x.h"

void setup()
{  
  Serial.begin(115200);  
  while (!mcp.begin()) {
    Serial.println("failed to initialize MCP");
    delay(200);
  }
}
void loop()
{
  Serial.println("1");//stuck detect
  int32_t adcdata = mcp.analogRead(MCP_CH0);
  Serial.println("2");//stuck detect
  double voltage = adcdata * mcp.getReference() / mcp.getMaxValue();  
  Serial.print("voltage: ");
  Serial.println(voltage, 10);
  delay(1000);
}

And the Serial out put:
_pinMISO: 11
_pinMOSI: 13
_pinCLK: 12
_pinCS: 10
1
mux

Any advice is greatly appreciated.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.