MCP4151 SPI

Hello all!

Im working on a project that requires me to use a MCP4151 digital potentiometer to output a 0-5V to a mass flow controller. Right now Im trying to figure out how i need to write the SPI code for data transfer between my Arduino MEGA and the MCP4151. Being all new to this means that Im learning new and useful stuff all the time so please inform me of anything that may help!

Im having trouble figuring out how I send data via a SPI.transfer()..

as far as i can understand, I know that I need to send a 16 bit command, the first four bits being the wiper address, then the 2 command bits, followed by 10 bits of data(at least as far as i can see on the data sheet).

My confusion is where do I find the wiper address(the MCP4151 only has one wiper right?) and after the first 6 bits, why is there an extra 2 bits? What am I missing?

Post code (using code tags), links to the device data sheets, etc. as described in "How to use this forum".

Useful library: GitHub - jmalloc/arduino-mcp4xxx: Control a Microchip MCP4XXX digital potentiometer with an Arduino.

I know how to copy and paste.. its very easy. Thanks for the link.

I was just curious if anybody could explain further on the 16bit command, but I understand that not everybody knows how to explain these things. I will keep combing the internet, thanks.

I know how to copy and paste.

Excellent start, but it won't get you far in using this forum.

Im having trouble figuring out how I send data via a SPI.transfer().

Google "arduino spi" to find the Arduino SPI reference guide on line.

The http://ww1.microchip.com/downloads/en/DeviceDoc/22060a.pdf datasheet chapters 6 and 7 clearly describe how to send 16 and 8 bit commands to the device via SPI.

Here is some code that I use to send 8 bit and 16 bit commands to a SPI device:

int fReadSPIdata16bits( spi_device_handle_t &h, int _address )
{
  uint8_t address = _address;
    esp_err_t intError = 0;
    low=0; high=0;
    spi_transaction_t trans_desc;
    trans_desc = { };
    trans_desc.addr =  0;
    trans_desc.cmd = 0;
    trans_desc.flags = 0;
    trans_desc.length = (8 * 3); // total data bits
    trans_desc.tx_buffer = txData;
    trans_desc.rxlength = 8 * 2 ; // Number of bits NOT number of bytes
    trans_desc.rx_buffer = rxData;
    txData[0] = address | 0x80;
    intError = spi_device_transmit( h, &trans_desc);
    low = rxData[0]; high = rxData[1];
  return intError;
} // void fSendSPI( uint8_t count, uint8_t address, uint8_t DataToSend)
////
int fWriteSPIdata8bits( spi_device_handle_t &h, int _address, int _sendData )
{
  uint8_t address =  _address;
  uint8_t sendData = _sendData;
  esp_err_t intError;
  spi_transaction_t trans_desc;
  trans_desc = { };
  trans_desc.addr =  0;
  trans_desc.cmd = 0;
  trans_desc.flags = 0;
  trans_desc.length = (8 * 2); // total data bits
  trans_desc.tx_buffer = txData;
  trans_desc.rxlength = 0 ; // Number of bits NOT number of bytes
  trans_desc.rx_buffer = NULL;
  txData[0] = address  & 0x7F;
  txData[1] = sendData;
  intError = spi_device_transmit( h, &trans_desc);
  return intError;
} // void fWriteSPIdata8bits(  spi_device_handle_t &h, uint8_t address, uint8_t sendData )

Idahowalker:
The http://ww1.microchip.com/downloads/en/DeviceDoc/22060a.pdf datasheet chapters 6 and 7 clearly describe how to send 16 and 8 bit commands to the device via SPI.

Here is some code that I use to send 8 bit and 16 bit commands to a SPI device:

int fReadSPIdata16bits( spi_device_handle_t &h, int _address )

{
  uint8_t address = _address;
    esp_err_t intError = 0;
    low=0; high=0;
    spi_transaction_t trans_desc;
    trans_desc = { };
    trans_desc.addr =  0;
    trans_desc.cmd = 0;
    trans_desc.flags = 0;
    trans_desc.length = (8 * 3); // total data bits
    trans_desc.tx_buffer = txData;
    trans_desc.rxlength = 8 * 2 ; // Number of bits NOT number of bytes
    trans_desc.rx_buffer = rxData;
    txData[0] = address | 0x80;
    intError = spi_device_transmit( h, &trans_desc);
    low = rxData[0]; high = rxData[1];
  return intError;
} // void fSendSPI( uint8_t count, uint8_t address, uint8_t DataToSend)
////
int fWriteSPIdata8bits( spi_device_handle_t &h, int _address, int _sendData )
{
  uint8_t address =  _address;
  uint8_t sendData = _sendData;
  esp_err_t intError;
  spi_transaction_t trans_desc;
  trans_desc = { };
  trans_desc.addr =  0;
  trans_desc.cmd = 0;
  trans_desc.flags = 0;
  trans_desc.length = (8 * 2); // total data bits
  trans_desc.tx_buffer = txData;
  trans_desc.rxlength = 0 ; // Number of bits NOT number of bytes
  trans_desc.rx_buffer = NULL;
  txData[0] = address  & 0x7F;
  txData[1] = sendData;
  intError = spi_device_transmit( h, &trans_desc);
  return intError;
} // void fWriteSPIdata8bits(  spi_device_handle_t &h, uint8_t address, uint8_t sendData )

thanks for the example! I think I understand a little more now.

So as the Arduino sends the first 8 command bits, the MCP4151 sends 6 HIGH bits, then a 7th bit HIGH or LOW depending on if the 4 address bits and 2 command bits are valid.. right?

from the pdf
"On the 7th bit, the SDO pin will output the
CMDERR bit state (see Section 7.3 “Error Condition”). The 8th bit state depends on the the command
selected. "

does that mean the 8th bit sent from SDO will be a 0 for a write command or 1 for a write command?

AsaBrown:
from the pdf
"On the 7th bit, the SDO pin will output the
CMDERR bit state (see Section 7.3 “Error Condition”). The 8th bit state depends on the the command
selected. "

does that mean the 8th bit sent from SDO will be a 0 for a write command or 1 for a write command?

See table 7-1 and figure 7-1 for the command bit placement.

Idahowalker:
See table 7-1 and figure 7-1 for the command bit placement.

“The Command Byte contains two data
bits, see Figure 7-1.”

so i look at figure 7-1… it saids C1 and C0 should read 00 for a write command, right? understood.

back to the figure 7-1 diagram… i need two more data bits to complete the command byte, D9 and D8. I understand that D9 will be the validation bit for the first 6 bits recieved… so now the last bit of the command byte should be a 0? and then I send my data byte, correct?

Sorry if this isnt not making sense…
If it didnt seem obvious enough, this is all new for me so explanations are more helpful than the datasheet links that Ive already looked at and am currently trying to understand. Ive looked for any and all examples of arduino/MCP4151 SPI communication all week and I just cant seem to find a single understandable or explained example of the code… I am unable to move forward on my project until I figure out how to correctly write the code to transfer a command byte and a data byte to the MCP4151.

I understand that nobody wants to explain every detail of SPI because it takes time, effort, and brains. If anybody has any more time than it takes to tell me “See table 7-1 and figure 7-1 for the command bit placement.”, that would be very much appreciated and very helpful. If you have ANY questions about my project, please ask them! I have plenty of time and am very willing to learn.

links to an example of a similar arduino/MCP4151 set up would be AMAZING if anybody could post one that I may have missed. Also if anybody knows of a great SPI tutorial video, that would ALSO amazing!

Thanks

Entering the words "arduino mcp41010 code example" into your favorite search engine should net a few results of examples.

I did a project with a bunch of these a while back. Check it out here.

I just used shiftOut() like this.

        digitalWrite(slaveSelectPin, LOW);// enable the communication with the chip
        shiftOut(dataPin, clockPin, MSBFIRST, 0);// the first byte is command stuff
        shiftOut(dataPin, clockPin, MSBFIRST, value);// then your value
        digitalWrite(slaveSelectPin2, HIGH);// disable communication with the chip

If you don't need to disable, just tie the SS pin to ground.

I think shiftOut() is basically software SPI so you can just define your own pins.

I have plenty of time and am very willing to learn.

Please explain why it is too much trouble to look at the MCP4151 library, linked in reply #1, that does all the hard work for you.