blob: 975ec5d5ca6d9fb05f8a211215df0755e9ffa48b [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- This is broken by doc revisioning.
-->
<link rel="shortcut icon" href="../../../img/favicon.ico">
<title>Basic Air Quality Sensor - Apache Mynewt</title>
<link href="../../../css/bootstrap-3.0.3.min.css" rel="stylesheet">
<link rel="stylesheet" href="../../../css/highlight.css">
<link href="../../../css/base.css" rel="stylesheet">
<link href="../../../css/custom.css" rel="stylesheet">
<link href="../../../css/v2.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<script>
(function(i, s, o, g, r, a, m) {
i["GoogleAnalyticsObject"] = r;
(i[r] =
i[r] ||
function() {
(i[r].q = i[r].q || []).push(arguments);
}),
(i[r].l = 1 * new Date());
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m);
})(window, document, "script", "//www.google-analytics.com/analytics.js", "ga");
ga("create", "UA-72162311-1", "auto");
ga("send", "pageview");
</script>
</head>
<body class="Basic Air Quality Sensor">
<div class="container">
<div class="row v2-main-banner">
<a class="logo-cell" href="/">
<img class="logo" src="/img/logo.png">
</a>
<div class="tagline-cell">
<h4 class="tagline">An OS to build, deploy and securely manage billions of devices</h4>
</div>
<div class="news-cell">
<div class="well">
<h4>Latest News:</h4> <a href="/download">Apache Mynewt 1.12.0, Apache NimBLE 1.7.0 </a> released (April 4, 2024)
</div>
</div>
</div>
</div>
<nav id="navbar" class="navbar navbar-inverse affix-top" data-spy="affix" data-offset-top="150" role="navigation">
<div class="container">
<!-- Collapsed navigation -->
<div class="navbar-header">
<!-- Expander button -->
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Expanded navigation -->
<div class="navbar-collapse collapse">
<!-- Main navigation -->
<ul class="nav navbar-nav navbar-right">
<li
class=""
>
<a href="/"><i class="fa fa-home" style="font-size: larger;"></i></a>
</li>
<li
class="important"
>
<a href="/quick-start/">Quick Start</a>
</li>
<li
class=""
>
<a href="/about/">About</a>
</li>
<li
class=""
>
<a href="/talks/">Talks</a>
</li>
<li
class="active"
>
<a href="/documentation/">Documentation</a>
</li>
<li
class=""
>
<a href="/download/">Download</a>
</li>
<li
class=""
>
<a href="/community/">Community</a>
</li>
<li
class=""
>
<a href="/events/">Events</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-md-3 v2-sidebar sidebar-container"><div id="docSidebar" class="hidden-print" role="complementary">
<div class="top">
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../../search.html" method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search documentation" />
</div>
</form>
</div>
</div>
<ul class="toc-nav">
<li class="doc-version"><select class="form-control" onchange="if (this.value) window.location.href=this.value">
<option value="/latest">
Version: master
</option>
<option value="/v1_12_0/" >
Version: 1.12.0
</option>
<option value="/v1_11_0/" >
Version: 1.11.0
</option>
<option value="/v1_10_0/" >
Version: 1.10.0
</option>
<option value="/v1_9_0/" >
Version: 1.9.0
</option>
<option value="/v1_8_0/" >
Version: 1.8.0
</option>
<option value="/v1_7_0/" >
Version: 1.7.0
</option>
<option value="/v1_6_0/" >
Version: 1.6.0
</option>
<option value="/v1_5_0/" >
Version: 1.5.0
</option>
<option value="/v1_4_0/" >
Version: 1.4.0
</option>
<option value="/v1_3_0/os/introduction" selected="selected" >
Version: 1.3.0
</option>
<option value="/v1_2_0/os/introduction" >
Version: 1.2.0
</option>
<option value="/v1_1_0/os/introduction" >
Version: 1.1.0
</option>
<option value="/v1_0_0/os/introduction" >
Version: 1.0.0
</option>
<option value="/v0_9_0/os/introduction" >
Version: 0.9.0
</option>
</select></li>
<li ><a href="../../introduction/">Mynewt Documentation</a>
<ul>
<li ><a href="../../get_started/get_started/">Basic Setup</a>
</li>
<li >
<a href="../../get_started/vocabulary/">Concepts</a>
</li>
<li ><a href="../tutorials/">Tutorials</a>
<ul>
<li ><a href="../blinky/">Project Blinky</a>
</li>
<li ><a href="../repo/add_repos/">Work with repositories</a>
</li>
<li ><a href="../project-slinky/">Project Slinky for Remote Comms</a>
</li>
<li><a href="
../ble_bare_bones/
">Bluetooth Low Energy</a>
</li>
<li><a href="
../lora/lorawanapp/
">LoRa</a>
</li>
<li><a href="
../event_queue/
">OS Fundamentals</a>
</li>
<li><a href="
../add_newtmgr/
">Remote Device Management</a>
</li>
<li><a href="
../sensors/sensors/
">Sensors</a>
<ul>
<li ><a href="../sensors/sensors/">Sensor Framework</a>
</li>
<li><a href="
./
">Air-quality Sensor project</a>
<ul>
<li class="active">
<a href="./">Basic Air Quality Sensor</a>
</li>
<li >
<a href="../air_quality_ble/">BLE-enabled Air Quality Sensor</a>
</li>
</ul>
</li>
<li >
<a href="../nrf52_adc/">Add an Analog Sensor</a>
</li>
</ul>
</li>
<li><a href="
../segger_rtt/
">Tooling</a>
</li>
<li><a href="
../codesize/
">Other</a>
</li>
</ul>
</li>
<li ><a href="../../os_user_guide/">OS User Guide</a>
</li>
<li><a href="
../../../network/ble/ble_intro/
">BLE User Guide</a>
</li>
<li ><a href="../../../newt/newt_intro/">Newt Tool Guide</a>
</li>
<li ><a href="../../../newtmgr/overview/">Newt Manager Guide</a>
</li>
<li >
<a href="../../../known_issues/">Known Issues</a>
</li>
</ul>
</li>
<li><a href="
../../../newt/install/prev_releases/
">Appendix</a>
</li>
</ul>
</div></div>
<div class="col-md-9" role="main">
<div class="doc-header">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="/documentation/">Docs</a></li>
<li>&raquo; Air-quality Sensor project</li>
<li>&raquo; Sensors</li>
<li>&raquo; <a href="os/tutorials/tutorials/">Tutorials</a></li>
<li>&raquo; <a href="os/introduction/">Mynewt Documentation</a></li>
<li>&raquo; Basic Air Quality Sensor</li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/apache/mynewt-site/blob/master/docs/os/tutorials/air_quality_sensor.md"
class="icon icon-github"> Edit on GitHub</a>
</li>
</ul>
</div>
</div>
<div class="alert alert-warning">
<p>
Version 1.3.0 is not the most recent version of the Apache Mynewt
documentation. Click <a href="/latest">here</a> to read the latest
version.
</p>
</div>
<h2 id="air-quality-sensor-project">Air quality sensor project</h2>
<h3 id="setting-up-source-tree-for-stuff-you-need">Setting up source tree for stuff you need</h3>
<p>To start with, you need to create a new project under which you will do this development. So you type in:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code> $ mkdir $HOME/src
$ cd $HOME/src
$ newt new air_quality
</code></pre></div>
<p>Let's say you are using Arduino Primo -- which is based on the Nordic Semi NRF52 chip -- as the platform.
You know you need the board support package for that hardware. You can look up its location, add it your
project, and fetch that along with the core OS components. Luckily, the Arduino Primo is supported in the
Mynewt Core, so there's nothing much to do here. </p>
<p>Your project.yml file should look like this:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code> [user@IsMyLaptop:~/src/air_quality]$ emacs project.yml &amp;
[user@IsMyLaptop:~/src/air_quality]$ cat project.yml
project.name: &quot;air_quality&quot;
project.repositories:
- apache-mynewt-core
# Use github&#39;s distribution mechanism for core ASF libraries.
# This provides mirroring automatically for us.
#
repository.apache-mynewt-core:
type: github
vers: 0-latest
user: apache
repo: mynewt-core
[user@IsMyLaptop:~/src/air_quality]$ newt install
apache-mynewt-core
[user@IsMyLaptop:~/src/air_quality]$ ls repos/
apache-mynewt-core
</code></pre></div>
<p>Good. You want to make sure you have all the needed bits for supporting your board;
so you decide to build the blinky project for the platform first.</p>
<p>Now create a target for it and build it. Easiest way to proceed is to copy the existing target for blinky, and modify it to build for Arduino Primo board.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>[user@IsMyLaptop:~/src/air_quality]$ newt target copy my_blinky_sim blink_primo
Target successfully copied; targets/my_blinky_sim --&gt; targets/blink_primo
[user@IsMyLaptop:~/src/air_quality]$ newt target set blink_primo bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52
Target targets/blink_nrf successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52
[user@IsMyLaptop:~/src/air_quality]$ newt build blink_primo
Compiling hal_bsp.c
...
Linking blinky.elf
App successfully built: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.elf
</code></pre></div>
<p>Good.</p>
<p>You know that this platform uses bootloader, which means you have to create a target for that too.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>[user@IsMyLaptop:~/src/air_quality]$ newt target create boot_primo
Target targets/boot_nrf successfully created
[user@IsMyLaptop:~/src/air_quality]$ newt target show
@apache-mynewt-core/targets/unittest
bsp=hw/bsp/native
build_profile=debug
compiler=compiler/sim
targets/blink_primo
app=apps/blinky
bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52
build_profile=debug
targets/boot_primo
targets/my_blinky_sim
app=apps/blinky
bsp=@apache-mynewt-core/hw/bsp/native
build_profile=debug
[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_primo bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52
Target targets/boot_nrf successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52
[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_primo app=@apache-mynewt-core/apps/boot
Target targets/boot_nrf successfully set target.app to @apache-mynewt-core/apps/boot
[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_primo build_profile=optimized
Target targets/boot_nrf successfully set target.build_profile to optimized
</code></pre></div>
<p>And then build it, and load it onto the board.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>newt build boot_primo
....
Linking boot.elf
App successfully built: /Users/user/src/air_quality/bin/boot_primo/apps/boot/boot.elf
[user@IsMyLaptop:~/src/air_quality]
$ newt load boot_primo
</code></pre></div>
<p>At this point, you may (or may not) see a bunch of error messages about not being able to connect to
your board, not being able to load the image, etc. If that's the case, and you haven't already, you
should most definitely go worth through the <a href="../blinky_primo/">blinky_primo</a> tutorial so that you
can properly communicate with your board.</p>
<p>Next you must download the targets to board, and see that the LED actually blinks. You plug in the
Arduino Primo board to your laptop, and say:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>[user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo
Loading app image into slot 1
Error: couldn&#39;t open /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img
Error: exit status 1
load - Load app image to target for &lt;target-name&gt;.
Usage:
newt load [flags]
Examples:
newt load &lt;target-name&gt;
Global Flags:
-l, --loglevel string Log level, defaults to WARN. (default &quot;WARN&quot;)
-o, --outfile string Filename to tee log output to
-q, --quiet Be quiet; only display error output.
-s, --silent Be silent; don&#39;t output anything.
-v, --verbose Enable verbose output when executing commands.
exit status 1
</code></pre></div>
<p>Ah. Forgot to create an image out of the blinky binary. Note that every time you want to build and
load a new firmware image to a target board, you need to run 'create-image' on it.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>[user@IsMyLaptop:~/src/air_quality]$ newt create-image blink_primo 0.0.1
App image successfully generated: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img
Build manifest: /Users/user/src/air_quality/bin/blink_nrf/apps/blinky/manifest.json
[user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo
</code></pre></div>
<p>And it's blinking.</p>
<p>Shortcut for doing build/create-image/load/debug steps all in one is 'newt run' command. Check
out the usage from command line help.</p>
<h3 id="create-test-project">Create test project</h3>
<p>Now that you have your system setup, you can start creating your own stuff.
First you want to create a project for yourself - you could start by using blinky as a project
template, but since we're going to want to be able to access the data via Bluetooth, let's
use the <code>bleprph</code> Bluetooth Peripheral project instead.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code> [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality
[user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/bleprph/pkg.yml apps/air_quality/
[user@IsMyLaptop:~/src/air_quality]$ cp -Rp repos/apache-mynewt-core/apps/bleprph/src apps/air_quality/
</code></pre></div>
<p>Then you modify the apps/air_quality/pkg.yml for air_quality in order to change the <em>pkg.name</em> to be <em>apps/air_quality</em>.
You'll need to add the <code>@apache-mynewt-core/</code> path to all the package dependencies, since the app no longer
resides within the apache-mynewt-core repository.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>[user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml
pkg.name: apps/air_quality
pkg.type: app
pkg.description: BLE Air Quality application.
pkg.author: &quot;Apache Mynewt &lt;dev@mynewt.apache.org&gt;&quot;
pkg.homepage: &quot;http://mynewt.apache.org/&quot;
pkg.keywords:
pkg.deps:
- &quot;@apache-mynewt-core/kernel/os&quot;
- &quot;@apache-mynewt-core/sys/shell&quot;
- &quot;@apache-mynewt-core/sys/stats/full&quot;
- &quot;@apache-mynewt-core/sys/log/full&quot;
- &quot;@apache-mynewt-core/mgmt/newtmgr&quot;
- &quot;@apache-mynewt-core/mgmt/newtmgr/transport/ble&quot;
- &quot;@apache-mynewt-core/net/nimble/controller&quot;
- &quot;@apache-mynewt-core/net/nimble/host&quot;
- &quot;@apache-mynewt-core/net/nimble/host/services/ans&quot;
- &quot;@apache-mynewt-core/net/nimble/host/services/gap&quot;
- &quot;@apache-mynewt-core/net/nimble/host/services/gatt&quot;
- &quot;@apache-mynewt-core/net/nimble/host/store/ram&quot;
- &quot;@apache-mynewt-core/net/nimble/transport/ram&quot;
- &quot;@apache-mynewt-core/sys/console/full&quot;
- &quot;@apache-mynewt-core/sys/sysinit&quot;
- &quot;@apache-mynewt-core/sys/id&quot;
</code></pre></div>
<p>And create a target for it:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>[user@IsMyLaptop:~/src/air_quality]$ newt target create air_q
Target targets/air_q successfully created
[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52
Target targets/air_q successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52
[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q app=apps/air_quality
Target targets/air_q successfully set target.app to apps/air_quality
[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q build_profile=debug
Target targets/air_q successfully set target.build_profile to debug
[user@IsMyLaptop:~/src/air_quality]$ newt build air_q
....
Linking /Users/dsimmons/dev/myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf
Target successfully built: targets/air_q
</code></pre></div>
<h3 id="create-packages-for-drivers">Create packages for drivers</h3>
<p>One of the sensors you want to enable is SenseAir K30, which will connect to the board over a serial port.
To start development of the driver, you first need to create a package description for it, and add stubs for sources.</p>
<p>The first thing to do is to create the directory structure for your driver:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/include/senseair
[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/src
</code></pre></div>
<p>Now you can add the files you need. You'll need a pkg.yml to describe the driver, and then header stub followed by source stub.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/pkg.yml
</code></pre></div>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #633820">#</span>
<span style="color: #633820"># Licensed to the Apache Software Foundation (ASF) under one</span>
<span style="color: #633820"># or more contributor license agreements. See the NOTICE file</span>
<span style="color: #633820"># distributed with this work for additional information</span>
<span style="color: #633820"># regarding copyright ownership. The ASF licenses this file</span>
<span style="color: #633820"># to you under the Apache License, Version 2.0 (the</span>
<span style="color: #633820"># &quot;License&quot;); you may not use this file except in compliance</span>
<span style="color: #633820"># with the License. You may obtain a copy of the License at</span>
<span style="color: #633820"># </span>
<span style="color: #633820"># http:</span><span style="color: #177500">//www.apache.org/licenses/LICENSE-2.0</span>
<span style="color: #633820">#</span>
<span style="color: #633820"># Unless required by applicable law or agreed to in writing,</span>
<span style="color: #633820"># software distributed under the License is distributed on an</span>
<span style="color: #633820"># &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY</span>
<span style="color: #633820"># KIND, either express or implied. See the License for the</span>
<span style="color: #633820"># specific language governing permissions and limitations</span>
<span style="color: #633820"># under the License.</span>
<span style="color: #633820">#</span>
<span style="color: #000000">pkg</span>.<span style="color: #000000">name:</span> <span style="color: #000000">libs/my_drivers/senseair</span>
<span style="color: #000000">pkg</span>.<span style="color: #000000">description:</span> <span style="color: #000000">Host</span> <span style="color: #000000">side</span> <span style="color: #000000">of</span> <span style="color: #000000">the</span> <span style="color: #000000">nimble</span> <span style="color: #000000">Bluetooth</span> <span style="color: #000000">Smart</span> <span style="color: #000000">stack</span>.
<span style="color: #000000">pkg</span>.<span style="color: #000000">author:</span> <span style="color: #C41A16">&quot;Apache Mynewt &lt;dev@mynewt.apache.org&gt;&quot;</span>
<span style="color: #000000">pkg</span>.<span style="color: #000000">homepage:</span> <span style="color: #C41A16">&quot;http://mynewt.apache.org/&quot;</span>
<span style="color: #000000">pkg</span>.<span style="color: #000000">keywords:</span>
<span style="color: #000000">-</span> <span style="color: #000000">ble</span>
<span style="color: #000000">-</span> <span style="color: #000000">bluetooth</span>
<span style="color: #000000">pkg</span>.<span style="color: #000000">deps:</span>
<span style="color: #000000">-</span> <span style="color: #C41A16">&quot;@apache-mynewt-core/kernel/os&quot;</span>
</code></pre></div>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/include/senseair/senseair.h
</code></pre></div>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #177500">/*</span>
<span style="color: #177500"> * Licensed to the Apache Software Foundation (ASF) under one</span>
<span style="color: #177500"> * or more contributor license agreements. See the NOTICE file</span>
<span style="color: #177500"> * distributed with this work for additional information</span>
<span style="color: #177500"> * regarding copyright ownership. The ASF licenses this file</span>
<span style="color: #177500"> * to you under the Apache License, Version 2.0 (the</span>
<span style="color: #177500"> * &quot;License&quot;); you may not use this file except in compliance</span>
<span style="color: #177500"> * with the License. You may obtain a copy of the License at</span>
<span style="color: #177500"> * </span>
<span style="color: #177500"> * http://www.apache.org/licenses/LICENSE-2.0</span>
<span style="color: #177500"> *</span>
<span style="color: #177500"> * Unless required by applicable law or agreed to in writing,</span>
<span style="color: #177500"> * software distributed under the License is distributed on an</span>
<span style="color: #177500"> * &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY</span>
<span style="color: #177500"> * KIND, either express or implied. See the License for the</span>
<span style="color: #177500"> * specific language governing permissions and limitations</span>
<span style="color: #177500"> * under the License.</span>
<span style="color: #177500">*/</span>
<span style="color: #633820">#ifndef _SENSEAIR_H_</span>
<span style="color: #633820">#define _SENSEAIR_H_</span>
<span style="color: #A90D91">void</span> <span style="color: #000000">senseair_init</span>(<span style="color: #A90D91">void</span>);
<span style="color: #633820">#endif </span><span style="color: #177500">/* _SENSEAIR_H_ */</span>
</code></pre></div>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c
</code></pre></div>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #177500">/**</span>
<span style="color: #177500"> * Licensed to the Apache Software Foundation (ASF) under one</span>
<span style="color: #177500"> * or more contributor license agreements. See the NOTICE file</span>
<span style="color: #177500"> * distributed with this work for additional information</span>
<span style="color: #177500"> * regarding copyright ownership. The ASF licenses this file</span>
<span style="color: #177500"> * to you under the Apache License, Version 2.0 (the</span>
<span style="color: #177500"> * &quot;License&quot;); you may not use this file except in compliance</span>
<span style="color: #177500"> * with the License. You may obtain a copy of the License at</span>
<span style="color: #177500"> * </span>
<span style="color: #177500"> * http://www.apache.org/licenses/LICENSE-2.0</span>
<span style="color: #177500"> *</span>
<span style="color: #177500"> * Unless required by applicable law or agreed to in writing,</span>
<span style="color: #177500"> * software distributed under the License is distributed on an</span>
<span style="color: #177500"> * &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY</span>
<span style="color: #177500"> * KIND, either express or implied. See the License for the</span>
<span style="color: #177500"> * specific language governing permissions and limitations</span>
<span style="color: #177500"> * under the License.</span>
<span style="color: #177500"> */</span>
<span style="color: #A90D91">void</span>
<span style="color: #000000">senseair_init</span>(<span style="color: #A90D91">void</span>)
{
}
</code></pre></div>
<p>And add dependency to this package in your project yml file.</p>
<p>Here's the listing from apps/air_quality/pkg.yml</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>pkg.name: apps/air_quality
pkg.type: app
pkg.description: Air quality sensor test
pkg.keywords:
pkg.deps:
- &quot;@apache-mynewt-core/libs/console/full&quot;
- &quot;@apache-mynewt-core/libs/newtmgr&quot;
- &quot;@apache-mynewt-core/libs/os&quot;
- &quot;@apache-mynewt-core/libs/shell&quot;
- &quot;@apache-mynewt-core/sys/config&quot;
- &quot;@apache-mynewt-core/sys/log/full&quot;
- &quot;@apache-mynewt-core/sys/stats/full&quot;
- libs/my_drivers/senseair
</code></pre></div>
<p>And add a call to your main() to initialize this driver.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code> [user@IsMyLaptop:~/src/air_quality]$ diff project/blinky/src/main.c project/air_quality/src/main.c
28a29
&gt; #include &lt;senseair/senseair.h&gt;
190a192
&gt; senseair_init();
[user@IsMyLaptop:~/src/air_quality
</code></pre></div>
<p>The ble_prph app runs everything in one task handler. For this project, we're going to add a second
task handler to respond to the shell, and then handle communicating with the senseair sensor for us.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #177500">/** shell task settings. */</span>
<span style="color: #633820">#define SHELL_TASK_PRIO 2</span>
<span style="color: #633820">#define SHELL_STACK_SIZE (OS_STACK_ALIGN(336))</span>
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">os_eventq</span> <span style="color: #000000">shell_evq</span>;
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">os_task</span> <span style="color: #000000">shell_task</span>;
<span style="color: #000000">bssnz_t</span> <span style="color: #000000">os_stack_t</span> <span style="color: #000000">shell_stack</span>[<span style="color: #000000">SHELL_STACK_SIZE</span>];
</code></pre></div>
<p>That defines the task, now we need to initialize it, add a task handler, and we're going to
use this task as our default task handler.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #177500">/**</span>
<span style="color: #177500"> * Event loop for the main shell task.</span>
<span style="color: #177500"> */</span>
<span style="color: #A90D91">static</span> <span style="color: #A90D91">void</span>
<span style="color: #000000">shell_task_handler</span>(<span style="color: #A90D91">void</span> <span style="color: #000000">*unused</span>)
{
<span style="color: #A90D91">while</span> (<span style="color: #1C01CE">1</span>) {
<span style="color: #000000">os_eventq_run</span>(<span style="color: #000000">&amp;shell_evq</span>);
}
}
</code></pre></div>
<p>And in your <code>main()</code> add:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code> <span style="color: #177500">/* Initialize shell eventq */</span>
<span style="color: #000000">os_eventq_init</span>(<span style="color: #000000">&amp;shell_evq</span>);
<span style="color: #177500">/* Create the shell task. </span>
<span style="color: #177500"> * All shell operations are performed in this task.</span>
<span style="color: #177500"> */</span>
<span style="color: #000000">os_task_init</span>(<span style="color: #000000">&amp;shell_task</span>, <span style="color: #C41A16">&quot;shell&quot;</span>, <span style="color: #000000">shell_task_handler</span>,
<span style="color: #A90D91">NULL</span>, <span style="color: #000000">SHELL_TASK_PRIO</span>, <span style="color: #000000">OS_WAIT_FOREVER</span>,
<span style="color: #000000">shell_stack</span>, <span style="color: #000000">SHELL_STACK_SIZE</span>);
</code></pre></div>
<p>Don't forget to change your default task handler!</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code> <span style="color: #000000">os_eventq_dflt_set</span>(<span style="color: #000000">&amp;shell_evq</span>);
</code></pre></div>
<p>And then build it to make sure all goes well.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>[user@IsMyLaptop:~/src/air_quality]$ newt build air_q
Compiling senseair.c
Archiving senseair.a
Linking air_quality.elf
App successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf
</code></pre></div>
<p>All looks good.</p>
<h3 id="add-cli-commands-for-testing-drivers">Add CLI commands for testing drivers</h3>
<p>While developing the driver, you want to issue operations from console asking it to do stuff. We'll assume that you've already worked through the tutorial
on how to <a href="../blinky_console/">enable the CLI</a>, so all we'll need to do is add the propper values to the project's <code>syscfg.yml</code> file:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>[user@IsMyLaptop:~/src/air_quality]$ cat targets/air_q/syscfg.yml
syscfg.vals:
# Set as per blinky_primo
OPENOCD_DEBUG: 1
# Enable the shell task.
SHELL_TASK: 1
STATS_CLI: 1
CONSOLE_TICKS: 1
CONSOLE_PROMPT: 1
</code></pre></div>
<p>Then register your senseair command with the shell by adding the following to <code>libs/my_drivers/senseair/src/senseair.c</code></p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #633820">#include</span> <span style="color: #177500">&lt;syscfg/syscfg.h&gt;</span>
<span style="color: #633820">#include</span> <span style="color: #177500">&lt;shell/shell.h&gt;</span>
<span style="color: #633820">#include</span> <span style="color: #177500">&lt;console/console.h&gt;</span>
<span style="color: #633820">#include</span> <span style="color: #177500">&lt;assert.h&gt;</span>
<span style="color: #A90D91">static</span> <span style="color: #A90D91">int</span> <span style="color: #000000">senseair_shell_func</span>(<span style="color: #A90D91">int</span> <span style="color: #000000">argc</span>, <span style="color: #A90D91">char</span> <span style="color: #000000">**argv</span>);
<span style="color: #A90D91">static</span> <span style="color: #A90D91">struct</span> <span style="color: #3F6E75">shell_cmd</span> <span style="color: #000000">senseair_cmd</span> <span style="color: #000000">=</span> {
.<span style="color: #000000">sc_cmd</span> <span style="color: #000000">=</span> <span style="color: #C41A16">&quot;senseair&quot;</span>,
.<span style="color: #000000">sc_cmd_func</span> <span style="color: #000000">=</span> <span style="color: #000000">senseair_shell_func</span>,
};
<span style="color: #A90D91">void</span>
<span style="color: #000000">senseair_init</span>(<span style="color: #A90D91">void</span>)
{
<span style="color: #A90D91">int</span> <span style="color: #000000">rc</span>;
<span style="color: #000000">rc</span> <span style="color: #000000">=</span> <span style="color: #000000">shell_cmd_register</span>(<span style="color: #000000">&amp;senseair_cmd</span>);
<span style="color: #000000">assert</span>(<span style="color: #000000">rc</span> <span style="color: #000000">==</span> <span style="color: #1C01CE">0</span>);
}
<span style="color: #A90D91">static</span> <span style="color: #A90D91">int</span>
<span style="color: #000000">senseair_shell_func</span>(<span style="color: #A90D91">int</span> <span style="color: #000000">argc</span>, <span style="color: #A90D91">char</span> <span style="color: #000000">**argv</span>)
{
<span style="color: #000000">console_printf</span>(<span style="color: #C41A16">&quot;Yay! Somebody called!\n&quot;</span>);
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">0</span>;
}
</code></pre></div>
<p>Now you can you build this, download to target, and start minicom on your console port. If you haven't already, familiarize yourself with
the tutorial on how to connect a serial port to your board <a href="../../get_started/serial_access/">here</a>.</p>
<p>You'll need to wire up your Board to a Serial converter first. On the Arduino Primo Board pin 1 is TX and pin 0 is RX so wire 1 to RX on your serial board, and 0 to TX on your serial board.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code> [user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2
Welcome to minicom 2.7
OPTIONS:
Compiled on Oct 12 2015, 07:48:30.
Port /dev/tty.usbserial-AH02MIE2, 13:44:40
Press CTRL-X Z for help on special keys
?
419: &gt; ?
Commands:
641: stat echo ? prompt ticks tasks
643: mempools date senseair
644: &gt; senseair
Yay! Somebody called!
1125: &gt;
53611: &gt; tasks
Tasks:
54047: task pri tid runtime csw stksz stkuse lcheck ncheck flg
54057: idle 255 0 54048 66890 64 30 0 0 0
54068: ble_ll 0 1 9 64986 80 58 0 0 0
54079: bleprph 1 2 0 1 336 32 0 0 0
54090: shell 2 3 0 2077 336 262 0 0 0
54101: &gt;
</code></pre></div>
<p>That's great. Your shell task is running, and is responding appropriately!
You can connect the hardware to your board and start developing code for the driver itself.</p>
<h3 id="use-of-hal-for-drivers">Use of HAL for drivers</h3>
<p>The sensor has a serial port connection, and that's how you are going to connect to it. Your original BSP, hw/bsp/arduino_primo_nrf52, has two UARTs set up.
We're using one for our shell/console. It also has a second UART set up as a 'bit-bang' UART but since the SenseAir only needs to
communicate at 9600 baud, this bit-banged uart is plenty fast enough.</p>
<p>You'll have to make a small change to the <code>syscfg.yml</code> file in your project's target directory to change the pin definitions
for this second UART. Those changes are as follows:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code> UART_0_PIN_TX: 23
UART_0_PIN_RX: 24
</code></pre></div>
<p>With this in place, you can refer to serial port where your SenseAir sensor by a logical number. This makes the code more platform independent - you could connect this sensor to another board, like Olimex. You will also use the HAL UART abstraction to do the UART port setup and data transfer. That way you don't need to have any platform dependent pieces within your little driver.</p>
<p>You will now see what the driver code ends up looking like. Here's the header file, filled in from the stub you created earlier.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #177500">/*</span>
<span style="color: #177500"> * Licensed to the Apache Software Foundation (ASF) under one</span>
<span style="color: #177500"> * or more contributor license agreements. See the NOTICE file</span>
<span style="color: #177500"> * distributed with this work for additional information</span>
<span style="color: #177500"> * regarding copyright ownership. The ASF licenses this file</span>
<span style="color: #177500"> * to you under the Apache License, Version 2.0 (the</span>
<span style="color: #177500"> * &quot;License&quot;); you may not use this file except in compliance</span>
<span style="color: #177500"> * with the License. You may obtain a copy of the License at</span>
<span style="color: #177500"> * </span>
<span style="color: #177500"> * http://www.apache.org/licenses/LICENSE-2.0</span>
<span style="color: #177500"> *</span>
<span style="color: #177500"> * Unless required by applicable law or agreed to in writing,</span>
<span style="color: #177500"> * software distributed under the License is distributed on an</span>
<span style="color: #177500"> * &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY</span>
<span style="color: #177500"> * KIND, either express or implied. See the License for the</span>
<span style="color: #177500"> * specific language governing permissions and limitations</span>
<span style="color: #177500"> * under the License.</span>
<span style="color: #177500">*/</span>
<span style="color: #633820">#ifndef _SENSEAIR_H_</span>
<span style="color: #633820">#define _SENSEAIR_H_</span>
<span style="color: #A90D91">enum</span> <span style="color: #000000">senseair_read_type</span> {
<span style="color: #000000">SENSEAIR_CO2</span>,
};
<span style="color: #A90D91">int</span> <span style="color: #000000">senseair_init</span>(<span style="color: #A90D91">int</span> <span style="color: #000000">uartno</span>);
<span style="color: #A90D91">int</span> <span style="color: #000000">senseair_read</span>(<span style="color: #A90D91">enum</span> <span style="color: #000000">senseair_read_type</span>);
<span style="color: #633820">#endif </span><span style="color: #177500">/* _SENSEAIR_H_ */</span>
</code></pre></div>
<p>As you can see, logical UART number has been added to the init routine. A 'read' function has been added,
which is a blocking read. If you were making a commercial product, you would probably have a callback for reporting the results.</p>
<p>And here is the source for the driver.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #177500">/**</span>
<span style="color: #177500"> * Licensed to the Apache Software Foundation (ASF) under one</span>
<span style="color: #177500"> * or more contributor license agreements. See the NOTICE file</span>
<span style="color: #177500"> * distributed with this work for additional information</span>
<span style="color: #177500"> * regarding copyright ownership. The ASF licenses this file</span>
<span style="color: #177500"> * to you under the Apache License, Version 2.0 (the</span>
<span style="color: #177500"> * &quot;License&quot;); you may not use this file except in compliance</span>
<span style="color: #177500"> * with the License. You may obtain a copy of the License at</span>
<span style="color: #177500"> *</span>
<span style="color: #177500"> * http://www.apache.org/licenses/LICENSE-2.0</span>
<span style="color: #177500"> *</span>
<span style="color: #177500"> * Unless required by applicable law or agreed to in writing,</span>
<span style="color: #177500"> * software distributed under the License is distributed on an</span>
<span style="color: #177500"> * &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY</span>
<span style="color: #177500"> * KIND, either express or implied. See the License for the</span>
<span style="color: #177500"> * specific language governing permissions and limitations</span>
<span style="color: #177500"> * under the License.</span>
<span style="color: #177500"> */</span>
<span style="color: #633820">#include</span> <span style="color: #177500">&lt;string.h&gt;</span>
<span style="color: #633820">#include</span> <span style="color: #177500">&lt;shell/shell.h&gt;</span>
<span style="color: #633820">#include</span> <span style="color: #177500">&lt;console/console.h&gt;</span>
<span style="color: #633820">#include</span> <span style="color: #177500">&lt;os/os.h&gt;</span>
<span style="color: #633820">#include</span> <span style="color: #177500">&lt;hal/hal_uart.h&gt;</span>
<span style="color: #633820">#include</span> <span style="color: #177500">&quot;senseair/senseair.h&quot;</span>
<span style="color: #A90D91">static</span> <span style="color: #A90D91">const</span> <span style="color: #A90D91">uint8_t</span> <span style="color: #000000">cmd_read_co2</span>[] <span style="color: #000000">=</span> {
<span style="color: #1C01CE">0xFE</span>, <span style="color: #1C01CE">0X44</span>, <span style="color: #1C01CE">0X00</span>, <span style="color: #1C01CE">0X08</span>, <span style="color: #1C01CE">0X02</span>, <span style="color: #1C01CE">0X9F</span>, <span style="color: #1C01CE">0X25</span>
};
<span style="color: #A90D91">static</span> <span style="color: #A90D91">int</span> <span style="color: #000000">senseair_shell_func</span>(<span style="color: #A90D91">int</span> <span style="color: #000000">argc</span>, <span style="color: #A90D91">char</span> <span style="color: #000000">**argv</span>);
<span style="color: #A90D91">static</span> <span style="color: #A90D91">struct</span> <span style="color: #3F6E75">shell_cmd</span> <span style="color: #000000">senseair_cmd</span> <span style="color: #000000">=</span> {
.<span style="color: #000000">sc_cmd</span> <span style="color: #000000">=</span> <span style="color: #C41A16">&quot;senseair&quot;</span>,
.<span style="color: #000000">sc_cmd_func</span> <span style="color: #000000">=</span> <span style="color: #000000">senseair_shell_func</span>,
};
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">senseair</span> {
<span style="color: #A90D91">int</span> <span style="color: #000000">uart</span>;
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">os_sem</span> <span style="color: #000000">sema</span>;
<span style="color: #A90D91">const</span> <span style="color: #A90D91">uint8_t</span> <span style="color: #000000">*tx_data</span>;
<span style="color: #A90D91">int</span> <span style="color: #000000">tx_off</span>;
<span style="color: #A90D91">int</span> <span style="color: #000000">tx_len</span>;
<span style="color: #A90D91">uint8_t</span> <span style="color: #000000">rx_data</span>[<span style="color: #1C01CE">32</span>];
<span style="color: #A90D91">int</span> <span style="color: #000000">rx_off</span>;
<span style="color: #A90D91">int</span> <span style="color: #000000">value</span>;
} <span style="color: #000000">senseair</span>;
<span style="color: #A90D91">static</span> <span style="color: #A90D91">int</span>
<span style="color: #000000">senseair_tx_char</span>(<span style="color: #A90D91">void</span> <span style="color: #000000">*arg</span>)
{
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">senseair</span> <span style="color: #000000">*s</span> <span style="color: #000000">=</span> <span style="color: #000000">&amp;senseair</span>;
<span style="color: #A90D91">int</span> <span style="color: #000000">rc</span>;
<span style="color: #A90D91">if</span> (<span style="color: #000000">s-&gt;tx_off</span> <span style="color: #000000">&gt;=</span> <span style="color: #000000">s-&gt;tx_len</span>) {
<span style="color: #177500">/*</span>
<span style="color: #177500"> * Command tx finished.</span>
<span style="color: #177500"> */</span>
<span style="color: #000000">s-&gt;tx_data</span> <span style="color: #000000">=</span> <span style="color: #A90D91">NULL</span>;
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">-1</span>;
}
<span style="color: #000000">rc</span> <span style="color: #000000">=</span> <span style="color: #000000">s-&gt;tx_data</span>[<span style="color: #000000">s-&gt;tx_off</span>];
<span style="color: #000000">s-&gt;tx_off++</span>;
<span style="color: #A90D91">return</span> <span style="color: #000000">rc</span>;
}
<span style="color: #177500">/*</span>
<span style="color: #177500"> * CRC for modbus over serial port.</span>
<span style="color: #177500"> */</span>
<span style="color: #A90D91">static</span> <span style="color: #A90D91">const</span> <span style="color: #A90D91">uint16_t</span> <span style="color: #000000">mb_crc_tbl</span>[] <span style="color: #000000">=</span> {
<span style="color: #1C01CE">0x0000</span>, <span style="color: #1C01CE">0xcc01</span>, <span style="color: #1C01CE">0xd801</span>, <span style="color: #1C01CE">0x1400</span>, <span style="color: #1C01CE">0xf001</span>, <span style="color: #1C01CE">0x3c00</span>, <span style="color: #1C01CE">0x2800</span>, <span style="color: #1C01CE">0xe401</span>,
<span style="color: #1C01CE">0xa001</span>, <span style="color: #1C01CE">0x6c00</span>, <span style="color: #1C01CE">0x7800</span>, <span style="color: #1C01CE">0xb401</span>, <span style="color: #1C01CE">0x5000</span>, <span style="color: #1C01CE">0x9c01</span>, <span style="color: #1C01CE">0x8801</span>, <span style="color: #1C01CE">0x4400</span>
};
<span style="color: #A90D91">static</span> <span style="color: #A90D91">uint16_t</span>
<span style="color: #000000">mb_crc</span>(<span style="color: #A90D91">const</span> <span style="color: #A90D91">uint8_t</span> <span style="color: #000000">*data</span>, <span style="color: #A90D91">int</span> <span style="color: #000000">len</span>, <span style="color: #A90D91">uint16_t</span> <span style="color: #000000">crc</span>)
{
<span style="color: #A90D91">while</span> (<span style="color: #000000">len--</span> <span style="color: #000000">&gt;</span> <span style="color: #1C01CE">0</span>) {
<span style="color: #000000">crc</span> <span style="color: #000000">^=</span> <span style="color: #000000">*data++</span>;
<span style="color: #000000">crc</span> <span style="color: #000000">=</span> (<span style="color: #000000">crc</span> <span style="color: #000000">&gt;&gt;</span> <span style="color: #1C01CE">4</span>) <span style="color: #000000">^</span> <span style="color: #000000">mb_crc_tbl</span>[<span style="color: #000000">crc</span> <span style="color: #000000">&amp;</span> <span style="color: #1C01CE">0xf</span>];
<span style="color: #000000">crc</span> <span style="color: #000000">=</span> (<span style="color: #000000">crc</span> <span style="color: #000000">&gt;&gt;</span> <span style="color: #1C01CE">4</span>) <span style="color: #000000">^</span> <span style="color: #000000">mb_crc_tbl</span>[<span style="color: #000000">crc</span> <span style="color: #000000">&amp;</span> <span style="color: #1C01CE">0xf</span>];
}
<span style="color: #A90D91">return</span> <span style="color: #000000">crc</span>;
}
<span style="color: #A90D91">static</span> <span style="color: #A90D91">int</span>
<span style="color: #000000">mb_crc_check</span>(<span style="color: #A90D91">const</span> <span style="color: #A90D91">void</span> <span style="color: #000000">*pkt</span>, <span style="color: #A90D91">int</span> <span style="color: #000000">len</span>)
{
<span style="color: #A90D91">uint16_t</span> <span style="color: #000000">crc</span>, <span style="color: #000000">cmp</span>;
<span style="color: #A90D91">uint8_t</span> <span style="color: #000000">*bp</span> <span style="color: #000000">=</span> (<span style="color: #A90D91">uint8_t</span> <span style="color: #000000">*</span>)<span style="color: #000000">pkt</span>;
<span style="color: #A90D91">if</span> (<span style="color: #000000">len</span> <span style="color: #000000">&lt;</span> <span style="color: #A90D91">sizeof</span>(<span style="color: #000000">crc</span>) <span style="color: #000000">+</span> <span style="color: #1C01CE">1</span>) {
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">-1</span>;
}
<span style="color: #000000">crc</span> <span style="color: #000000">=</span> <span style="color: #000000">mb_crc</span>(<span style="color: #000000">pkt</span>, <span style="color: #000000">len</span> <span style="color: #000000">-</span> <span style="color: #1C01CE">2</span>, <span style="color: #1C01CE">0xffff</span>);
<span style="color: #000000">cmp</span> <span style="color: #000000">=</span> <span style="color: #000000">bp</span>[<span style="color: #000000">len</span> <span style="color: #000000">-</span> <span style="color: #1C01CE">2</span>] <span style="color: #000000">|</span> (<span style="color: #000000">bp</span>[<span style="color: #000000">len</span> <span style="color: #000000">-</span> <span style="color: #1C01CE">1</span>] <span style="color: #000000">&lt;&lt;</span> <span style="color: #1C01CE">8</span>);
<span style="color: #A90D91">if</span> (<span style="color: #000000">crc</span> <span style="color: #000000">!=</span> <span style="color: #000000">cmp</span>) {
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">-1</span>;
} <span style="color: #A90D91">else</span> {
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">0</span>;
}
}
<span style="color: #A90D91">static</span> <span style="color: #A90D91">int</span>
<span style="color: #000000">senseair_rx_char</span>(<span style="color: #A90D91">void</span> <span style="color: #000000">*arg</span>, <span style="color: #A90D91">uint8_t</span> <span style="color: #000000">data</span>)
{
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">senseair</span> <span style="color: #000000">*s</span> <span style="color: #000000">=</span> (<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">senseair</span> <span style="color: #000000">*</span>)<span style="color: #000000">arg</span>;
<span style="color: #A90D91">int</span> <span style="color: #000000">rc</span>;
<span style="color: #A90D91">if</span> (<span style="color: #000000">s-&gt;rx_off</span> <span style="color: #000000">&gt;=</span> <span style="color: #A90D91">sizeof</span>(<span style="color: #000000">s-&gt;rx_data</span>)) {
<span style="color: #000000">s-&gt;rx_off</span> <span style="color: #000000">=</span> <span style="color: #1C01CE">0</span>;
}
<span style="color: #000000">s-&gt;rx_data</span>[<span style="color: #000000">s-&gt;rx_off</span>] <span style="color: #000000">=</span> <span style="color: #000000">data</span>;
<span style="color: #000000">s-&gt;rx_off++</span>;
<span style="color: #A90D91">if</span> (<span style="color: #000000">s-&gt;rx_off</span> <span style="color: #000000">==</span> <span style="color: #1C01CE">7</span>) {
<span style="color: #000000">rc</span> <span style="color: #000000">=</span> <span style="color: #000000">mb_crc_check</span>(<span style="color: #000000">s-&gt;rx_data</span>, <span style="color: #000000">s-&gt;rx_off</span>);
<span style="color: #A90D91">if</span> (<span style="color: #000000">rc</span> <span style="color: #000000">==</span> <span style="color: #1C01CE">0</span>) {
<span style="color: #000000">s-&gt;value</span> <span style="color: #000000">=</span> <span style="color: #000000">s-&gt;rx_data</span>[<span style="color: #1C01CE">3</span>] <span style="color: #000000">*</span> <span style="color: #1C01CE">256</span> <span style="color: #000000">+</span> <span style="color: #000000">s-&gt;rx_data</span>[<span style="color: #1C01CE">4</span>];
<span style="color: #000000">os_sem_release</span>(<span style="color: #000000">&amp;s-&gt;sema</span>);
}
}
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">0</span>;
}
<span style="color: #A90D91">void</span>
<span style="color: #000000">senseair_tx</span>(<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">senseair</span> <span style="color: #000000">*s</span>, <span style="color: #A90D91">const</span> <span style="color: #A90D91">uint8_t</span> <span style="color: #000000">*tx_data</span>, <span style="color: #A90D91">int</span> <span style="color: #000000">data_len</span>)
{
<span style="color: #000000">s-&gt;tx_data</span> <span style="color: #000000">=</span> <span style="color: #000000">tx_data</span>;
<span style="color: #000000">s-&gt;tx_len</span> <span style="color: #000000">=</span> <span style="color: #000000">data_len</span>;
<span style="color: #000000">s-&gt;tx_off</span> <span style="color: #000000">=</span> <span style="color: #1C01CE">0</span>;
<span style="color: #000000">s-&gt;rx_off</span> <span style="color: #000000">=</span> <span style="color: #1C01CE">0</span>;
<span style="color: #000000">hal_uart_start_tx</span>(<span style="color: #000000">s-&gt;uart</span>);
}
<span style="color: #A90D91">int</span>
<span style="color: #000000">senseair_read</span>(<span style="color: #A90D91">enum</span> <span style="color: #000000">senseair_read_type</span> <span style="color: #000000">type</span>)
{
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">senseair</span> <span style="color: #000000">*s</span> <span style="color: #000000">=</span> <span style="color: #000000">&amp;senseair</span>;
<span style="color: #A90D91">const</span> <span style="color: #A90D91">uint8_t</span> <span style="color: #000000">*cmd</span>;
<span style="color: #A90D91">int</span> <span style="color: #000000">cmd_len</span>;
<span style="color: #A90D91">int</span> <span style="color: #000000">rc</span>;
<span style="color: #A90D91">if</span> (<span style="color: #000000">s-&gt;tx_data</span>) {
<span style="color: #177500">/*</span>
<span style="color: #177500"> * busy</span>
<span style="color: #177500"> */</span>
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">-1</span>;
}
<span style="color: #A90D91">switch</span> (<span style="color: #000000">type</span>) {
<span style="color: #A90D91">case</span> <span style="color: #000000">SENSEAIR_CO2</span>:
<span style="color: #000000">cmd</span> <span style="color: #000000">=</span> <span style="color: #000000">cmd_read_co2</span>;
<span style="color: #000000">cmd_len</span> <span style="color: #000000">=</span> <span style="color: #A90D91">sizeof</span>(<span style="color: #000000">cmd_read_co2</span>);
<span style="color: #A90D91">break</span>;
<span style="color: #A90D91">default</span><span style="color: #000000">:</span>
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">-1</span>;
}
<span style="color: #000000">senseair_tx</span>(<span style="color: #000000">s</span>, <span style="color: #000000">cmd</span>, <span style="color: #000000">cmd_len</span>);
<span style="color: #000000">rc</span> <span style="color: #000000">=</span> <span style="color: #000000">os_sem_pend</span>(<span style="color: #000000">&amp;s-&gt;sema</span>, <span style="color: #000000">OS_TICKS_PER_SEC</span> <span style="color: #000000">/</span> <span style="color: #1C01CE">2</span>);
<span style="color: #A90D91">if</span> (<span style="color: #000000">rc</span> <span style="color: #000000">==</span> <span style="color: #000000">OS_TIMEOUT</span>) {
<span style="color: #177500">/*</span>
<span style="color: #177500"> * timeout</span>
<span style="color: #177500"> */</span>
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">-2</span>;
}
<span style="color: #A90D91">return</span> <span style="color: #000000">s-&gt;value</span>;
}
<span style="color: #A90D91">static</span> <span style="color: #A90D91">int</span>
<span style="color: #000000">senseair_shell_func</span>(<span style="color: #A90D91">int</span> <span style="color: #000000">argc</span>, <span style="color: #A90D91">char</span> <span style="color: #000000">**argv</span>)
{
<span style="color: #A90D91">int</span> <span style="color: #000000">value</span>;
<span style="color: #A90D91">enum</span> <span style="color: #000000">senseair_read_type</span> <span style="color: #000000">type</span>;
<span style="color: #A90D91">if</span> (<span style="color: #000000">argc</span> <span style="color: #000000">&lt;</span> <span style="color: #1C01CE">2</span>) {
<span style="color: #000000">usage</span>:
<span style="color: #000000">console_printf</span>(<span style="color: #C41A16">&quot;%s co2\n&quot;</span>, <span style="color: #000000">argv</span>[<span style="color: #1C01CE">0</span>]);
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">0</span>;
}
<span style="color: #A90D91">if</span> (<span style="color: #000000">!strcmp</span>(<span style="color: #000000">argv</span>[<span style="color: #1C01CE">1</span>], <span style="color: #C41A16">&quot;co2&quot;</span>)) {
<span style="color: #000000">type</span> <span style="color: #000000">=</span> <span style="color: #000000">SENSEAIR_CO2</span>;
} <span style="color: #A90D91">else</span> {
<span style="color: #A90D91">goto</span> <span style="color: #000000">usage</span>;
}
<span style="color: #000000">value</span> <span style="color: #000000">=</span> <span style="color: #000000">senseair_read</span>(<span style="color: #000000">type</span>);
<span style="color: #A90D91">if</span> (<span style="color: #000000">value</span> <span style="color: #000000">&gt;=</span> <span style="color: #1C01CE">0</span>) {
<span style="color: #000000">console_printf</span>(<span style="color: #C41A16">&quot;Got %d\n&quot;</span>, <span style="color: #000000">value</span>);
} <span style="color: #A90D91">else</span> {
<span style="color: #000000">console_printf</span>(<span style="color: #C41A16">&quot;Error while reading: %d\n&quot;</span>, <span style="color: #000000">value</span>);
}
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">0</span>;
}
<span style="color: #A90D91">int</span>
<span style="color: #000000">senseair_init</span>(<span style="color: #A90D91">int</span> <span style="color: #000000">uartno</span>)
{
<span style="color: #A90D91">int</span> <span style="color: #000000">rc</span>;
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">senseair</span> <span style="color: #000000">*s</span> <span style="color: #000000">=</span> <span style="color: #000000">&amp;senseair</span>;
<span style="color: #000000">rc</span> <span style="color: #000000">=</span> <span style="color: #000000">shell_cmd_register</span>(<span style="color: #000000">&amp;senseair_cmd</span>);
<span style="color: #A90D91">if</span> (<span style="color: #000000">rc</span>) {
<span style="color: #A90D91">return</span> <span style="color: #000000">rc</span>;
}
<span style="color: #000000">rc</span> <span style="color: #000000">=</span> <span style="color: #000000">os_sem_init</span>(<span style="color: #000000">&amp;s-&gt;sema</span>, <span style="color: #1C01CE">1</span>);
<span style="color: #A90D91">if</span> (<span style="color: #000000">rc</span>) {
<span style="color: #A90D91">return</span> <span style="color: #000000">rc</span>;
}
<span style="color: #000000">rc</span> <span style="color: #000000">=</span> <span style="color: #000000">hal_uart_init_cbs</span>(<span style="color: #000000">uartno</span>, <span style="color: #000000">senseair_tx_char</span>, <span style="color: #A90D91">NULL</span>,
<span style="color: #000000">senseair_rx_char</span>, <span style="color: #000000">&amp;senseair</span>);
<span style="color: #A90D91">if</span> (<span style="color: #000000">rc</span>) {
<span style="color: #A90D91">return</span> <span style="color: #000000">rc</span>;
}
<span style="color: #000000">rc</span> <span style="color: #000000">=</span> <span style="color: #000000">hal_uart_config</span>(<span style="color: #000000">uartno</span>, <span style="color: #1C01CE">9600</span>, <span style="color: #1C01CE">8</span>, <span style="color: #1C01CE">1</span>, <span style="color: #000000">HAL_UART_PARITY_NONE</span>,
<span style="color: #000000">HAL_UART_FLOW_CTL_NONE</span>);
<span style="color: #A90D91">if</span> (<span style="color: #000000">rc</span>) {
<span style="color: #A90D91">return</span> <span style="color: #000000">rc</span>;
}
<span style="color: #000000">s-&gt;uart</span> <span style="color: #000000">=</span> <span style="color: #000000">uartno</span>;
<span style="color: #A90D91">return</span> <span style="color: #1C01CE">0</span>;
}
</code></pre></div>
<p>And your modified main() for senseair driver init.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">int</span>
<span style="color: #000000">main</span>(<span style="color: #A90D91">int</span> <span style="color: #000000">argc</span>, <span style="color: #A90D91">char</span> <span style="color: #000000">**argv</span>)
{
....
<span style="color: #000000">senseair_init</span>(<span style="color: #1C01CE">0</span>);
....
}
</code></pre></div>
<p>You can see from the code that you are using the HAL interface to open a UART port, and using OS
semaphore as a way of blocking the task when waiting for read response to come back from the sensor.</p>
<p>Now comes the fun part: Hooking up the sensor! It's fun because a) hooking up a sensor is always
fun and b) the SenseAir sensor's PCB is entirely unlabeled, so you'll have to trust us on how to hook it up. </p>
<p>So here we go. </p>
<p>You'll have to do a little soldering. I soldered some header pins to the SenseAir K30 board to
make connecting wires easier using standard jumper wires, but you can also just solder wires
straight to the board if you prefer.</p>
<p>Here's what your SenseAir board should look like once it's wired up:</p>
<p><img alt="SenseAir Wiring" src="../pics/Senseair1.png" /></p>
<p>Now that you have that wired up, let's get the Arduino Primo wired up. A couple of things to note:</p>
<ul>
<li>The Arduino Primo's 'console' UART is actually UART1. </li>
<li>The secondary (bit-banged) UART is UART0, so that's where we'll have to hook up the SenseAir.</li>
</ul>
<p>Here's what your Arduino Primo should now look like with everything wired in:</p>
<p><img alt="SenseAir and Arduino Primo Wiring" src="../pics/Senseair2.png" /></p>
<p>Everything is wired and you're ready to go! Build and load your new app:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>$ newt build air_q
Building target targets/air_q
Compiling apps/air_quality/src/main.c
Archiving apps_air_quality.a
Linking myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf
Target successfully built: targets/air_q
$ newt create-image air_q 1.0.0
App image succesfully generated: myproj/bin/targets/air_q/app/apps/air_quality/air_quality.img
$ newt load air_q
Loading app image into slot 1
</code></pre></div>
<p>Now, you should be able to connect to your serial port and read values:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2
Welcome to minicom 2.7
OPTIONS:
Compiled on Oct 12 2015, 07:48:30.
Port /dev/tty.usbserial-AH02MIE2, 13:44:40
Press CTRL-X Z for help on special keys
1185: &gt; ?
Commands:
1382: stat echo ? prompt ticks tasks
1390: mempools date senseair
1395: &gt; senseair
senseair co2
2143: &gt; senseair co2
Got 973
</code></pre></div>
<p>And you're getting valid readings! Congratulations!</p>
<p>Next we'll hook this all up via Bluetooth so that you can read those values remotely. </p>
<div class="row">
<ul class="nav nav-pills" style="margin-bottom: 10px">
<li>
</li>
<li class="pull-right">
</li>
</ul>
</div>
<footer class="row">
<div class="col-xs-12">
<p class="copyright">Apache Mynewt is available under Apache License, version 2.0.</p>
</div>
<div class="col-xs-12">
<div class="logos">
<a href="https://www.apache.org/">
<img src="/img/asf_logo_wide_small.png" alt="Apache" title="Apache">
</a>
<p>
Copyright © 2015-2021 The Apache Software Foundation.<br>
<small class="footnote">
Apache Mynewt, Mynewt, Apache, the Apache feather logo, and the Apache Mynewt
project logo are either registered trademarks or trademarks of the Apache
Software Foundation in the United States and other countries.
</small>
</p>
<a href="">
<img src="https://www.countit.com/images/add_to_slack.png" alt="Slack Icon" title="Join our Slack Community" />
</a>
</div>
</div>
<a href="https://www.apache.org/licenses/">
<button class="button-footer-asf">
License
</button>
</a>
<a href="https://www.apache.org/foundation/sponsorship.html">
<button class="button-footer-asf">
Sponsorship
</button>
</a>
<a href="https://www.apache.org/foundation/thanks.html">
<button class="button-footer-asf">
Thanks
</button>
</a>
<a href="https://www.apache.org/security/">
<button class="button-footer-asf">
Security
</button>
</a>
<a href="https://apache.org/events/current-event">
<button class="button-footer-asf">
ASF Events
</button>
</a>
</footer>
</div>
</div>
</div>
<script src="../../../js/jquery-1.10.2.min.js"></script>
<script src="../../../js/bootstrap-3.0.3.min.js"></script>
<script src="../../../js/highlight.pack.js"></script>
<script src="../../../js/base.js"></script>
<script src="../../../js/custom.js"></script>
<script src="search/main.js"></script>
</body>
</html>