0:09
hello and welcome to controller Tech
0:12
this is ADC part two and the ninth video
0:15
in the es sp32 series using expressive
0:18
ID in the previous video we saw how to
0:21
use the ADC one shot mode to read
0:24
multiple channels we also saw how to
0:27
calibrate the channels so that we can
0:30
get more accurate results although we
0:32
could only convert one channel at a time
0:35
using the oneshot mode therefore when we
0:38
need to convert multiple channels we
0:40
call the onshot read function as many
0:42
times as the number of channels we are
0:45
converting today we will take a look at
0:47
another ADC reading method available in
0:51
es32 ADC continuous mode is used to read
0:57
continuously or we can also use this
0:59
mode to collect a huge number of samples
1:02
for a single Channel only the converted
1:05
data is transferred using the dma
1:08
therefore there is no load on the es32
1:11
CPU I am going to keep the same setup as
1:15
video here is the picture showing the
1:18
connection between the potentiometers
1:22
32 both the potentiometers are powered
1:25
with 3.3 volts from the board itself the
1:29
outp pins from the potentiometers are
1:31
connected to the pin VP and
1:34
VN these are the adc1 channel Z and
1:39
pins so we will use the same two
1:42
channels which we used in the previous
1:45
video all right let's open the ID and
1:48
create a new espressive
1:50
project we can refer to the ADC
1:53
continuous mode example provided in the
1:56
template let's rename the project and
1:59
click save to generate the
2:01
code here we have the ADC continuous
2:06
project you can run this project and get
2:10
output although since I am explaining
2:13
how to write this driver I am deleting
2:15
all the pre-generated
2:17
code then we will write everything from
2:20
scratch understanding the purpose of
2:22
each line we write let's start by
2:25
defining the array of two channels which
2:27
we will convert in the continuous mode
2:31
the ADC data array will contain the
2:33
converted raw data for both these
2:36
channels now we will Define the ADC
2:40
function the parameters of this function
2:43
are the pointer to the ADC channels and
2:45
the number of channels we want to
2:48
convert we will write our initialization
2:50
function based on the configurations
2:52
available in the ADC continuous header
2:55
file here at first we have the driver
2:58
initial configuration
3:00
the first member of this structure is
3:02
the max storage buffer size which is
3:05
basically the maximum length of the
3:07
conversion results the driver can
3:09
store this length should be in
3:12
bytes the next member of this structure
3:15
is the conversion frame size which is
3:19
bytes let's understand what these
3:23
mean here is the explanation for the
3:26
same as shown here one conver frame
3:30
contains multiple conversion
3:32
results the conversion frame size is
3:35
configured in the handle configuration
3:38
structure whenever one conversion frame
3:41
is generated by the hardware the ADC
3:45
interrupt even one conversion result
3:50
bytes the conversion result structure
3:52
consists of an ADC unit ADC Channel and
3:56
raw data the number of bytes per
3:59
conversion result varies for different
4:02
Hardwares and it is defined in the ADC
4:05
DG result bytes here for es32 this value
4:09
is two but it is different for es32 C
4:15
Hardwares that means each ADC conversion
4:18
result occupies two bytes in the memory
4:21
we can even generate multiple conversion
4:23
results for a single channel for example
4:27
if we set the max storage buffer size to
4:29
20 bytes it would generate 10 conversion
4:32
results if we are using a single channel
4:36
the ADC will sample the channel 10 times
4:38
and store the information in 10
4:40
conversion results now if the conversion
4:43
frame size is also set to 20 bytes an
4:46
interrupt will trigger after these 10
4:49
samples similarly if we have two
4:52
channels the ADC will sample both
4:54
channels five times each and store the
4:56
information in 10 conversion results if
5:00
we have 10 channels the ADC will sample
5:03
all the channels just once the
5:05
conversion frame size is an important
5:08
parameter here as it is responsible for
5:10
when the interrupt will trigger the size
5:13
of this parameter should be in multiple
5:15
of the ADC data bytes per conversion
5:17
which is again defined in the S so caps
5:20
header file this parameter also varies
5:23
with different es32 devices but here it
5:28
bytes this means in this case I can only
5:31
Define the conversion frame in the
5:33
multiple of four so I hope you
5:36
understood how the conversion result and
5:40
Works now we will Define this handle
5:42
configuration structure inside the ADC
5:47
function I am setting the conversion
5:49
frame size to 4 bytes and the buffer
5:53
bytes a conversion frame of 4 bytes
5:56
means that the interrupt will trigger
5:57
after two conversion results whereas the
6:00
buffer can store four conversion
6:03
results since we have two ADC channels
6:06
the buffer will store two samples for
6:09
Channel now we have defined the handle
6:12
configuration so let's call the function
6:14
ADC continuous new handle to set this
6:17
configuration to ADC handle we need to
6:20
define the ADC continuous handle as a
6:23
global variable so that it can be used
6:25
with other functions as well the next
6:28
structure in the header file is the
6:34
configuration the first member of this
6:37
structure is the pattern number which is
6:39
basically the number of ADC channels we
6:41
are using the next member is the pointer
6:44
to the pattern configuration which we
6:48
end next we have the sampling
6:51
frequency the higher and lower limits
6:54
for the sampling frequency are defined
6:56
in the S so caps header file
6:59
here you can see we have a sampling
7:01
frequency between 20 khz to 2
7:04
mahz the next member is the conversion
7:08
mode it is another structure type which
7:11
is defined in the ADC types header file
7:15
basically we can use either adc1 or adc2
7:19
both simultaneously or both
7:22
alternatively adc2 does not support dma
7:26
es32 so I am only going to use adc1
7:30
the next member is the output format
7:32
which is again an output format
7:34
structure type defined in the ADC types
7:37
we have two output formats type one and
7:41
type two you can get more details about
7:44
these types in the output data structure
7:47
here is the type one output where we get
7:49
only the data and the corresponding
7:52
channel in the output while in type 2
7:55
output we get the data Channel and the
8:00
if you are using multiple ADC units you
8:03
should use type 2 output with this you
8:06
will be able to get the data the ADC
8:09
Channel and the ADC unit for which this
8:11
current data correspond to as I
8:14
mentioned earlier in es32 the adc2 does
8:18
not support the dma mode therefore I can
8:21
only use the type 1 output here although
8:24
other esp32 devices might support adc2
8:28
dma mode so you are free to use either
8:30
of the output types now let's take a
8:33
look at the ADC pattern
8:36
configuration this structure configures
8:38
the ADC channels and we have the members
8:41
like attenuation channel number ADC unit
8:45
and the bit width I have already
8:47
discussed these in the previous video so
8:50
we will simply configure them so now we
8:53
will Define the structure ADC continuous
8:56
configuration in the ADC initialization
9:00
let's rename the previous configuration
9:02
to handle config and we will call this
9:04
configuration as ADC config the pattern
9:08
number is the number of channels we are
9:10
using it is already passed in the
9:12
parameter next is the conversion mode as
9:16
I mentioned I am only using ADC unit one
9:20
the next member is the output format I
9:24
am going to use the type 1 output format
9:29
frequency here I am using the lowest
9:32
sampling frequency that is 20
9:35
khz now we will configure the ADC
9:38
channels we have two channels to
9:41
configure so let's define the channel
9:43
configur Ray with two
9:45
elements I am going to use the same
9:47
configuration for both channels
9:49
therefore I am calling it in the F Loop
9:52
the first member is the channel itself
9:54
so let's pass the channel data from the
9:57
parameter of the function then we will
9:59
set the attenuation to 12 DB which will
10:03
allow us to measure the higher voltage
10:05
range next the bit width is set to 12 so
10:09
the resolution will be 12 bits and
10:12
finally the unit is ADC unit one for
10:15
both channels now we will pass our
10:18
Channel configuration to the ADC pattern
10:20
structure of the ADC config we have
10:23
prepared the entire ADC configuration so
10:26
let's call the function ADC continuous
10:28
configuration and pass the ADC config to
10:35
function next we have the event data
10:37
structure which we don't need for now
10:40
this is the call back function which is
10:43
called when the conversion frame is
10:48
generated let's define this call back
10:50
function in the main file I am calling
10:54
the function call back itself we will
10:57
write this function in a while next we
11:00
have the event call back structure the
11:03
first member of this structure is event
11:05
call back which is called when one
11:07
conversion frame is generated the next
11:10
member is the event call back which is
11:12
called when the internal pool is full
11:15
the call back function type Remains the
11:17
Same for both these call backs let's
11:20
define the call back event inside the
11:23
initialization function when the
11:25
conversion frame is generated we will
11:27
call the call back function which we
11:29
just defined globally we will skip the
11:32
Overflow call back in this tutorial but
11:35
if you want to Define it you need to
11:37
Define another call back function for
11:40
handling after defining the call back we
11:43
need to register it the function ADC
11:47
continuous register event call back
11:51
parameters the ADC handle for which the
11:55
defined pointer to the call back
12:00
and the user data which we will just
12:02
pass the null to let's go back to the
12:05
ADC continuous header file that is all
12:09
the configuration we have in this file
12:12
we can use the ADC continuous start
12:15
function to start the ADC
12:18
conversions once the required number of
12:20
conversion results are generated one
12:23
conversion frame will be generated and
12:25
an interrupt will trigger we can read
12:28
the results at any point in our code by
12:30
calling the function ADC continuous
12:33
read let's write the call back function
12:36
now we need to give the internal Ram
12:39
attribute to this function so it can
12:42
move there we will use this call back
12:45
function to notify another task where we
12:47
will retrieve the data from the
12:49
conversion result and store the data in
12:53
array let's define a task handle which
12:56
will be used to retrieve the data from
13:00
result inside the call back we will call
13:03
the function to notify the ADC task from
13:05
the interrupt service
13:07
routine the rest of the ADC data will be
13:11
processed inside this
13:13
task let's rename this handle to CB task
13:17
we will first create a task in the main
13:20
function the task code is CB task note
13:24
that it is different from the task
13:26
handle I am calling it The call back
13:29
task let's set the stack size to
13:32
512 and there are no parameters to pass
13:36
task I am setting the priority to zero
13:40
and the task handle is already defined
13:43
globally let's also call the function to
13:47
ADC the channel array is defined
13:50
globally and we are converting two
13:52
channels let's write the call back task
14:00
inside the infinite Loop we will wait
14:02
for the notification to be sent by the
14:04
interrupt function here I am setting the
14:07
weight time to infinite the notification
14:10
is sent by the call back function once
14:14
the notification is received it means
14:16
that the conversion frame is generated
14:19
we will call the function ADC continuous
14:22
read to read the converted data the
14:25
parameters of this function are the ADC
14:28
handle buffer where the data should be
14:30
stored the maximum expected length of
14:33
the data we have configured the max
14:35
buffer size to 8 bytes but the
14:38
conversion frame is only 4 bytes in size
14:41
I am setting the maximum expected data
14:43
length to 8 bytes set this value in
14:46
multiple of four out length is the
14:49
actual length of the data in the
14:50
conversion frame the number of
14:53
conversion results is this value divided
14:56
by two let's define the buffer where the
14:59
the received data will be stored also
15:02
Define the RX length variable it is a
15:05
32-bit variable and we need to pass the
15:08
address in the function parameter all
15:11
right now the data is stored in the
15:13
buffer so we will extract the values
15:16
from it each Channel content occupies
15:19
two bytes in the conversion result that
15:21
is why the F Loop increments by two we
15:24
have already discussed it in the
15:26
beginning the ABCD G result byes is is
15:29
defined as 2 bytes we can simply use the
15:32
definition so that the same code can be
15:35
used for other devices as well the
15:38
buffer is of type unsigned integer so we
15:40
need to change it to the adcg output
15:43
data form after that we can extract the
15:46
information like the channel number and
15:48
data for the corresponding channel here
15:51
we will store the data from the buffer
15:53
into the output data type structure now
15:57
extract the channel from the structure
15:59
and store it in the channel variable
16:02
also extract the data and store it in
16:04
the data variable now we will check if
16:07
the channel is Channel Zero if it is
16:11
then we will store the corresponding
16:12
channels value to the zeroth position in
16:15
the ADC data array and if the channel is
16:18
channel three then store the
16:20
corresponding channels data to the first
16:22
element of the array the call back task
16:25
will be called after the interrupt and
16:27
its purpose is to Extra ex ract and
16:29
store the result data in the data array
16:32
we can read this result array at any
16:34
point in our code and use the data as
16:38
requirement this should be ADC Channel
16:41
not adc1 Channel after initializing the
16:44
ADC in the main function we will call
16:47
the ADC continuous start function to
16:49
start the ADC once started the interrupt
16:53
function and the call back task will
16:55
start working after one conversion frame
16:58
is generated an interrupt will trigger
17:01
which will call the call back function
17:04
the call back function will notify the
17:06
call back task the call back task will
17:09
resume operation it will read the
17:11
conversion result extract the channel
17:13
and converted values from the data and
17:16
store them at the relevant positions in
17:19
array now inside the while loop we will
17:23
values here I am simply printing them on
17:27
console let's give some delay after each
17:34
print let's also Define a voltage array
17:37
where we will store the calculated
17:39
voltage values for both
17:42
channels inside the while loop we will
17:44
convert the ADC raw data to the
17:47
voltage for 12 bits resolution the
17:50
maximum raw of 4,000 and 95 corresponds
17:56
Ms I am only conver in the Channel Zero
17:59
to voltage value because the voltmeter
18:02
is connected to this pin
18:04
only therefore we will compare the
18:06
voltmeter reading with our calculated
18:09
value all right let's build and Flash
18:12
the project to the board
18:22
now we are getting an assert failed
18:24
error and this is causing the system to
18:27
reboot it might be because the stack
18:30
size is low so let me increase the stack
18:35
4,096 let's build and Flash the project
18:41
again all right the values are printing
18:45
now here you can see the setup it is the
18:48
same as what we saw in the previous
18:50
video the rotary pot is connected to
18:53
Channel Zero and the voltmeter is also
18:56
connected to this pot the sliding pot is
18:59
connected to channel 3 Let's rotate the
19:02
rotary pot now you can see the channel Z
19:06
value is reducing and so does the
19:10
reading now the printed voltage is
19:12
around 890 molts whereas the voltmeter
19:17
volt now I am rotating it in the other
19:21
direction the calculated voltage is
19:23
around 2,700 molts whereas the voltmeter
19:30
Vol so we get approximately the same
19:33
results let's vary the sliding
19:36
potentiometer now I have moved the
19:39
potentiometer to the extreme end and you
19:41
can see the channel 3 raw value is zero
19:45
point now I am moving it to the other
19:48
direction and you can see the value is
19:51
increasing the values are printing very
19:55
console let me reduce this delay to 10
19:59
let's build and Flash the project
20:02
again all right now the values are
20:05
printing very fast you can see the
20:08
channel 3 raw value is varying according
20:12
potentiometer so we are able to get the
20:14
output for both the channels in
20:16
continuous mode you can increase the
20:18
number of samples by increasing the
20:21
maximum buffer size and conversion frame
20:24
size but keep in mind a very large value
20:27
here will result in in slower response
20:29
for the potentiometer
20:31
variation this is because the ADC will
20:34
take more samples now and since we have
20:36
not increased the sampling frequency it
20:39
will Que in the number of
20:41
samples we do not need High sampling
20:43
frequency or more number of samples for
20:46
the potentiometer so even lower values
20:49
are fine more samples are useful when
20:52
you want to sample some kind of
20:54
sinusoidal signal so as to prevent any
20:57
loss you you can experiment with these
20:59
values and find the ones more suited for
21:03
application we will do more videos for
21:06
the ADC peripheral in future where we
21:08
will cover more practical applications
21:10
of it this is it for the
21:13
video I hope you understood how to work
21:16
with the ADC continuous mode to convert
21:18
the multiple channels
21:20
continuously you can download the
21:22
project from the link in the
21:25
description leave comments in case of
21:29
keep watching and have a nice day ahead