You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ad...@apache.org on 2017/02/01 06:52:09 UTC
[1/2] incubator-mynewt-site git commit: removed baselibc reference in
air quality sensor tutorial
Repository: incubator-mynewt-site
Updated Branches:
refs/heads/asf-site 7dc2cb547 -> b381d55c4
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/b381d55c/latest/mkdocs/search_index.json
----------------------------------------------------------------------
diff --git a/latest/mkdocs/search_index.json b/latest/mkdocs/search_index.json
index c98271b..8b86886 100644
--- a/latest/mkdocs/search_index.json
+++ b/latest/mkdocs/search_index.json
@@ -1267,7 +1267,7 @@
},
{
"location": "/os/tutorials/air_quality_sensor/",
- "text": "Air quality sensor project\n\n\nSetting up source tree for stuff you need\n\n\nTo start with, you need to create a new project under which you will do this development. So you type in:\n\n\n $ mkdir $HOME/src\n $ cd $HOME/src\n $ newt new air_quality\n\n\n\n\n\nLet's say you are using Arduino Primo -- which is based on the Nordic Semi NRF52 chip -- as the platform. \nYou know you need the board support package for that hardware. You can look up its location, add it your \nproject, and fetch that along with the core OS components. Luckily, the Arduino Primo is supported in the \nMynewt Core, so there's nothing much to do here. \n\n\nYour project.yml file should look like this:\n\n\n [user@IsMyLaptop:~/src/air_quality]$ emacs project.yml \n\n [user@IsMyLaptop:~/src/air_quality]$ cat project.yml\n project.name: \nair_quality\n\n\n project.repositories:\n - apache-mynewt-core\n\n # Use github\ns distribution mechanism for core ASF libr
aries.\n # This provides mirroring automatically for us.\n #\n repository.apache-mynewt-core:\n type: github\n vers: 0-latest\n user: apache\n repo: incubator-mynewt-core\n\n [user@IsMyLaptop:~/src/air_quality]$ newt install\n apache-mynewt-core\n [user@IsMyLaptop:~/src/air_quality]$ ls repos/\n apache-mynewt-core\n\n\n\n\n\nGood. You want to make sure you have all the needed bits for supporting your board; \nso you decide to build the blinky project for the platform first.\n\n\nNow 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.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target copy my_blinky_sim blink_primo\nTarget successfully copied; targets/my_blinky_sim --\n targets/blink_primo\n[user@IsMyLaptop:~/src/air_quality]$ newt target set blink_primo bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/blink_nrf succe
ssfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt build blink_primo\nCompiling hal_bsp.c\n...\nLinking blinky.elf\nApp successfully built: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.elf\n\n\n\n\n\nGood.\n\n\nYou know that this platform uses bootloader, which means you have to create a target for that too.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target create boot_primo\nTarget targets/boot_nrf successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target show\n@apache-mynewt-core/targets/unittest\n bsp=hw/bsp/native\n build_profile=debug\n compiler=compiler/sim\ntargets/blink_primo\n app=apps/blinky\n bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n build_profile=debug\ntargets/boot_primo\ntargets/my_blinky_sim\n app=apps/blinky\n bsp=@apache-mynewt-core/hw/bsp/native\n build_profile=debug\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf
bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/boot_nrf successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf app=@apache-mynewt-core/apps/boot\nTarget targets/boot_nrf successfully set target.app to @apache-mynewt-core/apps/boot\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf build_profile=optimized\nTarget targets/boot_nrf successfully set target.build_profile to optimized\n\n\n\n\n\nAnd then build it, and load it onto the board.\n\n\nnewt build boot_primo\n....\nLinking boot.elf\nApp successfully built: /Users/user/src/air_quality/bin/boot_primo/apps/boot/boot.elf\n[user@IsMyLaptop:~/src/air_quality]\n$ newt load boot_primo\n\n\n\n\n\nAt this point, you may (or may not) see a bunch of error messages about not being able to connect to\nyour board, not being able to load the image, etc. If that's the case, and you haven't already, you\nshould most definitely go
worth through the \nblinky_primo\n tutorial so that you\ncan properly communicate with your board.\n\n\nNext you must download the targets to board, and see that the LED actually blinks. You plug in the \nArduino Primo board to your laptop, and say:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo\nLoading app image into slot 1\nError: couldn\nt open /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img\n\nError: exit status 1\n\nload - Load app image to target for \ntarget-name\n.\n\nUsage:\n newt load [flags]\n\nExamples:\n newt load \ntarget-name\n\n\n\nGlobal Flags:\n -l, --loglevel string Log level, defaults to WARN. (default \nWARN\n)\n -o, --outfile string Filename to tee log output to\n -q, --quiet Be quiet; only display error output.\n -s, --silent Be silent; don\nt output anything.\n -v, --verbose Enable verbose output when executing commands.\nexit status 1\n\n\n\n\n\nAh. Forgot to create an image ou
t of the blinky binary. Note that every time you want to build and \nload a new firmware image to a target board, you need to run 'create-image' on it.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt create-image blink_primo 0.0.1\nApp image successfully generated: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img\nBuild manifest: /Users/user/src/air_quality/bin/blink_nrf/apps/blinky/manifest.json\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo\n\n\n\n\n\nAnd it's blinking.\n\n\nShortcut for doing build/create-image/load/debug steps all in one is 'newt run' command. Check \nout the usage from command line help.\n\n\nCreate test project\n\n\nNow that you have your system setup, you can start creating your own stuff.\nFirst you want to create a project for yourself - you could start by using blinky as a project \ntemplate, but since we're going to want to be able to access the data via Bluetooth, let's \nuse the \nbleprph\n Bluetooth Peripheral project inst
ead.\n\n\n [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality\n [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/bleprph/pkg.yml apps/air_quality/\n [user@IsMyLaptop:~/src/air_quality]$ cp -Rp repos/apache-mynewt-core/apps/bleprph/src apps/air_quality/\n\n\n\n\n\nThen you modify the apps/air_quality/pkg.yml for air_quality in order to change the \npkg.name\n to be \napps/air_quality\n.\nYou'll need to add the \n@apache-mynewt-core/\n path to all the package dependencies, since the app no longer\nresides within the apache-mynewt-core repository.\n\n\nThe Arduino Primo board has a limited amount of memory, so you must also switch your libc to be baselibc, instead of the standard one.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml\npkg.name: apps/air_quality\npkg.type: app\npkg.description: BLE Air Quality application.\npkg.author: \nApache Mynewt \ndev@mynewt.incubator.apache.org\n\npkg.homepage: \nhttp://mynewt.apache.org
/\n\npkg.keywords:\n\npkg.deps: \n - \n@apache-mynewt-core/kernel/os\n\n - \n@apache-mynewt-core/sys/shell\n\n - \n@apache-mynewt-core/sys/stats/full\n\n - \n@apache-mynewt-core/sys/log/full\n\n - \n@apache-mynewt-core/mgmt/newtmgr\n\n - \n@apache-mynewt-core/mgmt/newtmgr/transport/ble\n\n - \n@apache-mynewt-core/net/nimble/controller\n\n - \n@apache-mynewt-core/net/nimble/host\n\n - \n@apache-mynewt-core/net/nimble/host/services/ans\n\n - \n@apache-mynewt-core/net/nimble/host/services/gap\n\n - \n@apache-mynewt-core/net/nimble/host/services/gatt\n\n - \n@apache-mynewt-core/net/nimble/host/store/ram\n\n - \n@apache-mynewt-core/net/nimble/transport/ram\n\n - \n@apache-mynewt-core/sys/console/full\n\n - \n@apache-mynewt-core/sys/sysinit\n\n - \n@apache-mynewt-core/sys/id\n\n\n\n\n\n\nAnd create a target for it:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target create air_q\nTarget targets/air_q successfully created\n[user@IsMyLaptop:
~/src/air_quality]$ newt target set air_q bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/air_q successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q app=apps/air_quality \nTarget targets/air_q successfully set target.app to apps/air_quality\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q build_profile=debug\nTarget targets/air_q successfully set target.build_profile to debug\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\n ....\nLinking /Users/dsimmons/dev/myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf\nTarget successfully built: targets/air_q\n\n\n\n\n\nCreate packages for drivers\n\n\nOne of the sensors you want to enable is SenseAir K30, which will connect to the board over a serial port.\nTo start development of the driver, you first need to create a package description for it, and add stubs for sources.\n\n\nThe first thing to do is to creat
e the directory structure for your driver:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/include/senseair\n[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/src\n\n\n\n\n\nNow 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.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/pkg.yml\n\n\n\n\n\n#\n\n\n# Licensed to the Apache Software Foundation (ASF) under one\n\n\n# or more contributor license agreements. See the NOTICE file\n\n\n# distributed with this work for additional information\n\n\n# regarding copyright ownership. The ASF licenses this file\n\n\n# to you under the Apache License, Version 2.0 (the\n\n\n# \nLicense\n); you may not use this file except in compliance\n\n\n# with the License. You may obtain a copy of the License at\n\n\n# \n\n\n# http:\n//www.apache.org/licenses/LICENSE-2.0\n\n\n#\n\n\n# Unless required by applicab
le law or agreed to in writing,\n\n\n# software distributed under the License is distributed on an\n\n\n# \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n# KIND, either express or implied. See the License for the\n\n\n# specific language governing permissions and limitations\n\n\n# under the License.\n\n\n#\n\n\npkg\n.\nname\n: \nlibs/my_drivers/senseair\n\n\npkg\n.\ndescription\n: \nHost\n \nside\n \nof\n \nthe\n \nnimble\n \nBluetooth\n \nSmart\n \nstack\n.\n\npkg\n.\nauthor\n: \nApache Mynewt \ndev@mynewt.incubator.apache.org\n\n\npkg\n.\nhomepage\n: \nhttp://mynewt.apache.org/\n\n\npkg\n.\nkeywords\n:\n \n-\n \nble\n\n \n-\n \nbluetooth\n\n\n\npkg\n.\ndeps\n:\n \n-\n \n@apache-mynewt-core/kernel/os\n\n\n\n\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/include/senseair/senseair.h\n\n\n\n\n\n/*\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\
n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n * \n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n*/\n\n\n#ifndef _SENSEAIR_H_\n\n\n#define _SENSEAIR_H_\n\n\n\nvoid\n \nsenseair_init\n(\nvoid\n);\n\n\n#endif \n/* _SENSEAIR_H_ */\n\n\n\n\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c\n\n\n\n\n\n/**\n\n\n *
Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n * \n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n */\n\n\n\nvoid\n\n\nsenseair_init\n(\nvoid\n)\n{\n}\n\n\n\n\n\nAnd add dependency to this package in your project
yml file.\n\n\nHere's the listing from apps/air_quality/pkg.yml\n\n\npkg.name: apps/air_quality\npkg.type: app\npkg.description: Air quality sensor test\npkg.keywords:\n\npkg.deps:\n - \n@apache-mynewt-core/libs/console/full\n\n - \n@apache-mynewt-core/libs/newtmgr\n\n - \n@apache-mynewt-core/libs/os\n\n - \n@apache-mynewt-core/libs/shell\n\n - \n@apache-mynewt-core/sys/config\n\n - \n@apache-mynewt-core/sys/log/full\n\n - \n@apache-mynewt-core/sys/stats/full\n\n - \n@apache-mynewt-core/libs/baselibc\n\n - libs/my_drivers/senseair\n\n\n\n\n\nAnd add a call to your main() to initialize this driver.\n\n\n [user@IsMyLaptop:~/src/air_quality]$ diff project/blinky/src/main.c project/air_quality/src/main.c\n 28a29\n \n #include \nsenseair/senseair.h\n\n 190a192\n \n senseair_init();\n [user@IsMyLaptop:~/src/air_quality\n\n\n\n\n\nThe ble_prph app runs everything in one task handler. For this project, we're going to add a second\ntask handler t
o respond to the shell, and then handle communicating with the senseair sensor for us.\n\n\n/** shell task settings. */\n\n\n#define SHELL_TASK_PRIO 2\n\n\n#define SHELL_STACK_SIZE (OS_STACK_ALIGN(336))\n\n\n\nstruct\n \nos_eventq\n \nshell_evq\n;\n\nstruct\n \nos_task\n \nshell_task\n;\n\nbssnz_t\n \nos_stack_t\n \nshell_stack\n[\nSHELL_STACK_SIZE\n];\n\n\n\n\n\nThat defines the task, now we need to initialize it, add a task handler, and we're going to \nuse this task as our default task handler.\n\n\n/**\n\n\n * Event loop for the main shell task.\n\n\n */\n\n\nstatic\n \nvoid\n\n\nshell_task_handler\n(\nvoid\n \n*unused\n)\n{\n \nwhile\n (\n1\n) {\n \nos_eventq_run\n(\nshell_evq\n);\n }\n}\n\n\n\n\n\nAnd in your \nmain()\n add:\n\n\n \n/* Initialize shell eventq */\n\n \nos_eventq_init\n(\nshell_evq\n);\n\n \n/* Create the shell task. \n\n\n * All shell operations are performed in this task.\n\n\n */\n\n \nos_task_init\n(\nshel
l_task\n, \nshell\n, \nshell_task_handler\n,\n \nNULL\n, \nSHELL_TASK_PRIO\n, \nOS_WAIT_FOREVER\n,\n \nshell_stack\n, \nSHELL_STACK_SIZE\n);\n\n\n\n\n\nDon't forget to change your default task handler!\n\n\n \nos_eventq_dflt_set\n(\nshell_evq\n);\n\n\n\n\n\nAnd then build it to make sure all goes well.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\nCompiling senseair.c\nArchiving senseair.a\nLinking air_quality.elf\nApp successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf\n\n\n\n\n\nAll looks good.\n\n\nAdd CLI commands for testing drivers\n\n\nWhile 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 \non how to \nenable the CLI\n, so all we'll need to do is add the propper values to the project's \nsyscfg.yml\n file:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat targets/air_q
/syscfg.yml\nsyscfg.vals:\n # Set as per blinky_primo\n OPENOCD_DEBUG: 1\n # Enable the shell task.\n SHELL_TASK: 1\n STATS_CLI: 1\n CONSOLE_TICKS: 1\n CONSOLE_PROMPT: 1\n\n\n\n\n\nThen register your senseair command with the shell by adding the following to \nlibs/my_drivers/senseair/src/senseair.c\n\n\n#include \nshell/shell.h\n\n\n#include \nconsole/console.h\n\n\n#include \nassert.h\n\n\n\n\nstatic\n \nint\n \nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n);\n\nstatic\n \nstruct\n \nshell_cmd\n \nsenseair_cmd\n \n=\n {\n .\nsc_cmd\n \n=\n \nsenseair\n,\n .\nsc_cmd_func\n \n=\n \nsenseair_shell_func\n,\n};\n\n\nvoid\n\n\nsenseair_init\n(\nvoid\n)\n{\n \nint\n \nrc\n;\n\n \nrc\n \n=\n \nshell_cmd_register\n(\nsenseair_cmd\n);\n \nassert\n(\nrc\n \n==\n \n0\n);\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n \nconsole_printf\n(\nYay! Somebody called!\\n\n);\n \nreturn\n \n0\n;\n\n}\
n\n\n\n\n\nNow you can you build this, download to target, and start minicom on your console port. If you haven't already, familiarize yourself with\nthe tutorial on how to connect a serial port to your board \nhere\n.\n\n\nYou'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.\n\n\n [user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2\n\n\n Welcome to minicom 2.7\n\n OPTIONS: \n Compiled on Oct 12 2015, 07:48:30.\n Port /dev/tty.usbserial-AH02MIE2, 13:44:40\n\n Press CTRL-X Z for help on special keys\n\n ?\n 419: \n ?\n Commands:\n 641: stat echo ? prompt ticks tasks\n 643: mempools date senseair\n 644: \n senseair\n Yay! Somebody called!\n 1125: \n\n 53611: \n tasks\n Tasks:\n 54047: task pri tid runtime csw stksz stkuse lcheck ncheck flg\n
54057: idle 255 0 54048 66890 64 30 0 0 0\n 54068: ble_ll 0 1 9 64986 80 58 0 0 0\n 54079: bleprph 1 2 0 1 336 32 0 0 0\n 54090: shell 2 3 0 2077 336 262 0 0 0\n 54101: \n\n\n\n\n\n\nThat's great. Your shell task is running, and is responding appropriately!\nYou can connect the hardware to your board and start developing code for the driver itself.\n\n\nUse of HAL for drivers\n\n\nThe 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.\nWe'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\ncommunicate at 9600 baud, this bit-banged uart is plenty fast enough.\n\n\nYou'll have to make a small change to the \nsyscfg.yml\n file i
n your project's target directory to change the pin definitions \nfor this second UART. Those changes are as follows:\n\n\n UART_0_PIN_TX: 23\n UART_0_PIN_RX: 24\n\n\n\n\n\nWith 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.\n\n\nYou will now see what the driver code ends up looking like. Here's the header file, filled in from the stub you created earlier.\n\n\n/*\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Ap
ache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n * \n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n*/\n\n\n#ifndef _SENSEAIR_H_\n\n\n#define _SENSEAIR_H_\n\n\n\nenum\n \nsenseair_read_type\n {\n \nSENSEAIR_CO2\n,\n};\n\n\nint\n \nsenseair_init\n(\nint\n \nuartno\n);\n\n\nint\n \nsenseair_read\n(\nenum\n \nsenseair_read_type\n);\n\n\n#endif \n/* _SENSEAIR_H_ */\n\n\n\n\n\n\nAs you can see, logical UART number has been added to the init routine. A 'read' function has been added, \nwhich i
s a blocking read. If you were making a commercial product, you would probably have a callback for reporting the results.\n\n\nAnd here is the source for the driver.\n\n\n/**\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n *\n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language gov
erning permissions and limitations\n\n\n * under the License.\n\n\n */\n\n\n#include \nstring.h\n\n\n\n#include \nshell/shell.h\n\n\n#include \nconsole/console.h\n\n\n#include \nos/os.h\n\n\n\n#include \nhal/hal_uart.h\n\n\n\n#include \nsenseair/senseair.h\n\n\n\nstatic\n \nconst\n \nuint8_t\n \ncmd_read_co2\n[] \n=\n {\n \n0xFE\n, \n0\nX44\n, \n0\nX00\n, \n0\nX08\n, \n0\nX02\n, \n0\nX9F\n, \n0\nX25\n\n};\n\n\nstatic\n \nint\n \nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n);\n\nstatic\n \nstruct\n \nshell_cmd\n \nsenseair_cmd\n \n=\n {\n .\nsc_cmd\n \n=\n \nsenseair\n,\n .\nsc_cmd_func\n \n=\n \nsenseair_shell_func\n,\n};\n\n\nstruct\n \nsenseair\n { \n \nint\n \nuart\n;\n \nstruct\n \nos_sem\n \nsema\n;\n \nconst\n \nuint8_t\n \n*tx_data\n;\n \nint\n \ntx_off\n;\n \nint\n \ntx_len\n;\n \nuint8_t\n \nrx_data\n[\n32\n]; \n \nint\n \nrx_off\n;\n \nint\n \nvalue\n;\n} \nsenseair\n;\n\n\nstatic\n \nint\n\n\nsenseair_tx_char\n(\nvoid\n \n*a
rg\n)\n{\n \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n \nint\n \nrc\n;\n\n \nif\n (\ns-\ntx_off\n \n=\n \ns-\ntx_len\n) {\n \n/*\n\n\n * Command tx finished.\n\n\n */\n\n \ns-\ntx_data\n \n=\n \nNULL\n;\n \nreturn\n \n-\n1\n;\n }\n\n \nrc\n \n=\n \ns-\ntx_data\n[\ns-\ntx_off\n];\n \ns-\ntx_off++\n;\n \nreturn\n \nrc\n;\n}\n\n\n/*\n\n\n * CRC for modbus over serial port.\n\n\n */\n\n\nstatic\n \nconst\n \nuint16_t\n \nmb_crc_tbl\n[] \n=\n {\n \n0x0000\n, \n0xcc01\n, \n0xd801\n, \n0x1400\n, \n0xf001\n, \n0x3c00\n, \n0x2800\n, \n0xe401\n,\n \n0xa001\n, \n0x6c00\n, \n0x7800\n, \n0xb401\n, \n0x5000\n, \n0x9c01\n, \n0x8801\n, \n0x4400\n\n};\n\n\nstatic\n \nuint16_t\n\n\nmb_crc\n(\nconst\n \nuint8_t\n \n*data\n, \nint\n \nlen\n, \nuint16_t\n \ncrc\n)\n{\n \nwhile\n (\nlen--\n \n \n0\n) {\n \ncrc\n \n^=\n \n*data++\n;\n \ncrc\n \n=\n (\ncrc\n \n \n4\n) \n^\n \nmb_crc_tbl\n[\ncrc\n \n \n0xf\n];\n \nc
rc\n \n=\n (\ncrc\n \n \n4\n) \n^\n \nmb_crc_tbl\n[\ncrc\n \n \n0xf\n];\n }\n \nreturn\n \ncrc\n;\n}\n\n\nstatic\n \nint\n\n\nmb_crc_check\n(\nconst\n \nvoid\n \n*pkt\n, \nint\n \nlen\n)\n{\n \nuint16_t\n \ncrc\n, \ncmp\n;\n \nuint8_t\n \n*bp\n \n=\n (\nuint8_t\n \n*\n)\npkt\n;\n\n \nif\n (\nlen\n \n \nsizeof\n(\ncrc\n) \n+\n \n1\n) {\n \nreturn\n \n-\n1\n;\n }\n \ncrc\n \n=\n \nmb_crc\n(\npkt\n, \nlen\n \n-\n \n2\n, \n0xffff\n);\n \ncmp\n \n=\n \nbp\n[\nlen\n \n-\n \n2\n] \n|\n (\nbp\n[\nlen\n \n-\n \n1\n] \n \n8\n);\n \nif\n (\ncrc\n \n!=\n \ncmp\n) {\n \nreturn\n \n-\n1\n;\n } \nelse\n {\n \nreturn\n \n0\n;\n }\n}\n\n\nstatic\n \nint\n\n\nsenseair_rx_char\n(\nvoid\n \n*arg\n, \nuint8_t\n \ndata\n)\n{\n \nstruct\n \nsenseair\n \n*s\n \n=\n (\nstruct\n \nsenseair\n \n*\n)\narg\n;\n \nint\n \nrc\n;\n\n \nif\n (\ns-\nrx_off\n \n=\n \nsizeof\n(\ns-\nrx_data\n)) {\n \ns-\nrx_off\n \n=\n \n0\n;\n }\n \ns-\nrx_da
ta\n[\ns-\nrx_off\n] \n=\n \ndata\n;\n \ns-\nrx_off++\n;\n\n \nif\n (\ns-\nrx_off\n \n==\n \n7\n) {\n \nrc\n \n=\n \nmb_crc_check\n(\ns-\nrx_data\n, \ns-\nrx_off\n);\n \nif\n (\nrc\n \n==\n \n0\n) {\n \ns-\nvalue\n \n=\n \ns-\nrx_data\n[\n3\n] \n*\n \n256\n \n+\n \ns-\nrx_data\n[\n4\n];\n \nos_sem_release\n(\ns-\nsema\n);\n }\n }\n \nreturn\n \n0\n;\n}\n\n\nvoid\n\n\nsenseair_tx\n(\nstruct\n \nsenseair\n \n*s\n, \nconst\n \nuint8_t\n \n*tx_data\n, \nint\n \ndata_len\n)\n{\n \ns-\ntx_data\n \n=\n \ntx_data\n;\n \ns-\ntx_len\n \n=\n \ndata_len\n;\n \ns-\ntx_off\n \n=\n \n0\n;\n \ns-\nrx_off\n \n=\n \n0\n;\n\n \nhal_uart_start_tx\n(\ns-\nuart\n);\n}\n\n\nint\n\n\nsenseair_read\n(\nenum\n \nsenseair_read_type\n \ntype\n)\n{\n \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n \nconst\n \nuint8_t\n \n*cmd\n;\n \nint\n \ncmd_len\n;\n \nint\n \nrc\n;\n\n \nif\n (\ns-\ntx_data\n) {\n \n/*\n\n\n
* busy\n\n\n */\n\n \nreturn\n \n-\n1\n;\n }\n \nswitch\n (\ntype\n) {\n \ncase\n \nSENSEAIR_CO2\n:\n \ncmd\n \n=\n \ncmd_read_co2\n;\n \ncmd_len\n \n=\n \nsizeof\n(\ncmd_read_co2\n);\n \nbreak\n;\n \ndefault\n:\n\n \nreturn\n \n-\n1\n;\n }\n \nsenseair_tx\n(\ns\n, \ncmd\n, \ncmd_len\n);\n \nrc\n \n=\n \nos_sem_pend\n(\ns-\nsema\n, \nOS_TICKS_PER_SEC\n \n/\n \n2\n);\n \nif\n (\nrc\n \n==\n \nOS_TIMEOUT\n) {\n \n/*\n\n\n * timeout\n\n\n */\n\n \nreturn\n \n-\n2\n;\n }\n \nreturn\n \ns-\nvalue\n;\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n \nint\n \nvalue\n;\n \nenum\n \nsenseair_read_type\n \ntype\n;\n\n \nif\n (\nargc\n \n \n2\n) {\n\nusage\n:\n \nconsole_printf\n(\n%s co2\\n\n, \nargv\n[\n0\n]);\n \nreturn\n \n0\n;\n }\n \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \nco2\n)) {\n \ntype\n \n=\n \nSEN
SEAIR_CO2\n;\n } \nelse\n {\n \ngoto\n \nusage\n;\n }\n \nvalue\n \n=\n \nsenseair_read\n(\ntype\n);\n \nif\n (\nvalue\n \n=\n \n0\n) {\n \nconsole_printf\n(\nGot %d\\n\n, \nvalue\n);\n } \nelse\n {\n \nconsole_printf\n(\nError while reading: %d\\n\n, \nvalue\n);\n }\n \nreturn\n \n0\n;\n}\n\n\nint\n\n\nsenseair_init\n(\nint\n \nuartno\n)\n{\n \nint\n \nrc\n;\n \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n\n \nrc\n \n=\n \nshell_cmd_register\n(\nsenseair_cmd\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n\n \nrc\n \n=\n \nos_sem_init\n(\ns-\nsema\n, \n1\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n \nrc\n \n=\n \nhal_uart_init_cbs\n(\nuartno\n, \nsenseair_tx_char\n, \nNULL\n,\n \nsenseair_rx_char\n, \nsenseair\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n \nrc\n \n=\n \nhal_uart_config\n(\nuartno\n, \n9600\n, \n8\n, \n1\n, \nHAL_UART_PARITY_NONE\n,\n \nHAL
_UART_FLOW_CTL_NONE\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n \ns-\nuart\n \n=\n \nuartno\n;\n\n \nreturn\n \n0\n;\n}\n\n\n\n\n\nAnd your modified main() for senseair driver init.\n\n\nint\n\n\nmain\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n ....\n \nsenseair_init\n(\n0\n);\n ....\n }\n\n\n\n\n\nYou can see from the code that you are using the HAL interface to open a UART port, and using OS \nsemaphore as a way of blocking the task when waiting for read response to come back from the sensor.\n\n\nNow comes the fun part: Hooking up the sensor! It's fun because a) hooking up a sensor is always \nfun and b) the SenseAir sensor's PCB is entirely unlabeled, so you'll have to trust us on how to hook it up. \n\n\nSo here we go. \n\n\nYou'll have to do a little soldering. I soldered some header pins to the SenseAir K30 board to\nmake connecting wires easier using standard jumper wires, but you can also just solder wires\nstraight to the board if yo
u prefer.\n\n\nHere's what your SenseAir board should look like once it's wired up:\n\n\n\n\nNow that you have that wired up, let's get the Arduino Primo wired up. A couple of things to note:\n\n\n\n\nThe Arduino Primo's 'console' UART is actually UART1. \n\n\nThe secondary (bit-banged) UART is UART0, so that's where we'll have to hook up the SenseAir.\n\n\n\n\nHere's what your Arduino Primo should now look like with everything wired in:\n\n\n\n\nEverything is wired and you're ready to go! Build and load your new app:\n\n\n$ newt build air_q\nBuilding target targets/air_q\nCompiling apps/air_quality/src/main.c\nArchiving apps_air_quality.a\nLinking myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf\nTarget successfully built: targets/air_q\n$ newt create-image air_q 1.0.0\nApp image succesfully generated: myproj/bin/targets/air_q/app/apps/air_quality/air_quality.img\n$ newt load air_q\nLoading app image into slot 1\n\n\n\n\n\nNow, you should be able to connect to your ser
ial port and read values:\n\n\nuser@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2\n\n\n Welcome to minicom 2.7\n\n OPTIONS: \n Compiled on Oct 12 2015, 07:48:30.\n Port /dev/tty.usbserial-AH02MIE2, 13:44:40\n\n Press CTRL-X Z for help on special keys\n\n 1185: \n ?\n Commands:\n 1382: stat echo ? prompt ticks tasks\n 1390: mempools date senseair\n 1395: \n senseair\n senseair co2\n 2143: \n senseair co2\n Got 973\n\n\n\n\n\nAnd you're getting valid readings! Congratulations!\n\n\nNext we'll hook this all up via Bluetooth so that you can read those values remotely.",
+ "text": "Air quality sensor project\n\n\nSetting up source tree for stuff you need\n\n\nTo start with, you need to create a new project under which you will do this development. So you type in:\n\n\n $ mkdir $HOME/src\n $ cd $HOME/src\n $ newt new air_quality\n\n\n\n\n\nLet's say you are using Arduino Primo -- which is based on the Nordic Semi NRF52 chip -- as the platform. \nYou know you need the board support package for that hardware. You can look up its location, add it your \nproject, and fetch that along with the core OS components. Luckily, the Arduino Primo is supported in the \nMynewt Core, so there's nothing much to do here. \n\n\nYour project.yml file should look like this:\n\n\n [user@IsMyLaptop:~/src/air_quality]$ emacs project.yml \n\n [user@IsMyLaptop:~/src/air_quality]$ cat project.yml\n project.name: \nair_quality\n\n\n project.repositories:\n - apache-mynewt-core\n\n # Use github\ns distribution mechanism for core ASF libr
aries.\n # This provides mirroring automatically for us.\n #\n repository.apache-mynewt-core:\n type: github\n vers: 0-latest\n user: apache\n repo: incubator-mynewt-core\n\n [user@IsMyLaptop:~/src/air_quality]$ newt install\n apache-mynewt-core\n [user@IsMyLaptop:~/src/air_quality]$ ls repos/\n apache-mynewt-core\n\n\n\n\n\nGood. You want to make sure you have all the needed bits for supporting your board; \nso you decide to build the blinky project for the platform first.\n\n\nNow 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.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target copy my_blinky_sim blink_primo\nTarget successfully copied; targets/my_blinky_sim --\n targets/blink_primo\n[user@IsMyLaptop:~/src/air_quality]$ newt target set blink_primo bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/blink_nrf succe
ssfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt build blink_primo\nCompiling hal_bsp.c\n...\nLinking blinky.elf\nApp successfully built: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.elf\n\n\n\n\n\nGood.\n\n\nYou know that this platform uses bootloader, which means you have to create a target for that too.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target create boot_primo\nTarget targets/boot_nrf successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target show\n@apache-mynewt-core/targets/unittest\n bsp=hw/bsp/native\n build_profile=debug\n compiler=compiler/sim\ntargets/blink_primo\n app=apps/blinky\n bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n build_profile=debug\ntargets/boot_primo\ntargets/my_blinky_sim\n app=apps/blinky\n bsp=@apache-mynewt-core/hw/bsp/native\n build_profile=debug\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf
bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/boot_nrf successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf app=@apache-mynewt-core/apps/boot\nTarget targets/boot_nrf successfully set target.app to @apache-mynewt-core/apps/boot\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf build_profile=optimized\nTarget targets/boot_nrf successfully set target.build_profile to optimized\n\n\n\n\n\nAnd then build it, and load it onto the board.\n\n\nnewt build boot_primo\n....\nLinking boot.elf\nApp successfully built: /Users/user/src/air_quality/bin/boot_primo/apps/boot/boot.elf\n[user@IsMyLaptop:~/src/air_quality]\n$ newt load boot_primo\n\n\n\n\n\nAt this point, you may (or may not) see a bunch of error messages about not being able to connect to\nyour board, not being able to load the image, etc. If that's the case, and you haven't already, you\nshould most definitely go
worth through the \nblinky_primo\n tutorial so that you\ncan properly communicate with your board.\n\n\nNext you must download the targets to board, and see that the LED actually blinks. You plug in the \nArduino Primo board to your laptop, and say:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo\nLoading app image into slot 1\nError: couldn\nt open /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img\n\nError: exit status 1\n\nload - Load app image to target for \ntarget-name\n.\n\nUsage:\n newt load [flags]\n\nExamples:\n newt load \ntarget-name\n\n\n\nGlobal Flags:\n -l, --loglevel string Log level, defaults to WARN. (default \nWARN\n)\n -o, --outfile string Filename to tee log output to\n -q, --quiet Be quiet; only display error output.\n -s, --silent Be silent; don\nt output anything.\n -v, --verbose Enable verbose output when executing commands.\nexit status 1\n\n\n\n\n\nAh. Forgot to create an image ou
t of the blinky binary. Note that every time you want to build and \nload a new firmware image to a target board, you need to run 'create-image' on it.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt create-image blink_primo 0.0.1\nApp image successfully generated: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img\nBuild manifest: /Users/user/src/air_quality/bin/blink_nrf/apps/blinky/manifest.json\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo\n\n\n\n\n\nAnd it's blinking.\n\n\nShortcut for doing build/create-image/load/debug steps all in one is 'newt run' command. Check \nout the usage from command line help.\n\n\nCreate test project\n\n\nNow that you have your system setup, you can start creating your own stuff.\nFirst you want to create a project for yourself - you could start by using blinky as a project \ntemplate, but since we're going to want to be able to access the data via Bluetooth, let's \nuse the \nbleprph\n Bluetooth Peripheral project inst
ead.\n\n\n [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality\n [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/bleprph/pkg.yml apps/air_quality/\n [user@IsMyLaptop:~/src/air_quality]$ cp -Rp repos/apache-mynewt-core/apps/bleprph/src apps/air_quality/\n\n\n\n\n\nThen you modify the apps/air_quality/pkg.yml for air_quality in order to change the \npkg.name\n to be \napps/air_quality\n.\nYou'll need to add the \n@apache-mynewt-core/\n path to all the package dependencies, since the app no longer\nresides within the apache-mynewt-core repository.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml\npkg.name: apps/air_quality\npkg.type: app\npkg.description: BLE Air Quality application.\npkg.author: \nApache Mynewt \ndev@mynewt.incubator.apache.org\n\npkg.homepage: \nhttp://mynewt.apache.org/\n\npkg.keywords:\n\npkg.deps: \n - \n@apache-mynewt-core/kernel/os\n\n - \n@apache-mynewt-core/sys/shell\n\n - \n@apache-mynewt-c
ore/sys/stats/full\n\n - \n@apache-mynewt-core/sys/log/full\n\n - \n@apache-mynewt-core/mgmt/newtmgr\n\n - \n@apache-mynewt-core/mgmt/newtmgr/transport/ble\n\n - \n@apache-mynewt-core/net/nimble/controller\n\n - \n@apache-mynewt-core/net/nimble/host\n\n - \n@apache-mynewt-core/net/nimble/host/services/ans\n\n - \n@apache-mynewt-core/net/nimble/host/services/gap\n\n - \n@apache-mynewt-core/net/nimble/host/services/gatt\n\n - \n@apache-mynewt-core/net/nimble/host/store/ram\n\n - \n@apache-mynewt-core/net/nimble/transport/ram\n\n - \n@apache-mynewt-core/sys/console/full\n\n - \n@apache-mynewt-core/sys/sysinit\n\n - \n@apache-mynewt-core/sys/id\n\n\n\n\n\n\nAnd create a target for it:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target create air_q\nTarget targets/air_q successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/air_q successfully set target.b
sp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q app=apps/air_quality \nTarget targets/air_q successfully set target.app to apps/air_quality\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q build_profile=debug\nTarget targets/air_q successfully set target.build_profile to debug\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\n ....\nLinking /Users/dsimmons/dev/myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf\nTarget successfully built: targets/air_q\n\n\n\n\n\nCreate packages for drivers\n\n\nOne of the sensors you want to enable is SenseAir K30, which will connect to the board over a serial port.\nTo start development of the driver, you first need to create a package description for it, and add stubs for sources.\n\n\nThe first thing to do is to create the directory structure for your driver:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/include/senseair\n[us
er@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/src\n\n\n\n\n\nNow 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.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/pkg.yml\n\n\n\n\n\n#\n\n\n# Licensed to the Apache Software Foundation (ASF) under one\n\n\n# or more contributor license agreements. See the NOTICE file\n\n\n# distributed with this work for additional information\n\n\n# regarding copyright ownership. The ASF licenses this file\n\n\n# to you under the Apache License, Version 2.0 (the\n\n\n# \nLicense\n); you may not use this file except in compliance\n\n\n# with the License. You may obtain a copy of the License at\n\n\n# \n\n\n# http:\n//www.apache.org/licenses/LICENSE-2.0\n\n\n#\n\n\n# Unless required by applicable law or agreed to in writing,\n\n\n# software distributed under the License is distributed on an\n\n\n# \nAS IS\n BASIS, WITHOUT WARRANTIE
S OR CONDITIONS OF ANY\n\n\n# KIND, either express or implied. See the License for the\n\n\n# specific language governing permissions and limitations\n\n\n# under the License.\n\n\n#\n\n\npkg\n.\nname\n: \nlibs/my_drivers/senseair\n\n\npkg\n.\ndescription\n: \nHost\n \nside\n \nof\n \nthe\n \nnimble\n \nBluetooth\n \nSmart\n \nstack\n.\n\npkg\n.\nauthor\n: \nApache Mynewt \ndev@mynewt.incubator.apache.org\n\n\npkg\n.\nhomepage\n: \nhttp://mynewt.apache.org/\n\n\npkg\n.\nkeywords\n:\n \n-\n \nble\n\n \n-\n \nbluetooth\n\n\n\npkg\n.\ndeps\n:\n \n-\n \n@apache-mynewt-core/kernel/os\n\n\n\n\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/include/senseair/senseair.h\n\n\n\n\n\n/*\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you
under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n * \n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n*/\n\n\n#ifndef _SENSEAIR_H_\n\n\n#define _SENSEAIR_H_\n\n\n\nvoid\n \nsenseair_init\n(\nvoid\n);\n\n\n#endif \n/* _SENSEAIR_H_ */\n\n\n\n\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c\n\n\n\n\n\n/**\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * dis
tributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n * \n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n */\n\n\n\nvoid\n\n\nsenseair_init\n(\nvoid\n)\n{\n}\n\n\n\n\n\nAnd add dependency to this package in your project yml file.\n\n\nHere's the listing from apps/air_quality/pkg.yml\n\n\npkg.name: apps/air_quality\npkg.type: app\npkg.description: Air qualit
y sensor test\npkg.keywords:\n\npkg.deps:\n - \n@apache-mynewt-core/libs/console/full\n\n - \n@apache-mynewt-core/libs/newtmgr\n\n - \n@apache-mynewt-core/libs/os\n\n - \n@apache-mynewt-core/libs/shell\n\n - \n@apache-mynewt-core/sys/config\n\n - \n@apache-mynewt-core/sys/log/full\n\n - \n@apache-mynewt-core/sys/stats/full\n\n - libs/my_drivers/senseair\n\n\n\n\n\nAnd add a call to your main() to initialize this driver.\n\n\n [user@IsMyLaptop:~/src/air_quality]$ diff project/blinky/src/main.c project/air_quality/src/main.c\n 28a29\n \n #include \nsenseair/senseair.h\n\n 190a192\n \n senseair_init();\n [user@IsMyLaptop:~/src/air_quality\n\n\n\n\n\nThe ble_prph app runs everything in one task handler. For this project, we're going to add a second\ntask handler to respond to the shell, and then handle communicating with the senseair sensor for us.\n\n\n/** shell task settings. */\n\n\n#define SHELL_TASK_PRIO 2\n\n\n#define SHELL_STACK
_SIZE (OS_STACK_ALIGN(336))\n\n\n\nstruct\n \nos_eventq\n \nshell_evq\n;\n\nstruct\n \nos_task\n \nshell_task\n;\n\nbssnz_t\n \nos_stack_t\n \nshell_stack\n[\nSHELL_STACK_SIZE\n];\n\n\n\n\n\nThat defines the task, now we need to initialize it, add a task handler, and we're going to \nuse this task as our default task handler.\n\n\n/**\n\n\n * Event loop for the main shell task.\n\n\n */\n\n\nstatic\n \nvoid\n\n\nshell_task_handler\n(\nvoid\n \n*unused\n)\n{\n \nwhile\n (\n1\n) {\n \nos_eventq_run\n(\nshell_evq\n);\n }\n}\n\n\n\n\n\nAnd in your \nmain()\n add:\n\n\n \n/* Initialize shell eventq */\n\n \nos_eventq_init\n(\nshell_evq\n);\n\n \n/* Create the shell task. \n\n\n * All shell operations are performed in this task.\n\n\n */\n\n \nos_task_init\n(\nshell_task\n, \nshell\n, \nshell_task_handler\n,\n \nNULL\n, \nSHELL_TASK_PRIO\n, \nOS_WAIT_FOREVER\n,\n \nshell_stack\n, \nSHELL_S
TACK_SIZE\n);\n\n\n\n\n\nDon't forget to change your default task handler!\n\n\n \nos_eventq_dflt_set\n(\nshell_evq\n);\n\n\n\n\n\nAnd then build it to make sure all goes well.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\nCompiling senseair.c\nArchiving senseair.a\nLinking air_quality.elf\nApp successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf\n\n\n\n\n\nAll looks good.\n\n\nAdd CLI commands for testing drivers\n\n\nWhile 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 \non how to \nenable the CLI\n, so all we'll need to do is add the propper values to the project's \nsyscfg.yml\n file:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat targets/air_q/syscfg.yml\nsyscfg.vals:\n # Set as per blinky_primo\n OPENOCD_DEBUG: 1\n # Enable the shell task.\n SHELL_TASK: 1\n STATS_CLI: 1\n CONSOLE_TICKS: 1\n CONSOLE_PROM
PT: 1\n\n\n\n\n\nThen register your senseair command with the shell by adding the following to \nlibs/my_drivers/senseair/src/senseair.c\n\n\n#include \nshell/shell.h\n\n\n#include \nconsole/console.h\n\n\n#include \nassert.h\n\n\n\n\nstatic\n \nint\n \nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n);\n\nstatic\n \nstruct\n \nshell_cmd\n \nsenseair_cmd\n \n=\n {\n .\nsc_cmd\n \n=\n \nsenseair\n,\n .\nsc_cmd_func\n \n=\n \nsenseair_shell_func\n,\n};\n\n\nvoid\n\n\nsenseair_init\n(\nvoid\n)\n{\n \nint\n \nrc\n;\n\n \nrc\n \n=\n \nshell_cmd_register\n(\nsenseair_cmd\n);\n \nassert\n(\nrc\n \n==\n \n0\n);\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n \nconsole_printf\n(\nYay! Somebody called!\\n\n);\n \nreturn\n \n0\n;\n\n}\n\n\n\n\n\nNow you can you build this, download to target, and start minicom on your console port. If you haven't already, familiarize yourself with\nthe tutorial on how to connect a se
rial port to your board \nhere\n.\n\n\nYou'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.\n\n\n [user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2\n\n\n Welcome to minicom 2.7\n\n OPTIONS: \n Compiled on Oct 12 2015, 07:48:30.\n Port /dev/tty.usbserial-AH02MIE2, 13:44:40\n\n Press CTRL-X Z for help on special keys\n\n ?\n 419: \n ?\n Commands:\n 641: stat echo ? prompt ticks tasks\n 643: mempools date senseair\n 644: \n senseair\n Yay! Somebody called!\n 1125: \n\n 53611: \n tasks\n Tasks:\n 54047: task pri tid runtime csw stksz stkuse lcheck ncheck flg\n 54057: idle 255 0 54048 66890 64 30 0 0 0\n 54068: ble_ll 0 1 9 64986 80 58 0 0 0\n 54079: bl
eprph 1 2 0 1 336 32 0 0 0\n 54090: shell 2 3 0 2077 336 262 0 0 0\n 54101: \n\n\n\n\n\n\nThat's great. Your shell task is running, and is responding appropriately!\nYou can connect the hardware to your board and start developing code for the driver itself.\n\n\nUse of HAL for drivers\n\n\nThe 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.\nWe'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\ncommunicate at 9600 baud, this bit-banged uart is plenty fast enough.\n\n\nYou'll have to make a small change to the \nsyscfg.yml\n file in your project's target directory to change the pin definitions \nfor this second UART. Those changes are as follows:\n\n\n UART_0_PIN_TX: 23\n UART_0_PIN_RX: 24\n\n\n\n\n\nWith
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.\n\n\nYou will now see what the driver code ends up looking like. Here's the header file, filled in from the stub you created earlier.\n\n\n/*\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n * \n\n\n *
http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n*/\n\n\n#ifndef _SENSEAIR_H_\n\n\n#define _SENSEAIR_H_\n\n\n\nenum\n \nsenseair_read_type\n {\n \nSENSEAIR_CO2\n,\n};\n\n\nint\n \nsenseair_init\n(\nint\n \nuartno\n);\n\n\nint\n \nsenseair_read\n(\nenum\n \nsenseair_read_type\n);\n\n\n#endif \n/* _SENSEAIR_H_ */\n\n\n\n\n\n\nAs you can see, logical UART number has been added to the init routine. A 'read' function has been added, \nwhich is a blocking read. If you were making a commercial product, you would probably have a callback for reporting the results.\n\n\nAnd here is the source for the driver.\n\n\n/**\n\n\n * Li
censed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n *\n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n */\n\n\n#include \nstring.h\n\n\n\n#include \nshell/shell.h\n\n\n#include \nconsole/console.h\n\n\n#include \nos/os.h
\n\n\n\n#include \nhal/hal_uart.h\n\n\n\n#include \nsenseair/senseair.h\n\n\n\nstatic\n \nconst\n \nuint8_t\n \ncmd_read_co2\n[] \n=\n {\n \n0xFE\n, \n0\nX44\n, \n0\nX00\n, \n0\nX08\n, \n0\nX02\n, \n0\nX9F\n, \n0\nX25\n\n};\n\n\nstatic\n \nint\n \nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n);\n\nstatic\n \nstruct\n \nshell_cmd\n \nsenseair_cmd\n \n=\n {\n .\nsc_cmd\n \n=\n \nsenseair\n,\n .\nsc_cmd_func\n \n=\n \nsenseair_shell_func\n,\n};\n\n\nstruct\n \nsenseair\n { \n \nint\n \nuart\n;\n \nstruct\n \nos_sem\n \nsema\n;\n \nconst\n \nuint8_t\n \n*tx_data\n;\n \nint\n \ntx_off\n;\n \nint\n \ntx_len\n;\n \nuint8_t\n \nrx_data\n[\n32\n]; \n \nint\n \nrx_off\n;\n \nint\n \nvalue\n;\n} \nsenseair\n;\n\n\nstatic\n \nint\n\n\nsenseair_tx_char\n(\nvoid\n \n*arg\n)\n{\n \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n \nint\n \nrc\n;\n\n \nif\n (\ns-\ntx_off\n \n=\n \ns-\ntx_len\n) {\n \n/*\n\n\n * Command tx finished
.\n\n\n */\n\n \ns-\ntx_data\n \n=\n \nNULL\n;\n \nreturn\n \n-\n1\n;\n }\n\n \nrc\n \n=\n \ns-\ntx_data\n[\ns-\ntx_off\n];\n \ns-\ntx_off++\n;\n \nreturn\n \nrc\n;\n}\n\n\n/*\n\n\n * CRC for modbus over serial port.\n\n\n */\n\n\nstatic\n \nconst\n \nuint16_t\n \nmb_crc_tbl\n[] \n=\n {\n \n0x0000\n, \n0xcc01\n, \n0xd801\n, \n0x1400\n, \n0xf001\n, \n0x3c00\n, \n0x2800\n, \n0xe401\n,\n \n0xa001\n, \n0x6c00\n, \n0x7800\n, \n0xb401\n, \n0x5000\n, \n0x9c01\n, \n0x8801\n, \n0x4400\n\n};\n\n\nstatic\n \nuint16_t\n\n\nmb_crc\n(\nconst\n \nuint8_t\n \n*data\n, \nint\n \nlen\n, \nuint16_t\n \ncrc\n)\n{\n \nwhile\n (\nlen--\n \n \n0\n) {\n \ncrc\n \n^=\n \n*data++\n;\n \ncrc\n \n=\n (\ncrc\n \n \n4\n) \n^\n \nmb_crc_tbl\n[\ncrc\n \n \n0xf\n];\n \ncrc\n \n=\n (\ncrc\n \n \n4\n) \n^\n \nmb_crc_tbl\n[\ncrc\n \n \n0xf\n];\n }\n \nreturn\n \ncrc\n;\n}\n\n\nstatic\n \nint\n\n\nmb_crc_check\n(\nconst\n \nvoid\n \n*pkt\n, \nint\n \
nlen\n)\n{\n \nuint16_t\n \ncrc\n, \ncmp\n;\n \nuint8_t\n \n*bp\n \n=\n (\nuint8_t\n \n*\n)\npkt\n;\n\n \nif\n (\nlen\n \n \nsizeof\n(\ncrc\n) \n+\n \n1\n) {\n \nreturn\n \n-\n1\n;\n }\n \ncrc\n \n=\n \nmb_crc\n(\npkt\n, \nlen\n \n-\n \n2\n, \n0xffff\n);\n \ncmp\n \n=\n \nbp\n[\nlen\n \n-\n \n2\n] \n|\n (\nbp\n[\nlen\n \n-\n \n1\n] \n \n8\n);\n \nif\n (\ncrc\n \n!=\n \ncmp\n) {\n \nreturn\n \n-\n1\n;\n } \nelse\n {\n \nreturn\n \n0\n;\n }\n}\n\n\nstatic\n \nint\n\n\nsenseair_rx_char\n(\nvoid\n \n*arg\n, \nuint8_t\n \ndata\n)\n{\n \nstruct\n \nsenseair\n \n*s\n \n=\n (\nstruct\n \nsenseair\n \n*\n)\narg\n;\n \nint\n \nrc\n;\n\n \nif\n (\ns-\nrx_off\n \n=\n \nsizeof\n(\ns-\nrx_data\n)) {\n \ns-\nrx_off\n \n=\n \n0\n;\n }\n \ns-\nrx_data\n[\ns-\nrx_off\n] \n=\n \ndata\n;\n \ns-\nrx_off++\n;\n\n \nif\n (\ns-\nrx_off\n \n==\n \n7\n) {\n \nrc\n \n=\n \nmb_crc_check\n(\ns-\nrx_data\n, \ns-\nrx_off\n);\n
\nif\n (\nrc\n \n==\n \n0\n) {\n \ns-\nvalue\n \n=\n \ns-\nrx_data\n[\n3\n] \n*\n \n256\n \n+\n \ns-\nrx_data\n[\n4\n];\n \nos_sem_release\n(\ns-\nsema\n);\n }\n }\n \nreturn\n \n0\n;\n}\n\n\nvoid\n\n\nsenseair_tx\n(\nstruct\n \nsenseair\n \n*s\n, \nconst\n \nuint8_t\n \n*tx_data\n, \nint\n \ndata_len\n)\n{\n \ns-\ntx_data\n \n=\n \ntx_data\n;\n \ns-\ntx_len\n \n=\n \ndata_len\n;\n \ns-\ntx_off\n \n=\n \n0\n;\n \ns-\nrx_off\n \n=\n \n0\n;\n\n \nhal_uart_start_tx\n(\ns-\nuart\n);\n}\n\n\nint\n\n\nsenseair_read\n(\nenum\n \nsenseair_read_type\n \ntype\n)\n{\n \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n \nconst\n \nuint8_t\n \n*cmd\n;\n \nint\n \ncmd_len\n;\n \nint\n \nrc\n;\n\n \nif\n (\ns-\ntx_data\n) {\n \n/*\n\n\n * busy\n\n\n */\n\n \nreturn\n \n-\n1\n;\n }\n \nswitch\n (\ntype\n) {\n \ncase\n \nSENSEAIR_CO2\n:\n \ncmd\n \n=\n \ncmd_read_co2\n;\n \ncmd_
len\n \n=\n \nsizeof\n(\ncmd_read_co2\n);\n \nbreak\n;\n \ndefault\n:\n\n \nreturn\n \n-\n1\n;\n }\n \nsenseair_tx\n(\ns\n, \ncmd\n, \ncmd_len\n);\n \nrc\n \n=\n \nos_sem_pend\n(\ns-\nsema\n, \nOS_TICKS_PER_SEC\n \n/\n \n2\n);\n \nif\n (\nrc\n \n==\n \nOS_TIMEOUT\n) {\n \n/*\n\n\n * timeout\n\n\n */\n\n \nreturn\n \n-\n2\n;\n }\n \nreturn\n \ns-\nvalue\n;\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n \nint\n \nvalue\n;\n \nenum\n \nsenseair_read_type\n \ntype\n;\n\n \nif\n (\nargc\n \n \n2\n) {\n\nusage\n:\n \nconsole_printf\n(\n%s co2\\n\n, \nargv\n[\n0\n]);\n \nreturn\n \n0\n;\n }\n \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \nco2\n)) {\n \ntype\n \n=\n \nSENSEAIR_CO2\n;\n } \nelse\n {\n \ngoto\n \nusage\n;\n }\n \nvalue\n \n=\n \nsenseair_read\n(\ntype\n);\n \nif\n (\nvalue\n \n=\n \n0\n) {\n \nconsole_printf\n(\n
Got %d\\n\n, \nvalue\n);\n } \nelse\n {\n \nconsole_printf\n(\nError while reading: %d\\n\n, \nvalue\n);\n }\n \nreturn\n \n0\n;\n}\n\n\nint\n\n\nsenseair_init\n(\nint\n \nuartno\n)\n{\n \nint\n \nrc\n;\n \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n\n \nrc\n \n=\n \nshell_cmd_register\n(\nsenseair_cmd\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n\n \nrc\n \n=\n \nos_sem_init\n(\ns-\nsema\n, \n1\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n \nrc\n \n=\n \nhal_uart_init_cbs\n(\nuartno\n, \nsenseair_tx_char\n, \nNULL\n,\n \nsenseair_rx_char\n, \nsenseair\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n \nrc\n \n=\n \nhal_uart_config\n(\nuartno\n, \n9600\n, \n8\n, \n1\n, \nHAL_UART_PARITY_NONE\n,\n \nHAL_UART_FLOW_CTL_NONE\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n \ns-\nuart\n \n=\n \nuartno\n;\n\n \nreturn\n \n0\n;\n}\n\n\n\n\n\nAnd your modified main() for
senseair driver init.\n\n\nint\n\n\nmain\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n ....\n \nsenseair_init\n(\n0\n);\n ....\n }\n\n\n\n\n\nYou can see from the code that you are using the HAL interface to open a UART port, and using OS \nsemaphore as a way of blocking the task when waiting for read response to come back from the sensor.\n\n\nNow comes the fun part: Hooking up the sensor! It's fun because a) hooking up a sensor is always \nfun and b) the SenseAir sensor's PCB is entirely unlabeled, so you'll have to trust us on how to hook it up. \n\n\nSo here we go. \n\n\nYou'll have to do a little soldering. I soldered some header pins to the SenseAir K30 board to\nmake connecting wires easier using standard jumper wires, but you can also just solder wires\nstraight to the board if you prefer.\n\n\nHere's what your SenseAir board should look like once it's wired up:\n\n\n\n\nNow that you have that wired up, let's get the Arduino Primo wired up. A couple of things to
note:\n\n\n\n\nThe Arduino Primo's 'console' UART is actually UART1. \n\n\nThe secondary (bit-banged) UART is UART0, so that's where we'll have to hook up the SenseAir.\n\n\n\n\nHere's what your Arduino Primo should now look like with everything wired in:\n\n\n\n\nEverything is wired and you're ready to go! Build and load your new app:\n\n\n$ newt build air_q\nBuilding target targets/air_q\nCompiling apps/air_quality/src/main.c\nArchiving apps_air_quality.a\nLinking myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf\nTarget successfully built: targets/air_q\n$ newt create-image air_q 1.0.0\nApp image succesfully generated: myproj/bin/targets/air_q/app/apps/air_quality/air_quality.img\n$ newt load air_q\nLoading app image into slot 1\n\n\n\n\n\nNow, you should be able to connect to your serial port and read values:\n\n\nuser@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2\n\n\n Welcome to minicom 2.7\n\n OPTIONS: \n Compiled on Oct 12 2015, 07:48:30.\n P
ort /dev/tty.usbserial-AH02MIE2, 13:44:40\n\n Press CTRL-X Z for help on special keys\n\n 1185: \n ?\n Commands:\n 1382: stat echo ? prompt ticks tasks\n 1390: mempools date senseair\n 1395: \n senseair\n senseair co2\n 2143: \n senseair co2\n Got 973\n\n\n\n\n\nAnd you're getting valid readings! Congratulations!\n\n\nNext we'll hook this all up via Bluetooth so that you can read those values remotely.",
"title": "Basic Air Quality Sensor"
},
{
@@ -1282,12 +1282,12 @@
},
{
"location": "/os/tutorials/air_quality_sensor/#create-test-project",
- "text": "Now that you have your system setup, you can start creating your own stuff.\nFirst you want to create a project for yourself - you could start by using blinky as a project \ntemplate, but since we're going to want to be able to access the data via Bluetooth, let's \nuse the bleprph Bluetooth Peripheral project instead. [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality\n [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/bleprph/pkg.yml apps/air_quality/\n [user@IsMyLaptop:~/src/air_quality]$ cp -Rp repos/apache-mynewt-core/apps/bleprph/src apps/air_quality/ Then you modify the apps/air_quality/pkg.yml for air_quality in order to change the pkg.name to be apps/air_quality .\nYou'll need to add the @apache-mynewt-core/ path to all the package dependencies, since the app no longer\nresides within the apache-mynewt-core repository. The Arduino Primo board has a limited amount of memory, so you must also switch your li
bc to be baselibc, instead of the standard one. [user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml\npkg.name: apps/air_quality\npkg.type: app\npkg.description: BLE Air Quality application.\npkg.author: Apache Mynewt dev@mynewt.incubator.apache.org \npkg.homepage: http://mynewt.apache.org/ \npkg.keywords:\n\npkg.deps: \n - @apache-mynewt-core/kernel/os \n - @apache-mynewt-core/sys/shell \n - @apache-mynewt-core/sys/stats/full \n - @apache-mynewt-core/sys/log/full \n - @apache-mynewt-core/mgmt/newtmgr \n - @apache-mynewt-core/mgmt/newtmgr/transport/ble \n - @apache-mynewt-core/net/nimble/controller \n - @apache-mynewt-core/net/nimble/host \n - @apache-mynewt-core/net/nimble/host/services/ans \n - @apache-mynewt-core/net/nimble/host/services/gap \n - @apache-mynewt-core/net/nimble/host/services/gatt \n - @apache-mynewt-core/net/nimble/host/store/ram \n - @apache-mynewt-core/net/nimble/transport/ram \n - @apache-
mynewt-core/sys/console/full \n - @apache-mynewt-core/sys/sysinit \n - @apache-mynewt-core/sys/id And create a target for it: [user@IsMyLaptop:~/src/air_quality]$ newt target create air_q\nTarget targets/air_q successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/air_q successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q app=apps/air_quality \nTarget targets/air_q successfully set target.app to apps/air_quality\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q build_profile=debug\nTarget targets/air_q successfully set target.build_profile to debug\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\n ....\nLinking /Users/dsimmons/dev/myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf\nTarget successfully built: targets/air_q",
+ "text": "Now that you have your system setup, you can start creating your own stuff.\nFirst you want to create a project for yourself - you could start by using blinky as a project \ntemplate, but since we're going to want to be able to access the data via Bluetooth, let's \nuse the bleprph Bluetooth Peripheral project instead. [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality\n [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/bleprph/pkg.yml apps/air_quality/\n [user@IsMyLaptop:~/src/air_quality]$ cp -Rp repos/apache-mynewt-core/apps/bleprph/src apps/air_quality/ Then you modify the apps/air_quality/pkg.yml for air_quality in order to change the pkg.name to be apps/air_quality .\nYou'll need to add the @apache-mynewt-core/ path to all the package dependencies, since the app no longer\nresides within the apache-mynewt-core repository. [user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml\npkg.name: apps/air_q
uality\npkg.type: app\npkg.description: BLE Air Quality application.\npkg.author: Apache Mynewt dev@mynewt.incubator.apache.org \npkg.homepage: http://mynewt.apache.org/ \npkg.keywords:\n\npkg.deps: \n - @apache-mynewt-core/kernel/os \n - @apache-mynewt-core/sys/shell \n - @apache-mynewt-core/sys/stats/full \n - @apache-mynewt-core/sys/log/full \n - @apache-mynewt-core/mgmt/newtmgr \n - @apache-mynewt-core/mgmt/newtmgr/transport/ble \n - @apache-mynewt-core/net/nimble/controller \n - @apache-mynewt-core/net/nimble/host \n - @apache-mynewt-core/net/nimble/host/services/ans \n - @apache-mynewt-core/net/nimble/host/services/gap \n - @apache-mynewt-core/net/nimble/host/services/gatt \n - @apache-mynewt-core/net/nimble/host/store/ram \n - @apache-mynewt-core/net/nimble/transport/ram \n - @apache-mynewt-core/sys/console/full \n - @apache-mynewt-core/sys/sysinit \n - @apache-mynewt-core/sys/id And create a target for it:
[user@IsMyLaptop:~/src/air_quality]$ newt target create air_q\nTarget targets/air_q successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/air_q successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q app=apps/air_quality \nTarget targets/air_q successfully set target.app to apps/air_quality\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q build_profile=debug\nTarget targets/air_q successfully set target.build_profile to debug\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\n ....\nLinking /Users/dsimmons/dev/myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf\nTarget successfully built: targets/air_q",
"title": "Create test project"
},
{
"location": "/os/tutorials/air_quality_sensor/#create-packages-for-drivers",
- "text": "One of the sensors you want to enable is SenseAir K30, which will connect to the board over a serial port.\nTo start development of the driver, you first need to create a package description for it, and add stubs for sources. The first thing to do is to create the directory structure for your driver: [user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/include/senseair\n[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/src 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. [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/pkg.yml # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the #
License ); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http: //www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # pkg . name : libs/my_drivers/senseair pkg . description : Host side of the nimble Bluetooth Smart stack . pkg . author : Apache Mynewt dev@mynewt.incubator.apache.org pkg . homepage : http://mynewt.apache.org/ pkg . keywords :\n - ble \n - bluetooth pkg . deps :\n - @apache-mynewt-core/kernel/os [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/include/senseair/senseair.h /* * Licensed to the Apache Software Foundation (ASF) u
nder one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * License ); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _SENSEAIR_H_ #define _SENSEAIR_H_ void senseair_init ( void ); #endif /* _SENSEAIR_H_ */ [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c /** * Licensed to the Apache Software Fou
ndation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * License ); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ void senseair_init ( void )\n{\n} And add dependency to this package in your project yml file. Here's the listing from apps/air_quality/pkg.yml pkg.name: apps/air_quality\npkg.type: app\npkg.description: Air q
uality sensor test\npkg.keywords:\n\npkg.deps:\n - @apache-mynewt-core/libs/console/full \n - @apache-mynewt-core/libs/newtmgr \n - @apache-mynewt-core/libs/os \n - @apache-mynewt-core/libs/shell \n - @apache-mynewt-core/sys/config \n - @apache-mynewt-core/sys/log/full \n - @apache-mynewt-core/sys/stats/full \n - @apache-mynewt-core/libs/baselibc \n - libs/my_drivers/senseair And add a call to your main() to initialize this driver. [user@IsMyLaptop:~/src/air_quality]$ diff project/blinky/src/main.c project/air_quality/src/main.c\n 28a29\n #include senseair/senseair.h \n 190a192\n senseair_init();\n [user@IsMyLaptop:~/src/air_quality The ble_prph app runs everything in one task handler. For this project, we're going to add a second\ntask handler to respond to the shell, and then handle communicating with the senseair sensor for us. /** shell task settings. */ #define SHELL_TASK_PRIO 2 #define SHELL_STACK_SIZE
(OS_STACK_ALIGN(336)) struct os_eventq shell_evq ; struct os_task shell_task ; bssnz_t os_stack_t shell_stack [ SHELL_STACK_SIZE ]; That defines the task, now we need to initialize it, add a task handler, and we're going to \nuse this task as our default task handler. /** * Event loop for the main shell task. */ static void shell_task_handler ( void *unused )\n{\n while ( 1 ) {\n os_eventq_run ( shell_evq );\n }\n} And in your main() add: /* Initialize shell eventq */ \n os_eventq_init ( shell_evq );\n\n /* Create the shell task. * All shell operations are performed in this task. */ \n os_task_init ( shell_task , shell , shell_task_handler ,\n NULL , SHELL_TASK_PRIO , OS_WAIT_FOREVER ,\n shell_stack , SHELL_STACK_SIZE ); Don't forget to change your default task handler! os_eventq_dflt_set ( shell_evq ); And then build it to mak
e sure all goes well. [user@IsMyLaptop:~/src/air_quality]$ newt build air_q\nCompiling senseair.c\nArchiving senseair.a\nLinking air_quality.elf\nApp successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf All looks good.",
+ "text": "One of the sensors you want to enable is SenseAir K30, which will connect to the board over a serial port.\nTo start development of the driver, you first need to create a package description for it, and add stubs for sources. The first thing to do is to create the directory structure for your driver: [user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/include/senseair\n[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/src 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. [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/pkg.yml # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the #
License ); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http: //www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # pkg . name : libs/my_drivers/senseair pkg . description : Host side of the nimble Bluetooth Smart stack . pkg . author : Apache Mynewt dev@mynewt.incubator.apache.org pkg . homepage : http://mynewt.apache.org/ pkg . keywords :\n - ble \n - bluetooth pkg . deps :\n - @apache-mynewt-core/kernel/os [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/include/senseair/senseair.h /* * Licensed to the Apache Software Foundation (ASF) u
nder one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * License ); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _SENSEAIR_H_ #define _SENSEAIR_H_ void senseair_init ( void ); #endif /* _SENSEAIR_H_ */ [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c /** * Licensed to the Apache Software Fou
ndation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * License ); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ void senseair_init ( void )\n{\n} And add dependency to this package in your project yml file. Here's the listing from apps/air_quality/pkg.yml pkg.name: apps/air_quality\npkg.type: app\npkg.description: Air q
uality sensor test\npkg.keywords:\n\npkg.deps:\n - @apache-mynewt-core/libs/console/full \n - @apache-mynewt-core/libs/newtmgr \n - @apache-mynewt-core/libs/os \n - @apache-mynewt-core/libs/shell \n - @apache-mynewt-core/sys/config \n - @apache-mynewt-core/sys/log/full \n - @apache-mynewt-core/sys/stats/full \n - libs/my_drivers/senseair And add a call to your main() to initialize this driver. [user@IsMyLaptop:~/src/air_quality]$ diff project/blinky/src/main.c project/air_quality/src/main.c\n 28a29\n #include senseair/senseair.h \n 190a192\n senseair_init();\n [user@IsMyLaptop:~/src/air_quality The ble_prph app runs everything in one task handler. For this project, we're going to add a second\ntask handler to respond to the shell, and then handle communicating with the senseair sensor for us. /** shell task settings. */ #define SHELL_TASK_PRIO 2 #define SHELL_STACK_SIZE (OS_STACK_ALIGN(336)) struct os
_eventq shell_evq ; struct os_task shell_task ; bssnz_t os_stack_t shell_stack [ SHELL_STACK_SIZE ]; That defines the task, now we need to initialize it, add a task handler, and we're going to \nuse this task as our default task handler. /** * Event loop for the main shell task. */ static void shell_task_handler ( void *unused )\n{\n while ( 1 ) {\n os_eventq_run ( shell_evq );\n }\n} And in your main() add: /* Initialize shell eventq */ \n os_eventq_init ( shell_evq );\n\n /* Create the shell task. * All shell operations are performed in this task. */ \n os_task_init ( shell_task , shell , shell_task_handler ,\n NULL , SHELL_TASK_PRIO , OS_WAIT_FOREVER ,\n shell_stack , SHELL_STACK_SIZE ); Don't forget to change your default task handler! os_eventq_dflt_set ( shell_evq ); And then build it to make sure all goes well. [user@IsMyLaptop:~/s
rc/air_quality]$ newt build air_q\nCompiling senseair.c\nArchiving senseair.a\nLinking air_quality.elf\nApp successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf All looks good.",
"title": "Create packages for drivers"
},
{
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/b381d55c/latest/os/tutorials/air_quality_sensor/index.html
----------------------------------------------------------------------
diff --git a/latest/os/tutorials/air_quality_sensor/index.html b/latest/os/tutorials/air_quality_sensor/index.html
index ffbd8df..d22dd0a 100644
--- a/latest/os/tutorials/air_quality_sensor/index.html
+++ b/latest/os/tutorials/air_quality_sensor/index.html
@@ -625,7 +625,6 @@ use the <code>bleprph</code> Bluetooth Peripheral project instead.</p>
<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>
-<p>The Arduino Primo board has a limited amount of memory, so you must also switch your libc to be baselibc, instead of the standard one.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%">[user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml
pkg.name: apps/air_quality
pkg.type: app
@@ -791,7 +790,6 @@ pkg.deps:
- "@apache-mynewt-core/sys/config"
- "@apache-mynewt-core/sys/log/full"
- "@apache-mynewt-core/sys/stats/full"
- - "@apache-mynewt-core/libs/baselibc"
- libs/my_drivers/senseair
</pre></div>
[2/2] incubator-mynewt-site git commit: removed baselibc reference in
air quality sensor tutorial
Posted by ad...@apache.org.
removed baselibc reference in air quality sensor tutorial
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/commit/b381d55c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/tree/b381d55c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/diff/b381d55c
Branch: refs/heads/asf-site
Commit: b381d55c4059b8b736a4cf75839728292a26d176
Parents: 7dc2cb5
Author: aditihilbert <ad...@runtime.io>
Authored: Tue Jan 31 22:51:46 2017 -0800
Committer: aditihilbert <ad...@runtime.io>
Committed: Tue Jan 31 22:51:46 2017 -0800
----------------------------------------------------------------------
develop/mkdocs/search_index.json | 6 +++---
develop/os/tutorials/air_quality_sensor/index.html | 2 --
latest/mkdocs/search_index.json | 6 +++---
latest/os/tutorials/air_quality_sensor/index.html | 2 --
4 files changed, 6 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/b381d55c/develop/mkdocs/search_index.json
----------------------------------------------------------------------
diff --git a/develop/mkdocs/search_index.json b/develop/mkdocs/search_index.json
index c98271b..8b86886 100644
--- a/develop/mkdocs/search_index.json
+++ b/develop/mkdocs/search_index.json
@@ -1267,7 +1267,7 @@
},
{
"location": "/os/tutorials/air_quality_sensor/",
- "text": "Air quality sensor project\n\n\nSetting up source tree for stuff you need\n\n\nTo start with, you need to create a new project under which you will do this development. So you type in:\n\n\n $ mkdir $HOME/src\n $ cd $HOME/src\n $ newt new air_quality\n\n\n\n\n\nLet's say you are using Arduino Primo -- which is based on the Nordic Semi NRF52 chip -- as the platform. \nYou know you need the board support package for that hardware. You can look up its location, add it your \nproject, and fetch that along with the core OS components. Luckily, the Arduino Primo is supported in the \nMynewt Core, so there's nothing much to do here. \n\n\nYour project.yml file should look like this:\n\n\n [user@IsMyLaptop:~/src/air_quality]$ emacs project.yml \n\n [user@IsMyLaptop:~/src/air_quality]$ cat project.yml\n project.name: \nair_quality\n\n\n project.repositories:\n - apache-mynewt-core\n\n # Use github\ns distribution mechanism for core ASF libr
aries.\n # This provides mirroring automatically for us.\n #\n repository.apache-mynewt-core:\n type: github\n vers: 0-latest\n user: apache\n repo: incubator-mynewt-core\n\n [user@IsMyLaptop:~/src/air_quality]$ newt install\n apache-mynewt-core\n [user@IsMyLaptop:~/src/air_quality]$ ls repos/\n apache-mynewt-core\n\n\n\n\n\nGood. You want to make sure you have all the needed bits for supporting your board; \nso you decide to build the blinky project for the platform first.\n\n\nNow 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.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target copy my_blinky_sim blink_primo\nTarget successfully copied; targets/my_blinky_sim --\n targets/blink_primo\n[user@IsMyLaptop:~/src/air_quality]$ newt target set blink_primo bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/blink_nrf succe
ssfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt build blink_primo\nCompiling hal_bsp.c\n...\nLinking blinky.elf\nApp successfully built: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.elf\n\n\n\n\n\nGood.\n\n\nYou know that this platform uses bootloader, which means you have to create a target for that too.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target create boot_primo\nTarget targets/boot_nrf successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target show\n@apache-mynewt-core/targets/unittest\n bsp=hw/bsp/native\n build_profile=debug\n compiler=compiler/sim\ntargets/blink_primo\n app=apps/blinky\n bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n build_profile=debug\ntargets/boot_primo\ntargets/my_blinky_sim\n app=apps/blinky\n bsp=@apache-mynewt-core/hw/bsp/native\n build_profile=debug\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf
bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/boot_nrf successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf app=@apache-mynewt-core/apps/boot\nTarget targets/boot_nrf successfully set target.app to @apache-mynewt-core/apps/boot\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf build_profile=optimized\nTarget targets/boot_nrf successfully set target.build_profile to optimized\n\n\n\n\n\nAnd then build it, and load it onto the board.\n\n\nnewt build boot_primo\n....\nLinking boot.elf\nApp successfully built: /Users/user/src/air_quality/bin/boot_primo/apps/boot/boot.elf\n[user@IsMyLaptop:~/src/air_quality]\n$ newt load boot_primo\n\n\n\n\n\nAt this point, you may (or may not) see a bunch of error messages about not being able to connect to\nyour board, not being able to load the image, etc. If that's the case, and you haven't already, you\nshould most definitely go
worth through the \nblinky_primo\n tutorial so that you\ncan properly communicate with your board.\n\n\nNext you must download the targets to board, and see that the LED actually blinks. You plug in the \nArduino Primo board to your laptop, and say:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo\nLoading app image into slot 1\nError: couldn\nt open /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img\n\nError: exit status 1\n\nload - Load app image to target for \ntarget-name\n.\n\nUsage:\n newt load [flags]\n\nExamples:\n newt load \ntarget-name\n\n\n\nGlobal Flags:\n -l, --loglevel string Log level, defaults to WARN. (default \nWARN\n)\n -o, --outfile string Filename to tee log output to\n -q, --quiet Be quiet; only display error output.\n -s, --silent Be silent; don\nt output anything.\n -v, --verbose Enable verbose output when executing commands.\nexit status 1\n\n\n\n\n\nAh. Forgot to create an image ou
t of the blinky binary. Note that every time you want to build and \nload a new firmware image to a target board, you need to run 'create-image' on it.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt create-image blink_primo 0.0.1\nApp image successfully generated: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img\nBuild manifest: /Users/user/src/air_quality/bin/blink_nrf/apps/blinky/manifest.json\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo\n\n\n\n\n\nAnd it's blinking.\n\n\nShortcut for doing build/create-image/load/debug steps all in one is 'newt run' command. Check \nout the usage from command line help.\n\n\nCreate test project\n\n\nNow that you have your system setup, you can start creating your own stuff.\nFirst you want to create a project for yourself - you could start by using blinky as a project \ntemplate, but since we're going to want to be able to access the data via Bluetooth, let's \nuse the \nbleprph\n Bluetooth Peripheral project inst
ead.\n\n\n [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality\n [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/bleprph/pkg.yml apps/air_quality/\n [user@IsMyLaptop:~/src/air_quality]$ cp -Rp repos/apache-mynewt-core/apps/bleprph/src apps/air_quality/\n\n\n\n\n\nThen you modify the apps/air_quality/pkg.yml for air_quality in order to change the \npkg.name\n to be \napps/air_quality\n.\nYou'll need to add the \n@apache-mynewt-core/\n path to all the package dependencies, since the app no longer\nresides within the apache-mynewt-core repository.\n\n\nThe Arduino Primo board has a limited amount of memory, so you must also switch your libc to be baselibc, instead of the standard one.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml\npkg.name: apps/air_quality\npkg.type: app\npkg.description: BLE Air Quality application.\npkg.author: \nApache Mynewt \ndev@mynewt.incubator.apache.org\n\npkg.homepage: \nhttp://mynewt.apache.org
/\n\npkg.keywords:\n\npkg.deps: \n - \n@apache-mynewt-core/kernel/os\n\n - \n@apache-mynewt-core/sys/shell\n\n - \n@apache-mynewt-core/sys/stats/full\n\n - \n@apache-mynewt-core/sys/log/full\n\n - \n@apache-mynewt-core/mgmt/newtmgr\n\n - \n@apache-mynewt-core/mgmt/newtmgr/transport/ble\n\n - \n@apache-mynewt-core/net/nimble/controller\n\n - \n@apache-mynewt-core/net/nimble/host\n\n - \n@apache-mynewt-core/net/nimble/host/services/ans\n\n - \n@apache-mynewt-core/net/nimble/host/services/gap\n\n - \n@apache-mynewt-core/net/nimble/host/services/gatt\n\n - \n@apache-mynewt-core/net/nimble/host/store/ram\n\n - \n@apache-mynewt-core/net/nimble/transport/ram\n\n - \n@apache-mynewt-core/sys/console/full\n\n - \n@apache-mynewt-core/sys/sysinit\n\n - \n@apache-mynewt-core/sys/id\n\n\n\n\n\n\nAnd create a target for it:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target create air_q\nTarget targets/air_q successfully created\n[user@IsMyLaptop:
~/src/air_quality]$ newt target set air_q bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/air_q successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q app=apps/air_quality \nTarget targets/air_q successfully set target.app to apps/air_quality\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q build_profile=debug\nTarget targets/air_q successfully set target.build_profile to debug\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\n ....\nLinking /Users/dsimmons/dev/myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf\nTarget successfully built: targets/air_q\n\n\n\n\n\nCreate packages for drivers\n\n\nOne of the sensors you want to enable is SenseAir K30, which will connect to the board over a serial port.\nTo start development of the driver, you first need to create a package description for it, and add stubs for sources.\n\n\nThe first thing to do is to creat
e the directory structure for your driver:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/include/senseair\n[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/src\n\n\n\n\n\nNow 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.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/pkg.yml\n\n\n\n\n\n#\n\n\n# Licensed to the Apache Software Foundation (ASF) under one\n\n\n# or more contributor license agreements. See the NOTICE file\n\n\n# distributed with this work for additional information\n\n\n# regarding copyright ownership. The ASF licenses this file\n\n\n# to you under the Apache License, Version 2.0 (the\n\n\n# \nLicense\n); you may not use this file except in compliance\n\n\n# with the License. You may obtain a copy of the License at\n\n\n# \n\n\n# http:\n//www.apache.org/licenses/LICENSE-2.0\n\n\n#\n\n\n# Unless required by applicab
le law or agreed to in writing,\n\n\n# software distributed under the License is distributed on an\n\n\n# \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n# KIND, either express or implied. See the License for the\n\n\n# specific language governing permissions and limitations\n\n\n# under the License.\n\n\n#\n\n\npkg\n.\nname\n: \nlibs/my_drivers/senseair\n\n\npkg\n.\ndescription\n: \nHost\n \nside\n \nof\n \nthe\n \nnimble\n \nBluetooth\n \nSmart\n \nstack\n.\n\npkg\n.\nauthor\n: \nApache Mynewt \ndev@mynewt.incubator.apache.org\n\n\npkg\n.\nhomepage\n: \nhttp://mynewt.apache.org/\n\n\npkg\n.\nkeywords\n:\n \n-\n \nble\n\n \n-\n \nbluetooth\n\n\n\npkg\n.\ndeps\n:\n \n-\n \n@apache-mynewt-core/kernel/os\n\n\n\n\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/include/senseair/senseair.h\n\n\n\n\n\n/*\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\
n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n * \n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n*/\n\n\n#ifndef _SENSEAIR_H_\n\n\n#define _SENSEAIR_H_\n\n\n\nvoid\n \nsenseair_init\n(\nvoid\n);\n\n\n#endif \n/* _SENSEAIR_H_ */\n\n\n\n\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c\n\n\n\n\n\n/**\n\n\n *
Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n * \n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n */\n\n\n\nvoid\n\n\nsenseair_init\n(\nvoid\n)\n{\n}\n\n\n\n\n\nAnd add dependency to this package in your project
yml file.\n\n\nHere's the listing from apps/air_quality/pkg.yml\n\n\npkg.name: apps/air_quality\npkg.type: app\npkg.description: Air quality sensor test\npkg.keywords:\n\npkg.deps:\n - \n@apache-mynewt-core/libs/console/full\n\n - \n@apache-mynewt-core/libs/newtmgr\n\n - \n@apache-mynewt-core/libs/os\n\n - \n@apache-mynewt-core/libs/shell\n\n - \n@apache-mynewt-core/sys/config\n\n - \n@apache-mynewt-core/sys/log/full\n\n - \n@apache-mynewt-core/sys/stats/full\n\n - \n@apache-mynewt-core/libs/baselibc\n\n - libs/my_drivers/senseair\n\n\n\n\n\nAnd add a call to your main() to initialize this driver.\n\n\n [user@IsMyLaptop:~/src/air_quality]$ diff project/blinky/src/main.c project/air_quality/src/main.c\n 28a29\n \n #include \nsenseair/senseair.h\n\n 190a192\n \n senseair_init();\n [user@IsMyLaptop:~/src/air_quality\n\n\n\n\n\nThe ble_prph app runs everything in one task handler. For this project, we're going to add a second\ntask handler t
o respond to the shell, and then handle communicating with the senseair sensor for us.\n\n\n/** shell task settings. */\n\n\n#define SHELL_TASK_PRIO 2\n\n\n#define SHELL_STACK_SIZE (OS_STACK_ALIGN(336))\n\n\n\nstruct\n \nos_eventq\n \nshell_evq\n;\n\nstruct\n \nos_task\n \nshell_task\n;\n\nbssnz_t\n \nos_stack_t\n \nshell_stack\n[\nSHELL_STACK_SIZE\n];\n\n\n\n\n\nThat defines the task, now we need to initialize it, add a task handler, and we're going to \nuse this task as our default task handler.\n\n\n/**\n\n\n * Event loop for the main shell task.\n\n\n */\n\n\nstatic\n \nvoid\n\n\nshell_task_handler\n(\nvoid\n \n*unused\n)\n{\n \nwhile\n (\n1\n) {\n \nos_eventq_run\n(\nshell_evq\n);\n }\n}\n\n\n\n\n\nAnd in your \nmain()\n add:\n\n\n \n/* Initialize shell eventq */\n\n \nos_eventq_init\n(\nshell_evq\n);\n\n \n/* Create the shell task. \n\n\n * All shell operations are performed in this task.\n\n\n */\n\n \nos_task_init\n(\nshel
l_task\n, \nshell\n, \nshell_task_handler\n,\n \nNULL\n, \nSHELL_TASK_PRIO\n, \nOS_WAIT_FOREVER\n,\n \nshell_stack\n, \nSHELL_STACK_SIZE\n);\n\n\n\n\n\nDon't forget to change your default task handler!\n\n\n \nos_eventq_dflt_set\n(\nshell_evq\n);\n\n\n\n\n\nAnd then build it to make sure all goes well.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\nCompiling senseair.c\nArchiving senseair.a\nLinking air_quality.elf\nApp successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf\n\n\n\n\n\nAll looks good.\n\n\nAdd CLI commands for testing drivers\n\n\nWhile 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 \non how to \nenable the CLI\n, so all we'll need to do is add the propper values to the project's \nsyscfg.yml\n file:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat targets/air_q
/syscfg.yml\nsyscfg.vals:\n # Set as per blinky_primo\n OPENOCD_DEBUG: 1\n # Enable the shell task.\n SHELL_TASK: 1\n STATS_CLI: 1\n CONSOLE_TICKS: 1\n CONSOLE_PROMPT: 1\n\n\n\n\n\nThen register your senseair command with the shell by adding the following to \nlibs/my_drivers/senseair/src/senseair.c\n\n\n#include \nshell/shell.h\n\n\n#include \nconsole/console.h\n\n\n#include \nassert.h\n\n\n\n\nstatic\n \nint\n \nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n);\n\nstatic\n \nstruct\n \nshell_cmd\n \nsenseair_cmd\n \n=\n {\n .\nsc_cmd\n \n=\n \nsenseair\n,\n .\nsc_cmd_func\n \n=\n \nsenseair_shell_func\n,\n};\n\n\nvoid\n\n\nsenseair_init\n(\nvoid\n)\n{\n \nint\n \nrc\n;\n\n \nrc\n \n=\n \nshell_cmd_register\n(\nsenseair_cmd\n);\n \nassert\n(\nrc\n \n==\n \n0\n);\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n \nconsole_printf\n(\nYay! Somebody called!\\n\n);\n \nreturn\n \n0\n;\n\n}\
n\n\n\n\n\nNow you can you build this, download to target, and start minicom on your console port. If you haven't already, familiarize yourself with\nthe tutorial on how to connect a serial port to your board \nhere\n.\n\n\nYou'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.\n\n\n [user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2\n\n\n Welcome to minicom 2.7\n\n OPTIONS: \n Compiled on Oct 12 2015, 07:48:30.\n Port /dev/tty.usbserial-AH02MIE2, 13:44:40\n\n Press CTRL-X Z for help on special keys\n\n ?\n 419: \n ?\n Commands:\n 641: stat echo ? prompt ticks tasks\n 643: mempools date senseair\n 644: \n senseair\n Yay! Somebody called!\n 1125: \n\n 53611: \n tasks\n Tasks:\n 54047: task pri tid runtime csw stksz stkuse lcheck ncheck flg\n
54057: idle 255 0 54048 66890 64 30 0 0 0\n 54068: ble_ll 0 1 9 64986 80 58 0 0 0\n 54079: bleprph 1 2 0 1 336 32 0 0 0\n 54090: shell 2 3 0 2077 336 262 0 0 0\n 54101: \n\n\n\n\n\n\nThat's great. Your shell task is running, and is responding appropriately!\nYou can connect the hardware to your board and start developing code for the driver itself.\n\n\nUse of HAL for drivers\n\n\nThe 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.\nWe'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\ncommunicate at 9600 baud, this bit-banged uart is plenty fast enough.\n\n\nYou'll have to make a small change to the \nsyscfg.yml\n file i
n your project's target directory to change the pin definitions \nfor this second UART. Those changes are as follows:\n\n\n UART_0_PIN_TX: 23\n UART_0_PIN_RX: 24\n\n\n\n\n\nWith 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.\n\n\nYou will now see what the driver code ends up looking like. Here's the header file, filled in from the stub you created earlier.\n\n\n/*\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Ap
ache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n * \n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n*/\n\n\n#ifndef _SENSEAIR_H_\n\n\n#define _SENSEAIR_H_\n\n\n\nenum\n \nsenseair_read_type\n {\n \nSENSEAIR_CO2\n,\n};\n\n\nint\n \nsenseair_init\n(\nint\n \nuartno\n);\n\n\nint\n \nsenseair_read\n(\nenum\n \nsenseair_read_type\n);\n\n\n#endif \n/* _SENSEAIR_H_ */\n\n\n\n\n\n\nAs you can see, logical UART number has been added to the init routine. A 'read' function has been added, \nwhich i
s a blocking read. If you were making a commercial product, you would probably have a callback for reporting the results.\n\n\nAnd here is the source for the driver.\n\n\n/**\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n *\n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language gov
erning permissions and limitations\n\n\n * under the License.\n\n\n */\n\n\n#include \nstring.h\n\n\n\n#include \nshell/shell.h\n\n\n#include \nconsole/console.h\n\n\n#include \nos/os.h\n\n\n\n#include \nhal/hal_uart.h\n\n\n\n#include \nsenseair/senseair.h\n\n\n\nstatic\n \nconst\n \nuint8_t\n \ncmd_read_co2\n[] \n=\n {\n \n0xFE\n, \n0\nX44\n, \n0\nX00\n, \n0\nX08\n, \n0\nX02\n, \n0\nX9F\n, \n0\nX25\n\n};\n\n\nstatic\n \nint\n \nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n);\n\nstatic\n \nstruct\n \nshell_cmd\n \nsenseair_cmd\n \n=\n {\n .\nsc_cmd\n \n=\n \nsenseair\n,\n .\nsc_cmd_func\n \n=\n \nsenseair_shell_func\n,\n};\n\n\nstruct\n \nsenseair\n { \n \nint\n \nuart\n;\n \nstruct\n \nos_sem\n \nsema\n;\n \nconst\n \nuint8_t\n \n*tx_data\n;\n \nint\n \ntx_off\n;\n \nint\n \ntx_len\n;\n \nuint8_t\n \nrx_data\n[\n32\n]; \n \nint\n \nrx_off\n;\n \nint\n \nvalue\n;\n} \nsenseair\n;\n\n\nstatic\n \nint\n\n\nsenseair_tx_char\n(\nvoid\n \n*a
rg\n)\n{\n \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n \nint\n \nrc\n;\n\n \nif\n (\ns-\ntx_off\n \n=\n \ns-\ntx_len\n) {\n \n/*\n\n\n * Command tx finished.\n\n\n */\n\n \ns-\ntx_data\n \n=\n \nNULL\n;\n \nreturn\n \n-\n1\n;\n }\n\n \nrc\n \n=\n \ns-\ntx_data\n[\ns-\ntx_off\n];\n \ns-\ntx_off++\n;\n \nreturn\n \nrc\n;\n}\n\n\n/*\n\n\n * CRC for modbus over serial port.\n\n\n */\n\n\nstatic\n \nconst\n \nuint16_t\n \nmb_crc_tbl\n[] \n=\n {\n \n0x0000\n, \n0xcc01\n, \n0xd801\n, \n0x1400\n, \n0xf001\n, \n0x3c00\n, \n0x2800\n, \n0xe401\n,\n \n0xa001\n, \n0x6c00\n, \n0x7800\n, \n0xb401\n, \n0x5000\n, \n0x9c01\n, \n0x8801\n, \n0x4400\n\n};\n\n\nstatic\n \nuint16_t\n\n\nmb_crc\n(\nconst\n \nuint8_t\n \n*data\n, \nint\n \nlen\n, \nuint16_t\n \ncrc\n)\n{\n \nwhile\n (\nlen--\n \n \n0\n) {\n \ncrc\n \n^=\n \n*data++\n;\n \ncrc\n \n=\n (\ncrc\n \n \n4\n) \n^\n \nmb_crc_tbl\n[\ncrc\n \n \n0xf\n];\n \nc
rc\n \n=\n (\ncrc\n \n \n4\n) \n^\n \nmb_crc_tbl\n[\ncrc\n \n \n0xf\n];\n }\n \nreturn\n \ncrc\n;\n}\n\n\nstatic\n \nint\n\n\nmb_crc_check\n(\nconst\n \nvoid\n \n*pkt\n, \nint\n \nlen\n)\n{\n \nuint16_t\n \ncrc\n, \ncmp\n;\n \nuint8_t\n \n*bp\n \n=\n (\nuint8_t\n \n*\n)\npkt\n;\n\n \nif\n (\nlen\n \n \nsizeof\n(\ncrc\n) \n+\n \n1\n) {\n \nreturn\n \n-\n1\n;\n }\n \ncrc\n \n=\n \nmb_crc\n(\npkt\n, \nlen\n \n-\n \n2\n, \n0xffff\n);\n \ncmp\n \n=\n \nbp\n[\nlen\n \n-\n \n2\n] \n|\n (\nbp\n[\nlen\n \n-\n \n1\n] \n \n8\n);\n \nif\n (\ncrc\n \n!=\n \ncmp\n) {\n \nreturn\n \n-\n1\n;\n } \nelse\n {\n \nreturn\n \n0\n;\n }\n}\n\n\nstatic\n \nint\n\n\nsenseair_rx_char\n(\nvoid\n \n*arg\n, \nuint8_t\n \ndata\n)\n{\n \nstruct\n \nsenseair\n \n*s\n \n=\n (\nstruct\n \nsenseair\n \n*\n)\narg\n;\n \nint\n \nrc\n;\n\n \nif\n (\ns-\nrx_off\n \n=\n \nsizeof\n(\ns-\nrx_data\n)) {\n \ns-\nrx_off\n \n=\n \n0\n;\n }\n \ns-\nrx_da
ta\n[\ns-\nrx_off\n] \n=\n \ndata\n;\n \ns-\nrx_off++\n;\n\n \nif\n (\ns-\nrx_off\n \n==\n \n7\n) {\n \nrc\n \n=\n \nmb_crc_check\n(\ns-\nrx_data\n, \ns-\nrx_off\n);\n \nif\n (\nrc\n \n==\n \n0\n) {\n \ns-\nvalue\n \n=\n \ns-\nrx_data\n[\n3\n] \n*\n \n256\n \n+\n \ns-\nrx_data\n[\n4\n];\n \nos_sem_release\n(\ns-\nsema\n);\n }\n }\n \nreturn\n \n0\n;\n}\n\n\nvoid\n\n\nsenseair_tx\n(\nstruct\n \nsenseair\n \n*s\n, \nconst\n \nuint8_t\n \n*tx_data\n, \nint\n \ndata_len\n)\n{\n \ns-\ntx_data\n \n=\n \ntx_data\n;\n \ns-\ntx_len\n \n=\n \ndata_len\n;\n \ns-\ntx_off\n \n=\n \n0\n;\n \ns-\nrx_off\n \n=\n \n0\n;\n\n \nhal_uart_start_tx\n(\ns-\nuart\n);\n}\n\n\nint\n\n\nsenseair_read\n(\nenum\n \nsenseair_read_type\n \ntype\n)\n{\n \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n \nconst\n \nuint8_t\n \n*cmd\n;\n \nint\n \ncmd_len\n;\n \nint\n \nrc\n;\n\n \nif\n (\ns-\ntx_data\n) {\n \n/*\n\n\n
* busy\n\n\n */\n\n \nreturn\n \n-\n1\n;\n }\n \nswitch\n (\ntype\n) {\n \ncase\n \nSENSEAIR_CO2\n:\n \ncmd\n \n=\n \ncmd_read_co2\n;\n \ncmd_len\n \n=\n \nsizeof\n(\ncmd_read_co2\n);\n \nbreak\n;\n \ndefault\n:\n\n \nreturn\n \n-\n1\n;\n }\n \nsenseair_tx\n(\ns\n, \ncmd\n, \ncmd_len\n);\n \nrc\n \n=\n \nos_sem_pend\n(\ns-\nsema\n, \nOS_TICKS_PER_SEC\n \n/\n \n2\n);\n \nif\n (\nrc\n \n==\n \nOS_TIMEOUT\n) {\n \n/*\n\n\n * timeout\n\n\n */\n\n \nreturn\n \n-\n2\n;\n }\n \nreturn\n \ns-\nvalue\n;\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n \nint\n \nvalue\n;\n \nenum\n \nsenseair_read_type\n \ntype\n;\n\n \nif\n (\nargc\n \n \n2\n) {\n\nusage\n:\n \nconsole_printf\n(\n%s co2\\n\n, \nargv\n[\n0\n]);\n \nreturn\n \n0\n;\n }\n \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \nco2\n)) {\n \ntype\n \n=\n \nSEN
SEAIR_CO2\n;\n } \nelse\n {\n \ngoto\n \nusage\n;\n }\n \nvalue\n \n=\n \nsenseair_read\n(\ntype\n);\n \nif\n (\nvalue\n \n=\n \n0\n) {\n \nconsole_printf\n(\nGot %d\\n\n, \nvalue\n);\n } \nelse\n {\n \nconsole_printf\n(\nError while reading: %d\\n\n, \nvalue\n);\n }\n \nreturn\n \n0\n;\n}\n\n\nint\n\n\nsenseair_init\n(\nint\n \nuartno\n)\n{\n \nint\n \nrc\n;\n \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n\n \nrc\n \n=\n \nshell_cmd_register\n(\nsenseair_cmd\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n\n \nrc\n \n=\n \nos_sem_init\n(\ns-\nsema\n, \n1\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n \nrc\n \n=\n \nhal_uart_init_cbs\n(\nuartno\n, \nsenseair_tx_char\n, \nNULL\n,\n \nsenseair_rx_char\n, \nsenseair\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n \nrc\n \n=\n \nhal_uart_config\n(\nuartno\n, \n9600\n, \n8\n, \n1\n, \nHAL_UART_PARITY_NONE\n,\n \nHAL
_UART_FLOW_CTL_NONE\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n \ns-\nuart\n \n=\n \nuartno\n;\n\n \nreturn\n \n0\n;\n}\n\n\n\n\n\nAnd your modified main() for senseair driver init.\n\n\nint\n\n\nmain\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n ....\n \nsenseair_init\n(\n0\n);\n ....\n }\n\n\n\n\n\nYou can see from the code that you are using the HAL interface to open a UART port, and using OS \nsemaphore as a way of blocking the task when waiting for read response to come back from the sensor.\n\n\nNow comes the fun part: Hooking up the sensor! It's fun because a) hooking up a sensor is always \nfun and b) the SenseAir sensor's PCB is entirely unlabeled, so you'll have to trust us on how to hook it up. \n\n\nSo here we go. \n\n\nYou'll have to do a little soldering. I soldered some header pins to the SenseAir K30 board to\nmake connecting wires easier using standard jumper wires, but you can also just solder wires\nstraight to the board if yo
u prefer.\n\n\nHere's what your SenseAir board should look like once it's wired up:\n\n\n\n\nNow that you have that wired up, let's get the Arduino Primo wired up. A couple of things to note:\n\n\n\n\nThe Arduino Primo's 'console' UART is actually UART1. \n\n\nThe secondary (bit-banged) UART is UART0, so that's where we'll have to hook up the SenseAir.\n\n\n\n\nHere's what your Arduino Primo should now look like with everything wired in:\n\n\n\n\nEverything is wired and you're ready to go! Build and load your new app:\n\n\n$ newt build air_q\nBuilding target targets/air_q\nCompiling apps/air_quality/src/main.c\nArchiving apps_air_quality.a\nLinking myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf\nTarget successfully built: targets/air_q\n$ newt create-image air_q 1.0.0\nApp image succesfully generated: myproj/bin/targets/air_q/app/apps/air_quality/air_quality.img\n$ newt load air_q\nLoading app image into slot 1\n\n\n\n\n\nNow, you should be able to connect to your ser
ial port and read values:\n\n\nuser@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2\n\n\n Welcome to minicom 2.7\n\n OPTIONS: \n Compiled on Oct 12 2015, 07:48:30.\n Port /dev/tty.usbserial-AH02MIE2, 13:44:40\n\n Press CTRL-X Z for help on special keys\n\n 1185: \n ?\n Commands:\n 1382: stat echo ? prompt ticks tasks\n 1390: mempools date senseair\n 1395: \n senseair\n senseair co2\n 2143: \n senseair co2\n Got 973\n\n\n\n\n\nAnd you're getting valid readings! Congratulations!\n\n\nNext we'll hook this all up via Bluetooth so that you can read those values remotely.",
+ "text": "Air quality sensor project\n\n\nSetting up source tree for stuff you need\n\n\nTo start with, you need to create a new project under which you will do this development. So you type in:\n\n\n $ mkdir $HOME/src\n $ cd $HOME/src\n $ newt new air_quality\n\n\n\n\n\nLet's say you are using Arduino Primo -- which is based on the Nordic Semi NRF52 chip -- as the platform. \nYou know you need the board support package for that hardware. You can look up its location, add it your \nproject, and fetch that along with the core OS components. Luckily, the Arduino Primo is supported in the \nMynewt Core, so there's nothing much to do here. \n\n\nYour project.yml file should look like this:\n\n\n [user@IsMyLaptop:~/src/air_quality]$ emacs project.yml \n\n [user@IsMyLaptop:~/src/air_quality]$ cat project.yml\n project.name: \nair_quality\n\n\n project.repositories:\n - apache-mynewt-core\n\n # Use github\ns distribution mechanism for core ASF libr
aries.\n # This provides mirroring automatically for us.\n #\n repository.apache-mynewt-core:\n type: github\n vers: 0-latest\n user: apache\n repo: incubator-mynewt-core\n\n [user@IsMyLaptop:~/src/air_quality]$ newt install\n apache-mynewt-core\n [user@IsMyLaptop:~/src/air_quality]$ ls repos/\n apache-mynewt-core\n\n\n\n\n\nGood. You want to make sure you have all the needed bits for supporting your board; \nso you decide to build the blinky project for the platform first.\n\n\nNow 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.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target copy my_blinky_sim blink_primo\nTarget successfully copied; targets/my_blinky_sim --\n targets/blink_primo\n[user@IsMyLaptop:~/src/air_quality]$ newt target set blink_primo bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/blink_nrf succe
ssfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt build blink_primo\nCompiling hal_bsp.c\n...\nLinking blinky.elf\nApp successfully built: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.elf\n\n\n\n\n\nGood.\n\n\nYou know that this platform uses bootloader, which means you have to create a target for that too.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target create boot_primo\nTarget targets/boot_nrf successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target show\n@apache-mynewt-core/targets/unittest\n bsp=hw/bsp/native\n build_profile=debug\n compiler=compiler/sim\ntargets/blink_primo\n app=apps/blinky\n bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n build_profile=debug\ntargets/boot_primo\ntargets/my_blinky_sim\n app=apps/blinky\n bsp=@apache-mynewt-core/hw/bsp/native\n build_profile=debug\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf
bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/boot_nrf successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf app=@apache-mynewt-core/apps/boot\nTarget targets/boot_nrf successfully set target.app to @apache-mynewt-core/apps/boot\n[user@IsMyLaptop:~/src/air_quality]$ newt target set boot_nrf build_profile=optimized\nTarget targets/boot_nrf successfully set target.build_profile to optimized\n\n\n\n\n\nAnd then build it, and load it onto the board.\n\n\nnewt build boot_primo\n....\nLinking boot.elf\nApp successfully built: /Users/user/src/air_quality/bin/boot_primo/apps/boot/boot.elf\n[user@IsMyLaptop:~/src/air_quality]\n$ newt load boot_primo\n\n\n\n\n\nAt this point, you may (or may not) see a bunch of error messages about not being able to connect to\nyour board, not being able to load the image, etc. If that's the case, and you haven't already, you\nshould most definitely go
worth through the \nblinky_primo\n tutorial so that you\ncan properly communicate with your board.\n\n\nNext you must download the targets to board, and see that the LED actually blinks. You plug in the \nArduino Primo board to your laptop, and say:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo\nLoading app image into slot 1\nError: couldn\nt open /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img\n\nError: exit status 1\n\nload - Load app image to target for \ntarget-name\n.\n\nUsage:\n newt load [flags]\n\nExamples:\n newt load \ntarget-name\n\n\n\nGlobal Flags:\n -l, --loglevel string Log level, defaults to WARN. (default \nWARN\n)\n -o, --outfile string Filename to tee log output to\n -q, --quiet Be quiet; only display error output.\n -s, --silent Be silent; don\nt output anything.\n -v, --verbose Enable verbose output when executing commands.\nexit status 1\n\n\n\n\n\nAh. Forgot to create an image ou
t of the blinky binary. Note that every time you want to build and \nload a new firmware image to a target board, you need to run 'create-image' on it.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt create-image blink_primo 0.0.1\nApp image successfully generated: /Users/user/src/air_quality/bin/blink_primo/apps/blinky/blinky.img\nBuild manifest: /Users/user/src/air_quality/bin/blink_nrf/apps/blinky/manifest.json\n[user@IsMyLaptop:~/src/air_quality]$ newt load blink_primo\n\n\n\n\n\nAnd it's blinking.\n\n\nShortcut for doing build/create-image/load/debug steps all in one is 'newt run' command. Check \nout the usage from command line help.\n\n\nCreate test project\n\n\nNow that you have your system setup, you can start creating your own stuff.\nFirst you want to create a project for yourself - you could start by using blinky as a project \ntemplate, but since we're going to want to be able to access the data via Bluetooth, let's \nuse the \nbleprph\n Bluetooth Peripheral project inst
ead.\n\n\n [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality\n [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/bleprph/pkg.yml apps/air_quality/\n [user@IsMyLaptop:~/src/air_quality]$ cp -Rp repos/apache-mynewt-core/apps/bleprph/src apps/air_quality/\n\n\n\n\n\nThen you modify the apps/air_quality/pkg.yml for air_quality in order to change the \npkg.name\n to be \napps/air_quality\n.\nYou'll need to add the \n@apache-mynewt-core/\n path to all the package dependencies, since the app no longer\nresides within the apache-mynewt-core repository.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml\npkg.name: apps/air_quality\npkg.type: app\npkg.description: BLE Air Quality application.\npkg.author: \nApache Mynewt \ndev@mynewt.incubator.apache.org\n\npkg.homepage: \nhttp://mynewt.apache.org/\n\npkg.keywords:\n\npkg.deps: \n - \n@apache-mynewt-core/kernel/os\n\n - \n@apache-mynewt-core/sys/shell\n\n - \n@apache-mynewt-c
ore/sys/stats/full\n\n - \n@apache-mynewt-core/sys/log/full\n\n - \n@apache-mynewt-core/mgmt/newtmgr\n\n - \n@apache-mynewt-core/mgmt/newtmgr/transport/ble\n\n - \n@apache-mynewt-core/net/nimble/controller\n\n - \n@apache-mynewt-core/net/nimble/host\n\n - \n@apache-mynewt-core/net/nimble/host/services/ans\n\n - \n@apache-mynewt-core/net/nimble/host/services/gap\n\n - \n@apache-mynewt-core/net/nimble/host/services/gatt\n\n - \n@apache-mynewt-core/net/nimble/host/store/ram\n\n - \n@apache-mynewt-core/net/nimble/transport/ram\n\n - \n@apache-mynewt-core/sys/console/full\n\n - \n@apache-mynewt-core/sys/sysinit\n\n - \n@apache-mynewt-core/sys/id\n\n\n\n\n\n\nAnd create a target for it:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt target create air_q\nTarget targets/air_q successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/air_q successfully set target.b
sp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q app=apps/air_quality \nTarget targets/air_q successfully set target.app to apps/air_quality\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q build_profile=debug\nTarget targets/air_q successfully set target.build_profile to debug\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\n ....\nLinking /Users/dsimmons/dev/myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf\nTarget successfully built: targets/air_q\n\n\n\n\n\nCreate packages for drivers\n\n\nOne of the sensors you want to enable is SenseAir K30, which will connect to the board over a serial port.\nTo start development of the driver, you first need to create a package description for it, and add stubs for sources.\n\n\nThe first thing to do is to create the directory structure for your driver:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/include/senseair\n[us
er@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/src\n\n\n\n\n\nNow 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.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/pkg.yml\n\n\n\n\n\n#\n\n\n# Licensed to the Apache Software Foundation (ASF) under one\n\n\n# or more contributor license agreements. See the NOTICE file\n\n\n# distributed with this work for additional information\n\n\n# regarding copyright ownership. The ASF licenses this file\n\n\n# to you under the Apache License, Version 2.0 (the\n\n\n# \nLicense\n); you may not use this file except in compliance\n\n\n# with the License. You may obtain a copy of the License at\n\n\n# \n\n\n# http:\n//www.apache.org/licenses/LICENSE-2.0\n\n\n#\n\n\n# Unless required by applicable law or agreed to in writing,\n\n\n# software distributed under the License is distributed on an\n\n\n# \nAS IS\n BASIS, WITHOUT WARRANTIE
S OR CONDITIONS OF ANY\n\n\n# KIND, either express or implied. See the License for the\n\n\n# specific language governing permissions and limitations\n\n\n# under the License.\n\n\n#\n\n\npkg\n.\nname\n: \nlibs/my_drivers/senseair\n\n\npkg\n.\ndescription\n: \nHost\n \nside\n \nof\n \nthe\n \nnimble\n \nBluetooth\n \nSmart\n \nstack\n.\n\npkg\n.\nauthor\n: \nApache Mynewt \ndev@mynewt.incubator.apache.org\n\n\npkg\n.\nhomepage\n: \nhttp://mynewt.apache.org/\n\n\npkg\n.\nkeywords\n:\n \n-\n \nble\n\n \n-\n \nbluetooth\n\n\n\npkg\n.\ndeps\n:\n \n-\n \n@apache-mynewt-core/kernel/os\n\n\n\n\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/include/senseair/senseair.h\n\n\n\n\n\n/*\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you
under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n * \n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n*/\n\n\n#ifndef _SENSEAIR_H_\n\n\n#define _SENSEAIR_H_\n\n\n\nvoid\n \nsenseair_init\n(\nvoid\n);\n\n\n#endif \n/* _SENSEAIR_H_ */\n\n\n\n\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c\n\n\n\n\n\n/**\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * dis
tributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n * \n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n */\n\n\n\nvoid\n\n\nsenseair_init\n(\nvoid\n)\n{\n}\n\n\n\n\n\nAnd add dependency to this package in your project yml file.\n\n\nHere's the listing from apps/air_quality/pkg.yml\n\n\npkg.name: apps/air_quality\npkg.type: app\npkg.description: Air qualit
y sensor test\npkg.keywords:\n\npkg.deps:\n - \n@apache-mynewt-core/libs/console/full\n\n - \n@apache-mynewt-core/libs/newtmgr\n\n - \n@apache-mynewt-core/libs/os\n\n - \n@apache-mynewt-core/libs/shell\n\n - \n@apache-mynewt-core/sys/config\n\n - \n@apache-mynewt-core/sys/log/full\n\n - \n@apache-mynewt-core/sys/stats/full\n\n - libs/my_drivers/senseair\n\n\n\n\n\nAnd add a call to your main() to initialize this driver.\n\n\n [user@IsMyLaptop:~/src/air_quality]$ diff project/blinky/src/main.c project/air_quality/src/main.c\n 28a29\n \n #include \nsenseair/senseair.h\n\n 190a192\n \n senseair_init();\n [user@IsMyLaptop:~/src/air_quality\n\n\n\n\n\nThe ble_prph app runs everything in one task handler. For this project, we're going to add a second\ntask handler to respond to the shell, and then handle communicating with the senseair sensor for us.\n\n\n/** shell task settings. */\n\n\n#define SHELL_TASK_PRIO 2\n\n\n#define SHELL_STACK
_SIZE (OS_STACK_ALIGN(336))\n\n\n\nstruct\n \nos_eventq\n \nshell_evq\n;\n\nstruct\n \nos_task\n \nshell_task\n;\n\nbssnz_t\n \nos_stack_t\n \nshell_stack\n[\nSHELL_STACK_SIZE\n];\n\n\n\n\n\nThat defines the task, now we need to initialize it, add a task handler, and we're going to \nuse this task as our default task handler.\n\n\n/**\n\n\n * Event loop for the main shell task.\n\n\n */\n\n\nstatic\n \nvoid\n\n\nshell_task_handler\n(\nvoid\n \n*unused\n)\n{\n \nwhile\n (\n1\n) {\n \nos_eventq_run\n(\nshell_evq\n);\n }\n}\n\n\n\n\n\nAnd in your \nmain()\n add:\n\n\n \n/* Initialize shell eventq */\n\n \nos_eventq_init\n(\nshell_evq\n);\n\n \n/* Create the shell task. \n\n\n * All shell operations are performed in this task.\n\n\n */\n\n \nos_task_init\n(\nshell_task\n, \nshell\n, \nshell_task_handler\n,\n \nNULL\n, \nSHELL_TASK_PRIO\n, \nOS_WAIT_FOREVER\n,\n \nshell_stack\n, \nSHELL_S
TACK_SIZE\n);\n\n\n\n\n\nDon't forget to change your default task handler!\n\n\n \nos_eventq_dflt_set\n(\nshell_evq\n);\n\n\n\n\n\nAnd then build it to make sure all goes well.\n\n\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\nCompiling senseair.c\nArchiving senseair.a\nLinking air_quality.elf\nApp successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf\n\n\n\n\n\nAll looks good.\n\n\nAdd CLI commands for testing drivers\n\n\nWhile 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 \non how to \nenable the CLI\n, so all we'll need to do is add the propper values to the project's \nsyscfg.yml\n file:\n\n\n[user@IsMyLaptop:~/src/air_quality]$ cat targets/air_q/syscfg.yml\nsyscfg.vals:\n # Set as per blinky_primo\n OPENOCD_DEBUG: 1\n # Enable the shell task.\n SHELL_TASK: 1\n STATS_CLI: 1\n CONSOLE_TICKS: 1\n CONSOLE_PROM
PT: 1\n\n\n\n\n\nThen register your senseair command with the shell by adding the following to \nlibs/my_drivers/senseair/src/senseair.c\n\n\n#include \nshell/shell.h\n\n\n#include \nconsole/console.h\n\n\n#include \nassert.h\n\n\n\n\nstatic\n \nint\n \nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n);\n\nstatic\n \nstruct\n \nshell_cmd\n \nsenseair_cmd\n \n=\n {\n .\nsc_cmd\n \n=\n \nsenseair\n,\n .\nsc_cmd_func\n \n=\n \nsenseair_shell_func\n,\n};\n\n\nvoid\n\n\nsenseair_init\n(\nvoid\n)\n{\n \nint\n \nrc\n;\n\n \nrc\n \n=\n \nshell_cmd_register\n(\nsenseair_cmd\n);\n \nassert\n(\nrc\n \n==\n \n0\n);\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n \nconsole_printf\n(\nYay! Somebody called!\\n\n);\n \nreturn\n \n0\n;\n\n}\n\n\n\n\n\nNow you can you build this, download to target, and start minicom on your console port. If you haven't already, familiarize yourself with\nthe tutorial on how to connect a se
rial port to your board \nhere\n.\n\n\nYou'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.\n\n\n [user@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2\n\n\n Welcome to minicom 2.7\n\n OPTIONS: \n Compiled on Oct 12 2015, 07:48:30.\n Port /dev/tty.usbserial-AH02MIE2, 13:44:40\n\n Press CTRL-X Z for help on special keys\n\n ?\n 419: \n ?\n Commands:\n 641: stat echo ? prompt ticks tasks\n 643: mempools date senseair\n 644: \n senseair\n Yay! Somebody called!\n 1125: \n\n 53611: \n tasks\n Tasks:\n 54047: task pri tid runtime csw stksz stkuse lcheck ncheck flg\n 54057: idle 255 0 54048 66890 64 30 0 0 0\n 54068: ble_ll 0 1 9 64986 80 58 0 0 0\n 54079: bl
eprph 1 2 0 1 336 32 0 0 0\n 54090: shell 2 3 0 2077 336 262 0 0 0\n 54101: \n\n\n\n\n\n\nThat's great. Your shell task is running, and is responding appropriately!\nYou can connect the hardware to your board and start developing code for the driver itself.\n\n\nUse of HAL for drivers\n\n\nThe 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.\nWe'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\ncommunicate at 9600 baud, this bit-banged uart is plenty fast enough.\n\n\nYou'll have to make a small change to the \nsyscfg.yml\n file in your project's target directory to change the pin definitions \nfor this second UART. Those changes are as follows:\n\n\n UART_0_PIN_TX: 23\n UART_0_PIN_RX: 24\n\n\n\n\n\nWith
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.\n\n\nYou will now see what the driver code ends up looking like. Here's the header file, filled in from the stub you created earlier.\n\n\n/*\n\n\n * Licensed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n * \n\n\n *
http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n*/\n\n\n#ifndef _SENSEAIR_H_\n\n\n#define _SENSEAIR_H_\n\n\n\nenum\n \nsenseair_read_type\n {\n \nSENSEAIR_CO2\n,\n};\n\n\nint\n \nsenseair_init\n(\nint\n \nuartno\n);\n\n\nint\n \nsenseair_read\n(\nenum\n \nsenseair_read_type\n);\n\n\n#endif \n/* _SENSEAIR_H_ */\n\n\n\n\n\n\nAs you can see, logical UART number has been added to the init routine. A 'read' function has been added, \nwhich is a blocking read. If you were making a commercial product, you would probably have a callback for reporting the results.\n\n\nAnd here is the source for the driver.\n\n\n/**\n\n\n * Li
censed to the Apache Software Foundation (ASF) under one\n\n\n * or more contributor license agreements. See the NOTICE file\n\n\n * distributed with this work for additional information\n\n\n * regarding copyright ownership. The ASF licenses this file\n\n\n * to you under the Apache License, Version 2.0 (the\n\n\n * \nLicense\n); you may not use this file except in compliance\n\n\n * with the License. You may obtain a copy of the License at\n\n\n *\n\n\n * http://www.apache.org/licenses/LICENSE-2.0\n\n\n *\n\n\n * Unless required by applicable law or agreed to in writing,\n\n\n * software distributed under the License is distributed on an\n\n\n * \nAS IS\n BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n\n\n * KIND, either express or implied. See the License for the\n\n\n * specific language governing permissions and limitations\n\n\n * under the License.\n\n\n */\n\n\n#include \nstring.h\n\n\n\n#include \nshell/shell.h\n\n\n#include \nconsole/console.h\n\n\n#include \nos/os.h
\n\n\n\n#include \nhal/hal_uart.h\n\n\n\n#include \nsenseair/senseair.h\n\n\n\nstatic\n \nconst\n \nuint8_t\n \ncmd_read_co2\n[] \n=\n {\n \n0xFE\n, \n0\nX44\n, \n0\nX00\n, \n0\nX08\n, \n0\nX02\n, \n0\nX9F\n, \n0\nX25\n\n};\n\n\nstatic\n \nint\n \nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n);\n\nstatic\n \nstruct\n \nshell_cmd\n \nsenseair_cmd\n \n=\n {\n .\nsc_cmd\n \n=\n \nsenseair\n,\n .\nsc_cmd_func\n \n=\n \nsenseair_shell_func\n,\n};\n\n\nstruct\n \nsenseair\n { \n \nint\n \nuart\n;\n \nstruct\n \nos_sem\n \nsema\n;\n \nconst\n \nuint8_t\n \n*tx_data\n;\n \nint\n \ntx_off\n;\n \nint\n \ntx_len\n;\n \nuint8_t\n \nrx_data\n[\n32\n]; \n \nint\n \nrx_off\n;\n \nint\n \nvalue\n;\n} \nsenseair\n;\n\n\nstatic\n \nint\n\n\nsenseair_tx_char\n(\nvoid\n \n*arg\n)\n{\n \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n \nint\n \nrc\n;\n\n \nif\n (\ns-\ntx_off\n \n=\n \ns-\ntx_len\n) {\n \n/*\n\n\n * Command tx finished
.\n\n\n */\n\n \ns-\ntx_data\n \n=\n \nNULL\n;\n \nreturn\n \n-\n1\n;\n }\n\n \nrc\n \n=\n \ns-\ntx_data\n[\ns-\ntx_off\n];\n \ns-\ntx_off++\n;\n \nreturn\n \nrc\n;\n}\n\n\n/*\n\n\n * CRC for modbus over serial port.\n\n\n */\n\n\nstatic\n \nconst\n \nuint16_t\n \nmb_crc_tbl\n[] \n=\n {\n \n0x0000\n, \n0xcc01\n, \n0xd801\n, \n0x1400\n, \n0xf001\n, \n0x3c00\n, \n0x2800\n, \n0xe401\n,\n \n0xa001\n, \n0x6c00\n, \n0x7800\n, \n0xb401\n, \n0x5000\n, \n0x9c01\n, \n0x8801\n, \n0x4400\n\n};\n\n\nstatic\n \nuint16_t\n\n\nmb_crc\n(\nconst\n \nuint8_t\n \n*data\n, \nint\n \nlen\n, \nuint16_t\n \ncrc\n)\n{\n \nwhile\n (\nlen--\n \n \n0\n) {\n \ncrc\n \n^=\n \n*data++\n;\n \ncrc\n \n=\n (\ncrc\n \n \n4\n) \n^\n \nmb_crc_tbl\n[\ncrc\n \n \n0xf\n];\n \ncrc\n \n=\n (\ncrc\n \n \n4\n) \n^\n \nmb_crc_tbl\n[\ncrc\n \n \n0xf\n];\n }\n \nreturn\n \ncrc\n;\n}\n\n\nstatic\n \nint\n\n\nmb_crc_check\n(\nconst\n \nvoid\n \n*pkt\n, \nint\n \
nlen\n)\n{\n \nuint16_t\n \ncrc\n, \ncmp\n;\n \nuint8_t\n \n*bp\n \n=\n (\nuint8_t\n \n*\n)\npkt\n;\n\n \nif\n (\nlen\n \n \nsizeof\n(\ncrc\n) \n+\n \n1\n) {\n \nreturn\n \n-\n1\n;\n }\n \ncrc\n \n=\n \nmb_crc\n(\npkt\n, \nlen\n \n-\n \n2\n, \n0xffff\n);\n \ncmp\n \n=\n \nbp\n[\nlen\n \n-\n \n2\n] \n|\n (\nbp\n[\nlen\n \n-\n \n1\n] \n \n8\n);\n \nif\n (\ncrc\n \n!=\n \ncmp\n) {\n \nreturn\n \n-\n1\n;\n } \nelse\n {\n \nreturn\n \n0\n;\n }\n}\n\n\nstatic\n \nint\n\n\nsenseair_rx_char\n(\nvoid\n \n*arg\n, \nuint8_t\n \ndata\n)\n{\n \nstruct\n \nsenseair\n \n*s\n \n=\n (\nstruct\n \nsenseair\n \n*\n)\narg\n;\n \nint\n \nrc\n;\n\n \nif\n (\ns-\nrx_off\n \n=\n \nsizeof\n(\ns-\nrx_data\n)) {\n \ns-\nrx_off\n \n=\n \n0\n;\n }\n \ns-\nrx_data\n[\ns-\nrx_off\n] \n=\n \ndata\n;\n \ns-\nrx_off++\n;\n\n \nif\n (\ns-\nrx_off\n \n==\n \n7\n) {\n \nrc\n \n=\n \nmb_crc_check\n(\ns-\nrx_data\n, \ns-\nrx_off\n);\n
\nif\n (\nrc\n \n==\n \n0\n) {\n \ns-\nvalue\n \n=\n \ns-\nrx_data\n[\n3\n] \n*\n \n256\n \n+\n \ns-\nrx_data\n[\n4\n];\n \nos_sem_release\n(\ns-\nsema\n);\n }\n }\n \nreturn\n \n0\n;\n}\n\n\nvoid\n\n\nsenseair_tx\n(\nstruct\n \nsenseair\n \n*s\n, \nconst\n \nuint8_t\n \n*tx_data\n, \nint\n \ndata_len\n)\n{\n \ns-\ntx_data\n \n=\n \ntx_data\n;\n \ns-\ntx_len\n \n=\n \ndata_len\n;\n \ns-\ntx_off\n \n=\n \n0\n;\n \ns-\nrx_off\n \n=\n \n0\n;\n\n \nhal_uart_start_tx\n(\ns-\nuart\n);\n}\n\n\nint\n\n\nsenseair_read\n(\nenum\n \nsenseair_read_type\n \ntype\n)\n{\n \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n \nconst\n \nuint8_t\n \n*cmd\n;\n \nint\n \ncmd_len\n;\n \nint\n \nrc\n;\n\n \nif\n (\ns-\ntx_data\n) {\n \n/*\n\n\n * busy\n\n\n */\n\n \nreturn\n \n-\n1\n;\n }\n \nswitch\n (\ntype\n) {\n \ncase\n \nSENSEAIR_CO2\n:\n \ncmd\n \n=\n \ncmd_read_co2\n;\n \ncmd_
len\n \n=\n \nsizeof\n(\ncmd_read_co2\n);\n \nbreak\n;\n \ndefault\n:\n\n \nreturn\n \n-\n1\n;\n }\n \nsenseair_tx\n(\ns\n, \ncmd\n, \ncmd_len\n);\n \nrc\n \n=\n \nos_sem_pend\n(\ns-\nsema\n, \nOS_TICKS_PER_SEC\n \n/\n \n2\n);\n \nif\n (\nrc\n \n==\n \nOS_TIMEOUT\n) {\n \n/*\n\n\n * timeout\n\n\n */\n\n \nreturn\n \n-\n2\n;\n }\n \nreturn\n \ns-\nvalue\n;\n}\n\n\nstatic\n \nint\n\n\nsenseair_shell_func\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n \nint\n \nvalue\n;\n \nenum\n \nsenseair_read_type\n \ntype\n;\n\n \nif\n (\nargc\n \n \n2\n) {\n\nusage\n:\n \nconsole_printf\n(\n%s co2\\n\n, \nargv\n[\n0\n]);\n \nreturn\n \n0\n;\n }\n \nif\n (\n!strcmp\n(\nargv\n[\n1\n], \nco2\n)) {\n \ntype\n \n=\n \nSENSEAIR_CO2\n;\n } \nelse\n {\n \ngoto\n \nusage\n;\n }\n \nvalue\n \n=\n \nsenseair_read\n(\ntype\n);\n \nif\n (\nvalue\n \n=\n \n0\n) {\n \nconsole_printf\n(\n
Got %d\\n\n, \nvalue\n);\n } \nelse\n {\n \nconsole_printf\n(\nError while reading: %d\\n\n, \nvalue\n);\n }\n \nreturn\n \n0\n;\n}\n\n\nint\n\n\nsenseair_init\n(\nint\n \nuartno\n)\n{\n \nint\n \nrc\n;\n \nstruct\n \nsenseair\n \n*s\n \n=\n \nsenseair\n;\n\n \nrc\n \n=\n \nshell_cmd_register\n(\nsenseair_cmd\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n\n \nrc\n \n=\n \nos_sem_init\n(\ns-\nsema\n, \n1\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n \nrc\n \n=\n \nhal_uart_init_cbs\n(\nuartno\n, \nsenseair_tx_char\n, \nNULL\n,\n \nsenseair_rx_char\n, \nsenseair\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n \nrc\n \n=\n \nhal_uart_config\n(\nuartno\n, \n9600\n, \n8\n, \n1\n, \nHAL_UART_PARITY_NONE\n,\n \nHAL_UART_FLOW_CTL_NONE\n);\n \nif\n (\nrc\n) {\n \nreturn\n \nrc\n;\n }\n \ns-\nuart\n \n=\n \nuartno\n;\n\n \nreturn\n \n0\n;\n}\n\n\n\n\n\nAnd your modified main() for
senseair driver init.\n\n\nint\n\n\nmain\n(\nint\n \nargc\n, \nchar\n \n**argv\n)\n{\n ....\n \nsenseair_init\n(\n0\n);\n ....\n }\n\n\n\n\n\nYou can see from the code that you are using the HAL interface to open a UART port, and using OS \nsemaphore as a way of blocking the task when waiting for read response to come back from the sensor.\n\n\nNow comes the fun part: Hooking up the sensor! It's fun because a) hooking up a sensor is always \nfun and b) the SenseAir sensor's PCB is entirely unlabeled, so you'll have to trust us on how to hook it up. \n\n\nSo here we go. \n\n\nYou'll have to do a little soldering. I soldered some header pins to the SenseAir K30 board to\nmake connecting wires easier using standard jumper wires, but you can also just solder wires\nstraight to the board if you prefer.\n\n\nHere's what your SenseAir board should look like once it's wired up:\n\n\n\n\nNow that you have that wired up, let's get the Arduino Primo wired up. A couple of things to
note:\n\n\n\n\nThe Arduino Primo's 'console' UART is actually UART1. \n\n\nThe secondary (bit-banged) UART is UART0, so that's where we'll have to hook up the SenseAir.\n\n\n\n\nHere's what your Arduino Primo should now look like with everything wired in:\n\n\n\n\nEverything is wired and you're ready to go! Build and load your new app:\n\n\n$ newt build air_q\nBuilding target targets/air_q\nCompiling apps/air_quality/src/main.c\nArchiving apps_air_quality.a\nLinking myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf\nTarget successfully built: targets/air_q\n$ newt create-image air_q 1.0.0\nApp image succesfully generated: myproj/bin/targets/air_q/app/apps/air_quality/air_quality.img\n$ newt load air_q\nLoading app image into slot 1\n\n\n\n\n\nNow, you should be able to connect to your serial port and read values:\n\n\nuser@IsMyLaptop:~]$ minicom -D /dev/tty.usbserial-AH02MIE2\n\n\n Welcome to minicom 2.7\n\n OPTIONS: \n Compiled on Oct 12 2015, 07:48:30.\n P
ort /dev/tty.usbserial-AH02MIE2, 13:44:40\n\n Press CTRL-X Z for help on special keys\n\n 1185: \n ?\n Commands:\n 1382: stat echo ? prompt ticks tasks\n 1390: mempools date senseair\n 1395: \n senseair\n senseair co2\n 2143: \n senseair co2\n Got 973\n\n\n\n\n\nAnd you're getting valid readings! Congratulations!\n\n\nNext we'll hook this all up via Bluetooth so that you can read those values remotely.",
"title": "Basic Air Quality Sensor"
},
{
@@ -1282,12 +1282,12 @@
},
{
"location": "/os/tutorials/air_quality_sensor/#create-test-project",
- "text": "Now that you have your system setup, you can start creating your own stuff.\nFirst you want to create a project for yourself - you could start by using blinky as a project \ntemplate, but since we're going to want to be able to access the data via Bluetooth, let's \nuse the bleprph Bluetooth Peripheral project instead. [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality\n [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/bleprph/pkg.yml apps/air_quality/\n [user@IsMyLaptop:~/src/air_quality]$ cp -Rp repos/apache-mynewt-core/apps/bleprph/src apps/air_quality/ Then you modify the apps/air_quality/pkg.yml for air_quality in order to change the pkg.name to be apps/air_quality .\nYou'll need to add the @apache-mynewt-core/ path to all the package dependencies, since the app no longer\nresides within the apache-mynewt-core repository. The Arduino Primo board has a limited amount of memory, so you must also switch your li
bc to be baselibc, instead of the standard one. [user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml\npkg.name: apps/air_quality\npkg.type: app\npkg.description: BLE Air Quality application.\npkg.author: Apache Mynewt dev@mynewt.incubator.apache.org \npkg.homepage: http://mynewt.apache.org/ \npkg.keywords:\n\npkg.deps: \n - @apache-mynewt-core/kernel/os \n - @apache-mynewt-core/sys/shell \n - @apache-mynewt-core/sys/stats/full \n - @apache-mynewt-core/sys/log/full \n - @apache-mynewt-core/mgmt/newtmgr \n - @apache-mynewt-core/mgmt/newtmgr/transport/ble \n - @apache-mynewt-core/net/nimble/controller \n - @apache-mynewt-core/net/nimble/host \n - @apache-mynewt-core/net/nimble/host/services/ans \n - @apache-mynewt-core/net/nimble/host/services/gap \n - @apache-mynewt-core/net/nimble/host/services/gatt \n - @apache-mynewt-core/net/nimble/host/store/ram \n - @apache-mynewt-core/net/nimble/transport/ram \n - @apache-
mynewt-core/sys/console/full \n - @apache-mynewt-core/sys/sysinit \n - @apache-mynewt-core/sys/id And create a target for it: [user@IsMyLaptop:~/src/air_quality]$ newt target create air_q\nTarget targets/air_q successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/air_q successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q app=apps/air_quality \nTarget targets/air_q successfully set target.app to apps/air_quality\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q build_profile=debug\nTarget targets/air_q successfully set target.build_profile to debug\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\n ....\nLinking /Users/dsimmons/dev/myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf\nTarget successfully built: targets/air_q",
+ "text": "Now that you have your system setup, you can start creating your own stuff.\nFirst you want to create a project for yourself - you could start by using blinky as a project \ntemplate, but since we're going to want to be able to access the data via Bluetooth, let's \nuse the bleprph Bluetooth Peripheral project instead. [user@IsMyLaptop:~/src/air_quality]$ mkdir apps/air_quality\n [user@IsMyLaptop:~/src/air_quality]$ cp repos/apache-mynewt-core/apps/bleprph/pkg.yml apps/air_quality/\n [user@IsMyLaptop:~/src/air_quality]$ cp -Rp repos/apache-mynewt-core/apps/bleprph/src apps/air_quality/ Then you modify the apps/air_quality/pkg.yml for air_quality in order to change the pkg.name to be apps/air_quality .\nYou'll need to add the @apache-mynewt-core/ path to all the package dependencies, since the app no longer\nresides within the apache-mynewt-core repository. [user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml\npkg.name: apps/air_q
uality\npkg.type: app\npkg.description: BLE Air Quality application.\npkg.author: Apache Mynewt dev@mynewt.incubator.apache.org \npkg.homepage: http://mynewt.apache.org/ \npkg.keywords:\n\npkg.deps: \n - @apache-mynewt-core/kernel/os \n - @apache-mynewt-core/sys/shell \n - @apache-mynewt-core/sys/stats/full \n - @apache-mynewt-core/sys/log/full \n - @apache-mynewt-core/mgmt/newtmgr \n - @apache-mynewt-core/mgmt/newtmgr/transport/ble \n - @apache-mynewt-core/net/nimble/controller \n - @apache-mynewt-core/net/nimble/host \n - @apache-mynewt-core/net/nimble/host/services/ans \n - @apache-mynewt-core/net/nimble/host/services/gap \n - @apache-mynewt-core/net/nimble/host/services/gatt \n - @apache-mynewt-core/net/nimble/host/store/ram \n - @apache-mynewt-core/net/nimble/transport/ram \n - @apache-mynewt-core/sys/console/full \n - @apache-mynewt-core/sys/sysinit \n - @apache-mynewt-core/sys/id And create a target for it:
[user@IsMyLaptop:~/src/air_quality]$ newt target create air_q\nTarget targets/air_q successfully created\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q bsp=@apache-mynewt-core/hw/bsp/arduino_primo_nrf52\nTarget targets/air_q successfully set target.bsp to @apache-mynewt-core/hw/bsp/arduino_primo_nrf52\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q app=apps/air_quality \nTarget targets/air_q successfully set target.app to apps/air_quality\n[user@IsMyLaptop:~/src/air_quality]$ newt target set air_q build_profile=debug\nTarget targets/air_q successfully set target.build_profile to debug\n[user@IsMyLaptop:~/src/air_quality]$ newt build air_q\n ....\nLinking /Users/dsimmons/dev/myproj/bin/targets/air_q/app/apps/air_quality/air_quality.elf\nTarget successfully built: targets/air_q",
"title": "Create test project"
},
{
"location": "/os/tutorials/air_quality_sensor/#create-packages-for-drivers",
- "text": "One of the sensors you want to enable is SenseAir K30, which will connect to the board over a serial port.\nTo start development of the driver, you first need to create a package description for it, and add stubs for sources. The first thing to do is to create the directory structure for your driver: [user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/include/senseair\n[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/src 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. [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/pkg.yml # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the #
License ); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http: //www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # pkg . name : libs/my_drivers/senseair pkg . description : Host side of the nimble Bluetooth Smart stack . pkg . author : Apache Mynewt dev@mynewt.incubator.apache.org pkg . homepage : http://mynewt.apache.org/ pkg . keywords :\n - ble \n - bluetooth pkg . deps :\n - @apache-mynewt-core/kernel/os [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/include/senseair/senseair.h /* * Licensed to the Apache Software Foundation (ASF) u
nder one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * License ); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _SENSEAIR_H_ #define _SENSEAIR_H_ void senseair_init ( void ); #endif /* _SENSEAIR_H_ */ [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c /** * Licensed to the Apache Software Fou
ndation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * License ); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ void senseair_init ( void )\n{\n} And add dependency to this package in your project yml file. Here's the listing from apps/air_quality/pkg.yml pkg.name: apps/air_quality\npkg.type: app\npkg.description: Air q
uality sensor test\npkg.keywords:\n\npkg.deps:\n - @apache-mynewt-core/libs/console/full \n - @apache-mynewt-core/libs/newtmgr \n - @apache-mynewt-core/libs/os \n - @apache-mynewt-core/libs/shell \n - @apache-mynewt-core/sys/config \n - @apache-mynewt-core/sys/log/full \n - @apache-mynewt-core/sys/stats/full \n - @apache-mynewt-core/libs/baselibc \n - libs/my_drivers/senseair And add a call to your main() to initialize this driver. [user@IsMyLaptop:~/src/air_quality]$ diff project/blinky/src/main.c project/air_quality/src/main.c\n 28a29\n #include senseair/senseair.h \n 190a192\n senseair_init();\n [user@IsMyLaptop:~/src/air_quality The ble_prph app runs everything in one task handler. For this project, we're going to add a second\ntask handler to respond to the shell, and then handle communicating with the senseair sensor for us. /** shell task settings. */ #define SHELL_TASK_PRIO 2 #define SHELL_STACK_SIZE
(OS_STACK_ALIGN(336)) struct os_eventq shell_evq ; struct os_task shell_task ; bssnz_t os_stack_t shell_stack [ SHELL_STACK_SIZE ]; That defines the task, now we need to initialize it, add a task handler, and we're going to \nuse this task as our default task handler. /** * Event loop for the main shell task. */ static void shell_task_handler ( void *unused )\n{\n while ( 1 ) {\n os_eventq_run ( shell_evq );\n }\n} And in your main() add: /* Initialize shell eventq */ \n os_eventq_init ( shell_evq );\n\n /* Create the shell task. * All shell operations are performed in this task. */ \n os_task_init ( shell_task , shell , shell_task_handler ,\n NULL , SHELL_TASK_PRIO , OS_WAIT_FOREVER ,\n shell_stack , SHELL_STACK_SIZE ); Don't forget to change your default task handler! os_eventq_dflt_set ( shell_evq ); And then build it to mak
e sure all goes well. [user@IsMyLaptop:~/src/air_quality]$ newt build air_q\nCompiling senseair.c\nArchiving senseair.a\nLinking air_quality.elf\nApp successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf All looks good.",
+ "text": "One of the sensors you want to enable is SenseAir K30, which will connect to the board over a serial port.\nTo start development of the driver, you first need to create a package description for it, and add stubs for sources. The first thing to do is to create the directory structure for your driver: [user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/include/senseair\n[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/senseair/src 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. [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/pkg.yml # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the #
License ); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http: //www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # pkg . name : libs/my_drivers/senseair pkg . description : Host side of the nimble Bluetooth Smart stack . pkg . author : Apache Mynewt dev@mynewt.incubator.apache.org pkg . homepage : http://mynewt.apache.org/ pkg . keywords :\n - ble \n - bluetooth pkg . deps :\n - @apache-mynewt-core/kernel/os [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/include/senseair/senseair.h /* * Licensed to the Apache Software Foundation (ASF) u
nder one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * License ); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _SENSEAIR_H_ #define _SENSEAIR_H_ void senseair_init ( void ); #endif /* _SENSEAIR_H_ */ [user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/senseair/src/senseair.c /** * Licensed to the Apache Software Fou
ndation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * License ); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ void senseair_init ( void )\n{\n} And add dependency to this package in your project yml file. Here's the listing from apps/air_quality/pkg.yml pkg.name: apps/air_quality\npkg.type: app\npkg.description: Air q
uality sensor test\npkg.keywords:\n\npkg.deps:\n - @apache-mynewt-core/libs/console/full \n - @apache-mynewt-core/libs/newtmgr \n - @apache-mynewt-core/libs/os \n - @apache-mynewt-core/libs/shell \n - @apache-mynewt-core/sys/config \n - @apache-mynewt-core/sys/log/full \n - @apache-mynewt-core/sys/stats/full \n - libs/my_drivers/senseair And add a call to your main() to initialize this driver. [user@IsMyLaptop:~/src/air_quality]$ diff project/blinky/src/main.c project/air_quality/src/main.c\n 28a29\n #include senseair/senseair.h \n 190a192\n senseair_init();\n [user@IsMyLaptop:~/src/air_quality The ble_prph app runs everything in one task handler. For this project, we're going to add a second\ntask handler to respond to the shell, and then handle communicating with the senseair sensor for us. /** shell task settings. */ #define SHELL_TASK_PRIO 2 #define SHELL_STACK_SIZE (OS_STACK_ALIGN(336)) struct os
_eventq shell_evq ; struct os_task shell_task ; bssnz_t os_stack_t shell_stack [ SHELL_STACK_SIZE ]; That defines the task, now we need to initialize it, add a task handler, and we're going to \nuse this task as our default task handler. /** * Event loop for the main shell task. */ static void shell_task_handler ( void *unused )\n{\n while ( 1 ) {\n os_eventq_run ( shell_evq );\n }\n} And in your main() add: /* Initialize shell eventq */ \n os_eventq_init ( shell_evq );\n\n /* Create the shell task. * All shell operations are performed in this task. */ \n os_task_init ( shell_task , shell , shell_task_handler ,\n NULL , SHELL_TASK_PRIO , OS_WAIT_FOREVER ,\n shell_stack , SHELL_STACK_SIZE ); Don't forget to change your default task handler! os_eventq_dflt_set ( shell_evq ); And then build it to make sure all goes well. [user@IsMyLaptop:~/s
rc/air_quality]$ newt build air_q\nCompiling senseair.c\nArchiving senseair.a\nLinking air_quality.elf\nApp successfully built: /Users/user/src/air_quality/bin/air_q/apps/air_quality/air_quality.elf All looks good.",
"title": "Create packages for drivers"
},
{
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/b381d55c/develop/os/tutorials/air_quality_sensor/index.html
----------------------------------------------------------------------
diff --git a/develop/os/tutorials/air_quality_sensor/index.html b/develop/os/tutorials/air_quality_sensor/index.html
index f3473ba..4e4a906 100644
--- a/develop/os/tutorials/air_quality_sensor/index.html
+++ b/develop/os/tutorials/air_quality_sensor/index.html
@@ -625,7 +625,6 @@ use the <code>bleprph</code> Bluetooth Peripheral project instead.</p>
<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>
-<p>The Arduino Primo board has a limited amount of memory, so you must also switch your libc to be baselibc, instead of the standard one.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%">[user@IsMyLaptop:~/src/air_quality]$ cat apps/air_quality/pkg.yml
pkg.name: apps/air_quality
pkg.type: app
@@ -791,7 +790,6 @@ pkg.deps:
- "@apache-mynewt-core/sys/config"
- "@apache-mynewt-core/sys/log/full"
- "@apache-mynewt-core/sys/stats/full"
- - "@apache-mynewt-core/libs/baselibc"
- libs/my_drivers/senseair
</pre></div>