blob: 51021fdc1aa8d49efafa92b0fbdac1d8a3cad9ca [file] [log] [blame]
Paul Sokolovsky0a4cc242016-06-08 00:57:41 +03001.. currentmodule:: pyb
Damien George8e701602014-11-04 18:25:20 +00002.. _pyb.ADC:
3
Daniel Campora861fad52015-09-15 19:54:58 +02004class ADC -- analog to digital conversion
5=========================================
Damien George88d30542014-10-31 01:37:19 +00006
Daniel Camporacfcf47c2015-06-10 23:29:56 +02007.. only:: port_pyboard
Damien George88d30542014-10-31 01:37:19 +00008
Daniel Camporacfcf47c2015-06-10 23:29:56 +02009 Usage::
Daniel Campora861fad52015-09-15 19:54:58 +020010
Daniel Camporacfcf47c2015-06-10 23:29:56 +020011 import pyb
12
13 adc = pyb.ADC(pin) # create an analog object from a pin
14 val = adc.read() # read an analog value
15
Mike Causerce166e62016-08-01 09:52:00 +100016 adc = pyb.ADCAll(resolution) # create an ADCAll object
Daniel Camporacfcf47c2015-06-10 23:29:56 +020017 val = adc.read_channel(channel) # read the given channel
18 val = adc.read_core_temp() # read MCU temperature
19 val = adc.read_core_vbat() # read MCU VBAT
20 val = adc.read_core_vref() # read MCU VREF
Damien George88d30542014-10-31 01:37:19 +000021
Peter Hinch85d3b612016-03-11 10:49:44 +000022
Damien George88d30542014-10-31 01:37:19 +000023Constructors
24------------
25
Daniel Campora861fad52015-09-15 19:54:58 +020026
Daniel Camporacfcf47c2015-06-10 23:29:56 +020027.. only:: port_pyboard
Damien George88d30542014-10-31 01:37:19 +000028
Daniel Camporacfcf47c2015-06-10 23:29:56 +020029 .. class:: pyb.ADC(pin)
Daniel Campora861fad52015-09-15 19:54:58 +020030
Daniel Camporacfcf47c2015-06-10 23:29:56 +020031 Create an ADC object associated with the given pin.
32 This allows you to then read analog values on that pin.
Damien George88d30542014-10-31 01:37:19 +000033
Damien George88d30542014-10-31 01:37:19 +000034Methods
35-------
36
Daniel Camporacfcf47c2015-06-10 23:29:56 +020037.. only:: port_pyboard
Damien George88d30542014-10-31 01:37:19 +000038
Paul Sokolovskya384a532016-06-08 16:21:28 +030039 .. method:: ADC.read()
Daniel Campora861fad52015-09-15 19:54:58 +020040
41 Read the value on the analog pin and return it. The returned value
42 will be between 0 and 4095.
43
Paul Sokolovskya384a532016-06-08 16:21:28 +030044 .. method:: ADC.read_timed(buf, timer)
Daniel Camporacfcf47c2015-06-10 23:29:56 +020045
Damien George7693ef32015-07-22 19:37:21 +010046 Read analog values into ``buf`` at a rate set by the ``timer`` object.
47
48 ``buf`` can be bytearray or array.array for example. The ADC values have
49 12-bit resolution and are stored directly into ``buf`` if its element size is
50 16 bits or greater. If ``buf`` has only 8-bit elements (eg a bytearray) then
51 the sample resolution will be reduced to 8 bits.
52
53 ``timer`` should be a Timer object, and a sample is read each time the timer
54 triggers. The timer must already be initialised and running at the desired
55 sampling frequency.
56
57 To support previous behaviour of this function, ``timer`` can also be an
58 integer which specifies the frequency (in Hz) to sample at. In this case
59 Timer(6) will be automatically configured to run at the given frequency.
60
61 Example using a Timer object (preferred way)::
62
63 adc = pyb.ADC(pyb.Pin.board.X19) # create an ADC on pin X19
64 tim = pyb.Timer(6, freq=10) # create a timer running at 10Hz
65 buf = bytearray(100) # creat a buffer to store the samples
66 adc.read_timed(buf, tim) # sample 100 values, taking 10s
67
68 Example using an integer for the frequency::
69
Daniel Camporacfcf47c2015-06-10 23:29:56 +020070 adc = pyb.ADC(pyb.Pin.board.X19) # create an ADC on pin X19
71 buf = bytearray(100) # create a buffer of 100 bytes
72 adc.read_timed(buf, 10) # read analog values into buf at 10Hz
73 # this will take 10 seconds to finish
74 for val in buf: # loop over all values
75 print(val) # print the value out
Daniel Campora861fad52015-09-15 19:54:58 +020076
Daniel Camporacfcf47c2015-06-10 23:29:56 +020077 This function does not allocate any memory.
78
Peter Hinchc13b2f22016-01-11 06:48:35 +000079The ADCAll Object
80-----------------
81
Peter Hinch85d3b612016-03-11 10:49:44 +000082.. only:: port_pyboard
83
84 Instantiating this changes all ADC pins to analog inputs. The raw MCU temperature,
85 VREF and VBAT data can be accessed on ADC channels 16, 17 and 18 respectively.
86 Appropriate scaling will need to be applied. The temperature sensor on the chip
87 has poor absolute accuracy and is suitable only for detecting temperature changes.
88
89 The ``ADCAll`` ``read_core_vbat()`` and ``read_core_vref()`` methods read
90 the backup battery voltage and the (1.21V nominal) reference voltage using the
91 3.3V supply as a reference. Assuming the ``ADCAll`` object has been Instantiated with
92 ``adc = pyb.ADCAll(12)`` the 3.3V supply voltage may be calculated:
93
94 ``v33 = 3.3 * 1.21 / adc.read_core_vref()``
95
96 If the 3.3V supply is correct the value of ``adc.read_core_vbat()`` will be
97 valid. If the supply voltage can drop below 3.3V, for example in in battery
98 powered systems with a discharging battery, the regulator will fail to preserve
99 the 3.3V supply resulting in an incorrect reading. To produce a value which will
100 remain valid under these circumstances use the following:
101
102 ``vback = adc.read_core_vbat() * 1.21 / adc.read_core_vref()``
103
104 It is possible to access these values without incurring the side effects of ``ADCAll``::
105
106 def adcread(chan): # 16 temp 17 vbat 18 vref
107 assert chan >= 16 and chan <= 18, 'Invalid ADC channel'
108 start = pyb.millis()
109 timeout = 100
110 stm.mem32[stm.RCC + stm.RCC_APB2ENR] |= 0x100 # enable ADC1 clock.0x4100
111 stm.mem32[stm.ADC1 + stm.ADC_CR2] = 1 # Turn on ADC
112 stm.mem32[stm.ADC1 + stm.ADC_CR1] = 0 # 12 bit
113 if chan == 17:
114 stm.mem32[stm.ADC1 + stm.ADC_SMPR1] = 0x200000 # 15 cycles
115 stm.mem32[stm.ADC + 4] = 1 << 23
116 elif chan == 18:
117 stm.mem32[stm.ADC1 + stm.ADC_SMPR1] = 0x1000000
118 stm.mem32[stm.ADC + 4] = 0xc00000
119 else:
120 stm.mem32[stm.ADC1 + stm.ADC_SMPR1] = 0x40000
121 stm.mem32[stm.ADC + 4] = 1 << 23
122 stm.mem32[stm.ADC1 + stm.ADC_SQR3] = chan
123 stm.mem32[stm.ADC1 + stm.ADC_CR2] = 1 | (1 << 30) | (1 << 10) # start conversion
124 while not stm.mem32[stm.ADC1 + stm.ADC_SR] & 2: # wait for EOC
125 if pyb.elapsed_millis(start) > timeout:
126 raise OSError('ADC timout')
127 data = stm.mem32[stm.ADC1 + stm.ADC_DR] # clear down EOC
128 stm.mem32[stm.ADC1 + stm.ADC_CR2] = 0 # Turn off ADC
129 return data
130
131 def v33():
132 return 4096 * 1.21 / adcread(17)
133
134 def vbat():
135 return 1.21 * 2 * adcread(18) / adcread(17) # 2:1 divider on Vbat channel
136
137 def vref():
138 return 3.3 * adcread(17) / 4096
139
140 def temperature():
141 return 25 + 400 * (3.3 * adcread(16) / 4096 - 0.76)
142
143