mirror of
https://github.com/lupyuen/lupyuen.github.io.git
synced 2025-01-13 02:08:32 +08:00
1327 lines
No EOL
88 KiB
HTML
1327 lines
No EOL
88 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
|
||
<head>
|
||
<link rel="stylesheet" type="text/css" href="/_static/css/banner-styles.css?v=bsmaklHF" />
|
||
<link rel="stylesheet" type="text/css" href="/_static/css/iconochive.css?v=qtvMKcIJ" />
|
||
<link rel="canonical" href="https://lupyuen.org/articles/low-power-nb-iot-on-stm32-blue-pill-with-apache-mynewt-and-embedded-rust.html" />
|
||
<!-- End Wayback Rewrite JS Include -->
|
||
<title data-rh="true">Low Power NB-IoT on STM32 Blue Pill with Apache Mynewt and Embedded Rust</title>
|
||
<meta data-rh="true" charset="utf-8" />
|
||
<meta data-rh="true" name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
|
||
<meta data-rh="true" name="theme-color" content="#000000" />
|
||
<meta data-rh="true" property="og:type" content="article" />
|
||
<meta data-rh="true" property="article:published_time" content="2019-10-18T05:45:42.236Z" />
|
||
<meta data-rh="true" name="title"
|
||
content="Low Power NB-IoT on STM32 Blue Pill with Apache Mynewt and Embedded Rust" />
|
||
<meta data-rh="true" property="og:title"
|
||
content="Low Power NB-IoT on STM32 Blue Pill with Apache Mynewt and Embedded Rust" />
|
||
<meta data-rh="true" property="twitter:title"
|
||
content="Low Power NB-IoT on STM32 Blue Pill with Apache Mynewt and Embedded Rust" />
|
||
<meta data-rh="true" name="description"
|
||
content="How much power do Quectel NB-IoT modules consume? Let’s find out with the RuiDeng DPS 3005" />
|
||
<meta data-rh="true" property="og:description"
|
||
content="How much power do Quectel NB-IoT modules consume? Let’s find out with the RuiDeng DPS 3005" />
|
||
<meta data-rh="true" property="twitter:description"
|
||
content="How much power do Quectel NB-IoT modules consume? Let’s find out with the RuiDeng DPS 3005" />
|
||
<meta data-rh="true" name="twitter:card" content="summary_large_image" />
|
||
<meta data-rh="true" name="twitter:creator" content="@MisterTechBlog" />
|
||
<meta data-rh="true" name="author" content="Lup Yuen Lee 李立源" />
|
||
<meta data-rh="true" name="robots" content="index,follow" />
|
||
<meta data-rh="true" name="referrer" content="unsafe-url" />
|
||
<meta data-rh="true" name="twitter:label1" value="Reading time" />
|
||
<meta data-rh="true" name="twitter:data1" value="16 min read" />
|
||
<meta property="og:image"
|
||
content="https://lupyuen.github.io/images/legacy/t1.png">
|
||
|
||
<!-- Begin scripts/rustdoc-header.html: Header for Custom Markdown files processed by rustdoc, like chip8.md -->
|
||
<link rel="alternate" type="application/rss+xml" title="RSS Feed for lupyuen" href="/rss.xml" />
|
||
<link rel="stylesheet" type="text/css" href="../normalize.css">
|
||
<link rel="stylesheet" type="text/css" href="../rustdoc.css" id="mainThemeStyle">
|
||
|
||
<link rel="stylesheet" type="text/css" href="../light.css" id="themeStyle">
|
||
<link rel="stylesheet" type="text/css" href="../prism.css">
|
||
<script src="../storage.js"></script><noscript>
|
||
<link rel="stylesheet" href="../noscript.css"></noscript>
|
||
<link rel="shortcut icon" href="../favicon.ico">
|
||
<style type="text/css">
|
||
#crate-search {
|
||
background-image: url("../down-arrow.svg");
|
||
}
|
||
a {
|
||
color: #77d;
|
||
}
|
||
</style>
|
||
<!-- End scripts/rustdoc-header.html -->
|
||
|
||
</head>
|
||
|
||
<body>
|
||
<div id="root">
|
||
<div class="a b c">
|
||
<article>
|
||
<section class="cj ck cl cm ak cn ce n co"></section><span class="r"></span>
|
||
<div>
|
||
<div class="cp u cq cr cs ct"></div>
|
||
<section class="cu cv cw cx cy">
|
||
<div class="cz ak">
|
||
<div class="figure da cz ak paragraph-image">
|
||
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t1.png" /></p>
|
||
|
||
|
||
|
||
<figcaption><p><em>RuiDeng DPS 3005 Power Monitor measuring the
|
||
power consumption of STM32 Blue Pill connected to Quectel BC95-G NB-IoT module</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<div>
|
||
<div id="1bb6" class="ea eb ec bk ed b ee ef eg eh ei ej ek">
|
||
<h1 class="ed b ee el ec">Low Power NB-IoT on STM32 Blue Pill with Apache Mynewt and Embedded Rust
|
||
</h1>
|
||
</div>
|
||
<div class="em">
|
||
<div class="n en eo ep eq">
|
||
<div class="o n">
|
||
<div><a rel="noopener"
|
||
href="https://lupyuen.github.io">
|
||
<div class="dd er es">
|
||
<div class="bs n et o p cp eu ev ew ex ey ct"></div>
|
||
|
||
</div>
|
||
</a></div>
|
||
<div class="fa ak r">
|
||
<div class="n">
|
||
<div style="flex:1"><span class="bj b bk bl bm bn r ec q">
|
||
<div class="fb n o fc"><span class="bj dy ds bl di fd fe ff fg fh ec"><a
|
||
class="at au av aw ax ay az ba bb bc fi bf bg bh bi" rel="noopener"
|
||
href="https://lupyuen.github.io">Lup
|
||
Yuen Lee 李立源</a></span>
|
||
|
||
</div>
|
||
</span></div>
|
||
</div><span class="bj b bk bl bm bn r bo bp"><span class="bj dy ds bl di fd fe ff fg fh bo">
|
||
<div><a class="at au av aw ax ay az ba bb bc fi bf bg bh bi" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/low-power-nb-iot-on-stm32-blue-pill-with-apache-mynewt-and-embedded-rust">
|
||
30 Aug 2019</a> <!-- -->·
|
||
<!-- -->
|
||
<!-- -->16
|
||
<!-- --> min read
|
||
</div>
|
||
</span></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<p id="9328" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">In this article we’ll learn to
|
||
optimise the power consumption of the <a class="at cg gv gw gx gy" target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/rust-rocks-nb-iot-stm32-blue-pill-with-quectel-bc95-g-on-apache-mynewt">NB-IoT
|
||
Sensor Application in the previous tutorial</a> from this jagged power-hungry mess…</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure gz ha hb hc hd cz ak paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t2.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Power consumed by our IoT sensor device before
|
||
optimisation. From <a
|
||
href="https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit?usp=sharing"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit?usp=sharing</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<p id="2b80" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">To these well-disciplined bars…
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure gz ha hb hc hd cz ak paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t3.png" /></p>
|
||
|
||
<figcaption><p><em>Power consumed by our IoT sensor device after
|
||
optimisation. From <a
|
||
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<p id="e50d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">It’s a simple application (coded
|
||
in Embedded Rust) that polls Blue Pill’s internal temperature sensor and transmits the sensor data to
|
||
a server over NB-IoT.</p>
|
||
<p id="8c29" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The power optimisation (recorded
|
||
with a $25 <a
|
||
href="https://www.aliexpress.com/item/32684316119.html"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">RuiDeng DPS 3005 Power
|
||
Monitor</a>) becomes more apparent when we compare the charts side by side…</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure gz ha hb hc hd cz ak paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t4.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Power consumed by our IoT sensor device before
|
||
and after optimisation. From <a
|
||
href="https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit?usp=sharing"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit?usp=sharing</a>
|
||
and <a
|
||
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<p id="49c3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">From the charts above we can see
|
||
the secret to long battery life is this…</p>
|
||
<p id="9c97" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="hh">Stay in Deep Sleep
|
||
for as long as possible!</em></p>
|
||
<p id="7f4c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Our sensor device doesn’t need to
|
||
transmit sensor data every second. When it sleeps for a minute or more between transmissions, the
|
||
battery life is dramatically increased.</p>
|
||
<p id="2eef" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">However we need to be sure that
|
||
our NB-IoT module won’t become totally disconnected from the network as Blue Pill sleeps. We have the
|
||
solution for that.</p>
|
||
<p id="2091" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="hh">Can we go below 3
|
||
milliAmperes?</em></p>
|
||
<p id="2774" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Yes we can! Scrutinise the photo
|
||
at the top of the article… Notice that TWO power LEDs are still lit: Power LED for Blue Pill and Power
|
||
LED for the NB-IoT breakout board.</p>
|
||
<p id="1c6e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The two LEDs are always lit, even
|
||
during Deep Sleep. If we desolder the two LEDs, the current consumed will surely drop way below 3
|
||
milliAmperes. My colleague Upton Lai has previously <a
|
||
href="https://www.linkedin.com/feed/update/urn:li:activity:6473079182715863040/"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">desoldered the Blue Pill Power
|
||
LED</a> and recorded <strong class="gj hi">10 microAmperes</strong> of power consumption in Deep
|
||
Sleep! (Without NB-IoT)</p>
|
||
<p id="cfd3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">But for now we’ll keep the LEDs…
|
||
My intent is to let you recreate this experiment easily using off-the-shelf hardware. So that you can
|
||
follow me and discover for yourself the right way to conserve power.</p>
|
||
<p id="25bf" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="hh">There’s something
|
||
odd about the Current values in the charts…</em></p>
|
||
<p id="173c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Yes the charts look different
|
||
from High School Physics because I rendered the charts (in Google Sheets) using a <strong
|
||
class="gj hi">Logarithmic Scale</strong>.</p>
|
||
<p id="5562" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This makes the chart look more
|
||
scenic and poetic like a rolling hill… instead of a desolate landscape with steep mountains and
|
||
treacherous crevices. And I assure you that no values have been altered. (Just check the Google
|
||
Sheets)</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
|
||
<div class="figure gz ha hb hc hd cz hs ht paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t5.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Logarithmic Scale vs Normal Scale. From <a
|
||
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="f913" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">Quectel NB-IoT Power
|
||
Consumption</h1>
|
||
<p id="1439" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">It’s important to power down the
|
||
NB-IoT module when we have transmitted the data: <code class="dm ix iy iz ja b">AT+CFUN=0</code></p>
|
||
<p id="9a0e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">According to the documentation
|
||
for the above command in <em class="hh">“Quectel BC95-G & BC68 AT Commands Manual”…</em></p>
|
||
<blockquote class="jb jc jd">
|
||
<p id="b54d" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu">Deep sleep mode will be entered
|
||
when the system is quiescent, but only if it has been enabled by the network.</p>
|
||
</blockquote>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
|
||
<div class="figure gz ha hb hc hd cz hs ht paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t6.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Optimised NB-IoT Power Consumption. From <a
|
||
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1194739783"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1194739783</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<p id="7d91" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Instead of keeping our device
|
||
always connected to NB-IoT, we would have to reattach to the NB-IoT network (<code
|
||
class="dm ix iy iz ja b">AT+CGATT=1</code>) every time we wake up. Attaching to the NB-IoT network
|
||
may take a few seconds, consuming 40 milliAmperes throughout.</p>
|
||
<p id="e387" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="hh">(Mr Stefan de
|
||
Lange kindly pointed out that we could attach to the NB-IoT network at power on instead of wakeup.
|
||
We’ll explore that in a future article. Thanks Stefan!)</em></p>
|
||
<p id="841a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The actual NB-IoT transmission
|
||
takes a split second, reaching peaks of about 400 milliAmperes.</p>
|
||
<p id="4c43" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here’s the log from my optimised
|
||
Blue Pill, chronicling the events after Deep Sleep Wakeup…</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/6b7e491bb735db1d0cc42694c1f6180e.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>Blue Pill Log from <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/logs/standalone-node-standby.log"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/logs/standalone-node-standby.log</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="80e1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Note that we used the <code
|
||
class="dm ix iy iz ja b">NSOSTF</code> command instead of <code
|
||
class="dm ix iy iz ja b">NSOST</code> to send a UDP packet with flags. In my previous article we
|
||
used…</p>
|
||
<pre
|
||
class="gz ha hb hc hd jh ji jj"><span id="544b" class="jk if ec bk ja b ds jl jm r jn">AT+NSOST=1,104.199.85.211,5683,174,(data)…</span></pre>
|
||
<p id="8f7e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Now we use…</p>
|
||
<pre
|
||
class="gz ha hb hc hd jh ji jj"><span id="4efc" class="jk if ec bk ja b ds jl jm r jn">AT+<strong class="ja hi">NSOSTF</strong>=1,104.199.85.211,5683,<strong class="ja hi">0x200</strong>,174,(data)…</span></pre>
|
||
<p id="6819" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The extra parameter <code
|
||
class="dm ix iy iz ja b">0x200</code> is the “Early Release” flag… It tells the NB-IoT network that
|
||
we are not expecting any response messages. So we can safely go to sleep and save power.</p>
|
||
<p id="b6cf" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The “Early Release” flag was
|
||
recommended by Mr Henk Vergonet at <a
|
||
href="https://forum.iot.t-mobile.nl/topic/278/how-much-battery-lifetime-can-we-expect-with-a-sara-n200-module-on-our-iot-network/2"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">T-Mobile Netherlands</a></p>
|
||
<div class="figure gz ha hb hc hd cz dr jp cd jq jr js jt ju ba jv jw jx jy jz ka paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t7.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://gist.github.com/lupyuen/ef51005c6c965f6a21d496ad24eacc51"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://gist.github.com/lupyuen/ef51005c6c965f6a21d496ad24eacc51</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="bf4c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here’s a valuable tip from Mr
|
||
Stefan de Lange…</p>
|
||
<blockquote class="jb jc jd">
|
||
<p id="9c70" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu"><strong class="gj hi">ECL is a
|
||
key parameter to monitor</strong>. It determines the amount of repetitions the module will do. So
|
||
instead of sending a message once the module might send the message 10, 20 or 30 times to make sure
|
||
it arrives.</p>
|
||
</blockquote>
|
||
<p id="e985" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The ECL is displayed when we send
|
||
the <code class="dm ix iy iz ja b">AT+NUESTATS</code> command.</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="f9e3" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">When Apache Mynewt Idles</h1>
|
||
<p id="265a" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">Let’s dive deep into Mynewt and
|
||
understand what happens when our Blue Pill is idle, waiting to poll the temperature sensor or waiting
|
||
for an NB-IoT command to complete…</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/2eec3bc048bf3349cc14c585473456fb.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/apache/mynewt-core/blob/master/hw/mcu/stm/stm32_common/src/hal_os_tick.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/apache/mynewt-core/blob/master/hw/mcu/stm/stm32_common/src/hal_os_tick.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="bca3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The Arm processor inside our Blue
|
||
Pill has a built-in <a
|
||
href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0179b/ar01s02s08.html"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj hi">SysTick
|
||
Timer</strong></a>. It’s used by Mynewt to perform multitasking. In the code above, Mynewt
|
||
configures the SysTick Timer to generate an interrupt every millisecond.</p>
|
||
<p id="4c91" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">When the millisecond interrupt is
|
||
triggered, Mynewt checks whether it should continue running the current task, or switch to a
|
||
higher-priority task. If there are no tasks ready to run (which will most likely be the case for our
|
||
device), Mynewt still keeps <em class="hh">checking every single millisecond</em>. This is not good
|
||
for battery life.</p>
|
||
<p id="077c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">What happens when there are no
|
||
tasks ready to run? Mynewt calls <code class="dm ix iy iz ja b">os_task_idle()</code>, passing the
|
||
number of ticks that it should stay idle. (1 tick = 1 millisecond)</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/8d6744ffdcb3871d0f36371344796459.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/apache/mynewt-core/blob/master/hw/mcu/stm/stm32_common/src/hal_os_tick.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/apache/mynewt-core/blob/master/hw/mcu/stm/stm32_common/src/hal_os_tick.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="85e2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Mynewt computes the idle time
|
||
based on the list of pending tasks. So if the temperature sensor is supposed to be polled every 10
|
||
seconds, Mynewt knows that after polling the sensor, it should stay idle for roughly 10,000 ticks
|
||
before resuming the polling task.</p>
|
||
<p id="709f" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><code
|
||
class="dm ix iy iz ja b">WFI</code> in the code above is the Arm instruction “<strong
|
||
class="gj hi">Wait For Interrupt</strong>”. It means that the Arm processor will go into a
|
||
power-saving quick nap (not Deep Sleep) until an interrupt occurs.</p>
|
||
<p id="e6ad" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">BUT… remember that our <em
|
||
class="hh">SysTick Interrupt occurs every millisecond</em>… so our Blue Pill doesn’t sleep much!</p>
|
||
<p id="5391" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here’s proof of that… Watch what
|
||
happens when we add some debug output to <code class="dm ix iy iz ja b">os_task_idle()</code>...</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure gz ha hb hc hd cz ak paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t8.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Proof that Blue Pill wakes up every millisecond
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<blockquote class="jb jc jd">
|
||
<p id="5515" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu"><em class="bk">💎</em> <strong
|
||
class="gj hi">“Heisenberg’s Uncertainty Principle” for Embedded Systems…</strong></p>
|
||
<p id="3f5f" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu">Don’t try at home what you see
|
||
above! It’s NOT a good idea to display debug messages on the console when you’re deep inside the
|
||
operating system… like in the Task Scheduling code above.</p>
|
||
<p id="35ce" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu">How did I do it? My <code
|
||
class="dm ix iy iz ja b">console_print()</code> functions were specially designed to buffer output
|
||
messages into RAM (using <code class="dm ix iy iz ja b">mbufs</code>). So no I/O is performed by the
|
||
code above… Until the application flushes the console output.</p>
|
||
<p id="51a0" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu">If this debug code used a
|
||
normal console I/O call, it would interfere with the <code
|
||
class="dm ix iy iz ja b">os_task_idle()</code> operation (it might get deadlocked). So when you
|
||
insert debug code to observe what’s happening deep inside your microcontroller, you might actually
|
||
affect the outcome.</p>
|
||
<p id="8794" class="gh gi ec hh gj b gk gl gm gn go gp gq gr gs gt gu">Hence some folks call this “<a
|
||
href="https://en.wikipedia.org/wiki/Uncertainty_principle"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><em class="bk">Heisenberg’s
|
||
Uncertainty Principle</em></a>” (like in Quantum Mechanics)… Beware of Heisenberg! :-)</p>
|
||
</blockquote>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="7319" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">Going Tickless on Apache Mynewt
|
||
with Real Time Clock</h1>
|
||
<p id="ab59" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">Here’s the problem: We would like
|
||
to sleep longer and conserve power… But the SysTick Timer keeps waking us up every millisecond. Can we
|
||
do without SysTick? Can we go… <strong class="gj hi">Tickless</strong>? Yes we can!</p>
|
||
<p id="6a53" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Blue Pill and other STM32
|
||
microcontrollers have an onboard <strong class="gj hi">Real Time Clock</strong>. Unlike a real wall
|
||
clock, the Real Time Clock doesn’t tell you the time of the day. But it’s useful for two things…</p>
|
||
<p id="ed21" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1️⃣ <strong
|
||
class="gj hi">Counting the ticks</strong> that have elapsed since we powered on our device. It keeps
|
||
counting even in Deep Sleep!</p>
|
||
<p id="3e7d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ <strong
|
||
class="gj hi">Triggering an Alarm Interrupt</strong> at a time (in ticks) that we set</p>
|
||
<p id="3962" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Remember that Mynewt calls <code
|
||
class="dm ix iy iz ja b">os_task_idle(X)</code> when it’s ready to sleep for <code
|
||
class="dm ix iy iz ja b">X</code> milliseconds. Why don’t we set the Real Time Clock Alarm to wake
|
||
us up in <code class="dm ix iy iz ja b">X</code> milliseconds?</p>
|
||
<p id="ec96" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">So in the optimised task
|
||
scheduler for Mynewt, we eliminate SysTick altogether, replaced by the Real Time Clock Alarm. <code
|
||
class="dm ix iy iz ja b">os_task_idle()</code> now calls <code
|
||
class="dm ix iy iz ja b">power_sleep()</code>…</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/75b96f3a3da157d0b8cc4e9cb3c05bb0.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/low_power.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/low_power.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="ca30" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">What about <code
|
||
class="dm ix iy iz ja b">WFI</code>, the Wait For Interrupt instruction that we saw earlier? It
|
||
still works! Because the Real Time Clock triggers an interrupt (Alarm Interrupt) when the time is up.
|
||
Here’s how we call <code class="dm ix iy iz ja b">WFI</code> for a quick nap (<strong
|
||
class="gj hi">Sleep Now Mode</strong>)…</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/68c5ac770b56aa218da615df69d5ae27.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/low_power.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/low_power.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="5c95" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The <code
|
||
class="dm ix iy iz ja b">power_sleep()</code> function calls <code
|
||
class="dm ix iy iz ja b">target_enter_sleep_mode()</code> and <code
|
||
class="dm ix iy iz ja b">WFI</code> for a quick nap. When we have finished transmitting our sensor
|
||
data over NB-IoT, we could actually take a longer nap… this is the <strong class="gj hi">Deep Sleep
|
||
Standby Mode</strong> we saw earlier… the one that consumes only 3 milliAmperes! (With the power
|
||
LEDs still lit) We’ll cover Deep Sleep Standby Mode in a while.</p>
|
||
<p id="fbc0" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Zephyr RTOS has a good
|
||
explanation of <a
|
||
href="https://docs.zephyrproject.org/1.13.0/subsystems/power_management.html#tickless-idle"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">Tickless Task Scheduling here</a>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="2da0" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">Power Saving Modes on Blue Pill
|
||
</h1>
|
||
<p id="e8d5" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">There are <a
|
||
href="https://www.st.com/content/ccc/resource/technical/document/application_note/ff/0a/dc/d2/5e/f5/4b/5a/CD00171691.pdf/files/CD00171691.pdf/jcr:content/translations/en.CD00171691.pdf"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">three power saving modes</a> on
|
||
Blue Pill…</p>
|
||
<p id="0c62" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1️⃣ <strong class="gj hi">Sleep
|
||
Now Mode (10 milliAmperes)</strong>: This is the <code class="dm ix iy iz ja b">WFI</code> (Wait For
|
||
Interrupt) instruction that’s implemented in the Arm processor. It puts Blue Pill into a light nap
|
||
that still consumes substantial power. That’s because the Blue Pill peripherals (like the UART port)
|
||
are still powered on.</p>
|
||
<p id="343c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ <strong class="gj hi">Deep
|
||
Sleep Stop Mode</strong>: Similar to Sleep Now Mode, except that the peripherals (like UART) are
|
||
powered down. Consumes less power than Sleep Now Mode but more power than Deep Sleep Standby Mode. On
|
||
wakeup, Blue Pill resumes execution with the peripherals powered down. <em class="hh">RAM is
|
||
preserved.</em></p>
|
||
<p id="0078" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3️⃣ <strong class="gj hi">Deep
|
||
Sleep Standby Mode (3 milliAmperes, with power LEDs still lit)</strong>: The ultimate low power
|
||
mode. All peripherals powered down (same as Deep Sleep Stop Mode). BUT on wakeup, <em class="hh">Blue
|
||
Pill restarts</em> as though it was just powered on. <em class="hh">Everything in RAM is lost.</em>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
|
||
<div class="figure gz ha hb hc hd cz hs ht paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t9.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Sleep Now Mode vs Deep Sleep Standby Mode.
|
||
From <a
|
||
href="https://docs.google.com/spreadsheets/d/1ygUzKYWTo-BSSvKzL3J6ub3o4-7sVrjMUyvGLdAsHJ0/edit?usp=sharing"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1ygUzKYWTo-BSSvKzL3J6ub3o4-7sVrjMUyvGLdAsHJ0/edit?usp=sharing</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<p id="db8b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This may sound odd… But Deep
|
||
Sleep <strong class="gj hi">Standby Mode</strong> (the ultimate power saver) is <em class="hh">easier
|
||
to code</em> than Deep Sleep <strong class="gj hi">Stop Mode</strong>.</p>
|
||
<p id="5370" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">With Stop Mode we need to power
|
||
on the peripherals ourselves when waking up… And it gets complicated. With Standby Mode, we just
|
||
pretend that our Blue Pill has just powered on… Except that we can check a flag to distinguish whether
|
||
it’s a Power On or a Standby Wakeup.</p>
|
||
<p id="7869" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here’s how we check the flag…</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/9c37accdc0fc9315390dd8073a1b886a.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/low_power.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/low_power.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="761e" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">Embedded Rust Application For
|
||
Low Power</h1>
|
||
<p id="ce4a" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">Remember from our previous
|
||
tutorial that the IoT Sensor Application was developed in Rust. <em class="hh">Is Rust really suitable
|
||
for Low Power Devices? Does Rust make our device less power-efficient?</em></p>
|
||
<p id="6e25" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">I’m happy to report that <em
|
||
class="hh">Rust is just as power-efficient as C!</em> That’s because Rust is compiled into optimised
|
||
Arm machine code, so there’s no extra execution overhead when our application is written in Rust.</p>
|
||
<p id="2b68" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The Rust application logic was
|
||
tweaked slightly to make it more power-efficient…</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/ae5e50c2aa618a377e4ae367210303d4.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/rust/app/src/app_sensor.rs"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/rust/app/src/app_sensor.rs</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="44e0" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The top half of the function
|
||
<code class="dm ix iy iz ja b">start_sensor_listener()</code> is exactly the same as before. When our
|
||
device is powered up, we instruct Mynewt to poll the temperature sensor every 20 seconds. Mynewt
|
||
passes the sensor data to our function <code class="dm ix iy iz ja b">handle_sensor_data()</code> for
|
||
transmitting to the server.</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/e691257e5aa0dc589fff126961203622.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/rust/app/src/app_sensor.rs"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/rust/app/src/app_sensor.rs</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="53c9" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The lower half of <code
|
||
class="dm ix iy iz ja b">start_sensor_listener()</code> introduces a minor twist… When our device
|
||
wakes up from Deep Sleep Standby Mode, we read the temperature sensor directly, without polling. And
|
||
we transmit the sensor data the same way, via <code
|
||
class="dm ix iy iz ja b">handle_sensor_data()</code>.</p>
|
||
<p id="1e33" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This keeps our device fully
|
||
occupied during the precious few seconds that our device is awake, until it falls into Deep Sleep.</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/51bc6ecec5c9edd01dee5c01882fe61f.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/sensor_network/src/sensor_network.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/sensor_network/src/sensor_network.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="3323" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The <strong class="gj hi">Sensor
|
||
Network Library</strong> (written in C) has been optimised for low power operation as well. During
|
||
wakeup, the function attaches to the NB-IoT network and doesn’t return until it completes. (Previously
|
||
we started a background task to attach to the NB-IoT network so that we could run other tasks.)</p>
|
||
<p id="8b91" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This chart illustrates the power
|
||
consumed when our Blue Pill polls the onboard temperature sensor vs reading the sensor directly.</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
|
||
<div class="figure gz ha hb hc hd cz hs ht paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t10.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Polling vs Reading the temperature sensor.
|
||
From <a
|
||
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1194739783"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1194739783</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<p id="255c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The code changes are really
|
||
minor. Mynewt’s Sensor Framework has done an excellent job in managing the access to sensors in a
|
||
consistent, reusable way, even for Low Power. And Rust makes the code look much cleaner and simpler
|
||
than C.</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="7068" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">Measure Power Consumption with
|
||
RuiDeng DPS 3005 Power Monitor</h1>
|
||
<div class="figure gz ha hb hc hd cz cl cm paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t11.jpeg" /></p>
|
||
|
||
|
||
<figcaption><p><em>RuiDeng DPS 3005 Power Monitor measuring the
|
||
power consumption of STM32 Blue Pill connected to Quectel BC95-G NB-IoT module</em></p></figcaption>
|
||
</div>
|
||
<p id="4453" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Now let’s run our IoT Sensor
|
||
Device and measure the power consumption with <a
|
||
href="https://www.aliexpress.com/item/32684316119.html"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">RuiDeng DPS 3005 Power
|
||
Monitor</a>!</p>
|
||
<p id="5b29" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><a class="at cg gv gw gx gy"
|
||
target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/connect-the-nb-iot-hardware-stm32-blue-pill-and-quectel-bc95-g-module">Follow
|
||
the instructions here</a> to connect Blue Pill to the NB-IoT module and ST-Link.</p>
|
||
<p id="45f3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Let’s look at inputs and outputs
|
||
for the Power Monitor…</p>
|
||
<div class="figure gz ha hb hc hd cz dr jp cd jq jr js jt ju ba jv jw jx jy jz ka paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t12.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Inputs and Outputs for RuiDeng DPS 3005 Power
|
||
Monitor</em></p></figcaption>
|
||
</div>
|
||
<p id="a660" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><strong class="gj hi">Inputs at
|
||
Left Side (</strong><code
|
||
class="dm ix iy iz ja b"><strong class="gj hi">IN+, IN-</strong></code><strong
|
||
class="gj hi">)</strong>: Connect to the DC power supply. I used two 18650 lithium ion 3.7 Volt
|
||
batteries connected in series. Total 7.2 Volts, sufficient for providing 5 Volts to our Blue Pill and
|
||
NB-IoT module.</p>
|
||
<p id="4d35" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><strong class="gj hi">Outputs at
|
||
Right Side (</strong><code
|
||
class="dm ix iy iz ja b"><strong class="gj hi">OUT-, OUT+</strong></code><strong
|
||
class="gj hi">)</strong>: Connect to the Blue Pill and NB-IoT module. This will be the 5-Volt power
|
||
source for our Blue Pill and NB-IoT module.</p>
|
||
<p id="5be8" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here’s how I powered my Power
|
||
Monitor…</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
|
||
<div class="figure gz ha hb hc hd cz hs ht paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t13.jpeg" /></p>
|
||
|
||
|
||
<figcaption><p><em>RuiDeng DPS 3005 Power Monitor powered by
|
||
two 18650 lithium ion 3.7 Volt batteries</em></p></figcaption>
|
||
</div>
|
||
<div class="figure da cz hs ht paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<blockquote class="kp">
|
||
<div id="0a63" class="kq kr ks bk ed b kt ku kv kw kx ky gu">
|
||
<p class="ed b kz la bo">When Flashing Firmware…</p>
|
||
</div>
|
||
</blockquote>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
|
||
<div class="figure lb lc ld le lf cz hs ht paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t14.jpeg" /></p>
|
||
|
||
|
||
<figcaption><p><em>Blue Pill and NB-IoT Module connected to
|
||
ST-Link</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<div class="figure gz ha hb hc hd cz dr jp cd jq jr js jt ju ba jv lh li lj lk ka">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/58e4584448ab90098b033e996f228bca.js"></script></p>
|
||
|
||
|
||
</div>
|
||
<p id="73d3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">When flashing the firmware to
|
||
Blue Pill, connect ST-Link to Blue Pill and the NB-IoT module as shown.</p>
|
||
<p id="8ed1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Note that the NB-IoT module is
|
||
powered by the 5V pin from ST-Link.</p>
|
||
<p id="dc03" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Blue Pill’s 5V pin should be
|
||
disconnected.</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
|
||
<div class="figure gz ha hb hc hd cz hs ht paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<blockquote class="kp">
|
||
<div id="6218" class="kq kr ks bk ed b kt ku kv kw kx ky gu">
|
||
<p class="ed b kz la bo">When Monitoring Power Consumption…</p>
|
||
</div>
|
||
</blockquote>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
|
||
<div class="figure lb lc ld le lf cz hs ht paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t15.jpeg" /></p>
|
||
|
||
|
||
<figcaption><p><em>Blue Pill and NB-IoT Module connected to
|
||
RuiDeng DPS 3005 Power Monitor</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<div class="figure gz ha hb hc hd cz dr jp cd jq jr js jt ju ba jv lh li lj lk ka">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/9890b3511728c9e5ddcc0b49a35d5a91.js"></script></p>
|
||
|
||
|
||
</div>
|
||
<p id="cece" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">When monitoring the power
|
||
consumption, disconnect ST-Link.</p>
|
||
<p id="697c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Connect Blue Pill’s 5V pin to the
|
||
Power Meter.</p>
|
||
<p id="eae9" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The NB-IoT module should be
|
||
powered by the Power Meter as well.</p>
|
||
<div class="figure gz ha hb hc hd cz dr jp cd jq jr js jt ju ba jv jw jx jy jz ka paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t16.jpeg" /></p>
|
||
|
||
<figcaption><p><em>Bluetooth module for DPS 3005 Power Monitor
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="0487" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Make sure your DPS 3005 Power
|
||
Monitor is bundled with a <strong class="gj hi">Bluetooth module</strong>.</p>
|
||
<p id="ba98" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The module connects the Power
|
||
Monitor to your Windows computer wirelessly for recording data power consumption data (at 1 sample per
|
||
second). Sadly I couldn’t connect from macOS.</p>
|
||
<p id="754a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">RuiDeng’s software for DPS 3005
|
||
did not allow recording of data, so I used the open-source <code
|
||
class="dm ix iy iz ja b"><a href="https://github.com/lambcutlet/DPS5005_pyGUI" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">DPS5005_pyGUI</a></code>
|
||
data logger.</p>
|
||
<div class="figure gz ha hb hc hd cz cl cm paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t17.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>DPS5005_pyGUI data logger: <a
|
||
href="https://github.com/lambcutlet/DPS5005_pyGUI"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lambcutlet/DPS5005_pyGUI</a></em></p></figcaption>
|
||
</div>
|
||
<p id="4539" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The low power version of Apache
|
||
Mynewt and the updated Embedded Rust application may be installed <a class="at cg gv gw gx gy"
|
||
target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/install-low-power-apache-mynewt-and-embedded-rust-for-visual-studio-code-on-windows">according
|
||
to these instructions</a>.</p>
|
||
<div class="lp lq lr ls lt lu"><a rel="noopener"
|
||
href="https://lupyuen.github.io/articles/install-low-power-apache-mynewt-and-embedded-rust-for-visual-studio-code-on-windows">
|
||
<section class="lx cl cm ak ce n ar ly lz ma mb mc md me mf mg mh mi mj mk ml mm">
|
||
<div class="mn n co p mo mp">
|
||
<h2 class="bj ig mq bl ec">
|
||
<div class="di lv fe ff lw fh">Install Low Power Apache Mynewt and Embedded Rust for Visual
|
||
Studio Code on Windows</div>
|
||
</h2>
|
||
</div>
|
||
<div class="mt r">
|
||
<div class="mu r mv mw mx mt my mz na"></div>
|
||
</div>
|
||
</section>
|
||
</a></div>
|
||
<p id="ad11" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="hh">Is 1 sample per
|
||
second sufficient for understanding the power consumption?</em></p>
|
||
<p id="d3b4" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Honestly, no. There are peaks in
|
||
our power consumption during NB-IoT transmission. The peaks seem to reach 400 milliAmperes… But
|
||
because the sampling rate is so low, the peaks could possibly be much higher than that.</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="hj hk hl hm hn ho ag hp ah hq aj ak">
|
||
<div class="figure gz ha hb hc hd cz hs ht paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t18.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Peaks in NB-IoT Power Consumption. From <a
|
||
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1194739783"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1194739783</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<p id="a06b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Nonetheless, we now have a $25
|
||
setup that lets us quickly tweak our firmware and check whether the tweaks actually improve power
|
||
consumption. So the RuiDeng Power Monitor is an affordable way to guide us towards the right direction
|
||
to reduce power consumption. <em class="hh">When you have finalised the firmware, remember to use the
|
||
proper equipment to measure the real power consumption!</em></p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="a7b7" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">The Results</h1>
|
||
<p id="ea41" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">After optimising the power
|
||
consumption, how much longer did the battery last? A whopping… <em class="hh">26% increase in battery
|
||
life!</em></p>
|
||
<div class="figure gz ha hb hc hd cz cl cm paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t19.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Computed battery life for our IoT sensor
|
||
device. From <a
|
||
href="https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit#gid=1065153023"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit#gid=1065153023</a>
|
||
and <a
|
||
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1872735739"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit#gid=1872735739</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="41b9" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">But it’s a good start! Remember
|
||
that the power LEDs are still lit. And we have achieved flat lines of power usage during Deep Sleep.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure gz ha hb hc hd cz ak paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t20.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>Power consumed by our IoT sensor device before
|
||
and after optimisation. From <a
|
||
href="https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit?usp=sharing"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1QptBX2wn_RC5-oaVPyxynbmKROO5ElfHJyNcqcX0YhA/edit?usp=sharing</a>
|
||
and <a
|
||
href="https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://docs.google.com/spreadsheets/d/1Rb6HXaHBaSAM3KW1aWOTyXjpJDiOCEWZAwpA-nufGKo/edit?usp=sharing</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<p id="710a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Right now our Blue Pill wakes up
|
||
every 1 minute or so… If we could extend the Deep Sleep to 10 minutes or longer, we should get much
|
||
lower overall power consumption.</p>
|
||
<p id="74da" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Unfortunately I couldn’t get Blue
|
||
Pill to sleep beyond 1 minute… <em class="hh">Something is still waking it up. </em>Another timer? Or
|
||
NB-IoT?</p>
|
||
<p id="1063" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">I invite you to reproduce the
|
||
same setup with the steps I have described… And help me solve the mystery! (Or work around it… See the
|
||
<em class="hh">“Backup Registers”</em> section below)</p>
|
||
<p id="128a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">But I hope you now have a deeper
|
||
appreciation of all the components that make an IoT Sensor truly Low Power… <strong class="gj hi"><em
|
||
class="hh">the Network (NB-IoT), the Microcontroller (STM32) and the Operating System
|
||
(Mynewt)!</em></strong></p>
|
||
<p id="132a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu"><em class="hh">Many thanks to
|
||
</em><a href="https://www.starhub.com/"
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow"><strong class="gj hi"><em
|
||
class="hh">StarHub</em></strong></a><em class="hh"> for sponsoring the NB-IoT SIM that I used
|
||
for this article!</em></p>
|
||
<div class="figure gz ha hb hc hd cz cl cm paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t21.jpg" /></p>
|
||
|
||
|
||
<figcaption><p><em>Final data collection with RuiDeng DPS 3005
|
||
Power Monitor connected to STM32 Blue Pill and Quectel BC95-G NB-IoT module. The Bluetooth module
|
||
for the Power Monitor is in the centre (green board with red LED).</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="c98d" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">💎 Advanced Topic: Main and
|
||
Backup Power</h1>
|
||
<div class="figure gz ha hb hc hd cz cl cm paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t22.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>From “RM0008 Reference manual for
|
||
STM32F103xx”: <a
|
||
href="https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="b1b7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Let’s study the power input for
|
||
<strong class="gj hi">STM32F103C8T6</strong>, the STM32 microcontroller at the heart of Blue Pill.
|
||
Most parts of STM32F103C8T6 are powered by the <strong class="gj hi">Main Power </strong>(<code
|
||
class="dm ix iy iz ja b">VDD</code> in the above diagram).</p>
|
||
<p id="21d1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">STM32F103C8T6 has a <strong
|
||
class="gj hi">Backup Domain </strong>(highlighted in red)<strong class="gj hi"> </strong>that may be
|
||
powered by Main Power <code class="dm ix iy iz ja b">VDD</code> or <strong class="gj hi">Backup
|
||
Power</strong> <code class="dm ix iy iz ja b">VBAT</code>. The Backup Domain contains the minimum
|
||
components essential for Deep Sleep, such as the Real Time Clock.</p>
|
||
<p id="11df" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This means that it’s possible to
|
||
sustain Blue Pill in Deep Sleep just by supplying a bit of Backup Power to the <code
|
||
class="dm ix iy iz ja b">VBAT</code> pin, while the rest of Blue Pill (running on Main Power) is
|
||
powered down.</p>
|
||
<p id="8ef7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Everything in the Backup Domain
|
||
continues to operate as long as Backup Power is available. What’s inside the Backup Domain?</p>
|
||
<p id="29cf" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1️⃣ <strong class="gj hi">Low
|
||
Speed External (LSE) Oscillator</strong>: This generates the ticks that’s needed by the Real Time
|
||
Clock to track time accurately during Deep Sleep</p>
|
||
<p id="8b86" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ <strong class="gj hi">Backup
|
||
Registers (BKP)</strong>: These are ten 16-bit registers that we may use to store 20 bytes of data.
|
||
The contents of the registers will be preserved across restarts and wakeups, as long as Backup Power
|
||
is available. We’ll see later how Backup Registers may be used.</p>
|
||
<p id="f469" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3️⃣ <strong class="gj hi">Backup
|
||
Domain Control Register (BDCR)</strong>: This register is used to configure the LSE Oscillator and
|
||
Real Time Clock.</p>
|
||
<p id="7d9a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">4️⃣ <strong class="gj hi">Real
|
||
Time Clock (RTC)</strong>: This is needed to count the ticks produced by the LSE Oscillator and
|
||
track the elapsed time accurately. It also wakes up the microcontroller at the preset alarm time.</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="823a" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">💎 Advanced Topic: Configure
|
||
the Real Time Clock</h1>
|
||
<p id="ceea" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">This section explains how we
|
||
configured the Real Time Clock on Blue Pill. The <code class="dm ix iy iz ja b">alarm_setup()</code>
|
||
code looks tricky so we’ll study this step by step.</p>
|
||
<p id="c8b4" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">The <code
|
||
class="dm ix iy iz ja b">alarm_setup()</code> function is called at startup and wakeup by <code
|
||
class="dm ix iy iz ja b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/hal_os_tick.c" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">__wrap_os_tick_init</a>()</code>,
|
||
which is the intercepted version of <code class="dm ix iy iz ja b">os_tick_init()</code> that we’ll
|
||
see in the section<em class="hh"> “Advanced Topic: Patch Mynewt OS Functions”</em> below.</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/9cdbe047881bf69ee8bf63b95d1b78bb.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="3dc1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Blue Pill has three <strong
|
||
class="gj hi">Oscillator Clocks</strong>: <strong class="gj hi">HSE, LSE and LSI</strong>. These are
|
||
primitive clocks, good for producing ticks only. We may select one of these Oscillator Clocks to drive
|
||
the Real Time Clock and trigger the Deep Sleep wakeup alarm.</p>
|
||
<p id="9bd3" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1️⃣ <strong class="gj hi">High
|
||
Speed External (HSE)</strong> is the fastest clock (8 MHz crystal oscillator)… But also needs the
|
||
most power. HSE uses only Main Power, doesn’t work on Backup Power. So when we sleep and switch to
|
||
Backup Power, it stops. Not suitable for setting the Deep Sleep alarm.</p>
|
||
<p id="5cd2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ <strong class="gj hi">Low
|
||
Speed Internal (LSI) </strong>is a slower clock (~40 kHz RC oscillator) but it also runs on Main
|
||
Power, not Backup Power. So it’s not suitable for setting the Deep Sleep alarm either.</p>
|
||
<p id="38ca" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3️⃣ <strong class="gj hi">Low
|
||
Speed External (LSE)</strong> (32.768 kHz crystal oscillator) is the best choice because it works on
|
||
Backup Power (assuming that our Blue Pill has a Backup Power source when it goes into Deep Sleep)</p>
|
||
<p id="9028" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">What’s “<strong
|
||
class="gj hi">Prescaling</strong>”? Something you do on a fish? No, prescaling lets us run the Real
|
||
Time Clock as a fraction of the HSE / LSE / LSI clock speeds. So when we prescale LSE by 32, we run
|
||
the Real Time Clock at 1 tick per millisecond. (LSE ticks natively at 32.768 kHz, or 32,768 ticks per
|
||
second)</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/94abd5008e4403a9e51b919d84cb5217.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="881e" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Real Time Clock may be used in 3
|
||
ways to trigger interrupts…</p>
|
||
<p id="955c" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">1️⃣ <strong class="gj hi">After a
|
||
preset number of ticks</strong> (<code class="dm ix iy iz ja b">RTC_SEC</code>). So that the STM32
|
||
microcontroller’s Real Time Clock may be used like the Arm processor’s SysTick Timer.</p>
|
||
<p id="ff5b" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">2️⃣ <strong class="gj hi">At a
|
||
preset alarm time</strong> (<code class="dm ix iy iz ja b">RTC_ALR</code>). We’re using this to wake
|
||
up from Deep Sleep.</p>
|
||
<p id="e2e7" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">3️⃣ <strong class="gj hi">Upon
|
||
overflow</strong> (<code class="dm ix iy iz ja b">RTC_OW</code>). The Real Time Clock is a 32-bit
|
||
counter that counts the number of elapsed ticks from 0 to 4,294,967,295. When the counter overflows,
|
||
the Real Time Clock triggers this interrupt so that the operating system can do the necessary time
|
||
adjustments.</p>
|
||
<p id="40eb" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">We’ll be using only the Alarm
|
||
Interrupt <code class="dm ix iy iz ja b">RTC_ALR</code>. When the alarm goes off, the Arm processor
|
||
will call our function <code class="dm ix iy iz ja b">rtc_alarm_isr()</code></p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/90d67994a7639cbff8a690c16c76c363.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="d6a1" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">At power on we switch on the Real
|
||
Time Clock and set the counter value to 0 (<code class="dm ix iy iz ja b">rtc_set_counter_val</code>).
|
||
This is the counter we’ll be using to track the elapsed time (as millisecond ticks) in our
|
||
application.</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/f8ca47d25bdfea6147ca02b017e6c18d.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="546d" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">During wakeup from Deep Sleep we
|
||
don’t reset the Real Time Clock counter. That way we can track the elapsed time as Blue Pill sleeps.
|
||
Remember that the Real Time Clock keeps counting the ticks during Deep Sleep (powered by Backup
|
||
Power).</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/1de1451256e737806ff2dda3ee364b39.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="7675" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">For Deep Sleep Stop Mode: The
|
||
External Interrupt (EXTI) must be configured so that the Alarm Interrupt will wake us up (<code
|
||
class="dm ix iy iz ja b">exti_set_trigger</code>). This is not necessary for Deep Sleep Standby
|
||
Mode.</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/91fec08b925107d32905727fc61bfae6.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="e923" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Once we enable the Alarm
|
||
Interrupt via <code class="dm ix iy iz ja b">rtc_interrupt_enable(RTC_ALR)</code>, the alarm becomes
|
||
operational. We will call <code class="dm ix iy iz ja b">rtc_set_alarm_time()</code> to set the alarm
|
||
time (in ticks). When the alarm goes off, our function <code
|
||
class="dm ix iy iz ja b">rtc_alarm_isr()</code> will be called.</p>
|
||
<p id="3ae2" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Here’s how we set the alarm time
|
||
before entering Deep Sleep…</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/19229ac27fb794a5c6be8119d5606fdd.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/alarm.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure lb lc ld le lf cz ak paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy/t23.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>HSE, LSE and LSI clocks on STM32 Blue Pill
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="d2c0" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">💎 Advanced Topic: Backup
|
||
Registers</h1>
|
||
<p id="930d" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">Here’s the problem: Blue Pill
|
||
wakes up from Deep Sleep Standby Mode with amnesia… It doesn’t know what it was doing before it fell
|
||
into Deep Sleep, since the RAM has been erased. <em class="hh">How can we make Blue Pill memorise some
|
||
state information so that it can resume working after waking up? Without writing to Flash ROM?</em>
|
||
</p>
|
||
<p id="0481" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Solution: Use the <strong
|
||
class="gj hi">STM32 Backup Registers</strong>. Blue Pill’s Backup Registers are ten 16-bit registers
|
||
that we may use to store 20 bytes of data. The contents of the registers will be preserved across
|
||
restarts and wakeups,<strong class="gj hi"> as long as there is Backup Power (or Main Power) supplied
|
||
to Blue Pill</strong>. It works just the Real Time Clock!</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/ebe183a495201248127da64f50a28e89.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/codal-libopencm3/blob/master/stm32/bootloader/stm32f103/backup.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/codal-libopencm3/blob/master/stm32/bootloader/stm32f103/backup.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="2fa6" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">This code was used in my
|
||
Bootloader (from an earlier article) to remember whether Blue Pill is supposed to restart in
|
||
Bootloader Mode or Application Mode. Check out the article: <em class="hh">“</em><a
|
||
class="at cg gv gw gx gy" target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/stm32-blue-pill-bootloading-the-webusb-bootloader"><em
|
||
class="hh">STM32 Blue Pill — Bootloading the WebUSB Bootloader</em></a><em class="hh">”</em></p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="hv dy hw hx hy dv hz ia ib ic id" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah dz aj ak">
|
||
<h1 id="d9e6" class="ie if ec bk bj ig ih ii ij ik il im in io ip iq ir">💎 Advanced Topic: Patch Mynewt
|
||
OS Functions</h1>
|
||
<p id="a0c9" class="gh gi ec bk gj b gk is gm it go iu gq iv gs iw gu">The low power functions were
|
||
implemented in a custom library <code
|
||
class="dm ix iy iz ja b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/low-power/libs/low_power" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">libs/low_power</a></code>.
|
||
How did we patch the Mynewt OS functions like <code class="dm ix iy iz ja b">os_task_idle()</code>
|
||
with our custom library? By using the Linker Wrap directive in our library…</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/bd50adde39904592f144d32e089329b7.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/pkg.yml"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/pkg.yml</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="696a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">When the GNU Linker collates the
|
||
compiled object files (<code class="dm ix iy iz ja b">*.o</code>) to create the firmware image, it
|
||
will look for all calls to <code class="dm ix iy iz ja b">os_tick_idle()</code> and rename them as
|
||
calls to <code class="dm ix iy iz ja b">__wrap_os_tick_idle()</code>.</p>
|
||
<p id="b887" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Note that GNU Linker will NOT
|
||
rename the original <code class="dm ix iy iz ja b">os_tick_idle()</code> function defined in Mynewt.
|
||
Which means that we may implement the <code class="dm ix iy iz ja b">__wrap_os_tick_idle()</code>
|
||
function ourselves and the callers will happily pretend that it’s really <code
|
||
class="dm ix iy iz ja b">os_tick_idle()</code>. That’s how we intercept system functions in Mynewt…
|
||
</p>
|
||
<div class="figure gz ha hb hc hd cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/f6c7eb1dfd0728c2993f6044fa1e046b.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/hal_os_tick.c"
|
||
class="at cg gv gw gx gy" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/libs/low_power/src/hal_os_tick.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="0293" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">It’s a nasty way to alter the
|
||
behaviour of Mynewt (and I don’t condone it). But for exploratory and educational purposes, it’s
|
||
probably OK.</p>
|
||
<p id="737a" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Note that the firmware size is
|
||
close to 60 KB. Adding the 4 KB Stub Bootloader we get total 64 KB of Flash ROM used. This is very
|
||
close to Blue Pill’s 64 KB ROM capacity. When you’re not debugging, uncomment the <code
|
||
class="dm ix iy iz ja b">-Os</code> option in <code
|
||
class="dm ix iy iz ja b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/apps/my_sensor_app/pkg.yml" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">apps/my_sensor_app/pkg.yml</a></code>
|
||
</p>
|
||
<pre
|
||
class="gz ha hb hc hd jh ji jj"><span id="824d" class="jk if ec bk ja b ds jl jm r jn"># C compiler flags<br/>pkg.cflags:<br/> - -DFLOAT_SUPPORT # For encoding floats in CoAP messages<br/># - -Os # Optimise for smallest size</span></pre>
|
||
<p id="1511" class="gh gi ec bk gj b gk gl gm gn go gp gq gr gs gt gu">Also the random number generator
|
||
has been disabled to reduce code size, hence the Device ID is always <code
|
||
class="dm ix iy iz ja b">0000…</code> To enable it, change <code
|
||
class="dm ix iy iz ja b">HMAC_PRNG</code> to <code class="dm ix iy iz ja b">1</code> in <code
|
||
class="dm ix iy iz ja b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/low-power/targets/bluepill_my_sensor/syscfg.yml" class="at cg gv gw gx gy" target="_blank" rel="noopener nofollow">targets/bluepill_my_sensor/syscfg.yml</a></code>
|
||
</p>
|
||
<pre
|
||
class="gz ha hb hc hd jh ji jj"><span id="017a" class="jk if ec bk ja b ds jl jm r jn">HMAC_PRNG: 0 # Disable HMAC PRNG pseudorandom number generator</span></pre>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
</div>
|
||
|
||
<ul>
|
||
<li>
|
||
<p><a href="https://github.com/sponsors/lupyuen">Sponsor me a coffee</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io">Check out my articles</a></p>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://lupyuen.github.io/rss.xml">RSS Feed</a></p>
|
||
</li>
|
||
</ul>
|
||
|
||
</body>
|
||
|
||
</html>
|
||
<!--
|
||
FILE ARCHIVED ON 19:41:17 Dec 04, 2019 AND RETRIEVED FROM THE
|
||
INTERNET ARCHIVE ON 23:13:43 Feb 22, 2021.
|
||
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
|
||
|
||
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
|
||
SECTION 108(a)(3)).
|
||
-->
|
||
<!--
|
||
playback timings (ms):
|
||
exclusion.robots: 0.378
|
||
LoadShardBlock: 300.664 (3)
|
||
PetaboxLoader3.resolve: 210.656
|
||
RedisCDXSource: 11.309
|
||
PetaboxLoader3.datanode: 171.345 (4)
|
||
CDXLines.iter: 31.052 (3)
|
||
captures_list: 348.182
|
||
exclusion.robots.policy: 0.362
|
||
esindex: 0.011
|
||
load_resource: 237.74
|
||
--> |