1@page page_device_adc ADC Device
2
3# An Introduction to ADC
4
5An ADC (analog-to-digital converter) is a hardware device that converts continuously changing analog signals to discrete digital signals. Usually, these analog signals include temperature, pressure, sound, video and many other types of signals. Converting them is important, as digital signals are easier to store, process, and transmit. This conversion can be achieved by using an ADC device which is commonly integrated in various platforms. Historically, ADCs were first used to convert received wireless signals to digital signals, for example, television signals, or signals from long-short broadcast stations.
6
7## Conversion Process
8
9As shown in the figure below, the analog-to-digital conversion generally involves steps of sampling, holding, quantifying, and encoding. In actual circuits, some processes are combined, such as sampling and holding, while quantization and encoding are implemented simultaneously in the conversion process.
10
11![ADC Conversion Process](figures/adc-p.png)
12
13Sampling is the conversion of analog signals that changes continuously over time into time-discrete analog signals. It takes a certain amount of time for the analog signals obtained by sampling to be converted into digital signals. In order to provide a stable value for the subsequent quantization coding process, it is required to keep the sampling analog signals for a period of time after the sampling circuit.
14
15The process of converting a numerically continuous analog quantity into a digital quantity is called quantization. Digital signals are discrete numerically. The output voltage of the sample-and-hold circuit also needs to be naturalized to a corresponding discrete level in a similar way, and any digital quantity can only be an integer multiple of a certain minimum quantity unit. The quantized value also requires the encoding process, which is the digital output of the A/D converter.
16
17## Resolution
18
19Resolution is represented as binary (or decimal) numbers. Generally, it comes in 8 bits, 10 bits, 12 bits, 16 bits, etc. A larger resolution, in bits,  means more accuracy in the conversion of analog to digital signals.
20
21## Precision
22
23Precision is the maximum error value between analog signals and real ADC device numerical points’ values.An ADC with a high resolution might have a low precision, meaning that factors like noise can affect the numerical ADC reading more than small changes in the input signal.
24
25## Conversion Rate
26
27The conversion rate is the reciprocal of time taken for an ADC device to complete conversion from an analog to a digital signal. For example, an ADC device with a conversion rate of 1MHz means that the ADC conversion time is 1 microsecond.
28
29# Access ADC Device
30
31The application accesses the ADC hardware through the ADC device management interface provided by RT-Thread. The relevant interfaces are as follows:
32
33| **Function** | Description |
34| --------------- | ------------------ |
35| rt_device_find()  | Find device handles based on ADC device name |
36| rt_adc_enable()     | Enable ADC devices |
37| rt_adc_read()   | Read ADC device data |
38| rt_adc_disable()  | Close the ADC device |
39
40## Find ADC Devices
41
42The application gets the device handler based on the ADC device name to operate the ADC device. Following is the interface function to find the devices:
43
44```c
45rt_device_t rt_device_find(const char* name);
46```
47
48| **Parameter** | Description                |
49| -------- | ---------------------------------- |
50| name     | The name of the ADC device |
51| **Return** | ——                                 |
52| Device handle | Finding the corresponding device will return to the corresponding device handle |
53| RT_NULL | No device found
54                                             |
55
56In a nutshell, the names of the ADC devices are registered as adc0, adc1, and so on. What follows is an example on how to use it
57
58```c
59#define ADC_DEV_NAME        "adc1"  /* ADC device name */
60rt_adc_device_t adc_dev;            /* ADC device handle */
61/* find the device */
62adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
63```
64
65## Enable ADC Channel
66
67It is required to enable the ADC device with the following interface function before reading and operating the ADC device.
68
69```c
70rt_err_t rt_adc_enable(rt_adc_device_t dev, rt_uint32_t channel);
71```
72
73| Parameter | Description              |
74| ---------- | ------------------------------- |
75| dev        | ADC device handle            |
76| channel | ADC channel         |
77| **Return** | ——                             |
78| RT_EOK     | Succeed          |
79| -RT_ENOSYS | Failed, the device operation method is empty |
80| Other error code | Failed          |
81
82 An usage example is as follows:
83
84```c
85#define ADC_DEV_NAME        "adc1"  /* ADC device name */
86#define ADC_DEV_CHANNEL     5       /* ADC channel */
87rt_adc_device_t adc_dev;            /* ADC device handle */
88/* find the device */
89adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
90/* enable the device */
91rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
92```
93
94## Read ADC Channel Sample Values
95
96Reading the ADC channel sample values can be done by the following function:
97
98```c
99rt_uint32_t rt_adc_read(rt_adc_device_t dev, rt_uint32_t channel);
100```
101
102| Parameter | Description |
103| ---------- | ----------------- |
104| dev        | ADC device handle |
105| channel    | ADC channel   |
106| **Return** | ——                |
107| Read values |       |
108
109An example of using the ADC sampled voltage value is as follows:
110
111```c
112#define ADC_DEV_NAME        "adc1"      /* ADC device name */
113#define ADC_DEV_CHANNEL     5           /* ADC channel */
114#define REFER_VOLTAGE       330         /* Reference voltage 3.3V, data accuracy multiplied by 100 and reserve 2 decimal places*/
115#define CONVERT_BITS        (1 << 12)   /* The number of conversion bits is 12  */
116
117rt_adc_device_t adc_dev;                /* ADC device handle */
118rt_uint32_t value;
119/* find the device */
120adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
121/*  enable the device  */
122rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
123/* Read sampling values */
124value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
125/*  Convert to the corresponding voltage value  */
126vol = value * REFER_VOLTAGE / CONVERT_BITS;
127rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
128```
129
130The calculation formula of the actual voltage value is: `sampling value * reference voltage/(1 << resolution digit)`.  In the above example,  variable *vol* was enlarged 100 times, so finally the integer part of voltage is obtained through *vol / 100*, and the decimal part of voltage is obtained through *vol % 100*.
131
132## Disabling the ADC Channel
133
134An ADC channel can be disabled through the following function:
135
136```c
137rt_err_t rt_adc_disable(rt_adc_device_t dev, rt_uint32_t channel);
138```
139
140| **Parameter** | **Description**              |
141| ---------- | ------------------------------- |
142| dev        | ADC device handle            |
143| channel    | ADC channel         |
144| **Return** | ——                             |
145| RT_EOK | Succeed                                      |
146| -RT_ENOSYS | Failed, the device operation method is empty |
147| Other error code | Failed         |
148
149An example:
150
151```c
152#define ADC_DEV_NAME        "adc1"  /* ADC device name */
153#define ADC_DEV_CHANNEL     5       /* ADC channel */
154rt_adc_device_t adc_dev;            /* ADC device handle */
155rt_uint32_t value;
156/* find the device */
157adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
158/* enable the device */
159rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
160/* read sampling values */
161value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
162/*  convert to the corresponding voltage value */
163vol = value * REFER_VOLTAGE / CONVERT_BITS;
164rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
165/* close the channel */
166rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);
167```
168
169## FinSH Command
170
171To find out the registered device, you can use the command adc probe followed by the registered ADC device name as following,
172
173```c
174msh >adc probe adc1
175probe adc1 success
176```
177
178A channel of the enabled device can use the command `adc enable` followed by the channel number.
179
180```c
181msh >adc enable 5
182adc1 channel 5 enables success
183```
184
185To read data from a channel of an ADC device, you can use the command `adc read` followed by the channel number.
186
187```c
188msh >adc read 5
189adc1 channel 5  read value is 0x00000FFF
190msh >
191```
192
193To close a channel of an ADC device, you can use the command `adc disable` followed by the channel number.
194
195```c
196msh >adc disable 5
197adc1 channel 5 disable success
198msh >
199```
200
201# ADC Device Usage Example
202
203The specific usage of the ADC device can refer to the following sample code. The main steps of the sample code are as follows:
204
2051. First find the device handle based on the ADC device name “adc1”.
2062. After the device is enabled, read the sample value of the corresponding channel 5 of the adc1 device, and then calculate the actual voltage value with the resolution of 12 bits and the reference voltage of 3.3V.
2073. Finally close the corresponding channel of the ADC device.
208
209Running result: Print the raw and converted data which actually read , and print the calculated actual voltage value.
210
211```c
212/*
213 * Program Listing: ADC Device Usage Routines
214 * The routine exports the adc_sample command to the control terminal
215 * adc_sample Command call format: adc_sample
216 * Program function: The voltage value is sampled by the ADC device and converted to a numerical value.
217 *                   The sample code reference voltage is 3.3V and the number of conversion bits is 12 bits.
218*/
219
220#include <rtthread.h>
221#include <rtdevice.h>
222
223#define ADC_DEV_NAME        "adc1"      /* ADC device name */
224#define ADC_DEV_CHANNEL     5           /* ADC channel */
225#define REFER_VOLTAGE       330         /* Reference voltage 3.3V, data accuracy multiplied by 100 and reserve 2 decimal places*/
226#define CONVERT_BITS        (1 << 12)   /* The number of conversion bits is 12 */
227
228static int adc_vol_sample(int argc, char *argv[])
229{
230    rt_adc_device_t adc_dev;
231    rt_uint32_t value, vol;
232    rt_err_t ret = RT_EOK;
233
234    /* find the device */
235    adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
236    if (adc_dev == RT_NULL)
237    {
238        rt_kprintf("adc sample run failed! can't find %s device!\n", ADC_DEV_NAME);
239        return -RT_ERROR;
240    }
241
242    /* enable the device */
243    ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
244
245    /* read sampling values */
246    value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
247    rt_kprintf("the value is :%d \n", value);
248
249    /* convert to the corresponding voltage value */
250    vol = value * REFER_VOLTAGE / CONVERT_BITS;
251    rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
252
253    /* close the channel */
254    ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);
255
256    return ret;
257}
258/* export to the msh command list */
259MSH_CMD_EXPORT(adc_vol_sample, adc voltage convert sample);
260```
261
262
263
264