Skip to content

Instantly share code, notes, and snippets.

@aleksas
Last active October 2, 2022 11:53
Show Gist options
  • Save aleksas/c1be2763b62f2bba0ab56cb5cf55953a to your computer and use it in GitHub Desktop.
Save aleksas/c1be2763b62f2bba0ab56cb5cf55953a to your computer and use it in GitHub Desktop.
ADS8330 Manual Trigger Single Channel read (Arduino Due)
#include <SPI.h>
#define ADC_CS_PIN 2
#define ADC_CONVERSION_PIN 3
#define ADC_EOC_PIN 4
enum Command : uint16_t {
SEL_AN_IN_CHANNEL_0 = 0b0000 << 12,
SEL_AN_IN_CHANNEL_1 = 0b0001 << 12,
WAKE_UP = 0b1011 << 12,
READ_CFG_REGISTER = 0b1100 << 12,
READ_DATA = 0b1101 << 12,
WRITE_CFG_REGISTER = 0b1110 << 12,
RESET_CFG_REGISTER = 0b1111 << 12,
};
enum CfgReg : uint16_t {
SYSTEM_RESET_,
AUTO_SELECT = 0b1 << 11,
INTERNAL_CCLK = 0b1 << 10,
MANUAL_TRIGGER = 0b1 << 9,
EOC_ACTIVE_LOW = 0b1 << 7,
PIN_EOC = 0b1 << 6,
EOC_OUT = 0b1 << 5,
DISABLE_POWER_DOWN = 0b111 << 2,
ENABLE_TAG = 0b1 << 1,
NORMAL_OPERATION = 0b1 << 0,
};
uint16_t write_(uint16_t txBuffer) {
uint16_t data_;
digitalWrite(ADC_CS_PIN, LOW);
data_ = SPI.transfer16(txBuffer);
digitalWrite(ADC_CS_PIN, HIGH);
return data_;
}
uint16_t read_(int16_t channel)
{
// Select channel
write_(channel);
// Start conversion
digitalWrite(ADC_CONVERSION_PIN, LOW);
digitalWrite(ADC_CONVERSION_PIN, HIGH);
// Wait until EOC
while (digitalRead(ADC_EOC_PIN) == LOW);
// Read result
return write_(READ_DATA);
}
void setup()
{
Serial.begin(115200);
while (!Serial){
delay(1);
}
SPI.setDataMode(SPI_MODE0);
SPI.begin(0);
pinMode(ADC_CS_PIN, OUTPUT);
pinMode(ADC_CONVERSION_PIN, OUTPUT);
pinMode(ADC_EOC_PIN, INPUT);
digitalWrite(ADC_CS_PIN, HIGH);
digitalWrite(ADC_CONVERSION_PIN, HIGH);
uint16_t command = 0, result;
result = write_(WRITE_CFG_REGISTER | SYSTEM_RESET_);
result = write_(WRITE_CFG_REGISTER
| INTERNAL_CCLK
| MANUAL_TRIGGER
| EOC_ACTIVE_LOW
| PIN_EOC
| EOC_OUT
| DISABLE_POWER_DOWN
| NORMAL_OPERATION);
result = write_(READ_CFG_REGISTER);
result = write_(SEL_AN_IN_CHANNEL_0);
}
void loop()
{
// READ CH0
uint16_t adc_ch0_value = read_(SEL_AN_IN_CHANNEL_0);
// ------------------------
Serial.println(adc_ch0_value);
delay(10);
}
#include <SPI.h>
#define ADC_CS_PIN 2
#define ADC_CONVERSION_PIN 3
#define ADC_EOC_PIN 4
/* Command Definitions */
#define ADS8330_CMR_DEFAULT 0b1111000000000000ul /* reset to device default */
#define ADS8330_CMR_WCFR 0b1110000000000000ul /* write device commands */
#define ADS8330_CMR_RCFR 0b1100000000000000ul /* read device commands */
#define ADS8330_CMR_WAKE 0b1011000000000000ul /* wake device from nap */
#define ADS8330_CMR_RDATA 0b1101000000000000ul /* read ADC data */
#define ADS8330_CMR_CH0 0b0000000000000000ul /* select ADC channel 0 */
#define ADS8330_CMR_CH1 0b0001000000000000ul /* select ADC channel 1 */
#define ADS8330_CFR_D11 0b0000100000000000ul /* auto channel */
#define ADS8330_CFR_D10 0b0000010000000000ul /* internal conversion clock */
#define ADS8330_CFR_D9 0b0000001000000000ul /* manual conversion */
#define ADS8330_CFR_D6_7 0b0000000011000000ul /* EOC low */
#define ADS8330_CFR_D5 0b0000000000100000ul /* EOC output */
#define ADS8330_CFR_D2_3_4_MANU 0b0000000000010100ul /* power save */
#define ADS8330_CFR_D2_3_4_AUTO 0b0000000000011100ul /* power save */
#define ADS8330_CFR_D1 0b0000000000000010ul /* tag bit */
#define ADS8330_CFR_D0 0b0000000000000001ul /* device run normal/reset */
#define ADS8330_CMR_CONF_MANU ADS8330_CMR_WCFR | ADS8330_CFR_D10 | ADS8330_CFR_D9
#define ADS8330_CMR_CONF_AUTO ADS8330_CMR_WCFR | ADS8330_CFR_D10
#define ADS8330_CFR_CONF_MANU ADS8330_CFR_D6_7 | ADS8330_CFR_D5 | ADS8330_CFR_D2_3_4_MANU | ADS8330_CFR_D0
#define ADS8330_CFR_CONF_AUTO ADS8330_CFR_D6_7 | ADS8330_CFR_D5 | ADS8330_CFR_D2_3_4_AUTO | ADS8330_CFR_D0
uint16_t adc_ch0_value;
float adc_ch0_volts;
const float adc_referecnce_voltage = 3.3f;
const float adc_factor = adc_referecnce_voltage / UINT16_MAX;
void setup()
{
Serial.begin(115200);
while (!Serial){
delay(1);
}
SPI.setDataMode(SPI_MODE0);
SPI.begin(ADC_CS_PIN);
pinMode(ADC_CS_PIN, OUTPUT);
pinMode(ADC_CONVERSION_PIN, OUTPUT);
pinMode(ADC_EOC_PIN, INPUT);
digitalWrite(ADC_CS_PIN, HIGH);
digitalWrite(ADC_CONVERSION_PIN, HIGH);
uint16_t command = 0;
command = (ADS8330_CMR_WCFR | ADS8330_CMR_DEFAULT);
digitalWrite(ADC_CS_PIN, LOW);
SPI.transfer16(command);
digitalWrite(ADC_CS_PIN, HIGH);
command = (ADS8330_CMR_CONF_MANU | ADS8330_CFR_CONF_MANU);
digitalWrite(ADC_CS_PIN, LOW);
SPI.transfer16(command);
digitalWrite(ADC_CS_PIN, HIGH);
command = ADS8330_CMR_RCFR;
digitalWrite(ADC_CS_PIN, LOW);
SPI.transfer16(command);
digitalWrite(ADC_CS_PIN, HIGH);
command = ADS8330_CMR_CH0;
digitalWrite(ADC_CS_PIN, LOW);
SPI.transfer16(command);
digitalWrite(ADC_CS_PIN, HIGH);
}
void loop()
{
// READ CH0
digitalWrite(ADC_CS_PIN, LOW);
SPI.transfer16(ADS8330_CMR_CH0);
digitalWrite(ADC_CS_PIN, HIGH);
digitalWrite(ADC_CONVERSION_PIN, LOW);
digitalWrite(ADC_CONVERSION_PIN, HIGH);
while (digitalRead(ADC_EOC_PIN) == LOW);
digitalWrite(ADC_CS_PIN, LOW);
adc_ch0_value = SPI.transfer16(ADS8330_CMR_RDATA);
digitalWrite(ADC_CS_PIN, HIGH);
adc_ch0_volts = adc_ch0_value * adc_factor;
// ------------------------
Serial.println(adc_ch0_volts, 5);
Serial.println();
delay(10);
}
@Hennnnnnryyyy
Copy link

Hennnnnnryyyy commented Mar 8, 2022

2 years late but in case someone else has the same problem...

You need to first configure the ADC according the page 30 and 31 of the datasheet by sending 1110 followed by your config.
By default, the config is 111111111111, with Auto channel select enabled, where it will cycle between IN0 and IN1 readings.
If you want to specify the channel, you need to change the config to 011111111111.
I also find it easier to just have it auto trigger, or use config 010111111111. Remember to tie CONVST pin high if you are doing this.

The when you want to read it, you just sent it 0000 or 0001 (the following 12 bits don't matter) depending on the channel you want and it will give you that channel's reading in the next cycle.

Here is my code for ESP32-S2. You will need to change the SS pin and clk frequency based on what board you are using.
Also not totally related, but remember to wire up the voltage reference input to something. I thought it had an internal reference but turns out it doesn't.

#include <SPI.h>

#define SS 20
uint16_t val;

void setup() {
  pinMode(CONV, OUTPUT);
  pinMode(SS, OUTPUT);
  digitalWrite(CONV, HIGH);
  digitalWrite(SS, HIGH);

  SPI.begin();
  Serial.begin(115200);
  delay(100);

  SPI.beginTransaction (SPISettings (50000000, MSBFIRST, SPI_MODE1));
  digitalWrite(SS, LOW);
  SPI.transfer16(0b1110010111111111);  // configure ADC, manual channel sel, auto trigger
  digitalWrite(SS, HIGH);
}

void loop() {
  digitalWrite(SS, LOW);
  val = SPI.transfer16(0b0000000000000000);  // change to 0b0001000000000000 to read ch1
  digitalWrite(SS, HIGH);
  Serial.println(val);
}

@aleksas
Copy link
Author

aleksas commented Oct 2, 2022

Thanks @Hennnnnnryyyy project using ADS8830 is moving slowly so any help is welcome :) event 2 years later. Will try your suggested changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment