Fast ADC readings

Hi everyone,

is there a possibility to reconfigure the ADC for fast Measurements? I don’t need full precision (8bits are OK) and so I thought there should be space for optimizations.

I’ve an hardware-interrupt which is fired every 50us and a normal analogRead() (with ADC_SampleTime_3Cycles) takes 10 µs. So I’m losing 20% computing power just waiting for a ADC value.

I tried some changes in the ADC_HAL.c. After commenting out the pin-checks and averaging in the HAL_ADC_Read() function and decreasing the DMA buffer to 2 (in HAL_ADC_DMA_Init() ) I was able to get the ADC data within 2.5 µs. But one ADC cycle should last approx. 100 ns.

Most time-consuming are the HAL commands to activate and deactivate the DMA, enable and disabling the ADC and so on. But I have no idea how to configure the ADC to a single Conversion.

I tried also using the solution on this website, but i get som cloud compile-errors:
http://www.micromouseonline.com/2009/05/26/simple-adc-use-on-the-stm32/

Thanks a lot!

Have you had a look at this?

Hi,
thanks for the fast response.
I saw this post but its again with DMA.
The Problem is, that i need also other ADC channels so i have to reconfigure the ADC_RegularChannelConfig() twice wich takes 1.5 µs with aditional reconfiguring the DMA

How many? Which? At the same or different sampling rate?

In that repo there is also another example that will sample six channels near simultaneously (two at a time fully simultaneously).

If you could elaborate on your exact use case it might be easier to provide targeted advice.

Sorry for the unclear description of the problem.

I’m reading an 1Khz Sine-Wave from an IRIG- Time source. In the interrupt I’m checking last 4 samples to interpret the Data. I need to extract a exact 1PPS from this code. From Time to time I need to read a different analog voltage and results from two R2R networks (4Bits). I’m using the Pins A0, A1, A2 and A4.

The data processing needs to be done in an Interrupt to not miss the point of a new second. So this was my Idea of the interrupt:

Void interrupt (void){

GetLastADCval();
startNewADCcycle();
dataProcessing();

}

I think it’s not possible to use the code from rickkas7 to interpret this data in real-time.

Just to give you some insight how I deal with FFT on Photon. This is sampling just one analog channel but you can read more of them in interrupt routine. In main loop I parse the data with FFT and then controll some LED’s via I2C and in ThreadFunction I send copy of parsed data (by FFT.Compute() and FFT.ComplexToMagnitude() ) to Serial1 for future parsing on PC with spectrum analyser. In this scenario I don’t block main loop during Serial1.println().
analog channel is set to get sample every 100ns. Regarding to Photon reference you can change this parameter via setADCSampleTime(duration). and here is the link to Adafruit Python 2.7 spectrum analyser which I use.

here is the code sketch:

// This #include statement was automatically added by the Particle IDE.
#include <SparkIntervalTimer.h>
#include "Particle.h"


STARTUP(startupFunction());

SYSTEM_THREAD(ENABLED);

extern void startupFunction();

void samplingCbISR();

Thread *thread;

os_mutex_t mutex;

void startupFunction(){
  os_mutex_create(&mutex);
}



IntervalTimer samplingTimer;

#define CHANNEL A0                    // Input ADC pin for audio data.
#define POWER_LED_PIN D7
int SAMPLE_RATE_HZ = 44100;           // Sample rate of the audio in hertz.

                                      
const uint16_t SIZE = 128;            
double vReal[SIZE];
int sampleCounter = 0;
const int MAX_CHARS = 65;
char commandBuffer[MAX_CHARS];
const uint16_t len = sizeof(vReal)/sizeof(*vReal);
double vR_copy[len];


////////////////////////////////////////////////////////////////////////////////
// MAIN SKETCH FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

void setup() {
  
  SYSTEM_MODE(AUTOMATIC);
  setADCSampleTime(ADC_SampleTime_3Cycles);
  Serial1.begin(115200);
  os_mutex_lock(mutex);
  thread = new Thread("threadFunction", threadFunction);

//Turn on the power indicator LED.
  pinMode(POWER_LED_PIN, OUTPUT); 
     
//Begin sampling audio
  samplingBegin();
}

void loop() {

if (samplingIsDone()) {     
     // you can parse the raw data here and do whatever u want with it.
     // Then in threadFunction you can send the raw sample for future parsing on PC or whatever.
     // I'm using  loop to parse the raw saple with arduinoFFT lib. and controll power LEDS (RGB) via I2C
     // and the threadFunction is used to send data via Serial1 after parsed by FFT.Compute() and FFT.ComplexToMagnitude() functions
     // to analyse the data with spectrum analyser on PC.
     // in this case I don't block the main loop during Serial1.println(); and all works just perfect.
     memcpy(vR_copy, vReal, sizeof(double) * len);
     os_mutex_unlock(mutex);      
     samplingBegin();  	
	}
 }



////////////////////////////////////////////////////////////////////////////////
// SAMPLING FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

void samplingCbISR() {
 
  // Read from the ADC and store the sample data
  vReal[sampleCounter] =  analogRead(CHANNEL);
  sampleCounter += 1;

  if (sampleCounter >= SIZE) {
    samplingTimer.end();
    digitalWrite(POWER_LED_PIN, HIGH);
  }
}

void samplingBegin() {
  // Reset sample buffer position and start callback at necessary rate.
  digitalWrite(POWER_LED_PIN, LOW);
  sampleCounter = 0;
  samplingTimer.begin(samplingCbISR, 1000000/SAMPLE_RATE_HZ, uSec);
}

boolean samplingIsDone() {
  return sampleCounter >= SIZE;
}



void threadFunction() { 
	while(true) {
	    os_mutex_lock(mutex);
	   
	    while (Serial1.available() > 0) {
            char c = Serial1.read();
            // Add any characters that aren't the end of a command (semicolon) to the input buffer.
            if (c != ';') {
               c = toupper(c);
               strncat(commandBuffer, &c, 1);
            }
            else{
               char *command = commandBuffer;    
               if (strcmp(command, "GET MAGNITUDES") == 0) {
                   for(int i = 0; i<len; i++){
            		    Serial1.println(vR_copy[i]); 
            	      }
                        	  
                memset(commandBuffer, 0, sizeof(commandBuffer));
                }
            }
        }
    }
	
}

Thanks for your answer.
Have you measured the time of your interrupt routine? Your’re right with 100 ns sampling time but the function “analogRead();” takes an average over 5 values and it does some other configurations. Without modification I measured10 µs for one analogRead(); with setADCSampleTime(ADC_SampleTime_3Cycles).

Hi I didn’t measure time for one analogRead(); I even don’t know how to do that to get some “constructive results” also I didn’t measure time for entire interrupt routine but instead I add another global double array w 128 elements and then add (right after this line: vReal[sampleCounter] = analogRead(CHANNEL); in interrupt ) this line :

vMicros[sampleCounter] =  micros();

and then in main loop instead of:

 memcpy(vR_copy, vReal, sizeof(double) * len);

replaced with:

memcpy(vR_copy, vMicros, sizeof(double) * len);

Then printed the entire array of micros(); results from threadFunction and I get some weird results. I modify python spectrum analyser just to read from Serial1 and print to console.The array is pretty big and I don’t wanted to subtract, one by one, the time value manually. So python function to read from Serial looks like that:

self.fftSize  = 128
def get_magnitudes(self):
		"""Return an array of micros."""
		self.port.write('GET MAGNITUDES; ')
		raw_buff = [self.port.readline() for i in range(self.fftSize)]
		print "raw_buff", raw_buff
		foo = re.findall("\d \.\d ", str([raw_buff for i 
                range(self.fftSize)]))
		for i in range(self.fftSize-1):
			bar = [float(foo[i +1]) - float(foo[i])]
			print "read time  and i ", bar , i+1

and here is some printed results:

raw_buff ['1230222384.00\r\n', '1230222425.00\r\n', '1230222448.00\r\n', '1230222471.00\r\n', '1230222494.00\r\n', '1230222517.00\r\n', '1230222540.00\r\n', '1230225588.00\r\n', '1230225611.00\r\n', '1230225634.00\r\n', '1230229342.00\r\n', '1230229367.00\r\n', '1230229388.00\r\n', '1230233405.00\r\n', '1230233428.00\r\n', '1230233451.00\r\n', '1230237478.00\r\n', '1230237501.00\r\n', '1230237527.00\r\n', '1230241545.00\r\n', '1230241568.00\r\n', '1230241591.00\r\n', '1230245617.00\r\n', '1230245640.00\r\n', '1230245663.00\r\n', '1230249684.00\r\n', '1230249704.00\r\n', '1230249727.00\r\n', '1230253753.00\r\n', '1230253774.00\r\n', '1230253797.00\r\n', '1230257821.00\r\n', '1230257847.00\r\n', '1230257867.00\r\n', '1230257890.00\r\n', '1230261917.00\r\n', '1230261938.00\r\n', '1230261961.00\r\n', '1230265981.00\r\n', '1230266006.00\r\n', '1230266017.00\r\n', '1230270042.00\r\n', '1230270068.00\r\n', '1230270088.00\r\n', '1230274111.00\r\n', '1230274134.00\r\n', '1230274160.00\r\n', '1230278180.00\r\n', '1230278203.00\r\n', '1230278229.00\r\n', '1230282249.00\r\n', '1230282272.00\r\n', '1230282295.00\r\n', '1230286321.00\r\n', '1230286341.00\r\n', '1230286364.00\r\n', '1230290390.00\r\n', '1230290410.00\r\n', '1230290433.00\r\n', '1230294456.00\r\n', '1230294480.00\r\n', '1230294502.00\r\n', '1230298525.00\r\n', '1230298551.00\r\n', '1230298571.00\r\n', '1230302594.00\r\n', '1230302617.00\r\n', '1230302643.00\r\n', '1230306663.00\r\n', '1230306686.00\r\n', '1230306712.00\r\n', '1230310732.00\r\n', '1230310755.00\r\n', '1230310778.00\r\n', '1230314803.00\r\n', '1230314824.00\r\n', '1230314847.00\r\n', '1230314870.00\r\n', '1230318891.00\r\n', '1230318914.00\r\n', '1230318937.00\r\n', '1230322964.00\r\n', '1230322984.00\r\n', '1230323007.00\r\n', '1230327045.00\r\n', '1230327065.00\r\n', '1230327088.00\r\n', '1230331111.00\r\n', '1230331136.00\r\n', '1230331157.00\r\n', '1230335177.00\r\n', '1230335202.00\r\n', '1230335223.00\r\n', '1230339246.00\r\n', '1230339269.00\r\n', '1230339295.00\r\n', '1230343316.00\r\n', '1230343339.00\r\n', '1230343364.00\r\n', '1230347386.00\r\n', '1230347409.00\r\n', '1230347432.00\r\n', '1230351455.00\r\n', '1230351476.00\r\n', '1230351499.00\r\n', '1230355525.00\r\n', '1230355546.00\r\n', '1230355569.00\r\n', '1230359592.00\r\n', '1230359617.00\r\n', '1230359638.00\r\n', '1230363642.00\r\n', '1230363667.00\r\n', '1230363688.00\r\n', '1230367732.00\r\n', '1230367755.00\r\n', '1230367778.00\r\n', '1230371798.00\r\n', '1230371821.00\r\n', '1230371847.00\r\n', '1230371868.00\r\n', '1230375871.00\r\n', '1230375894.00\r\n', '1230375920.00\r\n', '1230379960.00\r\n', '1230379983.00\r\n', '1230380008.00\r\n', '1230384017.00\r\n']
read time  and i  [41.0] 1
read time  and i  [23.0] 2
read time  and i  [23.0] 3
read time  and i  [23.0] 4
read time  and i  [23.0] 5
read time  and i  [23.0] 6
read time  and i  [3048.0] 7
read time  and i  [23.0] 8
read time  and i  [23.0] 9
read time  and i  [3708.0] 10
read time  and i  [25.0] 11
read time  and i  [21.0] 12
read time  and i  [4017.0] 13
read time  and i  [23.0] 14
read time  and i  [23.0] 15
read time  and i  [4027.0] 16
read time  and i  [23.0] 17
read time  and i  [26.0] 18
read time  and i  [4018.0] 19
read time  and i  [23.0] 20
read time  and i  [23.0] 21
read time  and i  [4026.0] 22
read time  and i  [23.0] 23
read time  and i  [23.0] 24
read time  and i  [4021.0] 25
read time  and i  [20.0] 26
read time  and i  [23.0] 27
read time  and i  [4026.0] 28
read time  and i  [21.0] 29
read time  and i  [23.0] 30
read time  and i  [4024.0] 31
read time  and i  [26.0] 32
read time  and i  [20.0] 33
read time  and i  [23.0] 34
read time  and i  [4027.0] 35
read time  and i  [21.0] 36
read time  and i  [23.0] 37
read time  and i  [4020.0] 38
read time  and i  [25.0] 39
read time  and i  [11.0] 40
read time  and i  [4025.0] 41
read time  and i  [26.0] 42
read time  and i  [20.0] 43
read time  and i  [4023.0] 44
read time  and i  [23.0] 45
read time  and i  [26.0] 46
read time  and i  [4020.0] 47
read time  and i  [23.0] 48
read time  and i  [26.0] 49
read time  and i  [4020.0] 50
read time  and i  [23.0] 51
read time  and i  [23.0] 52
read time  and i  [4026.0] 53
read time  and i  [20.0] 54
read time  and i  [23.0] 55
read time  and i  [4026.0] 56
read time  and i  [20.0] 57
read time  and i  [23.0] 58
read time  and i  [4023.0] 59
read time  and i  [24.0] 60
read time  and i  [22.0] 61
read time  and i  [4023.0] 62
read time  and i  [26.0] 63
read time  and i  [20.0] 64
read time  and i  [4023.0] 65
read time  and i  [23.0] 66
read time  and i  [26.0] 67
read time  and i  [4020.0] 68
read time  and i  [23.0] 69
read time  and i  [26.0] 70
read time  and i  [4020.0] 71
read time  and i  [23.0] 72
read time  and i  [23.0] 73
read time  and i  [4025.0] 74
read time  and i  [21.0] 75
read time  and i  [23.0] 76
read time  and i  [23.0] 77
read time  and i  [4021.0] 78
read time  and i  [23.0] 79
read time  and i  [23.0] 80
read time  and i  [4027.0] 81
read time  and i  [20.0] 82
read time  and i  [23.0] 83
read time  and i  [4038.0] 84
read time  and i  [20.0] 85
read time  and i  [23.0] 86
read time  and i  [4023.0] 87
read time  and i  [25.0] 88
read time  and i  [21.0] 89
read time  and i  [4020.0] 90
read time  and i  [25.0] 91
read time  and i  [21.0] 92
read time  and i  [4023.0] 93
read time  and i  [23.0] 94
read time  and i  [26.0] 95
read time  and i  [4021.0] 96
read time  and i  [23.0] 97
read time  and i  [25.0] 98
read time  and i  [4022.0] 99
read time  and i  [23.0] 100
read time  and i  [23.0] 101
read time  and i  [4023.0] 102
read time  and i  [21.0] 103
read time  and i  [23.0] 104
read time  and i  [4026.0] 105
read time  and i  [21.0] 106
read time  and i  [23.0] 107
read time  and i  [4023.0] 108
read time  and i  [25.0] 109
read time  and i  [21.0] 110
read time  and i  [4004.0] 111
read time  and i  [25.0] 112
read time  and i  [21.0] 113
read time  and i  [4044.0] 114
read time  and i  [23.0] 115
read time  and i  [23.0] 116
read time  and i  [4020.0] 117
read time  and i  [23.0] 118
read time  and i  [26.0] 119
read time  and i  [21.0] 120
read time  and i  [4003.0] 121
read time  and i  [23.0] 122
read time  and i  [26.0] 123
read time  and i  [4040.0] 124
read time  and i  [23.0] 125
read time  and i  [25.0] 126
read time  and i  [4009.0] 127
raw_buff ['1230491109.00\r\n', '1230491150.00\r\n', '1230491173.00\r\n', '1230491196.00\r\n', '1230491220.00\r\n', '1230491243.00\r\n', '1230491265.00\r\n', '1230494317.00\r\n', '1230494339.00\r\n', '1230494362.00\r\n', '1230498338.00\r\n', '1230498361.00\r\n', '1230498384.00\r\n', '1230502406.00\r\n', '1230502431.00\r\n', '1230502452.00\r\n', '1230506480.00\r\n', '1230506503.00\r\n', '1230506526.00\r\n', '1230510544.00\r\n', '1230510567.00\r\n', '1230510590.00\r\n', '1230514616.00\r\n', '1230514639.00\r\n', '1230514662.00\r\n', '1230518684.00\r\n', '1230518707.00\r\n', '1230518730.00\r\n', '1230522754.00\r\n', '1230522774.00\r\n', '1230522797.00\r\n', '1230526827.00\r\n', '1230526847.00\r\n', '1230526870.00\r\n', '1230526893.00\r\n', '1230530939.00\r\n', '1230530962.00\r\n', '1230530985.00\r\n', '1230534984.00\r\n', '1230535007.00\r\n', '1230535021.00\r\n', '1230539042.00\r\n', '1230539068.00\r\n', '1230539088.00\r\n', '1230543111.00\r\n', '1230543134.00\r\n', '1230543157.00\r\n', '1230547180.00\r\n', '1230547203.00\r\n', '1230547229.00\r\n', '1230551250.00\r\n', '1230551273.00\r\n', '1230551297.00\r\n', '1230555318.00\r\n', '1230555341.00\r\n', '1230555364.00\r\n', '1230559390.00\r\n', '1230559410.00\r\n', '1230559433.00\r\n', '1230563456.00\r\n', '1230563479.00\r\n', '1230563502.00\r\n', '1230567525.00\r\n', '1230567551.00\r\n', '1230567571.00\r\n', '1230571594.00\r\n', '1230571620.00\r\n', '1230571640.00\r\n', '1230575662.00\r\n', '1230575685.00\r\n', '1230575711.00\r\n', '1230579730.00\r\n', '1230579753.00\r\n', '1230579776.00\r\n', '1230583801.00\r\n', '1230583824.00\r\n', '1230583847.00\r\n', '1230583872.00\r\n', '1230587891.00\r\n', '1230587914.00\r\n', '1230587937.00\r\n', '1230591960.00\r\n', '1230591983.00\r\n', '1230592021.00\r\n', '1230596045.00\r\n', '1230596065.00\r\n', '1230596088.00\r\n', '1230600109.00\r\n', '1230600132.00\r\n', '1230600155.00\r\n', '1230604179.00\r\n', '1230604204.00\r\n', '1230604225.00\r\n', '1230608246.00\r\n', '1230608269.00\r\n', '1230608292.00\r\n', '1230612294.00\r\n', '1230612317.00\r\n', '1230612343.00\r\n', '1230616385.00\r\n', '1230616408.00\r\n', '1230616431.00\r\n', '1230620454.00\r\n', '1230620477.00\r\n', '1230620500.00\r\n', '1230624507.00\r\n', '1230624527.00\r\n', '1230624550.00\r\n', '1230628593.00\r\n', '1230628615.00\r\n', '1230628638.00\r\n', '1230632662.00\r\n', '1230632688.00\r\n', '1230632708.00\r\n', '1230636732.00\r\n', '1230636757.00\r\n', '1230636778.00\r\n', '1230640800.00\r\n', '1230640823.00\r\n', '1230640849.00\r\n', '1230640869.00\r\n', '1230644891.00\r\n', '1230644914.00\r\n', '1230644937.00\r\n', '1230648962.00\r\n', '1230648985.00\r\n', '1230649011.00\r\n', '1230653021.00\r\n']
read time  and i  [41.0] 1
read time  and i  [23.0] 2
read time  and i  [23.0] 3
read time  and i  [24.0] 4
read time  and i  [23.0] 5
read time  and i  [22.0] 6
read time  and i  [3052.0] 7
read time  and i  [22.0] 8
read time  and i  [23.0] 9
read time  and i  [3976.0] 10
read time  and i  [23.0] 11
read time  and i  [23.0] 12
read time  and i  [4022.0] 13
read time  and i  [25.0] 14
read time  and i  [21.0] 15
read time  and i  [4028.0] 16
read time  and i  [23.0] 17
read time  and i  [23.0] 18
read time  and i  [4018.0] 19
read time  and i  [23.0] 20
read time  and i  [23.0] 21
read time  and i  [4026.0] 22
read time  and i  [23.0] 23
read time  and i  [23.0] 24
read time  and i  [4022.0] 25
read time  and i  [23.0] 26
read time  and i  [23.0] 27
read time  and i  [4024.0] 28
read time  and i  [20.0] 29
read time  and i  [23.0] 30
read time  and i  [4030.0] 31
read time  and i  [20.0] 32
read time  and i  [23.0] 33
read time  and i  [23.0] 34
read time  and i  [4046.0] 35
read time  and i  [23.0] 36
read time  and i  [23.0] 37
read time  and i  [3999.0] 38
read time  and i  [23.0] 39
read time  and i  [14.0] 40
read time  and i  [4021.0] 41
read time  and i  [26.0] 42
read time  and i  [20.0] 43
read time  and i  [4023.0] 44
read time  and i  [23.0] 45
read time  and i  [23.0] 46
read time  and i  [4023.0] 47
read time  and i  [23.0] 48
read time  and i  [26.0] 49
read time  and i  [4021.0] 50
read time  and i  [23.0] 51
read time  and i  [24.0] 52
read time  and i  [4021.0] 53
read time  and i  [23.0] 54
read time  and i  [23.0] 55
read time  and i  [4026.0] 56
read time  and i  [20.0] 57
read time  and i  [23.0] 58
read time  and i  [4023.0] 59
read time  and i  [23.0] 60
read time  and i  [23.0] 61
read time  and i  [4023.0] 62
read time  and i  [26.0] 63
read time  and i  [20.0] 64
read time  and i  [4023.0] 65
read time  and i  [26.0] 66
read time  and i  [20.0] 67
read time  and i  [4022.0] 68
read time  and i  [23.0] 69
read time  and i  [26.0] 70
read time  and i  [4019.0] 71
read time  and i  [23.0] 72
read time  and i  [23.0] 73
read time  and i  [4025.0] 74
read time  and i  [23.0] 75
read time  and i  [23.0] 76
read time  and i  [25.0] 77
read time  and i  [4019.0] 78
read time  and i  [23.0] 79
read time  and i  [23.0] 80
read time  and i  [4023.0] 81
read time  and i  [23.0] 82
read time  and i  [38.0] 83
read time  and i  [4024.0] 84
read time  and i  [20.0] 85
read time  and i  [23.0] 86
read time  and i  [4021.0] 87
read time  and i  [23.0] 88
read time  and i  [23.0] 89
read time  and i  [4024.0] 90
read time  and i  [25.0] 91
read time  and i  [21.0] 92
read time  and i  [4021.0] 93
read time  and i  [23.0] 94
read time  and i  [23.0] 95
read time  and i  [4002.0] 96
read time  and i  [23.0] 97
read time  and i  [26.0] 98
read time  and i  [4042.0] 99
read time  and i  [23.0] 100
read time  and i  [23.0] 101
read time  and i  [4023.0] 102
read time  and i  [23.0] 103
read time  and i  [23.0] 104
read time  and i  [4007.0] 105
read time  and i  [20.0] 106
read time  and i  [23.0] 107
read time  and i  [4043.0] 108
read time  and i  [22.0] 109
read time  and i  [23.0] 110
read time  and i  [4024.0] 111
read time  and i  [26.0] 112
read time  and i  [20.0] 113
read time  and i  [4024.0] 114
read time  and i  [25.0] 115
read time  and i  [21.0] 116
read time  and i  [4022.0] 117
read time  and i  [23.0] 118
read time  and i  [26.0] 119
read time  and i  [20.0] 120
read time  and i  [4022.0] 121
read time  and i  [23.0] 122
read time  and i  [23.0] 123
read time  and i  [4025.0] 124
read time  and i  [23.0] 125
read time  and i  [26.0] 126
read time  and i  [4010.0] 127

As you can see almost every 3th , 4th element in vMicros array is pretty big around 4000 us and average is around 23 us and I don’t have any idea why why why ?
Maybe I shouldn’t put :

vMicros[sampleCounter] =  micros();

inside interrupt routine but nothing is “bothering” interrupt routine until is done also after that I just print out copy of vMicros array so nothing at all shouldn’t block during sample reading in that interrupt routine so why this timing sample looks so weird :thinking:

Thats normal, because i measured 10 us for one analogRead() and millis() allso takes some time.
There are also interrupts from the system...

I found now a solution myself. I was using the wrong commands from the STM32_StdPeriph_Driver lib because i tried to use some from STM32F1xx-generation. Photon is based on STM32F2xx!

My working Code with 1.2 µs reading time!

/*
* returns the counts of a given ADC (ADC1 and AD2, ADC3 wans't working)
* takes approx. 1.2 µs
*/
uint16_t readADCx(ADC_TypeDef* ADCx){
  ADC_SoftwareStartConv(ADC2); // ca. 150 ns
  // Wait until conversion completion
  while(ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC) == RESET); // ca. 800 ns
  pinResetFast(D0);
  //ADC_ClearFlag(ADC1, ADC_FLAG_EOC); // is not necessarry
  return ADC_GetConversionValue(ADC2); //ca. 100ns
}
source complete
#include "Particle.h"
SYSTEM_THREAD(ENABLED); //multitasking with system thread
SYSTEM_MODE(MANUAL); //connection to wifi must be activated from code, the code itself is activated before connection

/*
* retruns the counts of a given ADC (ADC1 and AD2, ADC3 wans't working)
* takes approx. 1.2 µs
*/
uint16_t readADCx(ADC_TypeDef* ADCx){
  ADC_SoftwareStartConv(ADC2); // ca. 150 ns
  // Wait until conversion completion
  while(ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC) == RESET); // ca. 800 ns
  pinSetFast(D0);
  //ADC_ClearFlag(ADC1, ADC_FLAG_EOC); // is not necessarry
  return ADC_GetConversionValue(ADC2); //ca. 100ns
}

/*
* Configurate the given Pin to the given ADC
* takes approx. 4.4 µs but if i measured the parts inside single it was much longer????
*/
void configure_ADC_channel(ADC_TypeDef* ADCx, uint16_t pin){

  STM32_Pin_Info* PIN_MAP = HAL_Pin_Map(); // approx. 780 ns

  HAL_Pin_Mode(pin, AN_INPUT); // approx 3.8 µs
  ADC_RegularChannelConfig(ADCx, PIN_MAP[pin].adc_channel, 1, ADC_SampleTime_3Cycles); //4.4 µs ???

}

void ADCx_Configuration(ADC_TypeDef* ADCx)
{
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
  ADC_InitTypeDef ADC_InitStructure;

  /* Enable ADC's APB interface clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //if(ADCx==ADC1)
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE); //if(ADCx==ADC2)
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); //if(ADCx==ADC3)
  /* Common configuration (applicable for the three ADCs) *********************/
  /* Single ADC mode */
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
  /* ADCCLK = PCLK2/2 */
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
  /* Available only for multi ADC mode */
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
  /* Delay between 2 sampling phases */
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
  ADC_CommonInit(&ADC_CommonInitStructure);
  /* Configure ADCx to convert continously channel14 **************************/
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//old: ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = 1;
  ADC_Init(ADCx, &ADC_InitStructure);
  /* ADCx regular channel14 configuration */
  ADC_RegularChannelConfig(ADCx, ADC_Channel_14, 1, ADC_SampleTime_3Cycles);
  /* Enable ADCx */
  ADC_Cmd(ADCx, ENABLE);
  /* Start ADCx Software Conversion */
  //ADC_SoftwareStartConv(ADCx); //not here!, otherwise it was blocking sometimes...
}

void setup(){
  WiFi.off();
  Serial1.begin(115200); //Serial Comunication at  RX-TX pins
  analogRead(A0); //Dummi analogRead to configure pins in HAL well
  pinMode(D0, OUTPUT); //dummi pin-definition otherwise wrong ADC-Value (I don't know why)

  //DONT USE analogRead()!!!!!!!! IT WILL CHANGE PIN AND HARDWARE

  ADCx_Configuration(ADC2); // inilize the ADC in HAL
  configure_ADC_channel(ADC2,A3); //Connect PIN A3 to ADC2, takes 4.4 µs
}

uint32_t var=0;
void loop(){
  pinSetFast(D0);
  var=readADCx(ADC2); //ca. 1.2 µs
  pinReSetFast(D0);
  Serial1.println(var);
}


The red curve showes the voltage on pin 0. (the functions PinSetFast() and PinResetFast() take approx. 50 ns)

2 Likes

WOW !!! that’s amazing !!! thank you very much for explanation what is going on in my code and Tanks a lot for sharing your solution !!!
Best Regards,
Arek.

does this work with the photon 2?

There is currently no library to DMA-based ADC readings on the P2/Photon 2/M-SoM.

It's theoretically possible, though the sample rates are more limited on the RTL872x, mostly around audio frequencies (8K to 96K) instead of being arbitrarily based on a hardware timer as on the STM32 and nRF52.

1 Like