{"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-8e38c87cc1022cce5291d4caaf2a41be 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-dc5a65d471bcb16ccaeef47e1e40b3e6 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-b3898ba9e14f8049bc3f5c42dafac653 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-204bc752e3067b10e73a8ee7fc4d3180 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-d84fd3536c19df9f73b514668ae52392\">\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-115f32a42b116c59c8628250d259175c 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-65fafe366a0c68af85782dd1a448127e 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-9111fecd8828817ef234858a58064157 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-c2e442b4cdedfcbdf581bfc1f6f8a05e 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-939f52d83d38dcb91cea563334e08321 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-dcf05b7e71c724af504852595d4120dd\">\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-da6a850d724c1f7ee419e1c2df2e09b9 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-5c5da06a53f3aa844a8ecefc91d11b00 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-4a6922af7f4a620ef0637e88f756fbc1 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-d344f39a79b29b6f6a66879afe60a7d1 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-a686cc08e4ce6ade386906a700182a6e 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-12e415d088984d6cceb64fb51610d22d 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-e8b60f62dca5904e293f1c0599c7bc7d 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-6f414ad015185c8e73548efab3fc110a 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}]}}