mirror of
https://github.com/lupyuen/lupyuen.github.io.git
synced 2025-01-13 09:08:30 +08:00
976 lines
No EOL
66 KiB
HTML
976 lines
No EOL
66 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/connect-stm32-blue-pill-to-nb-iot-with-quectel-bc95-g-and-apache-mynewt.html" />
|
||
<!-- End Wayback Rewrite JS Include -->
|
||
<title data-rh="true">Connect STM32 Blue Pill to NB-IoT with Quectel BC95-G and Apache Mynewt</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-08-16T05:58:20.330Z" />
|
||
<meta data-rh="true" name="title" content="Connect STM32 Blue Pill to NB-IoT with Quectel BC95-G and Apache Mynewt" />
|
||
<meta data-rh="true" property="og:title"
|
||
content="Connect STM32 Blue Pill to NB-IoT with Quectel BC95-G and Apache Mynewt" />
|
||
<meta data-rh="true" property="twitter:title"
|
||
content="Connect STM32 Blue Pill to NB-IoT with Quectel BC95-G and Apache Mynewt" />
|
||
<meta data-rh="true" name="description"
|
||
content="Build a real IoT sensor with STM32 Blue Pill and Quectel BC95-G Global NB-IoT module" />
|
||
<meta data-rh="true" property="og:description"
|
||
content="Build a real IoT sensor with STM32 Blue Pill and Quectel BC95-G Global NB-IoT module" />
|
||
<meta data-rh="true" property="twitter:description"
|
||
content="Build a real IoT sensor with STM32 Blue Pill and Quectel BC95-G Global NB-IoT module" />
|
||
<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="10 min read" />
|
||
<meta property="og:image"
|
||
content="https://lupyuen.github.io/images/legacy2/a1.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/legacy2/a1.png" /></p>
|
||
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<div>
|
||
<div id="57ca" class="dt du dv bk dw b dx dy dz ea eb ec ed ee ef eg eh">
|
||
<h1 class="dw b dx ei dz ej eb ek ed el ef em dv">Connect STM32 Blue Pill to NB-IoT with Quectel
|
||
BC95-G and Apache Mynewt</h1>
|
||
</div>
|
||
<div class="en">
|
||
<div class="n eo ep eq er">
|
||
<div class="o n">
|
||
<div><a rel="noopener"
|
||
href="https://lupyuen.github.io">
|
||
<div class="dd es et">
|
||
<div class="bs n eu o p cp ev ew ex ey ez ct"></div>
|
||
|
||
|
||
</div>
|
||
</a></div>
|
||
<div class="fb ak r">
|
||
<div class="n">
|
||
<div style="flex:1"><span class="bj b bk bl bm bn r dv q">
|
||
<div class="fc n o fd"><span class="bj fe ff bl di fg fh fi fj fk dv"><a
|
||
class="at au av aw ax ay az ba bb bc fl 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 fe ff bl di fg fh fi fj fk bo">
|
||
<div><a class="at au av aw ax ay az ba bb bc fl bf bg bh bi" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/connect-stm32-blue-pill-to-nb-iot-with-quectel-bc95-g-and-apache-mynewt">
|
||
25 Jul 2019</a> <!-- -->·
|
||
<!-- -->
|
||
<!-- -->10
|
||
<!-- --> min read
|
||
</div>
|
||
</span></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<p id="92fd" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">In the <a
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/get-started-with-nb-iot-and-quectel-modules">previous
|
||
article</a> we learnt the AT commands for sending sensor data to a <a
|
||
href="https://en.wikipedia.org/wiki/Constrained_Application_Protocol"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">CoAP</a> Server via a Quectel
|
||
NB-IoT module. Now let’s build an <strong class="gm hc">IoT sensor</strong> with a real
|
||
microcontroller — <a
|
||
href="https://wiki.stm32duino.com/index.php?title=Blue_Pill"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow"><strong class="gm hc">STM32 Blue
|
||
Pill </strong></a>— and a real NB-IoT module — <a
|
||
href="https://www.quectel.com/product/bc95g.htm"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow"><strong class="gm hc">Quectel
|
||
BC95-G</strong></a>!</p>
|
||
<p id="f3ab" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><em class="hd">Why are we
|
||
building it with </em><a
|
||
href="https://mynewt.apache.org/"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow"><strong class="gm hc">Apache
|
||
Mynewt</strong></a><em class="hd"> realtime operating system?</em></p>
|
||
<p id="f3ff" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Because handling the AT
|
||
commands for the Quectel module is a little complicated… Imagine we’re polling the temperature sensor
|
||
every 10 seconds and transmitting the sensor data via NB-IoT. But the Quectel module hasn’t responded
|
||
to our AT command yet. <em class="hd">Do we give up and crash the application?</em></p>
|
||
<p id="4535" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Fortunately Mynewt is fully
|
||
capable of <strong class="gm hc">multitasking</strong> — it will wait for the AT command to complete
|
||
(or cancel it in case of timeout). It has a built-in <strong class="gm hc">CoAP library</strong> for
|
||
composing CoAP messages. And <strong class="gm hc">drivers for many sensors</strong>. So Mynewt is
|
||
perfect for building NB-IoT devices!</p>
|
||
<p id="cf7b" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Here’s what we’ll be building
|
||
today…</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure he hf hg hh hi cz">
|
||
<div class="dl r dd">
|
||
<div class="hj r"><iframe
|
||
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F5muOMHodSCE%3Ffeature%3Doembed&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D5muOMHodSCE&image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F5muOMHodSCE%2Fhqdefault.jpg&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=youtube"
|
||
allowfullscreen="" frameborder="0" height="300" width="400"
|
||
title="Connecting STM32 Blue Pill to Quectel NB-IoT modules" class="cp t u dh ak"
|
||
scrolling="auto"></iframe></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<p id="ba24" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">The complete source code is
|
||
located here…</p>
|
||
<div class="hk hl hm hn ho hp"><a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/nbiot"
|
||
rel="noopener nofollow">
|
||
<div class="hs n ar">
|
||
<div class="ht n co p hu hv">
|
||
<h2 class="bj hw hx bl dv">
|
||
<div class="di hq fh fi hr fk">lupyuen/stm32bluepill-mynewt-sensor</div>
|
||
</h2>
|
||
</div>
|
||
<div class="ia r">
|
||
<div class="ib r ic id ie ia if ig ih"></div>
|
||
</div>
|
||
</div>
|
||
</a></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="ii fe ij ik il im in io ip iq ir" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<h1 id="404d" class="is it dv bk bj hw dx iu dz iv iw ix iy iz ja jb jc">Hardware Required</h1>
|
||
<div class="figure he hf hg hh hi cz dr je cd jf jg jh ji jj ba jk jl jm jn jo jp paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/a2.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>STM32 Blue Pill, ST-Link V2, Quectel BC95-G
|
||
breakout board with antenna, NB-IoT SIM</em></p></figcaption>
|
||
</div>
|
||
<p id="2382" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">We’ll need the following
|
||
hardware…</p>
|
||
<p id="018a" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">1️⃣ <a
|
||
href="https://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20180924131057&SearchText=stm32f103c8t6+development+board"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow"><strong class="gm hc">STM32 Blue
|
||
Pill</strong></a></p>
|
||
<p id="0051" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">2️⃣ <a
|
||
href="https://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20180924134644&SearchText=st-link+v2"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow"><strong class="gm hc">ST-Link V2
|
||
USB Adapter</strong></a></p>
|
||
<p id="7ed8" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">3️⃣ <a
|
||
href="https://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20190725022150&SearchText=bc95-g+nb101&switch_new_app=y"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow"><strong class="gm hc">Quectel
|
||
BC95-G Global NB-IoT Module</strong></a> (breakout board with antenna). I ordered mine <a
|
||
href="https://item.taobao.com/item.htm?id=577310122904"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">here</a>. The manual in Chinese is
|
||
<a href="http://rs.iotxx.com/uploads/doc/%E8%B0%B7%E9%9B%A8NB10x%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%E4%B9%A6-V1.3.pdf"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">here</a>.</p>
|
||
<p id="d9b5" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">4️⃣ <strong
|
||
class="gm hc">NB-IoT SIM</strong> from your local NB-IoT network operator</p>
|
||
<p id="6520" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Many thanks to <a
|
||
href="https://www.starhub.com/" class="at cg gy gz ha hb"
|
||
target="_blank" rel="noopener nofollow"><strong class="gm hc">StarHub</strong></a> for sponsoring
|
||
the NB-IoT SIM that I used for this tutorial!</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="ii fe ij ik il im in io ip iq ir" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="cz ak">
|
||
<div class="figure he hf hg hh hi cz ak paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/a3.jpeg" /></p>
|
||
|
||
|
||
<figcaption><p><em>Blue Pill connected to Quectel BC95-G and
|
||
ST-Link</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<h1 id="dfec" class="is it dv bk bj hw dx jv dz jw iw jx iy jy ja jz jc">Connect Blue Pill to Quectel
|
||
Module</h1>
|
||
<p id="07e3" class="gk gl dv bk gm b gn ka gp kb gr kc gt kd gv ke gx cu">Connect Blue Pill to Quectel
|
||
BC95-G and ST-Link as follows…</p>
|
||
<div class="figure he hf hg hh hi cz">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/58e4584448ab90098b033e996f228bca.js"></script></p>
|
||
|
||
|
||
</div>
|
||
<p id="b8e9" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Both yellow jumpers on Blue
|
||
Pill should be set to the <code class="dm kg kh ki kj b">0</code> position, as shown in the above
|
||
photo.</p>
|
||
<p id="7114" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Note that we are powering the
|
||
Quectel module with<strong class="gm hc"> 5V from ST-Link instead of 3.3V from Blue Pill</strong>.
|
||
That’s because the module requires more power than Blue Pill can provide. (How did I find out? Because
|
||
the module kept restarting when I powered it from Blue Pill.)</p>
|
||
<p id="e180" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><strong class="gm hc">Check
|
||
the documentation for your Quectel breakout board to confirm that it supports 5V.</strong> (<a
|
||
href="http://rs.iotxx.com/uploads/doc/%E8%B0%B7%E9%9B%A8NB10x%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%E4%B9%A6-V1.3.pdf"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">Mine does</a>)</p>
|
||
<div class="figure he hf hg hh hi cz dr je cd jf jg jh ji jj ba jk jl jm jn jo jp paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/a4.png" /></p>
|
||
|
||
|
||
<figcaption><p><em>SIM partially exposed to show the unusual
|
||
orientation</em></p></figcaption>
|
||
</div>
|
||
<p id="f95d" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><strong class="gm hc">Insert
|
||
the NB-IoT SIM</strong> according to the orientation shown in the photo. (Yes the SIM notch faces
|
||
outward, not inward)</p>
|
||
<p id="0bd3" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><strong class="gm hc"><em
|
||
class="hd">Remember: Always connect the antenna before powering up the NB-IoT
|
||
module!</em></strong></p>
|
||
<p id="d37c" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><strong class="gm hc">Don’t
|
||
connect ST-Link to your computer yet,</strong> we’ll need to install the ST-Link driver in a while.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="ii fe ij ik il im in io ip iq ir" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<h1 id="4c8d" class="is it dv bk bj hw dx iu dz iv iw ix iy iz ja jb jc">Install Mynewt</h1>
|
||
<p id="d3d0" class="gk gl dv bk gm b gn ka gp kb gr kc gt kd gv ke gx cu">Follow the instructions below
|
||
to install the Mynewt build and application files on Windows…</p>
|
||
<div class="hk hl hm hn ho hp"><a rel="noopener"
|
||
href="https://lupyuen.github.io/articles/install-apache-mynewt-on-windows">
|
||
<div class="hs n ar">
|
||
<div class="ht n co p hu hv">
|
||
<h2 class="bj hw hx bl dv">
|
||
<div class="di hq fh fi hr fk">Install Apache Mynewt on Windows</div>
|
||
</h2>
|
||
</div>
|
||
</div>
|
||
</a></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="ii fe ij ik il im in io ip iq ir" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<h1 id="b4ad" class="is it dv bk bj hw dx iu dz iv iw ix iy iz ja jb jc">The NB-IoT Program</h1>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure he hf hg hh hi cz ak paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/a5.png" /></p>
|
||
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<p id="e671" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">We have just installed a
|
||
simple program that <strong class="gm hc">reads Blue Pill’s </strong><a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/nbiot/libs/temp_stm32"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow"><strong class="gm hc">internal
|
||
temperature sensor</strong></a> every 10 seconds and <strong class="gm hc">sends the data to a
|
||
CoAP Server</strong> (thethings.io) over the NB-IoT network.</p>
|
||
<blockquote class="kn">
|
||
<div id="8eac" class="ko kp kq bk dw b kr ks kt ku kv kw gx">
|
||
<p class="dw b kx ky bo">Function main()</p>
|
||
</div>
|
||
</blockquote>
|
||
<div class="figure la lb lc ld le cz dr je cd jf jg jh ji jj ba jk jl jm jn jo jp paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/a6.png" /></p>
|
||
|
||
|
||
</div>
|
||
<div class="figure da cz dr je cd jf jg jh ji jj ba jk lg lh li lj jp">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/a6005abcabcbf593c2a2185e2c00d586.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/apps/my_sensor_app/src/main.c"
|
||
class="at cg gy gz ha hb" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/apps/my_sensor_app/src/main.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="b90b" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b">main()</code> in <code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/apps/my_sensor_app/src/main.c" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">apps/my_sensor_app/src/main.c</a></code>
|
||
is the function called upon device startup. Mynewt applications are required to call <code
|
||
class="dm kg kh ki kj b">sysinit()</code> to start the system services and drivers, including the
|
||
drivers for the internal temperature sensor and the NB-IoT module.</p>
|
||
<p id="9905" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b">start_sensor_listener()</code> is called next to set up the polling
|
||
schedule for the temperature sensor. We’ll study this in a while.</p>
|
||
<p id="6e64" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/sensor_network/src/sensor_network.c#L134-L142" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">start_server_transport</a>()</code>
|
||
is called to connect the NB-IoT module to the NB-IoT network. This may take a few seconds to complete,
|
||
so <code class="dm kg kh ki kj b">start_server_transport()</code> will perform the connection as a <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/sensor_network/src/sensor_network.c#L152-L194"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">background task</a>. <code
|
||
class="dm kg kh ki kj b">start_server_transport()</code> is part of the <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/nbiot/libs/sensor_network"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">Sensor Network Library</a>.</p>
|
||
<p id="6b88" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">The main event loop appears at
|
||
the end of the <code class="dm kg kh ki kj b">main()</code> function. This is required by Mynewt for
|
||
processing system events.</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure he hf hg hh hi cz ak paragraph-image">
|
||
|
||
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<blockquote class="kn">
|
||
<div id="d2b7" class="ko kp kq bk dw b kr ks kt ku kv kw gx">
|
||
<p class="dw b kx ky bo">Functions start_network_sensor() and handle_sensor_data()</p>
|
||
</div>
|
||
</blockquote>
|
||
<div class="figure la lb lc ld le cz dr je cd jf jg jh ji jj ba jk jl jm jn jo jp paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/a7.png" /></p>
|
||
|
||
|
||
</div>
|
||
<div class="figure da cz dr je cd jf jg jh ji jj ba jk lg lh li lj jp">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/62fb126187d1f6401026647a94443edc.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/apps/my_sensor_app/src/sensor.c#L37-L62"
|
||
class="at cg gy gz ha hb" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/apps/my_sensor_app/src/sensor.c#L37-L62</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="b8bb" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b">start_sensor_listener()</code> in <code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/apps/my_sensor_app/src/sensor.c#L37-L62" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">apps/my_sensor_app/src/sensor.c</a></code>
|
||
is called by <code class="dm kg kh ki kj b">main()</code> to set the polling schedule for the
|
||
temperature sensor.</p>
|
||
<p id="350b" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b"><a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_mgr_api.html#c.sensor_set_poll_rate_ms" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">sensor_set_poll_rate_ms</a>()</code>
|
||
is the Mynewt system function that’s called to set the temperature sensor (<code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/nbiot/libs/temp_stm32" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">temp_stm32_0</a></code>)
|
||
to be polled every 10,000 milliseconds (or 10 seconds)</p>
|
||
<p id="ea66" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><em class="hd">What happens
|
||
when Mynewt has polled the sensor data?</em></p>
|
||
<p id="aa8b" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">In the call to <code
|
||
class="dm kg kh ki kj b"><a href="https://mynewt.apache.org/latest/os/modules/sensor_framework/sensor_listener_api.html#c.sensor_register_listener" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">sensor_register_listener</a>() </code>(another
|
||
Mynewt system function), we instruct Mynewt to call our function <code
|
||
class="dm kg kh ki kj b">handle_sensor_data()</code> whenever it has polled for new sensor data.</p>
|
||
<div class="figure he hf hg hh hi cz cl cm paragraph-image">
|
||
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
</div>
|
||
<div class="figure js cz dr je cd jf jg jh ji jj ba jk lg lh li lj jp">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/6c35aa0f59ed91b37192601f4f21a0e0.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/apps/my_sensor_app/src/sensor.c#L63-L89"
|
||
class="at cg gy gz ha hb" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/apps/my_sensor_app/src/sensor.c#L63-L89</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="b846" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Every 10 seconds after Mynewt
|
||
has obtained the raw sensor data from the temperature sensor, Mynewt calls <code
|
||
class="dm kg kh ki kj b">handle_sensor_data()</code> in <code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/apps/my_sensor_app/src/sensor.c#L63-L89" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">apps/my_sensor_app/src/sensor.c</a></code>
|
||
to work on the raw sensor data.</p>
|
||
<p id="0b15" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b">handle_sensor_data()</code> wraps the raw sensor data into a <code
|
||
class="dm kg kh ki kj b">sensor_value</code>. Here we specify that the raw sensor data should be
|
||
transmitted as an integer with field name <code class="dm kg kh ki kj b">t</code>. It then calls <code
|
||
class="dm kg kh ki kj b">send_sensor_data()</code> to transmit the sensor value.</p>
|
||
<p id="1bdf" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><em class="hd">Why do we
|
||
transmit the raw sensor data as an integer value (like </em><code
|
||
class="dm kg kh ki kj b">1715</code><em class="hd">) instead of a floating-point value (like
|
||
</em><code class="dm kg kh ki kj b">32.1</code><em class="hd"> degrees Celsius)?</em></p>
|
||
<p id="9264" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Remember that we are creating
|
||
an embedded application for a <strong class="gm hc">constrained, low-power microcontroller with little
|
||
ROM and RAM</strong>. On constrained devices, it takes a lot of ROM and RAM to convert temperature
|
||
values from integer to floating-point.</p>
|
||
<p id="e9b1" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Hence we <strong
|
||
class="gm hc">conserve device resources when we transmit sensor values in their raw, integer
|
||
forms</strong> and let the IoT cloud (thethings.io) convert the values into floating-point.</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure he hf hg hh hi cz ak paragraph-image">
|
||
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<blockquote class="kn">
|
||
<div id="7a02" class="ko kp kq bk dw b kr ks kt ku kv kw gx">
|
||
<p class="dw b kx ky bo">Function send_sensor_data()</p>
|
||
</div>
|
||
</blockquote>
|
||
<div class="figure la lb lc ld le cz dr je cd jf jg jh ji jj ba jk jl jm jn jo jp paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/a8.png" /></p>
|
||
|
||
|
||
</div>
|
||
<div class="figure da cz dr je cd jf jg jh ji jj ba jk lg lh li lj jp">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/7a1fc4b8873e6c9d9cc436b5553c04d0.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/apps/my_sensor_app/src/network.c"
|
||
class="at cg gy gz ha hb" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/apps/my_sensor_app/src/network.c</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="e846" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b">send_sensor_data()</code> in <code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/apps/my_sensor_app/src/network.c" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">apps/my_sensor_app/src/network.c</a></code>
|
||
is called by <code class="dm kg kh ki kj b">handle_sensor_data()</code> to transmit sensor data. In
|
||
this program we’re transmitting sensor data to the CoAP server at thethings.io.</p>
|
||
<p id="3bb1" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">thethings.io requires our
|
||
sensor data to be in this JSON format…</p>
|
||
<pre
|
||
class="he hf hg hh hi lq lr ls"><span id="88dc" class="lt it dv bk kj b ff lu lv r lw">{"values":[<br/> {"key":"device",<br/> "value":"010203"},<br/> {"key":"t", <br/> "value":1715}<br/>]}</span></pre>
|
||
<p id="96d8" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">By calling the macros <code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/sensor_coap/include/sensor_coap/sensor_coap.h#L223-L229" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">CP_ROOT</a></code>,
|
||
<code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/sensor_coap/include/sensor_coap/sensor_coap.h#L274-L280" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">CP_ARRAY</a></code>,
|
||
<code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/sensor_coap/include/sensor_coap/sensor_coap.h#L316-L324" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">CP_ITEM_STR</a></code>
|
||
and <code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/sensor_coap/include/sensor_coap/sensor_coap.h#L262-L267" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">CP_ITEM_INT_VAL</a></code>,
|
||
the program composes a JSON message in the above format based on our raw temperature value <code
|
||
class="dm kg kh ki kj b">t</code>.</p>
|
||
<p id="6c48" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">When <code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/sensor_network/src/sensor_network.c#L284-L293" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">do_server_post</a>()</code>
|
||
is called, the JSON message is encoded as the payload of a CoAP message. The CoAP message is
|
||
transmitted as a UDP packet to thethings.io over the NB-IoT network.</p>
|
||
<p id="e2a1" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">What’s <code
|
||
class="dm kg kh ki kj b">device</code> in the JSON message? We’ll find out in a while.</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure he hf hg hh hi cz ak paragraph-image">
|
||
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<h1 id="530f" class="is it dv bk bj hw dx jv dz jw iw jx iy jy ja jz jc"><strong class="az">Run The
|
||
Program</strong></h1>
|
||
<p id="5d91" class="gk gl dv bk gm b gn ka gp kb gr kc gt kd gv ke gx cu">1️⃣ Click <code
|
||
class="dm kg kh ki kj b">Debug → Start Debugging</code></p>
|
||
<div class="figure he hf hg hh hi cz dr je cd jf jg jh ji jj ba jk jl jm jn jo jp paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/a9.png" /></p>
|
||
|
||
|
||
</div>
|
||
<p id="d587" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">2️⃣ Click <code
|
||
class="dm kg kh ki kj b">View → Output</code></p>
|
||
<p id="de7e" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Select <code
|
||
class="dm kg kh ki kj b">Adapter Output</code> to see the Blue Pill log</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure he hf hg hh hi cz ak paragraph-image">
|
||
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<div class="figure la lb lc ld le cz dr je cd jf jg jh ji jj ba jk jl jm jn jo jp paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/a10.png" /></p>
|
||
|
||
|
||
</div>
|
||
<p id="35d0" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">3️⃣ The debugger pauses at the
|
||
line with <code class="dm kg kh ki kj b">LoopCopyDataInit</code></p>
|
||
<p id="330a" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Click <code
|
||
class="dm kg kh ki kj b">Continue</code> or press <code class="dm kg kh ki kj b">F5</code></p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure he hf hg hh hi cz ak paragraph-image">
|
||
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<div class="figure la lb lc ld le cz dr je cd jf jg jh ji jj ba jk jl jm jn jo jp paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/a11.png" /></p>
|
||
|
||
|
||
</div>
|
||
<p id="797f" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">4️⃣ The debugger pauses next
|
||
at the <code class="dm kg kh ki kj b">main()</code> function.</p>
|
||
<p id="9af7" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Click <code
|
||
class="dm kg kh ki kj b">Continue</code> or press <code class="dm kg kh ki kj b">F5</code></p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure he hf hg hh hi cz ak paragraph-image">
|
||
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<p id="451e" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">The program should now poll
|
||
the internal temperature sensor every 10 seconds and transmit to thethings.io. Let’s study the Blue
|
||
Pill execution log…</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="ii fe ij ik il im in io ip iq ir" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<h1 id="ea16" class="is it dv bk bj hw dx iu dz iv iw ix iy iz ja jb jc">Check The Log</h1>
|
||
<p id="8fc8" class="gk gl dv bk gm b gn ka gp kb gr kc gt kd gv ke gx cu">The log from our Blue Pill
|
||
should <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/logs/standalone-node.log"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">look like this</a>. When we see
|
||
this in the log…</p>
|
||
<pre
|
||
class="he hf hg hh hi lq lr ls"><span id="051e" class="lt it dv bk kj b ff lu lv r lw">AT> NCONFIG=AUTOCONNECT,FALSE<br/>AT= OK</span></pre>
|
||
<p id="40f2" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">It means that the program has
|
||
sent this AT command to the NB-IoT module…</p>
|
||
<pre
|
||
class="he hf hg hh hi lq lr ls"><span id="f4a3" class="lt it dv bk kj b ff lu lv r lw">AT+NCONFIG=AUTOCONNECT,FALSE</span></pre>
|
||
<p id="c1ef" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Followed by Carriage Return
|
||
<code class="dm kg kh ki kj b">CR</code> <code class="dm kg kh ki kj b">0x0d</code> and Line Feed
|
||
<code class="dm kg kh ki kj b">LF</code> <code class="dm kg kh ki kj b">0x0a</code> characters. Then
|
||
the NB-IoT module responded with…</p>
|
||
<pre
|
||
class="he hf hg hh hi lq lr ls"><span id="559f" class="lt it dv bk kj b ff lu lv r lw">OK</span></pre>
|
||
<p id="eaf1" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Since <code
|
||
class="dm kg kh ki kj b">AT+</code> is present in all AT commands, we won’t show the prefix <code
|
||
class="dm kg kh ki kj b">AT+</code> in the log. All the AT commands below are explained in <a
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/get-started-with-nb-iot-and-quectel-modules">my
|
||
previous article</a>.</p>
|
||
<div class="figure he hf hg hh hi cz dr je cd jf jg jh ji jj ba jk lg lh li lj jp">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/0bcaf1aba24538acae14c044636bb6af.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/logs/standalone-node.log#L61-L89"
|
||
class="at cg gy gz ha hb" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/logs/standalone-node.log#L61-L89</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="9a33" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">When the program starts, it
|
||
disables NB-IoT module’s auto-connection (<code
|
||
class="dm kg kh ki kj b">NCONFIG=AUTOCONNECT,FALSE</code>) and reboots the NB-IoT module (<code
|
||
class="dm kg kh ki kj b">NRB</code>).</p>
|
||
<p id="01df" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">It selects <strong
|
||
class="gm hc">NB-IoT Frequency Band 8</strong> (<code class="dm kg kh ki kj b">NBAND=8</code>),
|
||
enables the NB-IoT radio transceiver (<code class="dm kg kh ki kj b">CFUN=1</code>) and starts
|
||
attaching to the NB-IoT network (<code class="dm kg kh ki kj b">CGATT=1</code>)</p>
|
||
<p id="4b45" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><em class="hd">The </em><a
|
||
href="http://www.techplayon.com/nb-iot-frequency-bands-as-per-3gpp-rel-13-14-and-15/"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow"><em class="hd">NB-IoT Frequency
|
||
Band</em></a><em class="hd"> depends on your country and your NB-IoT network operator. Check with
|
||
your NB-IoT network operator for the Frequency Band to use.</em></p>
|
||
<p id="e731" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">The NB-IoT Band is configured
|
||
here: <code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/targets/bluepill_my_sensor/syscfg.yml" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">targets/bluepill_my_sensor/syscfg.yml</a></code>
|
||
</p>
|
||
<p id="9ab1" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">The program queries the NB-IoT
|
||
registration status (<code class="dm kg kh ki kj b">CEREG?</code>). The response <code
|
||
class="dm kg kh ki kj b">+CEREG:0,2</code> means that the NB-IoT module is still registering with
|
||
the NB-IoT network.</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure he hf hg hh hi cz ak paragraph-image">
|
||
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<div class="figure la lb lc ld le cz dr je cd jf jg jh ji jj ba jk lg lh li lj jp">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/31b0a00891a795a6973850d0157eaf68.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/logs/standalone-node.log#L102-L109"
|
||
class="at cg gy gz ha hb" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/logs/standalone-node.log#L102-L109</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="3c4d" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">The program continues to query
|
||
the registration status (<code class="dm kg kh ki kj b">CEREG?</code>). In a few seconds, we get the
|
||
response <code class="dm kg kh ki kj b">+CEREG:0,1</code> which means that the NB-IoT module has
|
||
registered with the NB-IoT network.</p>
|
||
<p id="9ded" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">We send <code
|
||
class="dm kg kh ki kj b">CGATT?</code> to check whether we have been attached to the NB-IoT network.
|
||
The response <code class="dm kg kh ki kj b">+CGATT:1</code> means that we have been successfully
|
||
attached to the NB-IoT network. We may start transmitting data to the network.</p>
|
||
<p id="fb52" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Before transmitting, we ask
|
||
the NB-IoT module to allocate a local UDP port (<code
|
||
class="dm kg kh ki kj b">NSOCR=DGRAM,17,0,1</code>). The module returns local port <code
|
||
class="dm kg kh ki kj b">1</code>.</p>
|
||
</div>
|
||
</div>
|
||
<div class="cz ak">
|
||
<div class="figure he hf hg hh hi cz ak paragraph-image">
|
||
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/h0.png" /></p>
|
||
|
||
</div>
|
||
</div>
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<div class="figure la lb lc ld le cz dr je cd jf jg jh ji jj ba jk lg lh li lj jp">
|
||
|
||
<p><script src="https://gist.github.com/lupyuen/72ff3872d4cfa166fdc1da407d2cafa9.js"></script></p>
|
||
|
||
|
||
<figcaption><p><em>From <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/logs/standalone-node.log#L113-L127"
|
||
class="at cg gy gz ha hb" target="_blank"
|
||
rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/logs/standalone-node.log#L113-L127</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="6d79" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Next the program reads the
|
||
Blue Pill’s internal temperature sensor (every 10 seconds) and obtains the raw temperature value <code
|
||
class="dm kg kh ki kj b">1757</code>.</p>
|
||
<p id="c0ac" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">The program composes the CoAP
|
||
message with JSON payload (described earlier)…</p>
|
||
<pre
|
||
class="he hf hg hh hi lq lr ls"><span id="e710" class="lt it dv bk kj b ff lu lv r lw">{"values": [<br/> {"key": "device",<br/> "value": "ac913c..."},<br/> {"key": "t",<br/> "value": 1757}<br/>]}</span></pre>
|
||
<p id="bd91" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">…And transmits the CoAP
|
||
message via the AT command <code class="dm kg kh ki kj b">NSOST=…</code> (not shown in the log).</p>
|
||
<p id="a3fa" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">The hex numbers <code
|
||
class="dm kg kh ki kj b">58 02 00 01 ...</code> are the bytes of the <strong class="gm hc">encoded
|
||
CoAP message</strong>. You may decode the CoAP message with Wireshark as explained in the <a
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/get-started-with-nb-iot-and-quectel-modules">previous
|
||
article</a>.</p>
|
||
<p id="403e" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">The CoAP message is
|
||
transmitted by the NB-IoT module to the CoAP server at thethings.io. Notice that the message includes
|
||
a device ID <code class="dm kg kh ki kj b">ac913c...</code> This is a <strong class="gm hc">random
|
||
number that’s transmitted in every CoAP message</strong>.</p>
|
||
<p id="951a" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">When we Ctrl-Click the URL in
|
||
the log…</p>
|
||
<pre
|
||
class="he hf hg hh hi lq lr ls"><span id="ad81" class="lt it dv bk kj b ff lu lv r lw"><a href="https://blue-pill-geolocate.appspot.com/?device=ac913c504b27e00bc8b68dfe843b297c" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">https://blue-pill-geolocate.appspot.com?device=ac913c</a>…</span></pre>
|
||
<div class="figure he hf hg hh hi cz dr je cd jf jg jh ji jj ba jk jl jm jn jo jp paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/a12.png" /></p>
|
||
|
||
|
||
</div>
|
||
<figcaption><p><em>Web page with computed temperature
|
||
</em></p></figcaption>
|
||
</div>
|
||
<p id="038e" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">…We see a web page with the
|
||
computed temperature value in degrees Celsius. That’s because <strong class="gm hc">thethings.io has
|
||
converted the raw temperature into the actual temperature</strong> (in degrees Celsius). We have
|
||
installed a <a
|
||
href="https://github.com/lupyuen/thethingsio-wifi-geolocation"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">script at thethings.io</a> that
|
||
pushes the computed temperature to <code
|
||
class="dm kg kh ki kj b">blue-pill-geolocate.appspot.com</code>, so that we could see the computed
|
||
temperature.</p>
|
||
<p id="794e" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">The URL (and the random
|
||
number) <strong class="gm hc">changes each time we restart the program</strong>. More details about
|
||
the setup for thethings.io may be found in the <a class="at cg gy gz ha hb" target="_blank"
|
||
rel="noopener"
|
||
href="https://lupyuen.github.io/articles/get-started-with-nb-iot-and-quectel-modules">previous
|
||
article</a>.</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="ii fe ij ik il im in io ip iq ir" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<h1 id="5447" class="is it dv bk bj hw dx iu dz iv iw ix iy iz ja jb jc">What’s Next?</h1>
|
||
<p id="dfe8" class="gk gl dv bk gm b gn ka gp kb gr kc gt kd gv ke gx cu">In the next article we’ll
|
||
create more NB-IoT devices… this time with <a class="at cg gy gz ha hb" target="_blank" rel="noopener"
|
||
href="https://web.archive.org/https://medium.com/@ly.lee/visual-programming-with-embedded-rust-yes-we-can-with-apache-mynewt-and-google-blockly-8b67ef7412d7"><strong
|
||
class="gm hc">Visual Rust</strong></a>!</p>
|
||
<div class="hk hl hm hn ho hp"><a rel="noopener"
|
||
href="https://lupyuen.github.io/articles/rust-rocks-nb-iot-stm32-blue-pill-with-quectel-bc95-g-on-apache-mynewt">
|
||
<div class="hs n ar">
|
||
<div class="ht n co p hu hv">
|
||
<h2 class="bj hw hx bl dv">
|
||
<div class="di hq fh fi hr fk">Rust Rocks NB-IoT! STM32 Blue Pill with Quectel BC95-G on
|
||
Apache Mynewt</div>
|
||
</h2>
|
||
</div>
|
||
<div class="ia r">
|
||
<div class="me r ic id ie ia if ig ih"></div>
|
||
</div>
|
||
</div>
|
||
</a></div>
|
||
<p id="d769" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">Also we’ll be checking out
|
||
these exciting NB-IoT developer kits with <strong class="gm hc">onboard low-power STM32
|
||
microcontrollers and Quectel NB-IoT modules</strong>. Stay tuned!</p>
|
||
<div class="figure he hf hg hh hi cz cl cm paragraph-image">
|
||
|
||
<p><img src="https://lupyuen.github.io/images/legacy2/a13.jpeg" /></p>
|
||
|
||
|
||
<figcaption><p><em>NB-IoT developer kit with onboard Quectel
|
||
BC35-G Global NB-IoT module and STM32L431RCT6 microcontroller. From <a
|
||
href="https://item.taobao.com/item.htm?spm=a230r.1.14.27.67a75d82e8brCe&id=577708190839&ns=1&abbucket=15#detail"
|
||
class="at cg gy gz ha hb" target="_blank"
|
||
rel="noopener nofollow">https://item.taobao.com/item.htm?spm=a230r.1.14.27.67a75d82e8brCe&id=577708190839&ns=1&abbucket=15#detail</a>
|
||
</em></p></figcaption>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="cz">
|
||
<div class="n p">
|
||
<div class="mh mi mj mk ml mm ag mn ah mo aj ak">
|
||
<div class="figure he hf hg hh hi cz">
|
||
<div class="dl r dd">
|
||
<div class="mp r"><iframe
|
||
src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FHJL9eONDF7Q%3Ffeature%3Doembed&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DHJL9eONDF7Q&image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FHJL9eONDF7Q%2Fhqdefault.jpg&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=youtube"
|
||
allowfullscreen="" frameborder="0" height="480" width="854"
|
||
title="Connecting STM32L431 to Quectel BC35-G NB-IoT module" class="cp t u dh ak"
|
||
scrolling="auto"></iframe></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="ii fe ij ik il im in io ip iq ir" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<h1 id="72f5" class="is it dv bk bj hw dx iu dz iv iw ix iy iz ja jb jc">References</h1>
|
||
<p id="59cd" class="gk gl dv bk gm b gn ka gp kb gr kc gt kd gv ke gx cu">The following Quectel
|
||
documents were very useful for understanding the AT commands. Download them from (free registration
|
||
required) <code
|
||
class="dm kg kh ki kj b"><a href="https://www.quectel.com/support/downloadb/TechnicalDocuments.htm" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">https://www.quectel.com/support/downloadb/TechnicalDocuments.htm</a></code>
|
||
</p>
|
||
<ol class="">
|
||
<li id="c054" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx mq mr ms"><strong
|
||
class="gm hc"><em class="hd">Quectel BC95-G Hardware Design V1.3</em></strong>: Details of the
|
||
BC95-G pins</li>
|
||
<li id="abc5" class="gk gl dv bk gm b gn mt gp mu gr mv gt mw gv mx gx mq mr ms"><strong
|
||
class="gm hc"><em class="hd">Quectel BC95 & BC95-G & BC68 Application Design Guide
|
||
V1.1</em></strong>: Designing applications for BC68</li>
|
||
<li id="7399" class="gk gl dv bk gm b gn mt gp mu gr mv gt mw gv mx gx mq mr ms"><strong
|
||
class="gm hc"><em class="hd">Quectel BC95-G & BC68 AT Commands Manual V1.4</em></strong>: AT
|
||
commands</li>
|
||
<li id="57dc" class="gk gl dv bk gm b gn mt gp mu gr mv gt mw gv mx gx mq mr ms"><strong
|
||
class="gm hc"><em class="hd">Quectel BC95-G & BC68 CoAP Application Note V1.0</em></strong>:
|
||
AT commands for CoAP. Unfortunately I was not able to use the AT commands here to transmit the
|
||
payload correctly (the transmitted payload was always empty). So I decided to encode the CoAP
|
||
messages myself.</li>
|
||
</ol>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<hr class="ii fe ij ik il im in io ip iq ir" />
|
||
<section class="cu cv cw cx cy">
|
||
<div class="n p">
|
||
<div class="ac ae af ag ah ds aj ak">
|
||
<h1 id="f6cf" class="is it dv bk bj hw dx iu dz iv iw ix iy iz ja jb jc">💎 Advanced Topic: Quectel
|
||
BC95-G Driver for Mynewt</h1>
|
||
<p id="fcc6" class="gk gl dv bk gm b gn ka gp kb gr kc gt kd gv ke gx cu">The Mynewt driver I have
|
||
created for Quectel BC95-G is located here…</p>
|
||
<p id="42e8" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/nbiot/libs/bc95g" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">https://github.com/lupyuen/stm32bluepill-mynewt-sensor/tree/nbiot/libs/bc95g</a></code>
|
||
</p>
|
||
<p id="0922" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/bc95g/src/driver.cpp" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">driver.cpp</a></code>
|
||
contains the main logic for the driver. It sends AT commands and handles responses and timeouts.</p>
|
||
<p id="2b3e" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/bc95g/src/ATParser.cpp" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">ATParser</a></code>
|
||
and <code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/bc95g/src/BufferedSerial.cpp" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">BufferedSerial</a></code>
|
||
libraries (ported from mbed) are called by <code class="dm kg kh ki kj b">driver.cpp</code> to parse
|
||
the AT responses from the Quectel module. The dynamic heap memory allocation in the original mbed
|
||
version has been replaced by static memory buffers, to reduce RAM and ROM size.</p>
|
||
<p id="8e78" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/bc95g/src/creator.cpp" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">creator.cpp</a></code>
|
||
contains the driver creation code required by Mynewt</p>
|
||
<p id="3878" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/bc95g/src/transport.cpp" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">transport.cpp</a></code>
|
||
provides the OIC (Open Interconnect Consortium) network transport required for transmitting CoAP
|
||
messages via Mynewt’s OIC framework</p>
|
||
<p id="6e51" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/bc95g/syscfg.yml" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">syscfg.yml</a></code>
|
||
defines one configuration setting: <code class="dm kg kh ki kj b">NBIOT_BAND</code>, the NB-IoT band
|
||
(defaults to <code class="dm kg kh ki kj b">8</code>)</p>
|
||
<p id="aaca" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/bc95g/pkg.yml" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">pkg.yml</a></code>
|
||
instructs Mynewt to call <code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/bc95g/src/creator.cpp#L35-L64" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">bc95g_create</a>()</code>
|
||
to initialise the driver during startup</p>
|
||
<p id="7df8" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><em class="hd">Why do we use
|
||
</em><code class="dm kg kh ki kj b">mbufs</code><em class="hd"> when transmitting sensor data? Like in
|
||
</em><code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/bc95g/src/driver.cpp#L553-L557" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">bc95g_socket_tx_mbuf</a>()</code>?
|
||
</p>
|
||
<p id="990e" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">An <code
|
||
class="dm kg kh ki kj b"><a href="https://mynewt.apache.org/latest/os/core_os/mbuf/mbuf.html" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">mbuf</a></code>
|
||
(“<a
|
||
href="https://mynewt.apache.org/latest/os/core_os/mbuf/mbuf.html"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">memory buffer</a>”) is a chain of
|
||
memory blocks that’s optimised for transmitting network messages. Recall the structure of our CoAP
|
||
message from the <a class="at cg gy gz ha hb" target="_blank" rel="noopener"
|
||
href="https://lupyuen.github.io/articles/get-started-with-nb-iot-and-quectel-modules">previous
|
||
article</a>… Every CoAP message has a <strong class="gm hc">Preamble and an Options Header</strong>
|
||
that are usually <strong class="gm hc">fixed in length</strong> for the session. But the Payload of
|
||
the message may vary, depending on the sensor data.</p>
|
||
<p id="4107" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu"><em class="hd">Shall we keep
|
||
reallocating and deallocating the memory blocks for the Preamble, Options and Payload every time we
|
||
transmit a CoAP message?</em></p>
|
||
<p id="3ec5" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">No, we may actually <strong
|
||
class="gm hc">reuse the same </strong><code
|
||
class="dm kg kh ki kj b"><strong class="gm hc">mbuf</strong></code> to hold the fixed-length
|
||
Preamble and Options. But depending on the sensor data, we’ll attach one or more <code
|
||
class="dm kg kh ki kj b">mbufs</code> to the chain to hold the entire Payload. This speeds up the
|
||
composition of CoAP messages.</p>
|
||
<p id="7446" class="gk gl dv bk gm b gn go gp gq gr gs gt gu gv gw gx cu">That’s why in the driver code
|
||
we see the program <a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/bc95g/src/driver.cpp#L512-L527"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">walking through each </a><code
|
||
class="dm kg kh ki kj b"><a href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/bc95g/src/driver.cpp#L512-L527" class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">mbuf</a></code><a
|
||
href="https://github.com/lupyuen/stm32bluepill-mynewt-sensor/blob/nbiot/libs/bc95g/src/driver.cpp#L512-L527"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow"> in the chain</a> and transmitting
|
||
each <code class="dm kg kh ki kj b">mbuf</code>. This keeps the networking code highly efficient, just
|
||
like <a
|
||
href="https://www.freebsd.org/cgi/man.cgi?query=mbuf&sektion=9&manpath=FreeBSD+6.0-stable"
|
||
class="at cg gy gz ha hb" target="_blank" rel="noopener nofollow">early versions of the Unix
|
||
operating system</a>.</p>
|
||
</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 16:57:12 Jan 30, 2020 AND RETRIEVED FROM THE
|
||
INTERNET ARCHIVE ON 01:29:35 Feb 23, 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):
|
||
LoadShardBlock: 181.709 (3)
|
||
PetaboxLoader3.datanode: 223.497 (4)
|
||
RedisCDXSource: 0.642
|
||
esindex: 0.015
|
||
CDXLines.iter: 21.936 (3)
|
||
captures_list: 207.814
|
||
load_resource: 186.973
|
||
exclusion.robots.policy: 0.291
|
||
exclusion.robots: 0.307
|
||
PetaboxLoader3.resolve: 35.68
|
||
--> |