{"id":3257,"date":"2025-02-27T14:13:49","date_gmt":"2025-02-27T14:13:49","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=3257"},"modified":"2025-02-27T14:13:51","modified_gmt":"2025-02-27T14:13:51","slug":"using-micropython-for-stm32f411-analog-read","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=3257","title":{"rendered":"Using Micropython for STM32F411: Analog Read"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/DALL\u00b7E-2025-02-13-09.56.17-A-detailed-high-quality-digital-illustration-depicting-the-process-of-compiling-and-flashing-MicroPython-onto-an-STM32F411-Nucleo-board.-The-image-sh-3.webp\" alt=\"\" class=\"wp-image-3258\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/DALL\u00b7E-2025-02-13-09.56.17-A-detailed-high-quality-digital-illustration-depicting-the-process-of-compiling-and-flashing-MicroPython-onto-an-STM32F411-Nucleo-board.-The-image-sh-3.webp 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/DALL\u00b7E-2025-02-13-09.56.17-A-detailed-high-quality-digital-illustration-depicting-the-process-of-compiling-and-flashing-MicroPython-onto-an-STM32F411-Nucleo-board.-The-image-sh-3-300x300.webp 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/DALL\u00b7E-2025-02-13-09.56.17-A-detailed-high-quality-digital-illustration-depicting-the-process-of-compiling-and-flashing-MicroPython-onto-an-STM32F411-Nucleo-board.-The-image-sh-3-150x150.webp 150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/DALL\u00b7E-2025-02-13-09.56.17-A-detailed-high-quality-digital-illustration-depicting-the-process-of-compiling-and-flashing-MicroPython-onto-an-STM32F411-Nucleo-board.-The-image-sh-3-768x768.webp 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/DALL\u00b7E-2025-02-13-09.56.17-A-detailed-high-quality-digital-illustration-depicting-the-process-of-compiling-and-flashing-MicroPython-onto-an-STM32F411-Nucleo-board.-The-image-sh-3-750x750.webp 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/DALL\u00b7E-2025-02-13-09.56.17-A-detailed-high-quality-digital-illustration-depicting-the-process-of-compiling-and-flashing-MicroPython-onto-an-STM32F411-Nucleo-board.-The-image-sh-3-400x400.webp 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/DALL\u00b7E-2025-02-13-09.56.17-A-detailed-high-quality-digital-illustration-depicting-the-process-of-compiling-and-flashing-MicroPython-onto-an-STM32F411-Nucleo-board.-The-image-sh-3-250x250.webp 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>In this guide, we shall see how to use micropython to read analog signal applied to analog pin of STM32F411 Nucleo-64. <\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>In this guide, we shall cover the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>What is ADC.<\/li>\n\n\n\n<li>Firmware Development.<\/li>\n\n\n\n<li>Results.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. What is ADC:<\/h2>\n\n\n\n<p>In&nbsp;electronics, an&nbsp;<strong>analog-to-digital converter<\/strong>&nbsp;(<strong>ADC<\/strong>,&nbsp;<strong>A\/D<\/strong>, or&nbsp;<strong>A-to-D<\/strong>) is a system that converts an&nbsp;analog signal, such as a sound picked up by a&nbsp;microphone&nbsp;or light entering a&nbsp;digital camera, into a&nbsp;digital signal that can be read by STM32.&nbsp;<\/p>\n\n\n\n<p>ADCs can vary greatly between microcontroller. The ADC on the STM32F411 is a 12-bit ADC meaning it has the ability to detect 4096(2^12) discrete analog levels (which is also called&nbsp;<strong><em>Resolution<\/em><\/strong>). Some microcontrollers have 8-bit ADCs (2^8 = 256 discrete levels) and some have 16-bit ADCs (2^16 = 65,536 discrete levels).<\/p>\n\n\n\n<p>The way an ADC works is fairly complex. There are a few different ways to achieve this feat (see Wikipedia&nbsp;<a href=\"http:\/\/en.wikipedia.org\/wiki\/Analog-to-digital_converter#ADC_types\">for a list<\/a>), but one of the most common technique uses the analog voltage to charge up an internal capacitor and then measure the time it takes to discharge across an internal resistor. The microcontroller monitors the number of clock cycles that pass before the capacitor is discharged. This number of cycles is the number that is returned once the ADC is complete. Other methods used called Successive-approximation ADC which you can read about it in details from this wikipedia page (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Successive-approximation_ADC\" target=\"_blank\" rel=\"noreferrer noopener\">Link<\/a>)<\/p>\n\n\n\n<p>For more information about how the adc of STM32F4 works, refer to the user manual (RM0383).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"relating-adc-value-to-voltage\">1.2 Relating ADC Value to Voltage<\/h2>\n\n\n\n<p>The ADC reports a&nbsp;<em>ratio metric value<\/em>. This means that the ADC assumes 3.3V is 4095 and anything less than 3.3V will be a ratio between 3.3V and 4095.<\/p>\n\n\n\n<p>For example if the sensor has output voltage of 1.66V hence the ADC output will be (4095\/3.3)*1.66=2059.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Firmware Development:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Before we start the firmware development, we need to install and configure thonny. For more details, please refer to this guide <a href=\"https:\/\/blog.embeddedexpert.io\/?p=3237\" data-type=\"link\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=3237\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p>After the configuration, we can develop the firmware.<\/p>\n\n\n\n<p>We start by importing machine as following:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">import machine<\/pre><\/div>\n\n\n\n<p>Also, include the time for delays as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">import time<\/pre><\/div>\n\n\n\n<p>Since the MCU has multiple ADC pins which they are fixed to STM32F411RE, we can declare the adc as following:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">adc1 = machine.ADC(0)  # ADC_CH0 ADC input\nadc2 = machine.ADC(1)  # ADC_CH1 ADC input<\/pre><\/div>\n\n\n\n<p>By default, the ADC is initialized in polling mode, single conversion.<\/p>\n\n\n\n<p>Declare while loop as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">while True:\n    value = adc1.read_u16()\n    value = value &gt;&gt; 4  # Scale down to 12 bits (0 to 4095)\n    voltage = value * (3.3 \/ 4095)  # Convert to volts\n    print(&quot;ADC1 Value:&quot;, value, &quot;Voltage:&quot;, voltage, &quot;V&quot;)\n    \n    value = adc2.read_u16()\n    value = value &gt;&gt; 4  # Scale down to 12 bits (0 to 4095)\n    voltage = value * (3.3 \/ 4095)  # Convert to volts\n    print(&quot;ADC2 Value:&quot;, value, &quot;Voltage:&quot;, voltage, &quot;V&quot;)\n    time.sleep(1)  # Read every 1 second<\/pre><\/div>\n\n\n\n<p>In the while, we shall read the ADC pin individually by using read_u16.<\/p>\n\n\n\n<p>Since the function map the value to 16-bit, we need to convert it back to 12 by using the following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">value = value&gt;&gt;4<\/pre><\/div>\n\n\n\n<p>This will convert the value back to correct 12-bit.<\/p>\n\n\n\n<p>Hence, the full code as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">import machine\nimport time\n\nadc1 = machine.ADC(0)  # ADC_CH0 ADC input\nadc2 = machine.ADC(1)  # ADC_CH1 ADC input\n\n\nwhile True:\n    value = adc1.read_u16()\n    value = value &gt;&gt; 4  # Scale down to 12 bits (0 to 4095)\n    voltage = value * (3.3 \/ 4095)  # Convert to volts\n    print(&quot;ADC1 Value:&quot;, value, &quot;Voltage:&quot;, voltage, &quot;V&quot;)\n    \n    value = adc2.read_u16()\n    value = value &gt;&gt; 4  # Scale down to 12 bits (0 to 4095)\n    voltage = value * (3.3 \/ 4095)  # Convert to volts\n    print(&quot;ADC2 Value:&quot;, value, &quot;Voltage:&quot;, voltage, &quot;V&quot;)\n    time.sleep(1)  # Read every 1 second\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Click on run as following:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"706\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/2025-02-15_15-36-02-1024x706.jpg\" alt=\"\" class=\"wp-image-3246\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/2025-02-15_15-36-02-1024x706.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/2025-02-15_15-36-02-300x207.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/2025-02-15_15-36-02-768x530.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/2025-02-15_15-36-02-1536x1059.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/2025-02-15_15-36-02-2048x1412.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/2025-02-15_15-36-02-1150x793.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/2025-02-15_15-36-02-750x517.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/2025-02-15_15-36-02-400x276.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/2025-02-15_15-36-02-250x172.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Results:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>In the shell, you should see the results as following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"365\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-27-at-5.12.16\u202fPM-1024x365.png\" alt=\"\" class=\"wp-image-3259\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-27-at-5.12.16\u202fPM-1024x365.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-27-at-5.12.16\u202fPM-300x107.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-27-at-5.12.16\u202fPM-768x274.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-27-at-5.12.16\u202fPM-1536x547.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-27-at-5.12.16\u202fPM-1150x410.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-27-at-5.12.16\u202fPM-750x267.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-27-at-5.12.16\u202fPM-400x142.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-27-at-5.12.16\u202fPM-250x89.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/02\/Screenshot-2025-02-27-at-5.12.16\u202fPM.png 1892w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding \ud83d\ude09<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, we shall see how to use micropython to read analog signal applied to analog pin of STM32F411 Nucleo-64. In this guide, we shall cover the following: 1. What is ADC: In&nbsp;electronics, an&nbsp;analog-to-digital converter&nbsp;(ADC,&nbsp;A\/D, or&nbsp;A-to-D) is a system that converts an&nbsp;analog signal, such as a sound picked up by a&nbsp;microphone&nbsp;or light entering a&nbsp;digital [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,11,12],"tags":[],"class_list":["post-3257","post","type-post","status-publish","format-standard","hentry","category-embedded-systems","category-peripheral-drivers","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3257"}],"collection":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3257"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3257\/revisions"}],"predecessor-version":[{"id":3260,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/3257\/revisions\/3260"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3257"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3257"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3257"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}