{"id":979,"date":"2022-05-31T07:37:52","date_gmt":"2022-05-31T07:37:52","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=979"},"modified":"2022-05-31T09:11:32","modified_gmt":"2022-05-31T09:11:32","slug":"measuring-the-rotation-speed-using-stm32-and-timer-in-encoder-mode","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=979","title":{"rendered":"Measuring The Rotation Speed Using STM32 and Timer in Encoder Mode"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"483\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/What-Does-RPM-Mean-in-Carss-1024x483.jpg\" alt=\"\" class=\"wp-image-980\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/What-Does-RPM-Mean-in-Carss-1024x483.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/What-Does-RPM-Mean-in-Carss-300x142.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/What-Does-RPM-Mean-in-Carss-768x362.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/What-Does-RPM-Mean-in-Carss-1150x542.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/What-Does-RPM-Mean-in-Carss-750x354.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/What-Does-RPM-Mean-in-Carss-400x189.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/What-Does-RPM-Mean-in-Carss-250x118.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/What-Does-RPM-Mean-in-Carss.jpg 1166w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>In the previous guide (<a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=430\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=430\" target=\"_blank\">here<\/a>), we saw how to configure timer to work in encoder mode. In this guide, we shall take it step further and measure the rotational speed in RPM (Revolutions per Minutes).<\/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>How to measure RPM.<\/li><li>Proposed experiment.<\/li><li>Firmware development.<\/li><li>Code.<\/li><li>Demo.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. How to Measure RPM:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Since the encoder is used to measure the RPM, the timer will overflow at each full rotation. Hence we can use interrupt to measure the timer between each full rotation in milliseconds.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"626\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-9.51.14-AM-1024x626.png\" alt=\"\" class=\"wp-image-983\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-9.51.14-AM-1024x626.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-9.51.14-AM-300x183.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-9.51.14-AM-768x470.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-9.51.14-AM-1536x939.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-9.51.14-AM-2048x1252.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-9.51.14-AM-1150x703.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-9.51.14-AM-750x459.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-9.51.14-AM-400x245.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-9.51.14-AM-250x153.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n\n<p>Since the timer will count up to the number of PPR provided by the encoder, an interrupt is generated. When the interrupt is generated, the time difference in milliseconds between each interrupt is measured and the the rptational speed in RPM is determined as following:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>First, measure the time difference in seconds as following:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"852\" height=\"158\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.18.08-AM.png\" alt=\"\" class=\"wp-image-984\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.18.08-AM.png 852w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.18.08-AM-300x56.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.18.08-AM-768x142.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.18.08-AM-750x139.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.18.08-AM-400x74.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.18.08-AM-250x46.png 250w\" sizes=\"(max-width: 852px) 100vw, 852px\" \/><\/figure><\/div>\n\n\n\n<p>Then determine the frequency in Hz as following:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"410\" height=\"124\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.19.53-AM.png\" alt=\"\" class=\"wp-image-985\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.19.53-AM.png 410w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.19.53-AM-300x91.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.19.53-AM-400x121.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.19.53-AM-250x76.png 250w\" sizes=\"(max-width: 410px) 100vw, 410px\" \/><\/figure><\/div>\n\n\n\n<p>Then determine the RPM by multiplying the frequency by 60:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"410\" height=\"100\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.20.54-AM.png\" alt=\"\" class=\"wp-image-986\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.20.54-AM.png 410w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.20.54-AM-300x73.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.20.54-AM-400x98.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-10.20.54-AM-250x61.png 250w\" sizes=\"(max-width: 410px) 100vw, 410px\" \/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">2. Proposed Experiment:<\/h2>\n\n\n\n<p>In order to test the code, a crude is conducted which includes the following components:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Stepper Motor NEMA17 (42HD2037)<\/li><li>Industrial Rotary encoder (LPD3806-360BM-G5-24C)<\/li><li>Coupling (6mm-6mm)<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"966\" height=\"300\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-11.47.42-AM.png\" alt=\"\" class=\"wp-image-992\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-11.47.42-AM.png 966w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-11.47.42-AM-300x93.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-11.47.42-AM-768x239.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-11.47.42-AM-750x233.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-11.47.42-AM-400x124.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/Screen-Shot-2022-05-31-at-11.47.42-AM-250x78.png 250w\" sizes=\"(max-width: 966px) 100vw, 966px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/IMG_8488-1024x768.jpg\" alt=\"\" class=\"wp-image-993\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/IMG_8488-1024x768.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/IMG_8488-300x225.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/IMG_8488-768x576.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/IMG_8488-1536x1152.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/IMG_8488-2048x1536.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/IMG_8488-1150x863.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/IMG_8488-750x563.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/IMG_8488-400x300.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/IMG_8488-250x188.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Firmware development:<\/h2>\n\n\n\n<p>Since the timer in encoder is already discussed, we shall implement it here differently, we shall use timer3 and pins PB4 and PB5 as inputs for the timer<\/p>\n\n\n\n<p>Hence the initializing the encoder mode 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;}\">void Encoder_init(uint16_t max_count)\n\t{\n\tRCC-&gt;APB1ENR|=RCC_APB1ENR_TIM3EN;\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOBEN;\n\n\t\/*GPIO B configuration for timer mode *\/\n\tGPIOB-&gt;MODER|=GPIO_MODER_MODE4_1|GPIO_MODER_MODE5_1;\n\tGPIOB-&gt;MODER&amp;=~(GPIO_MODER_MODE4_0|GPIO_MODER_MODE5_0);\n\tGPIOB-&gt;AFR[0]|=(AF02&lt;&lt;16)|(AF02&lt;&lt;20);\n\n\t\/*Timer configuration for encoder mode *\/\n\tTIM3-&gt;ARR = max_count; \/\/set the max count\n\t\/*Timer in encoder mode*\/\n\tTIM3-&gt;CCMR1 |= (TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0 );\n\tTIM3-&gt;CCER &amp;= ~(TIM_CCER_CC1P | TIM_CCER_CC2P);\n\tTIM3-&gt;SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1;\n\t\/*Enable interrupt*\/\n\tTIM3-&gt;DIER|=TIM_DIER_UIE;\n\tNVIC_EnableIRQ(TIM3_IRQn);\n\t\/*Start the timer *\/\n\tTIM3-&gt;CR1|=TIM_CR1_CEN;\n\n\t}\n<\/pre><\/div>\n\n\n\n<p>The interrupt handler 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;}\">void TIM3_IRQHandler(void)\n\t{\n\n\tif(TIM_SR_UIF&amp;&amp;TIM3-&gt;SR)\n\t\t{\n\t\tif(dir==1)\n\t\t\t{\n\t\t\ttime=millis()-first;\n\t\t\tdir=0;\n\t\t\t}\n\t\telse {\n\t\t\tfirst =millis();\n\t\t\tdir=1;\n\t\t\t}\n\n\t\tTIM3-&gt;SR&amp;=~TIM_SR_UIF;\n\t\t}\n\t}\n<\/pre><\/div>\n\n\n\n<p>For measuring RPM function:<\/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_rpm()\n\t{\n\ttime=(time\/1000); \/*from microseconds to seconds*\/\n\tif(0==time)return 0;\n\tfrequency=1\/time;\n\treturn frequency*60;\n\t}<\/pre><\/div>\n\n\n\n<p>If the time difference is zero, we shall return 0 indicating that the RPM is zero or beyond the capability of the current implantation.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Global variable:<\/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;stdint.h&quot;\n#include &quot;RPM_Encoder.h&quot;\n#include &quot;delay.h&quot;\nconst int AF02=0x02;\nvolatile uint64_t first, second, dir;\nfloat frequency;\nfloat time;<\/pre><\/div>\n\n\n\n<p>The header file:<\/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;}\">\n#ifndef RPM_ENCODER_H_\n#define RPM_ENCODER_H_\n\nvoid Encoder_init(uint16_t max_count);\nfloat get_rpm();\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Since the code requires millis function, systick timer is used to generate interrupt each 1 milliseconds and delay as well as 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;}\">#include &quot;delay.h&quot;\n#include &quot;stm32f4xx.h&quot;                  \/\/ Device header\n\n\nvolatile uint64_t ms,rms;\nvoid systick_init_ms(uint32_t freq)\n\t{\n\t__disable_irq();\n\tSysTick-&gt;LOAD=(freq\/1000)-1;\n\tSysTick-&gt;VAL=0;\n\tSysTick-&gt;CTRL=7; \/\/0b00000111;\n\tNVIC_SetPriority(SysTick_IRQn,7);\n\t__enable_irq();\t\n}\n\nuint64_t millis(void)\n\t{\n\t__disable_irq();\n\trms=ms; \/\/store current ms in rms\n\t__enable_irq();\n\treturn rms;\n\t}\n\nvoid SysTick_Handler(void){\nms++;\n}\n\nvoid delay(uint32_t delay)\n\t{\n\t\n\t\tuint64_t start=millis();\n\tdo\n\t\t{}while(millis()-start!=delay);\n\t}\n<\/pre><\/div>\n\n\n\n<p>The header:<\/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;}\">#ifndef __delay__H__\n#define __delay__H__\n\n\n#include &lt;stdint.h&gt;\nuint64_t millis(void);\nvoid systick_init_ms(uint32_t freq);\nvoid delay(uint32_t delay);\n#endif\n<\/pre><\/div>\n\n\n\n<p>For the lcd screen, i2c based one is used and you can get the code from <a href=\"https:\/\/blog.embeddedexpert.io\/?p=655\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=655\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p>For the stepper motor, please refer to the <a href=\"https:\/\/blog.embeddedexpert.io\/?p=594\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=594\" target=\"_blank\" rel=\"noreferrer noopener\">following<\/a> topic.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Code:<\/h2>\n\n\n\n<p>You may download the code from here:<\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/RPM_Encoder.zip\">RPM_Encoder<\/a><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/05\/RPM_Encoder.zip\" class=\"wp-block-file__button\" download>Download<\/a><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Demo:<\/h2>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"RPM measurement using timer in encoder mode\" width=\"1170\" height=\"658\" src=\"https:\/\/www.youtube.com\/embed\/b6g6kSf2zRs?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe>\n<\/div><\/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 saw how to configure timer to work in encoder mode. In this guide, we shall take it step further and measure the rotational speed in RPM (Revolutions per Minutes). In this guide, we shall cover the following: How to measure RPM. Proposed experiment. Firmware development. Code. Demo. 1. How [&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,12],"tags":[],"class_list":["post-979","post","type-post","status-publish","format-standard","hentry","category-embedded-systems","category-lcd","category-peripheral-drivers","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/979"}],"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=979"}],"version-history":[{"count":5,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/979\/revisions"}],"predecessor-version":[{"id":994,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/979\/revisions\/994"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=979"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=979"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=979"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}