Message Boards Message Boards

Use SPI protocol with Arduino & ADC?

Posted 7 years ago

Hi, I'm interested in how I use SPI protocol. In Mathematics documentation has information that might somehow use the SPI library in Arduino. I have an Arduino Uno, and I want to connect ADC such as MAX 6675, with SPI protocol. MAX 6675 is the ADC for temperature measurement using SPI protocol for sharing information, and there are several skeches to gather information from it.

I can not imagine how.

I am interested in whether someone has sample code to work with SPI protocol.

POSTED BY: Bohdan Romanchuk
5 Replies
Posted 3 years ago

Does this documentation will be working for spi standard with PIC32 mcu?

POSTED BY: Jane Mole

Hi Ian.

I have purchased for my experiments board EVAL-AD7177-2. It has a AD7177-2 and voltage reference ADR445 and all that is needed for the work.

I'm a beginner in digital electronics and not sure what it was doing well. I read the datasheet for AD7177-2 and to Arduino and it looks as if I combine everything as shown in the picture.

Datasheet on the Arduino, says that you need to use a PIN 10-13 they are for SPI. I use the same pin?

What do I do next after skech will fill in Arduino?

#include <SPI.h>
#define ADCMODE 0x01
#define CONTINUOUS_READ 0x8000
#define DATA 0x04
#define READ (0 << 6)
#define WRITE (1 << 6)
void setup(){
    SPI.begin();
    //setup the device for continuous reading
    // take the SS pin low to select the chip:
    digitalWrite(10, LOW);
    //send a write command to set the ADC into continuous read mode
    //need to write this mode to the ADCMODE register
    SPI.transfer(WRITE | ADCMODE);
    SPI.transfer(CONTINUOUS_READ);
    // take the SS pin high to de-select the chip:
    digitalWrite(10, HIGH);
}
void loop(){
    //select the device for reading
    digitalWrite(10, LOW);
    //transfer the 4 bytes
    uint8_t buffer[4] = {0};
    //read from the DATA register
    SPI.transfer(READ | DATA);
    //get the data into the buffer
    SPI.transfer(buffer,4);
    //now need to combine the bytes together - NOTE this is for MSB
    unsigned long int value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
    digitalWrite(10, HIGH);
    //need to determine what to set RATE to to get sufficient readings - see page 18 of datasheet
    delay(5);
}
Attachments:
POSTED BY: Bohdan Romanchuk

Hi Ian.

I am extremely grateful to you for a detailed explanation of working with ADC, MAX 6675.

I used your code to obtain information on MAX 6675, everything works as it should.

I also have another ADC with whom I would like to receive data. This AD7177-2. Unfortunately I could not find the library for it probably need to get "raw data" through the SPI protocol.

I would appreciate to you for the example code to work with the device without a library for it.

result

POSTED BY: Bohdan Romanchuk

I'm glad that you got the example to work. I'm afraid I don't have the exact device you mentioned to test with, but I can give you an overview of the general direction you would go about implementing the code for communicating with this device.

Firstly, as the datasheet explains starting on page 49 of the datasheet, you need to initiate the conversion on the device by sending a command to the device, then wait an appropriate amount of time and then issue a read command for the DATA register. So for example, in Arduino you would do something like this (note this code isn't being provided as 100%, you will likely need to add some more details, but hopefully you get the point for how to do the SPI interfacing):

#define ADCMODE 0x01
#define CONTINUOUS_READ 0x8000
#define DATA 0x04
#define READ (0 << 6)
#define WRITE (1 << 6)
void setup(){
    SPI.begin();
    //setup the device for continuous reading
    // take the SS pin low to select the chip:
    digitalWrite(slaveSelectPin, LOW);
    //send a write command to set the ADC into continuous read mode
    //need to write this mode to the ADCMODE register
    SPI.transfer(WRITE | ADCMODE);
    SPI.transfer(CONTINUOUS_READ);
    // take the SS pin high to de-select the chip:
    digitalWrite(slaveSelectPin, HIGH);
}
void loop(){
    //select the device for reading
    digitalWrite(slaveSelectPin, LOW);
    //transfer the 4 bytes
    uint8_t buffer[4] = {0};
    //read from the DATA register
    SPI.transfer(READ | DATA);
    //get the data into the buffer
    SPI.transfer(buffer,4);
    //now need to combine the bytes together - NOTE this is for MSB
    unsigned long int value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
    digitalWrite(slaveSelectPin, HIGH);
    //need to determine what to set RATE to to get sufficient readings - see page 18 of datasheet
    delay(RATE);
}

The datasheet I am referencing can be found here : http://www.analog.com/media/en/technical-documentation/data-sheets/AD7177-2.pdf

Once you get this code working in the Arduino IDE directly, then you can modify the code so it works with the Arduino driver in Mathematica.

POSTED BY: Ian Johnson

Hi Bohdan,

You can in fact use the Mathematica Arduino driver for this : http://reference.wolfram.com/language/ref/device/Arduino.html

You will need a way to connect to the device and read from it. For your specific MAX 6675 device, there is an Adafruit library you can use to interface with the device. The basic gist of this is that you download the library somewhere on your computer, then you can deploy a customized sketch to the Arduino that then acts like a wrapper to the Adafruit library. I use this library as an example because it is a simple one, but you can certainly forgo this library and directly do the SPI interaction using the Arduino SPI library, but that code is more complicated. I am basically copying the example code that Adafruit provides and turning it into Mathematica code.

First, we declare the initialization or global code that we need access to:

libInit = "
int thermoDO = 4;
int thermoCS = 5;
int thermoCLK = 6;
int vccPin = 3;
int gndPin = 2;
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
";

Next we declare the "BootFunction", which is akin to the setup function normally found in Arduino sketches to setup our pins for us:

bootFunc = "void bootFunc(){
pinMode(vccPin, OUTPUT);
digitalWrite(vccPin, HIGH);
pinMode(gndPin, OUTPUT);
digitalWrite(gndPin, LOW);
delay(500);}
";

Finally, we make a simple wrapper function to return back the temperature in celsius as a Real:

readFunc = "
double readTempCel(){
    return thermocouple.readCelsius();
}";

Putting this all together in a call to DeviceConfigure we have :

DeviceConfigure["Arduino", "Upload"->{
"Libraries" -> {"SPI", "/path/to/MAX6675_library"}, 
Initialization -> libInit,
"BootFunction" -> <|"Code" ->bootFunc |>, 
"Functions" -> <|"readCelsius"-><|"Code"->readFunc ,"ReturnType"->Real|>|>
}]

You can then execute the "readCelsius" function with DeviceExecute as follows:

DeviceExecute["Arduino","readCelsius"]

Hope this helps.

Thanks,

Ian

POSTED BY: Ian Johnson
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract