I am trying to squeeze more precision out of the ADC on my Seeeduino LoRaWAN board which is based on the Arduino Zero but I'm having trouble with the parameters. I have downloaded ATMEL's AT07627: ASF Manual (SAM D21) and have looked at examples of how to address the ADC but seem to be missing something in the process and am having trouble understanding which parameters to set.
For background, I want to read a sensor every 15 minutes, so speed of the readings isn't an issue. For development, I'm using a capacitance soil moisture sensor, but my main issue is in reading a dendrometer, which needs more precision. For the dendrometer, accuracy isn't as much of an issue as precision, as long as the accuracy doesn't drift during the day.
Here is my test code. I get a compiler error 'struct Adc' has no member named 'adc_resolution' on the line addressing the ADC (and have the same error with attempts to set other parameters). I get the same error if I try to set the board to a Zero instead of Seeeduino LoRaWAN.
/*Code to read a Teros 10 capacitance soil moisture sensor, output reading to Serial
* All LoRaWAN code removed for debugging
* Written for Seeeduino so the serial port to the computer is SerialUSB
* The current requirement of the sensor is 12 mA at 3VDC so can power from digital pin
*/
// millis timer global------------------------------------------------------------------
#include <millisDelay.h> //handy timing library
//https://www.forward.com.au/pfod/ArduinoProgramming/TimingDelaysInArduino.html
millisDelay SensorDelay; // the delay object
// battery of Seeeduino LoRaWAN
const short pin_battery_status = A5;
const short pin_battery_voltage = A4; //note that this will read the USB voltage if plugged into computer
boolean arStatus; //not very useful
int arVoltage;
float bvoltage;
const int Apin = A3; //analog pin connected to sensor +
const int ReadingTime = 20; //time to read from Apin in ms 10 is minimum
int SensorBits = 0; //variable to store sensor reading from 12 bit A/D converter
double SensorMV = 0; //store sensor reading converted to mV
// Setup readings global-----------------------------------------------------------
const unsigned long DelayTime = 1000*60; // have const here so it is easy to find and change (in mS)
// end global----------------------------------------------------------------------
void setup() {
// put your setup code here, to run once:
pinMode(Apin, INPUT);
pinMode(LED_BUILTIN, OUTPUT); //During testing have the LED on when taking a reading
SerialUSB.begin(19200);
while (!SerialUSB) {
; // wait for serial port to connect
}
//analogReadResolution(12); //will do this through direct addressing
//analogReference(AR_INTERNAL); //2.23V SAMD Boards e.g. Zero/Seeeduino only has error
//Read sensor once as throwaway value but print it out
SerialUSB.println("Read in setup");
digitalWrite(LED_BUILTIN, HIGH);
delay(10);
SensorBits = analogRead(Apin);
digitalWrite(LED_BUILTIN, LOW);
SerialUSB.print("SensorBits = ");
SerialUSB.println(SensorBits);
SensorMV = SensorBits/4096.0*3.3; //Not sure if this should be 4095. Assumes 3.3 mV analog reference
SerialUSB.print("SensorMV = ");
SerialUSB.println(SensorMV);
//Read sensor again after setting ADC for testing as throwaway value but print it out
SerialUSB.println("Set ADC using direct addressing");
configure_adc();
digitalWrite(LED_BUILTIN, HIGH);
delay(10);
SensorBits = analogRead(Apin);
digitalWrite(LED_BUILTIN, LOW);
SerialUSB.print("SensorBits = ");
SerialUSB.println(SensorBits);
SensorMV = SensorBits/4096.0*3.3; //Not sure if this should be 4095. Assumes 3.3 mV analog reference
SerialUSB.print("SensorMV = ");
SerialUSB.println(SensorMV);
SensorDelay.start(DelayTime); //Start millis delay timer for sensor reading intervals
} //end setup
void loop() {
// put your main code here, to run repeatedly:
if (SensorDelay.justFinished()) { // repeat delay and take reading
SensorDelay.repeat(); // repeat
SerialUSB.print("millis() = ");
SerialUSB.println(millis());
ReadTeros10();
// SendPayload();
}
} //end loop
void configure_adc(void){
/* This routine uses commands that send instructions directly to the SAM-D21 chip
* so it is not portable to other systems
* they are taken from the AT07627: ASF Manual (SAM D21)
* not sure which commands are needed so trial and error
*/
ADC->adc_resolution = ADC_RESOLUTION_16BIT;
} //end configure_adc
void ReadTeros10() {
digitalWrite(LED_BUILTIN, HIGH);
delay(10);
SensorBits = analogRead(Apin);
digitalWrite(LED_BUILTIN, LOW);
SerialUSB.print("SensorBits = ");
SerialUSB.println(SensorBits);
SensorMV = SensorBits/4096.0*3.3; //Not sure if this should be 4095. Assumes 3.3 mV analog reference
SerialUSB.print("SensorMV = ");
SerialUSB.println(SensorMV);
} //end ReadTeros10