{"id":1700,"date":"2023-04-20T06:03:34","date_gmt":"2023-04-20T06:03:34","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=1700"},"modified":"2023-04-20T06:03:39","modified_gmt":"2023-04-20T06:03:39","slug":"working-with-stm32-and-acs712-current-sensor-measuring-ac-current","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=1700","title":{"rendered":"Working with STM32 and ACS712 Current Sensor: Measuring AC current"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"800\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/current-sensor-acs712-30a-robotics-bangladesh-1.jpg\" alt=\"\" class=\"wp-image-1701\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/current-sensor-acs712-30a-robotics-bangladesh-1.jpg 800w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/current-sensor-acs712-30a-robotics-bangladesh-1-300x300.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/current-sensor-acs712-30a-robotics-bangladesh-1-150x150.jpg 150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/current-sensor-acs712-30a-robotics-bangladesh-1-768x768.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/current-sensor-acs712-30a-robotics-bangladesh-1-750x750.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/current-sensor-acs712-30a-robotics-bangladesh-1-400x400.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/current-sensor-acs712-30a-robotics-bangladesh-1-250x250.jpg 250w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/figure>\n\n\n\n<p>In the previous guide (<a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=1687\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=1687\" target=\"_blank\">here<\/a>), we took a look at ACS712 current sensor and how to measure DC current. In this guide we shall use this sensor to measure AC current.<\/p>\n\n\n\n<p class=\"has-vivid-red-color has-text-color has-large-font-size\">NOTE: This guide uses main voltages. Please handle with care<\/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\"><li>What is RMS in AC.<\/li><li>ACS712 connection with main.<\/li><li>ACS712 connection with STM32F4.<\/li><li>Driver development.<\/li><li>Code.<\/li><li>Results.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. What RMS in AC:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>The term \u201cRMS\u201d stands for \u201cRoot-Mean-Squared\u201d. Most books define this as the \u201camount of AC power that produces the same heating effect as an equivalent DC power\u201d, or something similar along these lines, but an RMS value is more than just that.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>The term \u201cRMS\u201d stands for \u201cRoot-Mean-Squared\u201d. Most books define this as the \u201camount of AC power that produces the same heating effect as an equivalent DC power\u201d, or something similar along these lines, but an RMS value is more than just that.<\/p>\n\n\n\n<p>The RMS value is the square root of the mean (average) value of the squared function of the instantaneous values. The symbols used for defining an RMS value are&nbsp;V<sub>RMS<\/sub>&nbsp;or&nbsp;I<sub>RMS<\/sub>.<\/p>\n\n\n\n<p>The term RMS, ONLY refers to time-varying sinusoidal voltages, currents or complex waveforms were the magnitude of the waveform changes over time and is not used in DC circuit analysis or calculations were the magnitude is always constant.<\/p>\n\n\n\n<p>When used to compare the equivalent RMS voltage value of an alternating sinusoidal waveform that supplies the same electrical power to a given load as an equivalent DC circuit, the RMS value is called the \u201ceffective value\u201d and is generally presented as:&nbsp;V<sub>eff<\/sub>&nbsp;or&nbsp;I<sub>eff<\/sub>.<\/p>\n\n\n\n<p>In other words, the effective value is an equivalent DC value which tells you how many volts or amps of DC that a time-varying sinusoidal waveform is equal to in terms of its ability to produce the same power.<\/p>\n\n\n\n<p>For example, the domestic mains supply in the United Kingdom is 240Vac. This value is assumed to indicate an effective value of \u201c240 Volts rms\u201d. This means then that the sinusoidal rms voltage from the wall sockets of a UK home is capable of producing the same average positive power as 240 volts of steady DC voltage as shown below.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">RMS Voltage Equivalent<\/h3>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/www.electronics-tutorials.ws\/wp-content\/uploads\/2018\/05\/articles-rms1.gif\" alt=\"rms voltage\" title=\"RMS Voltage\" \/><\/figure><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. ACS712 connection with main:<\/h2>\n\n\n\n<p>The connection as following:<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"551\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/2023-04-20_08-24-46-1024x551.jpg\" alt=\"\" class=\"wp-image-1702\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/2023-04-20_08-24-46-1024x551.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/2023-04-20_08-24-46-300x162.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/2023-04-20_08-24-46-768x413.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/2023-04-20_08-24-46-1536x827.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/2023-04-20_08-24-46-1150x619.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/2023-04-20_08-24-46-750x404.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/2023-04-20_08-24-46-400x215.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/2023-04-20_08-24-46-250x135.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/2023-04-20_08-24-46.jpg 1746w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-vivid-red-color has-text-color has-large-font-size\">Please handle mains voltage with care.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. ACS712 connection with STM32F4:<\/h2>\n\n\n\n<p>The connection of I2C LCD and ACS712 Current sensor module as following:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"507\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-15-at-4.31.00-PM-1024x507.png\" alt=\"\" class=\"wp-image-1691\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-15-at-4.31.00-PM-1024x507.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-15-at-4.31.00-PM-300x149.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-15-at-4.31.00-PM-768x380.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-15-at-4.31.00-PM-1536x761.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-15-at-4.31.00-PM-2048x1014.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-15-at-4.31.00-PM-1150x570.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-15-at-4.31.00-PM-750x371.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-15-at-4.31.00-PM-400x198.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/Screenshot-2023-04-15-at-4.31.00-PM-250x124.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><tbody><tr><td>ACS712<\/td><td>STM32F4xx<\/td><\/tr><tr><td>Vcc<\/td><td>3V3<\/td><\/tr><tr><td>Vout<\/td><td>PA1<\/td><\/tr><tr><td>GND<\/td><td>GND<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Driver development:<\/h2>\n\n\n\n<p>In this guide, we shall use ADC with DMA in double buffer mode and to be triggered using timer. For more details check this guide <a href=\"https:\/\/blog.embeddedexpert.io\/?p=858\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=858\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p>Also, Kalman filter is used to obtain stable noiseless results, please refer to <a href=\"https:\/\/blog.embeddedexpert.io\/?p=791\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=791\" target=\"_blank\" rel=\"noreferrer noopener\">this<\/a> guide about Kalman filter.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>First, we shall declare two arrays with size of 100:<\/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;}\">#define size_of_data 100\n\n\nuint16_t current_data1[size_of_data];\n\nuint16_t current_data2[size_of_data];<\/pre><\/div>\n\n\n\n<p>When the second array is being filled, we shall process the fist one. <\/p>\n\n\n\n<p>extra variables needed:<\/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;}\">float calc,result;\n\nfloat current_result, current_previous;<\/pre><\/div>\n\n\n\n<p>Define the offset which is the raw adc value when no current is applied due to hall effect:<\/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;}\">#define offset 2010<\/pre><\/div>\n\n\n\n<p>In this case, it is 2010 (change according to your needing)&gt;<\/p>\n\n\n\n<p>For acs712 initializing, the following steps are required:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Enable floating point unit.<\/li><li>Set PA1 as analog mode.<\/li><li>Configure ADC to work in DMA and triggered using timer.<\/li><li>Configure DMA in double buffer mode and half transfer interrupt.<\/li><\/ul>\n\n\n\n<p>Enabling FPU:<\/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;}\">\t\/*Enable floating point unit:  Enable CP10 and CP11 full access*\/\n\tSCB-&gt;CPACR |=(1&lt;&lt;20);\n\tSCB-&gt;CPACR |=(1&lt;&lt;21);\n\tSCB-&gt;CPACR |=(1&lt;&lt;22);\n\tSCB-&gt;CPACR |=(1&lt;&lt;23);<\/pre><\/div>\n\n\n\n<p>Set PA1 as analog mode:<\/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;}\">\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN; \/\/enable gpio a clock\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODER1;  \/\/set the PA1 to analog mode<\/pre><\/div>\n\n\n\n<p>ADC setup:<\/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;}\">\/*ADC related set up*\/\n\n\tRCC-&gt;APB2ENR\t\t|=RCC_APB2ENR_ADC1EN;\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_DMA|ADC_CR2_DDS;\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_EXTEN_0;\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_EXTSEL_1|ADC_CR2_EXTSEL_2;\n\tADC1-&gt;SQR3\t\t\t|=(1&lt;&lt;ADC_SQR3_SQ1_Pos);\n\tADC1-&gt;SMPR2\t\t\t|=(0x07&lt;&lt;ADC_SMPR2_SMP1_Pos);<\/pre><\/div>\n\n\n\n<p>DMA setup:<\/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;}\">\/*DMA related setup*\/\n\tRCC-&gt;AHB1ENR\t\t|=RCC_AHB1ENR_DMA2EN;\n\tDMA2_Stream0-&gt;CR\t&amp;=~DMA_SxCR_EN;\n\n\twhile(DMA2_Stream0-&gt;CR ==DMA_SxCR_EN){;}\n\n\tDMA2_Stream0-&gt;CR\t|=DMA_SxCR_MSIZE_0|DMA_SxCR_PSIZE_0|DMA_SxCR_MINC|DMA_SxCR_HTIE|DMA_SxCR_CIRC|DMA_SxCR_DBM;\n\n\tDMA2_Stream0-&gt;PAR\t =(uint32_t)(&amp;(ADC1-&gt;DR));\n\n\tDMA2_Stream0-&gt;M0AR \t =(uint32_t )(current_data1);\n\n\tDMA2_Stream0-&gt;M1AR \t =(uint32_t )(current_data2);\n\n\tDMA2_Stream0-&gt;NDTR\t =size_of_data;\n\n\tNVIC_EnableIRQ(DMA2_Stream0_IRQn);<\/pre><\/div>\n\n\n\n<p>Timer setup:<\/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;}\">\t\/* Timer related setup*\/\n\tRCC-&gt;APB1ENR\t\t|=RCC_APB1ENR_TIM2EN;\n\tTIM2-&gt;PSC\t\t\t =1600-1;\n\tTIM2-&gt;ARR\t\t\t =10-1;\n\tTIM2-&gt;CR2\t\t\t|=TIM_CR2_MMS_1;<\/pre><\/div>\n\n\n\n<p>Launching everything:<\/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;}\">\t\/*Launch the ADC*\/\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_ADON;\n\t\/*Launch the DMA*\/\n\tDMA2_Stream0-&gt;CR \t|=DMA_SxCR_EN;\n\t\/*Launch the timer*\/\n\tTIM2-&gt;CR1\t\t\t|=TIM_CR1_CEN;<\/pre><\/div>\n\n\n\n<p>For interrupt handler:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Check interrupt source if it is half transfer, set finished to 1 and clear the pending flag:<\/li><\/ul>\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;}\">void DMA2_Stream0_IRQHandler(void)\n{\n\n\tif(((DMA2-&gt;LISR)&amp;DMA_LISR_HTIF0))\n\t{\n\t\tfinished=1;\n\t\tDMA2-&gt;LIFCR=DMA_LIFCR_CHTIF0;\n\t\t}\n\t\tNVIC_ClearPendingIRQ(DMA2_Stream0_IRQn);\n\t}\n<\/pre><\/div>\n\n\n\n<p>For getting the current:<\/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;}\">float get_acs712_current()\n{\n\tif(finished==1)\n\t{\n\t\tfinished=0;\n\n\t\tif((DMA2_Stream0-&gt;CR &amp; DMA_SxCR_CT)&gt;&gt; DMA_SxCR_CT_Pos == 1 )\n\t\t{\n\t\t\treturn calculate_rms(current_data2);\n\t\t}\n\n\t\telse\n\t\t{\n\t\t\treturn calculate_rms(current_data1);\n\t\t}\n\n\t}\n\n\telse\n\t{\n\t\treturn current_previous;\n\t}\n\n}<\/pre><\/div>\n\n\n\n<p>First check if DMA finshed filling the buffer by checking finished, if it is:<\/p>\n\n\n\n<p>The following steps are performed:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Set finished to 0.<\/li><li>Check the CT bit and see which buffer is used and process the buffer accordingly.<\/li><\/ul>\n\n\n\n<p>If the DMA has not yet finished the filling process, return previous values.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>RSM calculation:<\/p>\n\n\n\n<p>The equation to calculate the RMS is as following:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"480\" height=\"200\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/root-mean-square-formula.jpg\" alt=\"\" class=\"wp-image-1703\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/root-mean-square-formula.jpg 480w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/root-mean-square-formula-300x125.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/root-mean-square-formula-400x167.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/root-mean-square-formula-250x104.jpg 250w\" sizes=\"(max-width: 480px) 100vw, 480px\" \/><\/figure><\/div>\n\n\n\n<p>We need to summation of values squared then divide by number of samples and then the square root of the final value.<\/p>\n\n\n\n<p>Hence, the function 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;}\">static float calculate_rms(uint16_t * values)\n{\n\tcalc=0;\n\tfor (int i=0;i&lt;size_of_data;i++)\n\t{\n\t\tcalc=calc+((values[i]-offset) * (values[i]-offset));\n\t}\n\tcalc=calc\/size_of_data;\n\tcalc=sqrt(calc);\n\n\tresult=kalman_filter(calc);\n\tresult=0.0206*result-0.2;\n\tcurrent_previous=result;\n\treturn result;\n}<\/pre><\/div>\n\n\n\n<p>The steps as following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Reset the calc variable.<\/li><li>Multiply the current values minus the offset and added to previous calc value using for loop.<\/li><li>Divide the result by number of samples.<\/li><li>Take the square root of the result and store it in calc.<\/li><li>Store the filtered calc value into result.<\/li><li>Store the current result in current_previous.<\/li><li>Return the result.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p>For the kalman filter:<\/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;}\">static float kalman_filter(float RMS_Value)\n{\n    float x_k1_k1,x_k_k1;\n\n    static float RMS_OLD_Value=0;\n\n    float Z_k;\n\n    static float P_k1_k1;\n\n    static float Q = 0.01;\/\/Q: Regulation noise, Q increases, dynamic response becomes faster, and convergence stability becomes worse\n    static float R = 0.5; \/\/R: Test noise, R increases, dynamic response becomes slower, convergence stability becomes better\n    static float Kg = 0;\n    static float P_k_k1 = 1;\n\n    float kalman_rms;\n    static float kalman_rms_old=0;\n    Z_k = RMS_Value;\n    x_k1_k1 = kalman_rms_old;\n\n    x_k_k1 = x_k1_k1;\n    P_k_k1 = P_k1_k1 + Q;\n\n    Kg = P_k_k1\/(P_k_k1 + R);\n\n    kalman_rms = x_k_k1 + Kg * (Z_k - kalman_rms_old);\n    P_k1_k1 = (1 - Kg)*P_k_k1;\n    P_k_k1 = P_k1_k1;\n\n    RMS_OLD_Value = RMS_Value;\n    kalman_rms_old = kalman_rms;\n\n    return kalman_rms;\n}<\/pre><\/div>\n\n\n\n<p>Hence, the entire source 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;}\">#include &quot;stm32f4xx.h&quot;\n#include &quot;acs712.h&quot;\n#include &quot;math.h&quot;\n\n\nfloat calc,result;\n\n#define size_of_data 100\n\n\nuint16_t current_data1[size_of_data];\n\nuint16_t current_data2[size_of_data];\n\n\nvolatile uint8_t finished;\n\n#define offset 2010\n\n\nfloat current_result, current_previous;\n\n\n\n\n\n\nvoid acs712_init()\n{\n\t\/*Enable floating point unit:  Enable CP10 and CP11 full access*\/\n\tSCB-&gt;CPACR |=(1&lt;&lt;20);\n\tSCB-&gt;CPACR |=(1&lt;&lt;21);\n\tSCB-&gt;CPACR |=(1&lt;&lt;22);\n\tSCB-&gt;CPACR |=(1&lt;&lt;23);\n\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN; \/\/enable gpio a clock\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODER1;  \/\/set the PA1 to analog mode\n\n\n\n\t\/*ADC related set up*\/\n\n\tRCC-&gt;APB2ENR\t\t|=RCC_APB2ENR_ADC1EN;\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_DMA|ADC_CR2_DDS;\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_EXTEN_0;\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_EXTSEL_1|ADC_CR2_EXTSEL_2;\n\tADC1-&gt;SQR3\t\t\t|=(1&lt;&lt;ADC_SQR3_SQ1_Pos);\n\tADC1-&gt;SMPR2\t\t\t|=(0x07&lt;&lt;ADC_SMPR2_SMP1_Pos);\n\n\t\/*DMA related setup*\/\n\tRCC-&gt;AHB1ENR\t\t|=RCC_AHB1ENR_DMA2EN;\n\tDMA2_Stream0-&gt;CR\t&amp;=~DMA_SxCR_EN;\n\n\twhile(DMA2_Stream0-&gt;CR ==DMA_SxCR_EN){;}\n\n\tDMA2_Stream0-&gt;CR\t|=DMA_SxCR_MSIZE_0|DMA_SxCR_PSIZE_0|DMA_SxCR_MINC|DMA_SxCR_HTIE|DMA_SxCR_CIRC|DMA_SxCR_DBM;\n\n\tDMA2_Stream0-&gt;PAR\t =(uint32_t)(&amp;(ADC1-&gt;DR));\n\n\tDMA2_Stream0-&gt;M0AR \t =(uint32_t )(current_data1);\n\n\tDMA2_Stream0-&gt;M1AR \t =(uint32_t )(current_data2);\n\n\tDMA2_Stream0-&gt;NDTR\t =size_of_data;\n\n\tNVIC_EnableIRQ(DMA2_Stream0_IRQn);\n\n\t\/* Timer related setup*\/\n\tRCC-&gt;APB1ENR\t\t|=RCC_APB1ENR_TIM2EN;\n\tTIM2-&gt;PSC\t\t\t =1600-1;\n\tTIM2-&gt;ARR\t\t\t =10-1;\n\tTIM2-&gt;CR2\t\t\t|=TIM_CR2_MMS_1;\n\t\n\t\n\t\/*Launch the ADC*\/\n\tADC1-&gt;CR2\t\t\t|=ADC_CR2_ADON;\n\t\/*Launch the DMA*\/\n\tDMA2_Stream0-&gt;CR \t|=DMA_SxCR_EN;\n\t\/*Launch the timer*\/\n\tTIM2-&gt;CR1\t\t\t|=TIM_CR1_CEN;\n\n}\n\n\nstatic float kalman_filter(float RMS_Value)\n{\n    float x_k1_k1,x_k_k1;\n\n    static float RMS_OLD_Value=0;\n\n    float Z_k;\n\n    static float P_k1_k1;\n\n    static float Q = 0.01;\/\/Q: Regulation noise, Q increases, dynamic response becomes faster, and convergence stability becomes worse\n    static float R = 0.5; \/\/R: Test noise, R increases, dynamic response becomes slower, convergence stability becomes better\n    static float Kg = 0;\n    static float P_k_k1 = 1;\n\n    float kalman_rms;\n    static float kalman_rms_old=0;\n    Z_k = RMS_Value;\n    x_k1_k1 = kalman_rms_old;\n\n    x_k_k1 = x_k1_k1;\n    P_k_k1 = P_k1_k1 + Q;\n\n    Kg = P_k_k1\/(P_k_k1 + R);\n\n    kalman_rms = x_k_k1 + Kg * (Z_k - kalman_rms_old);\n    P_k1_k1 = (1 - Kg)*P_k_k1;\n    P_k_k1 = P_k1_k1;\n\n    RMS_OLD_Value = RMS_Value;\n    kalman_rms_old = kalman_rms;\n\n    return kalman_rms;\n}\n\n\nstatic float calculate_rms(uint16_t * values)\n{\n\tcalc=0;\n\tfor (int i=0;i&lt;size_of_data;i++)\n\t{\n\t\tcalc=calc+((values[i]-offset) * (values[i]-offset));\n\t}\n\tcalc=calc\/size_of_data;\n\tcalc=sqrt(calc);\n\n\tresult=kalman_filter(calc);\n\tresult=0.0206*result-0.2;\n\tcurrent_previous=result;\n\treturn result;\n}\n\n\nfloat get_acs712_current()\n{\n\tif(finished==1)\n\t{\n\t\tfinished=0;\n\n\t\tif((DMA2_Stream0-&gt;CR &amp; DMA_SxCR_CT)&gt;&gt; DMA_SxCR_CT_Pos == 1 )\n\t\t{\n\t\t\treturn calculate_rms(current_data2);\n\t\t}\n\n\t\telse\n\t\t{\n\t\t\treturn calculate_rms(current_data1);\n\t\t}\n\n\t}\n\telse\n\t{\n\t\treturn current_previous;\n\t}\n}\n\n\nvoid DMA2_Stream0_IRQHandler(void)\n{\n\n\tif(((DMA2-&gt;LISR)&amp;DMA_LISR_HTIF0))\n\t{\n\t\tfinished=1;\n\t\tDMA2-&gt;LIFCR=DMA_LIFCR_CHTIF0;\n\t\t}\n\t\tNVIC_ClearPendingIRQ(DMA2_Stream0_IRQn);\n\t}\n<\/pre><\/div>\n\n\n\n<p>main.c:<\/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;}\">#include &quot;stdio.h&quot;\n#include &quot;delay.h&quot;\n#include &quot;lcd.h&quot;\n#include &quot;i2c.h&quot;\n\n#include &quot;acs712.h&quot;\n\nfloat current_value;\n\nchar curr_data[15];\nint main(void)\n{\n\ti2c_init();\n\tsystick_init_ms(16000000);\n\tlcd_init();\n\tacs712_init();\n\n\twhile(1)\n\t{\n\n\t\tcurrent_value=get_acs712_current();\n\t\tif(millis()%400==0){\n\t\tsetCursor(0,0);\n\t\tlcd_send_string(&quot;AC Current=&quot;);\n\t\tsprintf(curr_data,&quot;%0.3f   &quot;,current_value);\n\t\tsetCursor(0,1);\n\t\tlcd_send_string(curr_data);}\n\n\t}\n}\n<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">5. Code:<\/h2>\n\n\n\n<p>You may download the entire source code from here:<\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/ACS712_Current_Sensor_AC_Current.zip\">ACS712_Current_Sensor_AC_Current<\/a><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/ACS712_Current_Sensor_AC_Current.zip\" class=\"wp-block-file__button\" download>Download<\/a><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6. Results:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/IMG_0615-1024x768.jpg\" alt=\"\" class=\"wp-image-1706\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/IMG_0615-1024x768.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/IMG_0615-300x225.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/IMG_0615-768x576.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/IMG_0615-1536x1152.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/IMG_0615-2048x1536.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/IMG_0615-1150x863.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/IMG_0615-750x563.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/IMG_0615-400x300.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/04\/IMG_0615-250x188.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous guide (here), we took a look at ACS712 current sensor and how to measure DC current. In this guide we shall use this sensor to measure AC current. NOTE: This guide uses main voltages. Please handle with care In this guide, we shall cover the following: What is RMS in AC. ACS712 [&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,19,11,7,12],"tags":[],"class_list":["post-1700","post","type-post","status-publish","format-standard","hentry","category-embedded-systems","category-lcd","category-peripheral-drivers","category-state-machine","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1700"}],"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=1700"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1700\/revisions"}],"predecessor-version":[{"id":1707,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1700\/revisions\/1707"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1700"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1700"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1700"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}