{"id":3280,"date":"2025-02-03T06:19:46","date_gmt":"2025-02-03T06:19:46","guid":{"rendered":"https:\/\/iotthinghub.com\/?p=3280"},"modified":"2025-02-03T08:28:58","modified_gmt":"2025-02-03T08:28:58","slug":"i2c-weather-forecasting","status":"publish","type":"post","link":"https:\/\/iotthinghub.com\/?p=3280","title":{"rendered":"I2C : Weather Forecasting"},"content":{"rendered":"\n<p class=\"has-text-color has-link-color wp-elements-1 wp-block-paragraph\" style=\"color:#5c5c5c\">In our previous article we use AHT20 sensor which can measure temperature &amp; humidity. But it can\u2019t measure air biometric pressure, so we use another sensor either BME280 or BMP280. Both BMP280 &amp; BME280 can measure biometric pressure &amp; temperature, but BME280 has one extra feature of measuring humidity along with temperature &amp; pressure. In this article we use both AHT20 &amp; BMP280 for weather forecasting, both has I<sup>2<\/sup>C interfacing feature. We use OLED in the same I<sup>2<\/sup>C bus. Let\u2019s not wasting any time &amp; go to our I<sup>2<\/sup>C device BMP280.<\/p>\n\n\n\n<p class=\"has-text-color has-link-color wp-elements-2 wp-block-paragraph\" style=\"color:#5c5c5c\">BMP280 can operate in 3 different modes, i.e. sleep mode, normal mode &amp; forced mode. The I\u00b2C slave BMP280 has 7-bit device address of 111011x. The 6 MSB bits are fixed. The last bit is changeable by SDO value and can be changed during operation. Connecting SDO to GND results in slave address 1110110 (0x76); connection it to V<sub>DDIO<\/sub> results in slave address 1110111 (0x77). Let first look at the register mapping &amp; setting according to our requirement.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"390\" src=\"https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/Table-1-1024x390.jpg\" alt=\"\" class=\"wp-image-3285\" srcset=\"https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/Table-1-1024x390.jpg 1024w, https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/Table-1-300x114.jpg 300w, https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/Table-1-768x293.jpg 768w, https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/Table-1.jpg 1488w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-text-color has-link-color wp-elements-3 wp-block-paragraph\" style=\"color:#5c5c5c\">According to the memory map if we first read the register 0xD0 we get the chip id 0x58. Example for soft reset just transmits 0xB6 to the control register 0xE0 we will read out 0x00 as soon as reset done. The HAL Library has lots of I<sup>2<\/sup>C function. For making BMP280 library we just use one function-<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\nHAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)\n<\/pre><\/div>\n\n\n<p class=\"has-text-color has-link-color wp-elements-4 wp-block-paragraph\" style=\"color:#5c5c5c\">Here,<\/p>\n\n\n\n<ul style=\"color:#5c5c5c\" class=\"wp-block-list has-text-color has-link-color wp-elements-5\">\n<li>DevAddress &nbsp;&nbsp;: 1&lt;&lt;(0x76 or 0x77) = 0xEC or 0xEE<\/li>\n\n\n\n<li>MemAddress : Internal memory address<\/li>\n\n\n\n<li>MemAddSize : Size of internal memory address<\/li>\n\n\n\n<li>pData &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: Pointer to data buffer<\/li>\n\n\n\n<li>Size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Amount of data to be sent<\/li>\n\n\n\n<li>Timeout &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: Timeout duration<\/li>\n<\/ul>\n\n\n\n<p class=\"has-text-color has-link-color wp-elements-6 wp-block-paragraph\" style=\"color:#5c5c5c\">For example to check if the device has connected or not we need to transmit 0xD0 &amp; receive value will be 0x58. The SD0 pin to GND.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\n#define BME280_ADDRESS 0xEC\nuint8_t chipID;\nHAL_I2C_Mem_Read(&amp;hi2c1,BME280_ADDRESS,0xD0,1,&amp;chipID,1,1000);\n<\/pre><\/div>\n\n\n<p class=\"has-text-color has-link-color wp-elements-7 wp-block-paragraph\" style=\"color:#5c5c5c\">The variable chipID will have the value 0x58, otherwise check the SD0 pin or connection.<\/p>\n\n\n\n<p class=\"has-text-color has-link-color wp-elements-8 wp-block-paragraph\" style=\"color:#5c5c5c\">For initialization we will only concern with config -&gt; 0xF5, ctrl_meas -&gt; 0xF4 register.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"428\" src=\"https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/function-3-1024x428.jpg\" alt=\"\" class=\"wp-image-3295\" srcset=\"https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/function-3-1024x428.jpg 1024w, https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/function-3-300x125.jpg 300w, https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/function-3-768x321.jpg 768w, https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/function-3.jpg 1479w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-text-color has-link-color wp-elements-9 wp-block-paragraph\" style=\"color:#5c5c5c\">For proper operation the datasheet can provide optimal settings as below-<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"212\" src=\"https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/tabile-2-1024x212.jpg\" alt=\"\" class=\"wp-image-3299\" srcset=\"https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/tabile-2-1024x212.jpg 1024w, https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/tabile-2-300x62.jpg 300w, https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/tabile-2-768x159.jpg 768w, https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/tabile-2.jpg 1464w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-text-color has-link-color wp-elements-10 wp-block-paragraph\" style=\"color:#5c5c5c\">For example to operate in Indoor Navigation mode, the setting will be o<sub>mode<\/sub>-&gt; normal, f<sub>filter <\/sub>-&gt; filter coefficient 16, C<sub>i2c <\/sub>-&gt; SPI off,&nbsp; t<sub>standby <\/sub>-&gt; 0.5ms, T<sub>oversampling <\/sub>-&gt; Oversampling x 2, P<sub>oversampling <\/sub>-&gt; Oversampling x 16.<\/p>\n\n\n\n<ul style=\"color:#5c5c5c\" class=\"wp-block-list has-text-color has-link-color wp-elements-11\">\n<li>config Reg &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0xF5 -&gt; 0b00010000 or 0x10<\/li>\n\n\n\n<li>ctrl_meas Reg 0xF4 -&gt; 0b01010111 or 0x57<\/li>\n<\/ul>\n\n\n\n<p class=\"has-text-color has-link-color wp-elements-12 wp-block-paragraph\" style=\"color:#5c5c5c\">Next step is to read out Trimming parameter. The trimming parameters are programmed into the devices\u2019 non-volatile memory (NVM) during production and cannot be altered by the customer. Each compensation word is a 16-bit signed or unsigned integer value stored in two\u2019s complement. As the memory is organized into 8-bit words, two words must always be combined in order to represent the compensation word. The 8-bit registers are named calib00\u2026calib25 and are stored at memory addresses 0x88\u20260xA1. The corresponding compensation words are named dig_T# for temperature compensation related values and dig_P# for pressure compensation related values.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"238\" src=\"https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/function-4-1024x238.jpg\" alt=\"\" class=\"wp-image-3303\" srcset=\"https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/function-4-1024x238.jpg 1024w, https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/function-4-300x70.jpg 300w, https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/function-4-768x178.jpg 768w, https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/function-4.jpg 1278w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-text-color has-link-color wp-elements-13 wp-block-paragraph\" style=\"color:#5c5c5c\">Let\u2019s look at the code for initialization-<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\n#define BME280_ADDRESS 0xEC\nuint16_t dig_T1, dig_P1; \nint16_t  dig_T2, dig_T3, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9;\nvoid BMP280_init(uint8_t t_sb,uint8_t filter, uint8_t osrs_t, uint8_t osrs_p,uint8_t mode)\n{\n\tuint8_t u8_config,u8_ctrl_meas;\n\tu8_config=(t_sb&lt;&lt;5)|(filter&lt;&lt;2);\n\tu8_ctrl_meas=(osrs_t&lt;&lt;5)|(osrs_p&lt;&lt;2)|mode;\n\tHAL_I2C_Mem_Read(&amp;hi2c1,BME280_ADDRESS,CONFIG_REG,1,&amp;u8_config,1,1000);\n\tHAL_I2C_Mem_Read(&amp;hi2c1,BME280_ADDRESS,CTRL_MEAS_REG,1,&amp;u8_ctrl_meas,1,1000);\n\tuint8_t trimming_buff&#x5B;24];\n    HAL_I2C_Mem_Read(&amp;hi2c1,BME280_ADDRESS,TRIMMING_PRA,1,trimming_buff,24,1000);\n\tdig_T1=(trimming_buff&#x5B;0])+(trimming_buff&#x5B;1]&lt;&lt;8);\n\tdig_T2=(trimming_buff&#x5B;2])+(trimming_buff&#x5B;3]&lt;&lt;8);\n\tdig_T3=(trimming_buff&#x5B;4])+(trimming_buff&#x5B;5]&lt;&lt;8);\n\tdig_P1=(trimming_buff&#x5B;6])+(trimming_buff&#x5B;7]&lt;&lt;8);\n\tdig_P2=(trimming_buff&#x5B;8])+(trimming_buff&#x5B;9]&lt;&lt;8);\n\tdig_P3=(trimming_buff&#x5B;10])+(trimming_buff&#x5B;11]&lt;&lt;8);\n\tdig_P4=(trimming_buff&#x5B;12])+(trimming_buff&#x5B;13]&lt;&lt;8);\n\tdig_P5=(trimming_buff&#x5B;14])+(trimming_buff&#x5B;15]&lt;&lt;8);\n\tdig_P6=(trimming_buff&#x5B;16])+(trimming_buff&#x5B;17]&lt;&lt;8);\n\tdig_P7=(trimming_buff&#x5B;18])+(trimming_buff&#x5B;19]&lt;&lt;8);\n\tdig_P8=(trimming_buff&#x5B;20])+(trimming_buff&#x5B;21]&lt;&lt;8);\n\tdig_P9=(trimming_buff&#x5B;22])+(trimming_buff&#x5B;23]&lt;&lt;8);\n} \n<\/pre><\/div>\n\n\n<p class=\"has-text-color has-link-color wp-elements-14 wp-block-paragraph\" style=\"color:#5c5c5c\">The Trimming parameters are saved in the variables. The \u201cstatus\u201d register -&gt; 0xF3 contains two bits which indicate the status of the device. Bit3 represents the measuring status &amp; Bit0 represents image register update. After measuring the data will store in the \u201ctemp\u201d register. Reading procedure will be from register 0xF7 to 0xFC total 6byte, upper 3byte contents temperature_row value &amp; lower 3byte content pressure_row value.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\nint32_t temperature_raw, pressure_raw;\nuint8_t status, rx_buff&#x5B;6];\n\tdo\n\t{\n\tHAL_I2C_Mem_Read(&amp;hi2c1,BME280_ADDRESS,STATUS_REG,1,&amp;status,1,1000);\n\t} while(((status&amp;0b00001000)==8)||((status&amp;0b00000001)==1));\n    HAL_I2C_Mem_Read(&amp;hi2c1,BME280_ADDRESS,TEMP_REG,1,rx_buff,6,1000);\n    temperature_raw=(rx_buff&#x5B;3]&lt;&lt;12)+(rx_buff&#x5B;4]&lt;&lt;4)+(rx_buff&#x5B;5]&gt;&gt;4);\n    pressure_raw=(rx_buff&#x5B;0]&lt;&lt;12)+(rx_buff&#x5B;1]&lt;&lt;4)+(rx_buff&#x5B;2]&gt;&gt;4);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">For measuring of temperature &amp; pressure the time will be, Total time T<sub>total <\/sub>= T<sub>measure <\/sub>+ T<sub>standby .<\/sub><\/p>\n\n\n\n<p class=\"has-text-color has-link-color wp-elements-15 wp-block-paragraph\" style=\"color:#5c5c5c\">For calculating the API available from Bosch Sensortec to perform readout and compensation. According to the datasheet here we use 32bit calculation-<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\n    float BMP280_Temperature, BMP280_Pressure, BMP280_Altitude;\n    double var1, var2;\n\tvar1=(((double)temperature_raw)\/16384.0-((double)dig_T1)\/1024.0)*((double)dig_T2);\n\tvar2=((((double)temperature_raw)\/131072.0-((double)dig_T1)\/8192.0)*(((double)temperature_raw)\/131072.0-((double)dig_T1)\/8192.0))*((double)dig_T3);\n\tdouble t_fine = (int32_t)(var1+var2);\n    volatile\tfloat T = (var1+var2)\/5120.0;\n\tBMP280_Temperature=T;\n\tvar1=((double)t_fine\/2.0)-64000.0;\n    var2=var1*var1*((double)dig_P6)\/32768.0;\n    var2=var2+var1*((double)dig_P5)*2.0;\n    var2=(var2\/4.0)+(((double)dig_P4)*65536.0);\n    var1=(((double)dig_P3)*var1*var1\/524288.0+((double)dig_P2)*var1)\/524288.0;\n    var1=(1.0+var1\/32768.0)*((double)dig_P1);\n\tvolatile double p=1048576.0-(double)pressure_raw;\n    p=(p-(var2\/4096.0))*6250.0\/var1;\n    var1=((double)dig_P9)*p*p\/2147483648.0;\n    var2=p*((double)dig_P8)\/32768.0;\n    p=p+(var1+var2+((double)dig_P7))\/16.0;\n    BMP280_Pressure=p;\n<\/pre><\/div>\n\n\n<p class=\"has-text-color has-link-color wp-elements-16 wp-block-paragraph\" style=\"color:#5c5c5c\">For altitude calculation use barometric function &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/p>\n\n\n\n<p class=\"has-text-color has-link-color wp-elements-17 wp-block-paragraph\" style=\"color:#252525\">Altitude, h = 44330 x (1-(P\/P<sub>0<\/sub>)<sup>1\/5.255<\/sup>) m, current sea level P<sub>0<\/sub> = 1013.25 millibars<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\n#include &quot;math.h&quot;\nBMP280_Altitude=44330.0*(1-pow(BMP280_Pressure\/101325.0,1.0\/5.255));\n<\/pre><\/div>\n\n\n<p class=\"has-text-color has-link-color wp-elements-18 wp-block-paragraph\" style=\"color:#5c5c5c\">For data &amp; time use RTC function, please go to my RTC article for detail. For configuration &amp; output please follow my Youtube video.<\/p>\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 title=\"STM32 I2C : \u22c6.\u0cc3\u0fd4\u26c8 \u0741 \u02d6*\u0f04 Weather Forecasting \ud83c\udf21\ufe0f  AHT20 + BMP280\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/A-lRYOUSe3Y?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-7387b849 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-3e41869c wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/Weather-Forecasting.rar\" style=\"padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--50);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--50)\">Download<\/a><\/div>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p class=\"has-text-color has-link-color wp-elements-19 wp-block-paragraph\" style=\"color:#252525\"><a href=\"https:\/\/iotthinghub.com\/wp-content\/uploads\/2025\/02\/Weather-Forecasting.rar\">Weather Forecasting.rar<\/a><\/p>\n<\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In our previous article we use AHT20 sensor which can measure temperature &amp; humidity. But it can\u2019t measure air biometric pressure, so we use another sensor either BME280 or BMP280. Both BMP280 &amp; BME280 can measure biometric pressure &amp; temperature, but BME280 has one extra feature of measuring humidity along with temperature &amp; pressure. In [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23],"tags":[],"class_list":["post-3280","post","type-post","status-publish","format-standard","hentry","category-stm-arm-tutorials"],"_links":{"self":[{"href":"https:\/\/iotthinghub.com\/index.php?rest_route=\/wp\/v2\/posts\/3280","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/iotthinghub.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/iotthinghub.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/iotthinghub.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/iotthinghub.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3280"}],"version-history":[{"count":34,"href":"https:\/\/iotthinghub.com\/index.php?rest_route=\/wp\/v2\/posts\/3280\/revisions"}],"predecessor-version":[{"id":3326,"href":"https:\/\/iotthinghub.com\/index.php?rest_route=\/wp\/v2\/posts\/3280\/revisions\/3326"}],"wp:attachment":[{"href":"https:\/\/iotthinghub.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3280"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/iotthinghub.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3280"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/iotthinghub.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3280"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}