I'm planning to use a ADS1220 4-channel 24 bit adc but I really have no experience with SPI. I have found this library but I can't really understand the code that much and also this is measuring the differential voltage. I want to use this for my accelerometer (x, y and z data) but I can't seem to find how to do read from 3 channels, and I can't understand the code in the library :( I've also found a video for this adc in youtube but he didn't used it for multiple channels. I'm sorry for asking this, I'm just pressured since the deadline is really soon.
EDITED
sketch
#include "Protocentral_ADS1220.h"
#include <SPI.h>
#define PGA 1 // Programmable Gain = 1
#define VREF 3.3
#define VFSR VREF/PGA
#define FSR (((long int)1<<23)-1)
volatile byte MSB;
volatile byte data;
volatile byte LSB;
//volatile char SPI_RX_Buff[3];
volatile byte *SPI_RX_Buff_Ptr;
long int bit32, data1, data2, data3;
long int bit24;
Protocentral_ADS1220 ADS1220;
void setup() {
pinMode(ADS1220_CS_PIN, OUTPUT);
pinMode(ADS1220_DRDY_PIN, INPUT);
ADS1220.begin();
//ADS1220.Single_shot_mode_ON();
}
void loop() {
byte *config_reg;
data1 = aRead(0x81);
data2 = aRead(0x91);
data3 = aRead(0xA1);
Serial.print(data1);
Serial.print(" ");
Serial.print(data2);
Serial.print(" ");
Serial.println(data3);
delay(500);
}
long int aRead(uint8_t config_byte) {
ADS1220.writeRegister(CONFIG_REG0_ADDRESS , config_byte);
uint8_t r = ADS1220.readRegister(CONFIG_REG0_ADDRESS);
//Serial.println(r,HEX);
ADS1220.SPI_Start();
while (ADS1220.NewDataAvailable == false) {
SPI_RX_Buff_Ptr = ADS1220.Read_Data();
}
if(ADS1220.NewDataAvailable = true) {
ADS1220.NewDataAvailable = false;
MSB = SPI_RX_Buff_Ptr[0];
data = SPI_RX_Buff_Ptr[1];
LSB = SPI_RX_Buff_Ptr[2];
bit24 = MSB;
bit24 = (bit24 << 8) | data;
bit24 = (bit24 << 8) | LSB;
bit24= ( bit24 << 8 );
bit32 = ( bit24 >> 8 );
}
return bit32;
}
I tried to use the above sketch and I successfully read from 3 different channels but I noticed that the readings vary too much, compared to the example code. In the example code when I turn my potentiometer full CW, it outputs 8388607 which is correct right? since it is signed int.
But when running this sketch, the image below shows the output when the potentiometer is fully CW. Also turning the potentiometer fully CCW leads to negative values (shown in the 2nd picture) but in the example code, it gives 100-300 decimal values. Also these are the configuration registers I sent in registers 1-3 (I edited it in the part of the library) and for register 0, it is on the sketch.
Config_Reg1 = 0x00;
Config_Reg2 = 0x40;
Config_Reg3 = 0x00;
serial monitor output enter image description here
using accelerometer
format is (x,y,z) enter image description here
-
What kind of deadline? School project or assignment?Mikael Patel– Mikael Patel12/10/2016 20:05:53Commented Dec 10, 2016 at 20:05
-
Writing ADC driver code from scratch is NOT easy. What is wrong with the ADC built into most Arduino's processors? The ADC driver for most Arduino's is already part of the Arduino SDK.st2000– st200012/10/2016 20:15:33Commented Dec 10, 2016 at 20:15
-
What's the model number of the accelerometer? Many of them digitize their results already.James Waldby - jwpat7– James Waldby - jwpat712/10/2016 21:47:57Commented Dec 10, 2016 at 21:47
-
@MikaelPatel it's for my thesis in collegeRalph– Ralph12/11/2016 12:00:18Commented Dec 11, 2016 at 12:00
-
@jwpat7 adxl335, this has analog outputs, my adviser wants to have a 24 bit output accelerometer, I know there are lots of accelerometer that has 16 bit output which is already enough for precise measurements but I wanna give a try implementing an external adc before suggesting to my adviser to use accelerometers with digitized outputsRalph– Ralph12/11/2016 12:03:24Commented Dec 11, 2016 at 12:03
1 Answer 1
To get an understanding of how to read from the various ADS1220 channels, first review Figure 38, Analog Input Multiplexer, in the Datasheet as obtained from a link on TI.com's ADS1220 technicaldocuments webpage.
Figure 38 As can be seen, you'll need to close a switch from an AINx input line to the AINp bus, and also close the switch between AINn and AVSS. The IDACx switches and the BCS switches should remain open.
To operate those switches, first look at §8.6.1, Configuration Registers, in the Register Map section of the Datasheet. You'll see that MUX bits are in register 0, BCS is in register 1, IDAC is in register 2, and IxMUX are in register 3. To see what to put into those fields, look at Tables 16, 17, 19, and 20. For the MUX field, you will want a binary value like 1000, 1001, 1010, or 1011 to select one of AIN0-AIN3 as the AINp input and AVSS as the AINn input. BCS, IDAC, I1MUX, and I2MUX all should be zero.
For example, to read channels 0, 1, 2 in sequence, set MUX to 1000, set up other register fields, and trigger a conversion. After reading the result, change MUX to 1001, trigger a conversion, read result, change MUX to 1010, trigger a conversion, read result, etc.
Edit 1: In slightly more detail, one could do as follows.
• Use a WREG command [as in §8.5.3.6; or some library equivalent] to send three bytes to set up Configuration Registers 1, 2, 3.
• For i=0, 1, and 2 in turn, construct a configuration byte, send that byte to Configuration Register 0, start a conversion, await result, read result; as follows:Set the MUX field of a byte to i
Set PGA as desired (ie, to 1, 2, or 4, via codes 000, 001, or 010)
Set the PGA_BYPASS bit (as required when AINn = AVSS)
Use a WREG to send the constructed byte to Configuration Register 0
Use a START/SYNC command to start a conversion (see §8.5.3.2)
Wait for DRDY to go low
Use an RDATA command to read ith ADC result (see §8.5.3.4)
Edit 2: In Protocentral's ADS1220.ino sketch, one finds the code sequence
MSB = SPI_RX_Buff_Ptr[0];
data = SPI_RX_Buff_Ptr[1];
LSB = SPI_RX_Buff_Ptr[2];
bit24 = MSB;
bit24 = (bit24 << 8) | data;
bit24 = (bit24 << 8) | LSB; // Converting 3 bytes to a 24 bit int
bit24= ( bit24 << 8 );
bit32 = ( bit24 >> 8 ); // Converting 24 bit two's complement to 32 bit two's complement
More competently and concisely, and with SPI_RX_Buff_Ptr
renamed to SPI_RX_Buff
, this could be written as:
bit32 = (((long)(SPI_RX_Buff[0]<<8 | SPI_RX_Buff[1])<<8 | SPI_RX_Buff[2])<<8)>>8;
which acts as follows: Assemble three bytes from SPI_RX_Buff
into a 24-bit twos-complement-signed number. Shift that number left 8 bits so that its sign bit now sits in the sign bit position of a 32-bit signed integer. Shift that result 8 bits right with sign extension so that the final result is a signed 32-bit integer with possible values from -223 up to (223-1).
Sign extension occurs – usually – because in many implementations of C, the >>
operator does an arithmetic shift instead of a logical shift when its operand is signed.
-
I just read this and it made me understand the datasheet, thank you so much!! I'll just update you if I was able to make it workRalph– Ralph12/13/2016 18:17:02Commented Dec 13, 2016 at 18:17
-
hello I'm wondering what would I send first when I want to read the data. I found this youtube video and he started with setting CS to low (which I think I should also do in my case) then sends a byte which is equal primary byte with a start bit and single/diff mode
and
to a register mask that isolates 3 LSB. I'm sorry if I'm noob but it would mean a lot to me if you helpRalph– Ralph12/13/2016 18:42:32Commented Dec 13, 2016 at 18:42 -
I'm guessing I should send all those 4 configuration registers? I just don't know the flow I'm sorryRalph– Ralph12/13/2016 19:06:40Commented Dec 13, 2016 at 19:06
-
oh I get it why he
and
it with a mask, just to be sure that the config register will not be changed during the process, now my main concern is how to send these configuration registersRalph– Ralph12/13/2016 19:09:18Commented Dec 13, 2016 at 19:09 -
Edit 1 reflects my understanding (from datasheet) of the process - I haven't tried it out, and haven't looked at what library calls might applyJames Waldby - jwpat7– James Waldby - jwpat712/13/2016 19:32:43Commented Dec 13, 2016 at 19:32