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/16 05:50:57 UTC

[1/5] incubator-mynewt-site git commit: New ADC tutorial for Beta Release

Repository: incubator-mynewt-site
Updated Branches:
  refs/heads/develop c28a73bbe -> eceb15e72


New ADC tutorial for Beta Release


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/9183cab3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/tree/9183cab3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/diff/9183cab3

Branch: refs/heads/develop
Commit: 9183cab35577afac9773b242a867a4652a585ebf
Parents: 307f05a
Author: David G. Simmons <sa...@mac.com>
Authored: Wed Feb 8 12:35:56 2017 -0500
Committer: David G. Simmons <sa...@mac.com>
Committed: Wed Feb 8 12:35:56 2017 -0500

----------------------------------------------------------------------
 docs/os/tutorials/nrf52_adc.md                  | 658 +++++++++++++++++++
 .../os/tutorials/pics/MyNewtSensorReader006.jpg | Bin 0 -> 211399 bytes
 mkdocs.yml                                      |   1 +
 3 files changed, 659 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/9183cab3/docs/os/tutorials/nrf52_adc.md
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/nrf52_adc.md b/docs/os/tutorials/nrf52_adc.md
new file mode 100644
index 0000000..4d3009b
--- /dev/null
+++ b/docs/os/tutorials/nrf52_adc.md
@@ -0,0 +1,658 @@
+## Adding an Analog Sensor on nRF52
+
+<br>
+
+### Objective
+
+We will be adding an analog sensor to the NRF52DK development board and using the Analog to Digital Converter
+(ADC) to read the values from the sensor. It's also using Bluetooth to allow you to connect to the app and
+read the value of the sensor. Please see the following section for the required hardware
+in order to complete this tutorial.
+
+<br>
+
+### Hardware needed
+
+* nRF52 Development Kit (one of the following)
+    * Dev Kit from Nordic - PCA 10040
+    * Eval Kit from Rigado - BMD-300-EVAL-ES
+* eTape Liquid Sensor -- buy from [Adafruit](https://www.adafruit.com/products/1786)
+* Laptop running Mac OS
+* It is assumed you have already installed newt tool. 
+* It is assumed you already installed native tools as described [here](../get_started/native_tools.md)
+
+<br>
+
+### Create a project.  
+
+Create a new project to hold your work.  For a deeper understanding, you can read about project creation in 
+[Get Started -- Creating Your First Project](../get_started/project_create.md)
+or just follow the commands below.
+
+```
+    $ mkdir ~/dev
+    $ cd ~/dev
+    $ newt new myadc
+    Downloading project skeleton from apache/incubator-mynewt-blinky...
+    Installing skeleton in myadc...
+    Project myadc successfully created.
+    $ cd myadc
+    
+``` 
+
+<br>
+
+###Add Additional Repositories
+
+The board-specific libraries for the NRF52dk board are in an external repository at present, so
+you'll need to include that remote repository and install it as well. If you're not familiar
+with using repositories, see the section on [repositories](repo/add_repos.md) before
+continuiing. Or just copy and paste the following.
+
+In your `project.yml` file, add `- mynewt_nordic` to the `project.repositories` section, and 
+then add the proper repository definition. When you're done, your `project.yml` file
+should look like this:
+
+```
+project.name: "my_project"
+
+project.repositories:
+    - apache-mynewt-core
+    - mynewt_nordic
+
+# Use github's distribution mechanism for core ASF libraries.
+# This provides mirroring automatically for us.
+#
+repository.apache-mynewt-core:
+    type: github
+    vers: 0-dev
+    user: apache
+    repo: incubator-mynewt-core
+repository.mynewt_nordic:
+    type: github
+    vers: 0-latest
+    user: runtimeinc
+    repo: mynewt_nordic
+```
+
+<br>
+
+###Install Everything
+
+Now that you have defined the needed repositories, it's time to install everything so
+that you can get started.
+
+```
+    $ newt install -v 
+    apache-mynewt-core
+    Downloading repository description for apache-mynewt-core... success!
+    ...
+    apache-mynewt-core successfully installed version 0.9.0-none
+    ...
+    mynewt_nordic
+    Downloading repository description for mynewt_nordic... success!
+    ...
+    mynewt_nordic successfully installed version 0.9.9-none
+```
+
+<br>
+
+### Create the targets
+
+Create two targets - one for the bootloader and one for the nrf52 board.  
+
+<font color="#F2853F">
+Note: The correct bsp must be chosen for the board you are using. </font>
+
+* For the Nordic Dev Kit choose @apache-mynewt-core/hw/bsp/nrf52dk instead (in the highlighted lines)
+* For the Rigado Eval Kit choose @apache-mynewt-core/hw/bsp/bmd300eval instead (in the highlighted lines)
+
+
+```hl_lines="3 8"
+$ newt target create nrf52_adc
+$ newt target set nrf52_adc app=@apache-mynewt-core/apps/nrf52_adc
+Target targets/nrf52_adc successfully set target.app to @apache-mynewt-core/apps/nrf52_adc
+$ newt target set nrf52_adc_ bsp=@apache-mynewt-core/hw/bsp/nrf52dk
+$ newt target set nrf52_adc build_profile=debug
+
+$ newt target create nrf52_boot
+$ newt target set nrf52_boot app=@apache-mynewt-core/apps/boot
+$ newt target set nrf52_boot bsp=@apache-mynewt-core/hw/bsp/nrf52dk
+$ newt target set nrf52_boot build_profile=optimized
+
+$ newt target show 
+targets/nrf52_adc
+    app=@apache-mynewt-core/apps/nrf52_adc
+    bsp=@apache-mynewt-core/hw/bsp/nrf52dk
+    build_profile=debug
+targets/nrf52_boot
+    app=@apache-mynewt-core/apps/boot
+    bsp=@apache-mynewt-core/hw/bsp/nrf52dk
+    build_profile=optimized
+```
+
+<font color="#F2853F">
+Note: If you've already built and installed a bootloader for your NRF52dk then you do
+not need to create a target for it here, or build and load it as below. </font>
+<br>
+
+### Build the target executables 
+
+```
+$ newt build nrf52_boot
+...
+Compiling boot.c
+Archiving boot.a
+Linking boot.elf
+App successfully built: ~/dev/myadc/bin/nrf52_boot/apps/boot/boot.elf
+```
+```
+$ newt build nrf52_adc
+...
+Compiling main.c
+Archiving nrf52_adc.a
+Linking nrf52_adc.elf
+App successfully built: ~/dev/myadc/bin/nrf52_adc/apps/nrf52_adc/nrf52_adc.elf
+```
+
+<br>
+
+### Sign and create the nrf52_adc application image 
+
+You must sign and version your application image to download it using newt to the board. 
+Use the newt create-image command to perform this action. You may assign an arbitrary 
+version (e.g. 1.0.0) to the image.
+
+```
+$ newt create-image nrf52_adc 1.0.0
+App image successfully generated: ~/dev/myadc/bin/nrf52_adc/apps/nrf52_adc/nrf52_adc.img
+Build manifest: ~/dev/myadc/bin/nrf52_adc/apps/nrf52_adc/manifest.json
+```
+
+<br>
+
+### Connect the board
+
+Connect the evaluation board via micro-USB to your PC via USB cable.
+        
+<br>
+
+### Download to the target
+
+Download the bootloader first and then the nrf52_adc executable to the target platform. 
+Don't forget to reset the board if you don't see the LED blinking right away!
+
+```
+$ newt -v load nrf52_boot
+$ newt -v load nrf52_adc
+```
+
+<br>
+
+**Note:** If you want to erase the flash and load the image again, you can use JLinkExe to issue an `erase` command.
+
+```
+$ JLinkExe -device nRF52 -speed 4000 -if SWD
+SEGGER J-Link Commander V5.12c (Compiled Apr 21 2016 16:05:51)
+DLL version V5.12c, compiled Apr 21 2016 16:05:45
+
+Connecting to J-Link via USB...O.K.
+Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Mar 15 2016 18:03:17
+Hardware version: V1.00
+S/N: 682863966
+VTref = 3.300V
+
+
+Type "connect" to establish a target connection, '?' for help
+J-Link>erase
+Cortex-M4 identified.
+Erasing device (0;?i?)...
+Comparing flash   [100%] Done.
+Erasing flash     [100%] Done.
+Verifying flash   [100%] Done.
+J-Link: Flash download: Total time needed: 0.363s (Prepare: 0.093s, Compare: 0.000s, Erase: 0.262s, Program: 0.000s, Verify: 0.000s, Restore: 0.008s)
+Erasing done.
+J-Link>exit
+$
+```
+
+<br>
+
+### Building the BLE Services
+
+The nrf52_adc app is a Bluetooth-enabled sensor app that will allow you to read the value of the eTape Water Level Sensor
+via Bluetooth. So let's go through some of the code.
+
+As with the [ble peripheral](bleprph/bleprph-app.md) app, we will advertise a couple of values from our app. The first is
+not strictly necessary, but it will help us build an iOS app later. We've defiined a service and the characteristics in
+that service in `bleadc.h` as follows:
+
+```c
+/* Sensor Data */
+/* e761d2af-1c15-4fa7-af80-b5729002b340 */
+static const uint8_t gatt_svr_svc_sns_uuid[16] = {
+    0x40, 0xb3, 0x20, 0x90, 0x72, 0xb5, 0x80, 0xaf,
+    0xa7, 0x4f, 0x15, 0x1c, 0xaf, 0xd2, 0x61, 0xe7 };
+#define ADC_SNS_TYPE          0xDEAD
+#define ADC_SNS_VAL           0xBEEF
+#define ADC_SNS_STRING "eTape Water Level Sensor"
+
+uint16_t gatt_adc_val; 
+```
+
+The first is the UUID of the service, followed by the 2 characteristics we are going to offer.
+The first characteristic is going to advertise the *type* of sensor we are advertising, and
+it will be a read-only characteristic. The second characteristic will be the sensor value
+itself, and we will allow connected devices to 'subscribe' to it in order to get 
+constantly-updated values.
+
+The value that we'll be updating is also defined here as `gatt_adc_val`.
+
+If we then go look at `gatt_srv.c` we can see the structure of the service and
+characteristic offering that we set up:
+
+```c
+
+    {
+        /*** Alert Notification Service. */
+        .type = BLE_GATT_SVC_TYPE_PRIMARY,
+        .uuid128 = BLE_UUID16(GATT_SVR_SVC_ALERT_UUID),
+        .characteristics = (struct ble_gatt_chr_def[]) { {
+            .uuid128 = BLE_UUID16(GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID),
+            .access_cb = gatt_svr_chr_access_alert,
+            .flags = BLE_GATT_CHR_F_READ,
+        }, {
+            .uuid128 = BLE_UUID16(GATT_SVR_CHR_NEW_ALERT),
+            .access_cb = gatt_svr_chr_access_alert,
+            .flags = BLE_GATT_CHR_F_NOTIFY,
+        }, {
+            .uuid128 = BLE_UUID16(GATT_SVR_CHR_SUP_UNR_ALERT_CAT_UUID),
+            .access_cb = gatt_svr_chr_access_alert,
+            .flags = BLE_GATT_CHR_F_READ,
+        }, {
+            .uuid128 = BLE_UUID16(GATT_SVR_CHR_UNR_ALERT_STAT_UUID),
+            .access_cb = gatt_svr_chr_access_alert,
+            .flags = BLE_GATT_CHR_F_NOTIFY,
+        }, {
+            .uuid128 = BLE_UUID16(GATT_SVR_CHR_ALERT_NOT_CTRL_PT),
+            .access_cb = gatt_svr_chr_access_alert,
+            .flags = BLE_GATT_CHR_F_WRITE,
+        }, {
+            0, /* No more characteristics in this service. */
+        } },
+    },
+    {
+        /*** Water Level Notification Service. */
+        .type = BLE_GATT_SVC_TYPE_PRIMARY,
+        .uuid128 = gatt_svr_svc_sns_uuid,
+        .characteristics = (struct ble_gatt_chr_def[]) { {
+            .uuid128 = BLE_UUID16(ADC_SNS_TYPE),
+            .access_cb = gatt_svr_sns_access,
+            .flags = BLE_GATT_CHR_F_READ,
+        }, {
+            .uuid128 = BLE_UUID16(ADC_SNS_VAL),
+            .access_cb = gatt_svr_sns_access,
+            .flags = BLE_GATT_CHR_F_NOTIFY,
+        }, {
+            0, /* No more characteristics in this service. */
+        } },
+    },
+    {
+        0, /* No more services. */
+    },
+};
+
+```
+
+You should recognize the first services from the [BLE Peripheral](bleprph/bleprph-intro.md)
+tutorial earlier. We're just adding another Service, with 2 new Characteristics, to 
+that application.
+
+We'll need to fill in the function that will be called for this service, `gatt_srv_sns_access`
+next so that the service knows what to do.
+
+```c
+static int
+gatt_svr_sns_access(uint16_t conn_handle, uint16_t attr_handle,
+                          struct ble_gatt_access_ctxt *ctxt,
+                          void *arg)
+{
+    uint16_t uuid16;
+    int rc;
+
+    uuid16 = ble_uuid_128_to_16(ctxt->chr->uuid128);
+    assert(uuid16 != 0);
+
+    switch (uuid16) {
+    case ADC_SNS_TYPE:
+        assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
+        rc = os_mbuf_append(ctxt->om, ADC_SNS_STRING, sizeof ADC_SNS_STRING);
+        BLEADC_LOG(INFO, "ADC SENSOR TYPE READ: %s\n", ADC_SNS_STRING);
+        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+        
+    case ADC_SNS_VAL:
+        if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
+            rc = gatt_svr_chr_write(ctxt->om, 0,
+                                    sizeof gatt_adc_val,
+                                    &gatt_adc_val,
+                                    &gatt_adc_val_len);
+            return rc;
+        } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
+            rc = os_mbuf_append(ctxt->om, &gatt_adc_val,
+                                sizeof gatt_adc_val);
+            return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
+        }
+    default:
+        assert(0);
+        return BLE_ATT_ERR_UNLIKELY;
+    }                              
+}
+```
+
+You can see that when the `ADC_SNS_TYPE` is read, we return the
+Sensor Type we defined earlier. If the `ADC_SNS_VAL` we'll return the
+`gatt_adc_val` value. 
+
+If you build, load and run this application now, you will see all those Services and Characteristics
+advertised, and you will even be able to read the "Sensor Type" String via the ADC_SNS_TYPE
+Characteristic, but when you subscribe to the ADC_SNS_VALUE Characteristic, you
+aren't getting any data. That's because we haven't set up the ADC Sensor yet, or
+created a task to update the value.
+
+<br>
+
+### Creating the ADC Task
+
+In order for the application to send new sensor readings to a connected device, we'll need
+to create a new OS Task to gather values and update them. If you've worked through the
+[Add tasks](task_lesson.md) tutorial, this should look familiar to you at this point.
+
+First, in `main.c` we'll define all the ADC-related things we'll need:
+
+```c
+/* ADC */
+#include "nrf.h"
+#include "app_util_platform.h"
+#include "app_error.h"
+#include <adc/adc.h>
+#include <adc_nrf52/adc_nrf52.h>
+#include <adc_nrf52/adc_nrf52.h>
+#include "nrf_drv_saadc.h"
+
+nrf_drv_saadc_config_t adc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
+```
+
+Next we need to add the task-related requirements:
+
+```c
+/* ADC Task settings */
+#define ADC_TASK_PRIO           5
+#define ADC_STACK_SIZE          (OS_STACK_ALIGN(336))
+struct os_task adc_task;
+bssnz_t os_stack_t adc_stack[ADC_STACK_SIZE];
+```
+
+We'll also need to define a task handler for that task:
+
+```c
+/**
+ * Event loop for the ADC task.
+ */
+static void
+adc_task_handler(void *unused)
+{
+    
+    gatt_adc_val = 0; 
+    int rc = 0;
+        
+    while (1) {
+        gatt_adc_val++;
+        uint16_t chr_val_handle;
+        
+        rc = ble_gatts_find_chr(gatt_svr_svc_sns_uuid,
+                                  BLE_UUID16(ADC_SNS_VAL),
+                                  NULL, &chr_val_handle);
+        assert(rc == 0);
+
+        ble_gatts_chr_updated(chr_val_handle);
+        
+        /* Wait 2 second */
+        os_time_delay(OS_TICKS_PER_SEC*2);
+        
+    }
+}
+```
+
+At this point you'll notice that we are just incrementing a value, not sending any actual 
+sensor data. Be patient, we'll get there. We're initializiing our 'sensor' data
+variable, `gatt_adc_val` and then heading into our task-loop. 
+
+Once in the task loop, we use `ble_gatts_find_chr()` to get the handle for the 
+characteristic we're updating. and then we let that characteristic know that
+we've updated it's value by calling ` ble_gatts_chr_updated()` with the
+handle for the characteristic. 
+
+Finally we set the update frequency of the characteristic's data via a call to 
+`os_time_delay()` though there are other meachanisms for doing this.
+
+Now that we have this all done, you can actually run this app and see the 
+'sensor' value increase when you're subscribed to it.
+
+<br>
+
+### Implementing an Analog to Digital Converter (ADC)
+
+So far we have a functioning BLE Peripheral device that will update a counter
+and send that counter's value to any connected device that asks for it. It's
+a lot, but it's still a far cry from useful. What we realy need is to add a
+real sensor! The sensor we're using, the eTape Liquid Level Sensor, is a
+pretty basic Analog Sensor. As the fluid level changes, the voltage output
+of the sensor changes. In order to read this value, we'll need to access
+the ADC on the nrf52dk, and that's going to take a bit of work. 
+
+If we look at the configuration for the project by running `newt target config nrf52_adc`
+you'll see the configuration of the ADC:
+
+```no-highlight
+* PACKAGE: hw/bsp/nrf52dk
+  * Setting: ADC_0
+    * Description: TBD
+    * Value: 1
+  * Setting: ADC_0_INTERRUPT_PRIORITY
+    * Description: TBD
+    * Value: SAADC_CONFIG_IRQ_PRIORITY
+  * Setting: ADC_0_OVERSAMPLE
+    * Description: TBD
+    * Value: SAADC_CONFIG_OVERSAMPLE
+  * Setting: ADC_0_RESOLUTION
+    * Description: TBD
+    * Value: SAADC_CONFIG_RESOLUTION
+  * Setting: BSP_NRF52
+    * Description: TBD
+    * Value: 1
+```
+
+Next we can look in `hw/bsp/nrf52dk/src/hal_bsp.c`
+and make sure the proper device-creation takes place:
+
+```c
+#if MYNEWT_VAL(ADC_0)
+static struct adc_dev os_bsp_adc0;
+static nrf_drv_saadc_config_t os_bsp_adc0_config = {
+    .resolution         = MYNEWT_VAL(ADC_0_RESOLUTION),
+    .oversample         = MYNEWT_VAL(ADC_0_OVERSAMPLE),
+    .interrupt_priority = MYNEWT_VAL(ADC_0_INTERRUPT_PRIORITY),
+};
+#endif
+```
+
+And also make sure that it gets properly initialized in the 
+`hal_bsp_init()` function:
+
+```
+#if MYNEWT_VAL(ADC_0)
+    rc = os_dev_create((struct os_dev *) &os_bsp_adc0, "adc0",
+            OS_DEV_INIT_KERNEL, OS_DEV_INIT_PRIO_DEFAULT,
+            nrf52_adc_dev_init, &os_bsp_adc0_config);
+    assert(rc == 0);
+#endif
+```
+
+
+### Adding the eTape Water Sensor
+
+Now that we have a fully functioning BLE App that we can subscribe to sensor
+values from, it's time to turn that incrementing-counter into an actual sensor value!
+
+As previous;y mentioned, we're going to be using an eTape Water Level Sensor. You can 
+get one from [Adafruit](https://www.adafruit.com/products/1786). 
+
+We're going to use the sensor as a resistive sensor, and the setup is very simple. 
+I'll be using a 'breadboard` to put this all together for illustrative purposes. 
+First, attach a jumper-wire from Vdd on the board to the breadboard.
+Next, attach a jumper wire from pin P0.03 on the board to the breadboard. This will be
+our ADC-in. The sensor should have come with a 560 ohm resistor, so plug that
+into the baord between Vdd and ADC-in holes. Finally, attach a jumper from
+GND on the board to your breadboard. At this point, your breadboard should look
+like this:
+
+![Bread Board Setup](pics/breadboard.png)
+
+Now attach one of the middle 2 leads from the sensor to ground on the breadboad and 
+the other middle lead to the ADC-in on the breadboard. Your breadboard should now look
+like this:
+
+![Bread Board Final](pics/adc-demo-1.png)
+
+And yhour eTape Sensor should look like this (at least if you have it mounted in a
+graduated cylinder as I do).
+
+![eTape Sensor Setup](pics/adc-demo-2.png)
+
+That concludes the hardware portion. Easy!
+
+<br>
+
+### Reading the eTape Water Sensor Values
+
+This is the meat of the application. We've got our BLE application broadcasting and we can connect
+to it and get notified when sensor values change. And we've got our sensor all wired
+up correctly. So let's now make sure the correct values get sent.
+
+First we'll make some changes to the `adc_task_handler()` function to properly initialize
+the ADC.
+
+```c
+    struct adc_dev *adc;
+    nrf_saadc_channel_config_t cc =
+        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
+    cc.gain = NRF_SAADC_GAIN1_6;
+    cc.reference = NRF_SAADC_REFERENCE_INTERNAL;
+    adc = (struct adc_dev *) os_dev_open("adc0", 0, &adc_config);
+    assert(adc != NULL);
+    
+    adc_chan_config(adc, 0, &cc);
+    
+    sample_buffer1 = malloc(adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    sample_buffer2 = malloc(adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    memset(sample_buffer1, 0, adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    memset(sample_buffer2, 0, adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    
+    adc_buf_set(adc, sample_buffer1, sample_buffer2,
+            adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    adc_event_handler_set(adc, adc_read_event, (void *) NULL);
+```
+
+A few things need to be said about this part, as it is the most confusing. First, 
+we're using a **default** configuration for the ADC Channel via the `NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE`
+macro. The important part here is that we're actually using `AIN1`. I know what you're thinking, "But 
+we want ADC-0!" and that's true. The board is actually labelled 'A0, A1, A2' etc., and the actual pin 
+numbers are also listed on the board, which seems handy. At first. But it gets messy very
+quickly.
+
+If you try to use AIN0, and then go poke around in the registers while this is running, 
+
+```
+(gdb) p/x {NRF_SAADC_Type}0x40007000
+...
+ CH = {{
+      PSELP = 0x1,
+      PSELN = 0x0,
+      CONFIG = 0x20000,
+      LIMIT = 0x7fff8000
+    }, 
+```
+
+You'll see that the pin for channel 0 is set to 1, which corresponts to AIN0, but that's **NOT**
+the same as A0 -- pin P0.03, the one we're using. For that, you use AIN1, which would set the
+pin value to 2. Messy. 
+
+
+The only other thing to note here is that we're using the internal reference voltage, rather than
+setting our own. There's nothing wrong with that, but since we are, we'll have to crank up
+the gain a bit by using `NRF_SAADC_GAIN1_6`.
+
+So, since that's all clear, our task-loop in the `adc_task_handler()` function is extremely simple:
+
+```c
+while (1) {
+    adc_sample(adc);
+    /* Wait 2 second */
+    os_time_delay(OS_TICKS_PER_SEC * 2);
+}
+```
+
+We'll just sample the ADC every 2 seconds or so.
+
+If you noticed above the call to `adc_event_handler_set()` then you'll also know that we'd 
+better define that callback function we set `adc_read_event()`
+
+```c
+int
+adc_read_event(struct adc_dev *dev, void *arg, uint8_t etype,
+        void *buffer, int buffer_len)
+{
+    int i;
+    int adc_result;
+    uint16_t chr_val_handle;
+    int rc;
+    for (i = 0; i < ADC_NUMBER_SAMPLES; i++) {
+        rc = adc_buf_read(dev, buffer, buffer_len, i, &adc_result);
+        if (rc != 0) {
+            goto err;
+        }
+        
+        gatt_adc_val = adc_result_mv(dev, 0, adc_result);
+        rc = ble_gatts_find_chr(gatt_svr_svc_sns_uuid, BLE_UUID16(ADC_SNS_VAL), NULL, &chr_val_handle);
+        assert(rc == 0);
+        ble_gatts_chr_updated(chr_val_handle);
+    }
+
+    adc_buf_release(dev, buffer, buffer_len);
+    return (0);
+err:
+    return (rc);
+}
+```
+
+Whenever the ADC has a sample for us in its buffer, we'll run through the samples available, convert them
+to millivolts, and then update the NOTIFY value so that any connected devices get the updated
+sensor values.
+
+<br>
+
+### Conclusion
+
+Congratulations, you've now completed both a hardware project and a software project by connecting a
+sensor to your device and using Mynewt to read data from that sensor and send it via Bluetooth
+to a connected device. That's no small feat!
+
+If you see anything missing or want to send us feedback, please do so by signing up for 
+appropriate mailing lists on our [Community Page](../../community.md).
+
+Keep on hacking and sensing!
+
+
+
+
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/9183cab3/docs/os/tutorials/pics/MyNewtSensorReader006.jpg
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/pics/MyNewtSensorReader006.jpg b/docs/os/tutorials/pics/MyNewtSensorReader006.jpg
new file mode 100644
index 0000000..c15d69d
Binary files /dev/null and b/docs/os/tutorials/pics/MyNewtSensorReader006.jpg differ

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/9183cab3/mkdocs.yml
----------------------------------------------------------------------
diff --git a/mkdocs.yml b/mkdocs.yml
index fc43b49..51b7b38 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -64,6 +64,7 @@ pages:
             - 'BLE Peripheral App' : 'os/tutorials/bleprph/bleprph-app.md'
         - 'BLE iBeacon': 'os/tutorials/ibeacon.md'
         - 'BLE HCI interface': 'os/tutorials/blehci_project.md'
+        - 'Add an Analog Sensor': 'os/tutorials/nrf52_adc.md'
     - OS User Guide:
         - toc: 'os/os_user_guide.md'
         - OS Core:


[4/5] incubator-mynewt-site git commit: Merge branch 'adc_tutorial' of https://github.com/davidgs/incubator-mynewt-site into develop

Posted by ad...@apache.org.
Merge branch 'adc_tutorial' of https://github.com/davidgs/incubator-mynewt-site into develop


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/9e020bfc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/tree/9e020bfc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/diff/9e020bfc

Branch: refs/heads/develop
Commit: 9e020bfc8b9d32f89146fb3b3e9ac12d52fc7f82
Parents: c28a73b 9fc9992
Author: aditihilbert <ad...@runtime.io>
Authored: Wed Feb 15 12:17:59 2017 -0800
Committer: aditihilbert <ad...@runtime.io>
Committed: Wed Feb 15 12:17:59 2017 -0800

----------------------------------------------------------------------
 docs/os/tutorials/nrf52_adc.md                  | 828 +++++++++++++++++++
 .../os/tutorials/pics/MyNewtSensorReader006.jpg | Bin 0 -> 211399 bytes
 docs/os/tutorials/pics/adc-demo-1.png           | Bin 0 -> 530153 bytes
 docs/os/tutorials/pics/adc-demo-2.png           | Bin 0 -> 435709 bytes
 docs/os/tutorials/pics/breadboard.png           | Bin 0 -> 546231 bytes
 mkdocs.yml                                      |   1 +
 6 files changed, 829 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/9e020bfc/mkdocs.yml
----------------------------------------------------------------------
diff --cc mkdocs.yml
index e55efcc,51b7b38..622ece9
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@@ -64,8 -63,8 +64,9 @@@ pages
              - 'GAP Event Callbacks': 'os/tutorials/bleprph/bleprph-gap-event.md'
              - 'BLE Peripheral App' : 'os/tutorials/bleprph/bleprph-app.md'
          - 'BLE iBeacon': 'os/tutorials/ibeacon.md'
 +        - 'BLE Eddystone': 'os/tutorials/eddystone.md'
          - 'BLE HCI interface': 'os/tutorials/blehci_project.md'
+         - 'Add an Analog Sensor': 'os/tutorials/nrf52_adc.md'
      - OS User Guide:
          - toc: 'os/os_user_guide.md'
          - OS Core:


[5/5] incubator-mynewt-site git commit: Cleaned up etape sensor tutorial. This closes #152.

Posted by ad...@apache.org.
Cleaned up etape sensor tutorial. This closes #152.


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/eceb15e7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/tree/eceb15e7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/diff/eceb15e7

Branch: refs/heads/develop
Commit: eceb15e72f18cf38b6537bb1a8541b0b1c1f30ff
Parents: 9e020bf
Author: aditihilbert <ad...@runtime.io>
Authored: Wed Feb 15 21:50:37 2017 -0800
Committer: aditihilbert <ad...@runtime.io>
Committed: Wed Feb 15 21:50:37 2017 -0800

----------------------------------------------------------------------
 docs/os/tutorials/nrf52_adc.md | 107 ++++++++++++++++++++++++++----------
 mkdocs.yml                     |   6 +-
 2 files changed, 80 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/eceb15e7/docs/os/tutorials/nrf52_adc.md
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/nrf52_adc.md b/docs/os/tutorials/nrf52_adc.md
index d520b14..643d66f 100644
--- a/docs/os/tutorials/nrf52_adc.md
+++ b/docs/os/tutorials/nrf52_adc.md
@@ -116,10 +116,10 @@ $ mkdir -p apps/nrf52_adc
 $ cp -Rp repos/apache-mynewt-core/apps/bleprph/* apps/nrf52_adc
 ```
 
-Next, you'll modify the `pkg.yml` file for your app:
+Next, you'll modify the `pkg.yml` file for your app. Note the change in `pkg.name` and `pkg.description`. Also make sure that you specify the full path of all the packages with the prefix `@apache-mynewt-core/` as shown in the third highlighted line.
 
-```
-$ cat app/nrf52_adc/pkg.yml
+```hl_lines="3 5 11"
+$ cat apps/nrf52_adc/pkg.yml
 ...
 pkg.name: apps/nrf52_adc
 pkg.type: app
@@ -128,23 +128,24 @@ pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
 pkg.homepage: "http://mynewt.apache.org/"
 pkg.keywords:
 
-pkg.deps:
-    - boot/split
-    - kernel/os
-    - mgmt/newtmgr
-    - mgmt/newtmgr/transport/ble
-    - net/nimble/controller
-    - net/nimble/host
-    - net/nimble/host/services/ans
-    - net/nimble/host/services/gap
-    - net/nimble/host/services/gatt
-    - net/nimble/host/store/ram
-    - net/nimble/transport/ram
-    - sys/console/full
-    - sys/log/full
-    - sys/stats/full
-    - sys/sysinit
-    - sys/id
+pkg.deps: 
+    - "@apache-mynewt-core/boot/split"
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-core/mgmt/imgmgr"
+    - "@apache-mynewt-core/mgmt/newtmgr"
+    - "@apache-mynewt-core/mgmt/newtmgr/transport/ble"
+    - "@apache-mynewt-core/net/nimble/controller"
+    - "@apache-mynewt-core/net/nimble/host"
+    - "@apache-mynewt-core/net/nimble/host/services/ans"
+    - "@apache-mynewt-core/net/nimble/host/services/gap"
+    - "@apache-mynewt-core/net/nimble/host/services/gatt"
+    - "@apache-mynewt-core/net/nimble/host/store/ram"
+    - "@apache-mynewt-core/net/nimble/transport/ram"
+    - "@apache-mynewt-core/sys/console/full"
+    - "@apache-mynewt-core/sys/log/full"
+    - "@apache-mynewt-core/sys/stats/full"
+    - "@apache-mynewt-core/sys/sysinit"
+    - "@apache-mynewt-core/sys/id"
 ```
 
 Great! We have our very own app so let's make sure we have all of our targets set
@@ -304,10 +305,10 @@ Now you can add the files you need. You'll need a pkg.yml to describe the driver
 pkg.name: libs/my_drivers/myadc
 pkg.deps:
     - "@apache-mynewt-core/hw/hal"
-    - "@mynewt-nordic/hw/drivers/adc/adc_nrf52"
+    - "@mynewt_nordic/hw/drivers/adc/adc_nrf52"
 ```
 
-First, let's create the required header file `myadc.h` in the includes directory.
+First, let's create the required header file `myadc.h` in the includes directory i.e. `libs/my_drivers/myadc/include/myadc/myadc.h`.
 It's a pretty straightforward header file, since we only need to do 2 things:
 
 * Initialize the ADC device
@@ -519,7 +520,40 @@ syscfg.defs:
         value: 'SAADC_CONFIG_IRQ_PRIORITY'
 ```
 
-Once that's all done, you should have a working ADC Driver for your NRF52DK board.
+Once that's all done, you should have a working ADC Driver for your NRF52DK board. The last step in getting the driver set up is to include it in the package dependency defined by `pkg.deps` in the `pkg.yml` file of your app. Add it in `apps/nrf52_adc/pkg.yml` as shown by the highlighted line below.
+
+```hl_lines="29"
+# Licensed to the Apache Software Foundation (ASF) under one
+# <snip>
+
+pkg.name: apps/nrf52_adc
+pkg.type: app
+pkg.description: Simple BLE peripheral application for ADC sensor.
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps: 
+    - "@apache-mynewt-core/boot/split"
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-core/mgmt/imgmgr"
+    - "@apache-mynewt-core/mgmt/newtmgr"
+    - "@apache-mynewt-core/mgmt/newtmgr/transport/ble"
+    - "@apache-mynewt-core/net/nimble/controller"
+    - "@apache-mynewt-core/net/nimble/host"
+    - "@apache-mynewt-core/net/nimble/host/services/ans"
+    - "@apache-mynewt-core/net/nimble/host/services/gap"
+    - "@apache-mynewt-core/net/nimble/host/services/gatt"
+    - "@apache-mynewt-core/net/nimble/host/store/ram"
+    - "@apache-mynewt-core/net/nimble/transport/ram"
+    - "@apache-mynewt-core/sys/console/full"
+    - "@apache-mynewt-core/sys/log/full"
+    - "@apache-mynewt-core/sys/stats/full"
+    - "@apache-mynewt-core/sys/sysinit"
+    - "@apache-mynewt-core/sys/id"
+    - libs/my_drivers/myadc
+```
+
 
 <br>
 
@@ -541,9 +575,9 @@ struct os_task adc_task;
 bssnz_t os_stack_t adc_stack[ADC_STACK_SIZE];
 ```
 
-Next we'll need  o initialize the task `event_q` so we'll add the following to `main()` :
+Next we'll need  o initialize the task `event_q` so we'll add the highlighted code to `main()` as shown below:
 
-```c
+```c hl_lines="7 8 9 10 11 12 13 14 15"
     /* Set the default device name. */
     rc = ble_svc_gap_device_name_set("nimble-adc");
     assert(rc == 0);
@@ -586,7 +620,7 @@ adc_task_handler(void *unused)
 }
 ```
 
-Finally, we'll need to handle those `adc_read_event()` calls:
+Above the `adc_task_handler`, add code to handle the `adc_read_event()` calls:
 
 ```c
 int
@@ -628,7 +662,7 @@ via Bluetooth we'll need to actually define those Services and Characteristics.
 
 As with the [ble peripheral](bleprph/bleprph-app.md) app, we will advertise a couple of values from our app. The first is
 not strictly necessary, but it will help us build an iOS app later. We've defined a service and the characteristics in
-that service in `bleadc.h` as follows:
+that service in `bleadc.h` in the `apps/nrf52_adc/src/` directory as follows:
 
 ```c
 /* Sensor Data */
@@ -639,7 +673,7 @@ static const ble_uuid128_t gatt_svr_svc_adc_uuid =
 #define ADC_SNS_TYPE          0xDEAD
 #define ADC_SNS_STRING "eTape Liquid Level Sensor"
 #define ADC_SNS_VAL           0xBEAD
-uint16_t gatt_adc_val; 
+extern uint16_t gatt_adc_val; 
 ```
 
 The first is the UUID of the service, followed by the 2 characteristics we are going to offer.
@@ -657,7 +691,7 @@ The value that we'll be updating is also defined here as `gatt_adc_val`.
 If we then go look at `gatt_srv.c` we can see the structure of the service and
 characteristic offering that we set up:
 
-```c
+```c hl_lines="21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37"
 static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
     {
         /*** Service: Security test. */
@@ -731,7 +765,7 @@ gatt_svr_sns_access(uint16_t conn_handle, uint16_t attr_handle,
             rc = gatt_svr_chr_write(ctxt->om, 0,
                                     sizeof gatt_adc_val,
                                     &gatt_adc_val,
-                                    &gatt_adc_val_len);
+                                    NULL);
             return rc;
         } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
             rc = os_mbuf_append(ctxt->om, &gatt_adc_val,
@@ -751,6 +785,19 @@ You can see that when request is for the `ADC_SNS_TYPE`, we return the
 Sensor Type we defined earlier. If the request if for `ADC_SNS_VAL` we'll return the
 `gatt_adc_val` value. 
 
+Don't forget to include the `bleadc.h` include file at the top of the `gatt_svr.c` file!
+
+```hl_lines="8"
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "bsp/bsp.h"
+#include "host/ble_hs.h"
+#include "host/ble_uuid.h"
+#include "bleprph.h"
+#include "bleadc.h"
+```
+
 If you build, load and run this application now, you will see all those Services and Characteristics
 advertised, and you will even be able to read the "Sensor Type" String via the ADC_SNS_TYPE
 Characteristic.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/eceb15e7/mkdocs.yml
----------------------------------------------------------------------
diff --git a/mkdocs.yml b/mkdocs.yml
index 622ece9..b69741f 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -46,9 +46,6 @@ pages:
         - 'Tasks and Priority Management': 'os/tutorials/tasks_lesson.md'
         - 'Enable Wi-Fi on Arduino Zero': 'os/tutorials/wi-fi_on_arduino.md'
         - 'Write a Test Suite for a Package': 'os/tutorials/unit_test.md'
-        - 'Air-quality Sensor project': 
-            - 'Basic Air Quality Sensor': 'os/tutorials/air_quality_sensor.md'
-            - 'Bluetooth-enabled Air Quality Sensor': 'os/tutorials/air_quality_ble.md'
         - 'Add task to manage multiple events': 'os/tutorials/event_queue.md'
         - 'Project Slinky for remote comms':
             - 'Slinky on sim device': 'os/tutorials/project-slinky.md'
@@ -66,6 +63,9 @@ pages:
         - 'BLE iBeacon': 'os/tutorials/ibeacon.md'
         - 'BLE Eddystone': 'os/tutorials/eddystone.md'
         - 'BLE HCI interface': 'os/tutorials/blehci_project.md'
+        - 'Air-quality Sensor project':
+            - 'Basic Air Quality Sensor': 'os/tutorials/air_quality_sensor.md'
+            - 'BLE-enabled Air Quality Sensor': 'os/tutorials/air_quality_ble.md'
         - 'Add an Analog Sensor': 'os/tutorials/nrf52_adc.md'
     - OS User Guide:
         - toc: 'os/os_user_guide.md'


[2/5] incubator-mynewt-site git commit: Fully functioning ADC Tutorial

Posted by ad...@apache.org.
Fully functioning ADC 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/03cd817d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/tree/03cd817d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/diff/03cd817d

Branch: refs/heads/develop
Commit: 03cd817d1d405c557d41547444c7644c6e46e092
Parents: 9183cab
Author: David G. Simmons <sa...@mac.com>
Authored: Wed Feb 8 15:22:46 2017 -0500
Committer: David G. Simmons <sa...@mac.com>
Committed: Wed Feb 8 15:22:46 2017 -0500

----------------------------------------------------------------------
 docs/os/tutorials/nrf52_adc.md | 772 ++++++++++++++++++++++--------------
 1 file changed, 471 insertions(+), 301 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/03cd817d/docs/os/tutorials/nrf52_adc.md
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/nrf52_adc.md b/docs/os/tutorials/nrf52_adc.md
index 4d3009b..d520b14 100644
--- a/docs/os/tutorials/nrf52_adc.md
+++ b/docs/os/tutorials/nrf52_adc.md
@@ -47,7 +47,7 @@ or just follow the commands below.
 The board-specific libraries for the NRF52dk board are in an external repository at present, so
 you'll need to include that remote repository and install it as well. If you're not familiar
 with using repositories, see the section on [repositories](repo/add_repos.md) before
-continuiing. Or just copy and paste the following.
+continuing. Or just copy and paste the following.
 
 In your `project.yml` file, add `- mynewt_nordic` to the `project.repositories` section, and 
 then add the proper repository definition. When you're done, your `project.yml` file
@@ -107,12 +107,54 @@ Note: The correct bsp must be chosen for the board you are using. </font>
 * For the Nordic Dev Kit choose @apache-mynewt-core/hw/bsp/nrf52dk instead (in the highlighted lines)
 * For the Rigado Eval Kit choose @apache-mynewt-core/hw/bsp/bmd300eval instead (in the highlighted lines)
 
+For the app itself we're going to extend the [bleprph](belpprph/bleprph-app.md) app so that we
+get the Bluetooth communications built in, so the first thing we'll need to do is copy that app
+into our own app directory:
+
+```no-highlight
+$ mkdir -p apps/nrf52_adc
+$ cp -Rp repos/apache-mynewt-core/apps/bleprph/* apps/nrf52_adc
+```
+
+Next, you'll modify the `pkg.yml` file for your app:
+
+```
+$ cat app/nrf52_adc/pkg.yml
+...
+pkg.name: apps/nrf52_adc
+pkg.type: app
+pkg.description: Simple BLE peripheral application for ADC Sensors.
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - boot/split
+    - kernel/os
+    - mgmt/newtmgr
+    - mgmt/newtmgr/transport/ble
+    - net/nimble/controller
+    - net/nimble/host
+    - net/nimble/host/services/ans
+    - net/nimble/host/services/gap
+    - net/nimble/host/services/gatt
+    - net/nimble/host/store/ram
+    - net/nimble/transport/ram
+    - sys/console/full
+    - sys/log/full
+    - sys/stats/full
+    - sys/sysinit
+    - sys/id
+```
+
+Great! We have our very own app so let's make sure we have all of our targets set
+correctly:
 
 ```hl_lines="3 8"
 $ newt target create nrf52_adc
-$ newt target set nrf52_adc app=@apache-mynewt-core/apps/nrf52_adc
-Target targets/nrf52_adc successfully set target.app to @apache-mynewt-core/apps/nrf52_adc
-$ newt target set nrf52_adc_ bsp=@apache-mynewt-core/hw/bsp/nrf52dk
+$ newt target set nrf52_adc app=apps/nrf52_adc
+Target targets/nrf52_adc successfully set target.app to apps/nrf52_adc
+$ newt target set nrf52_adc bsp=@apache-mynewt-core/hw/bsp/nrf52dk
 $ newt target set nrf52_adc build_profile=debug
 
 $ newt target create nrf52_boot
@@ -122,7 +164,7 @@ $ newt target set nrf52_boot build_profile=optimized
 
 $ newt target show 
 targets/nrf52_adc
-    app=@apache-mynewt-core/apps/nrf52_adc
+    app=apps/nrf52_adc
     bsp=@apache-mynewt-core/hw/bsp/nrf52dk
     build_profile=debug
 targets/nrf52_boot
@@ -183,8 +225,8 @@ Download the bootloader first and then the nrf52_adc executable to the target pl
 Don't forget to reset the board if you don't see the LED blinking right away!
 
 ```
-$ newt -v load nrf52_boot
-$ newt -v load nrf52_adc
+$ newt load nrf52_boot
+$ newt load nrf52_adc
 ```
 
 <br>
@@ -215,28 +257,388 @@ Erasing done.
 J-Link>exit
 $
 ```
+<br>
+
+So you have a BLE app, but really all you've done is change the name of the **bleprph** app to **nrf52_adc** and load that.
+Not all that impressive, and it certainly won't read an Analog Sensor right now. So let's do that next. In order to 
+read an ADC sensor, and since the ADC package is in an external, licensed, repository, we'll create a driver for it
+here in our app that will leverage the existing driver in the external repository. It adds another layer of 
+indirection, but it will also give us a look at building our own driver, so we'll do it this way. 
+
+<br>
+
+### Building a Driver
+
+The first thing to do is to create the directory structure for your driver:
+
+```no-highlight
+[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/myadc/include/myadc
+[user@IsMyLaptop:~/src/air_quality]$ mkdir -p libs/my_drivers/myadc/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.
+
+```no-highlight
+[user@IsMyLaptop:~/src/air_quality]$ cat libs/my_drivers/myadc/pkg.yml
+```
+
+```c
+#
+# 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/myadc
+pkg.deps:
+    - "@apache-mynewt-core/hw/hal"
+    - "@mynewt-nordic/hw/drivers/adc/adc_nrf52"
+```
+
+First, let's create the required header file `myadc.h` in the includes directory.
+It's a pretty straightforward header file, since we only need to do 2 things:
+
+* Initialize the ADC device
+* Read ADC Values
+
+
+```c
+#ifndef _NRF52_ADC_H_
+#define _NRF52_ADC_H_
+
+void * adc_init(void);
+int adc_read(void *buffer, int buffer_len);
+
+#endif /* _NRF52_ADC_H_ */
+
+```
+
+Next we'll need a corresponding source file `myadc.c` in the src directory. This is where
+we'll implement the specifics of the driver:
+
+```c
+
+#include <assert.h>
+#include <os/os.h>
+/* ADC */
+#include "myadc/myadc.h"
+#include "nrf.h"
+#include "app_util_platform.h"
+#include "app_error.h"
+#include <adc/adc.h>
+#include <adc_nrf52/adc_nrf52.h>
+#include "nrf_drv_saadc.h"
+
+
+#define ADC_NUMBER_SAMPLES (2)
+#define ADC_NUMBER_CHANNELS (1)
+
+nrf_drv_saadc_config_t adc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
+
+struct adc_dev *adc;
+uint8_t *sample_buffer1;
+uint8_t *sample_buffer2;
+
+static struct adc_dev os_bsp_adc0;
+static nrf_drv_saadc_config_t os_bsp_adc0_config = {
+    .resolution         = MYNEWT_VAL(ADC_0_RESOLUTION),
+    .oversample         = MYNEWT_VAL(ADC_0_OVERSAMPLE),
+    .interrupt_priority = MYNEWT_VAL(ADC_0_INTERRUPT_PRIORITY),
+};
+void *
+adc_init(void)
+{
+    int rc = 0;
+    
+    rc = os_dev_create((struct os_dev *) &os_bsp_adc0, "adc0",
+            OS_DEV_INIT_KERNEL, OS_DEV_INIT_PRIO_DEFAULT,
+            nrf52_adc_dev_init, &os_bsp_adc0_config);
+    assert(rc == 0);
+    nrf_saadc_channel_config_t cc = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
+    cc.gain = NRF_SAADC_GAIN1_6;
+    cc.reference = NRF_SAADC_REFERENCE_INTERNAL;
+    adc = (struct adc_dev *) os_dev_open("adc0", 0, &adc_config);
+    assert(adc != NULL);
+    adc_chan_config(adc, 0, &cc);
+    sample_buffer1 = malloc(adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    sample_buffer2 = malloc(adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    memset(sample_buffer1, 0, adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    memset(sample_buffer2, 0, adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    adc_buf_set(adc, sample_buffer1, sample_buffer2,
+        adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    return adc;
+}
+
+
+int
+adc_read(void *buffer, int buffer_len)
+{
+    int i;
+    int adc_result;
+    int my_result_mv = 0;
+    int rc;
+    for (i = 0; i < ADC_NUMBER_SAMPLES; i++) {
+        rc = adc_buf_read(adc, buffer, buffer_len, i, &adc_result);
+        if (rc != 0) {
+            goto err;
+        }
+        my_result_mv = adc_result_mv(adc, 0, adc_result);
+    }        
+    adc_buf_release(adc, buffer, buffer_len);
+    return my_result_mv;
+err:
+    return (rc);
+}
+```
+There's a lot going on in here, so let's walk through it step by step. 
+
+First, we define a default configuration, with the resolution, oversample and interrupt priority. You'll see
+that these are `MYNEWT_VAL` values, which means that we'll define them shortly in
+a `syscfg.yml` file to be passed to the compiler at build time. 
+
+```c
+static struct adc_dev os_bsp_adc0;
+static nrf_drv_saadc_config_t os_bsp_adc0_config = {
+    .resolution         = MYNEWT_VAL(ADC_0_RESOLUTION),
+    .oversample         = MYNEWT_VAL(ADC_0_OVERSAMPLE),
+    .interrupt_priority = MYNEWT_VAL(ADC_0_INTERRUPT_PRIORITY),
+};
+```
+
+Next, in `adc_init()` , we need to tell the OS to create the device.
+
+```c
+void *
+adc_init(void)
+{
+    int rc = 0;
+    
+    rc = os_dev_create((struct os_dev *) &os_bsp_adc0, "adc0",
+            OS_DEV_INIT_KERNEL, OS_DEV_INIT_PRIO_DEFAULT,
+            nrf52_adc_dev_init, &os_bsp_adc0_config);
+    assert(rc == 0);
+    nrf_saadc_channel_config_t cc = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
+    cc.gain = NRF_SAADC_GAIN1_6;
+    cc.reference = NRF_SAADC_REFERENCE_INTERNAL;
+    adc = (struct adc_dev *) os_dev_open("adc0", 0, &adc_config);
+    assert(adc != NULL);
+    adc_chan_config(adc, 0, &cc);
+    sample_buffer1 = malloc(adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    sample_buffer2 = malloc(adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    memset(sample_buffer1, 0, adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    memset(sample_buffer2, 0, adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    adc_buf_set(adc, sample_buffer1, sample_buffer2,
+        adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
+    return adc;
+}
+
+```
+A few things need to be said about this part, as it is the most confusing. First, 
+we're using a **default** configuration for the ADC Channel via the `NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE`
+macro. The important part here is that we're actually using `AIN1`. I know what you're thinking, "But 
+we want ADC-0!" and that's true. The board is actually labelled 'A0, A1, A2' etc., and the actual pin 
+numbers are also listed on the board, which seems handy. At first. But it gets messy very quickly.
+
+If you try to use AIN0, and then go poke around in the registers while this is running, 
+
+```
+(gdb) p/x {NRF_SAADC_Type}0x40007000
+...
+ CH = {{
+      PSELP = 0x1,
+      PSELN = 0x0,
+      CONFIG = 0x20000,
+      LIMIT = 0x7fff8000
+    }, 
+```
+
+You'll see that the pin for channel 0 is set to 1, which corresponds to AIN0, but that's **NOT**
+the same as A0 -- pin P0.03, the one we're using. For that, you use AIN1, which would set the
+pin value to 2. Messy. Someone, somewhere, thought this made sense. 
+
+
+The only other thing to note here is that we're using the internal reference voltage, rather than
+setting our own. There's nothing wrong with that, but since we are, we'll have to crank up
+the gain a bit by using `NRF_SAADC_GAIN1_6`.
+
+Then, in `adc_read()` we will take readings, convert the raw readings to 
+a millivolt equivalent, and return the result. 
+
+```c
+int
+adc_read(void *buffer, int buffer_len)
+{
+    int i;
+    int adc_result;
+    int my_result_mv = 0;
+    int rc;
+    for (i = 0; i < ADC_NUMBER_SAMPLES; i++) {
+        rc = adc_buf_read(adc, buffer, buffer_len, i, &adc_result);
+        if (rc != 0) {
+            goto err;
+        }
+        my_result_mv = adc_result_mv(adc, 0, adc_result);
+    }        
+    adc_buf_release(adc, buffer, buffer_len);
+    return my_result_mv;
+err:
+    return (rc);
+}
+```
+
+Finally, we'll need some settings for our driver, as mentioned earlier. In the `myadc` directory
+you'll need to add a `syscfg.yml` file:
+
+```no-highlight
+# Package: libs/my_driver/myadc
+
+syscfg.defs:
+    ADC_0:
+        description: 'TBD'
+        value:  1
+    ADC_0_RESOLUTION:
+        description: 'TBD'
+        value: 'SAADC_CONFIG_RESOLUTION'
+    ADC_0_OVERSAMPLE:
+        description: 'TBD'
+        value: 'SAADC_CONFIG_OVERSAMPLE'
+    ADC_0_INTERRUPT_PRIORITY:
+        description: 'TBD'
+        value: 'SAADC_CONFIG_IRQ_PRIORITY'
+```
+
+Once that's all done, you should have a working ADC Driver for your NRF52DK board.
+
+<br>
+
+### Creating the ADC Task
+
+Now that the driver is done, we'll need to add calls to the main app's `main.c` file, as well
+as a few other things. First, we'll need to update the includes, and add a task for our ADC
+sampling.
+
+
+```c
+#include "myadc/myadc.h"
+...
+/* ADC Task settings */
+#define ADC_TASK_PRIO           5
+#define ADC_STACK_SIZE          (OS_STACK_ALIGN(336))
+struct os_eventq adc_evq;
+struct os_task adc_task;
+bssnz_t os_stack_t adc_stack[ADC_STACK_SIZE];
+```
+
+Next we'll need  o initialize the task `event_q` so we'll add the following to `main()` :
+
+```c
+    /* Set the default device name. */
+    rc = ble_svc_gap_device_name_set("nimble-adc");
+    assert(rc == 0);
+    
+    conf_load();
+    
+    /* Initialize adc sensor task eventq */
+    os_eventq_init(&adc_evq);
+
+    /* Create the ADC reader task.  
+     * All sensor operations are performed in this task.
+     */
+    os_task_init(&adc_task, "sensor", adc_task_handler,
+            NULL, ADC_TASK_PRIO, OS_WAIT_FOREVER,
+            adc_stack, ADC_STACK_SIZE);
+```
+We'll need that `adc_task_handler()` function to exist, and that's where we'll initialize the ADC Device
+and set the event handler. In the task's while() loop, we'll just make a call to `adc_sample()` to cause
+the ADC driver to sample the adc device.
+
+```c
+/**
+ * Event loop for the sensor task.
+ */
+static void
+adc_task_handler(void *unused)
+{
+    struct adc_dev *adc;
+    int rc;
+    /* ADC init */
+    adc = adc_init();
+    rc = adc_event_handler_set(adc, adc_read_event, (void *) NULL);
+    assert(rc == 0);
+    
+    while (1) {
+        adc_sample(adc);
+        /* Wait 2 second */
+        os_time_delay(OS_TICKS_PER_SEC * 2);
+    }
+}
+```
+
+Finally, we'll need to handle those `adc_read_event()` calls:
+
+```c
+int
+adc_read_event(struct adc_dev *dev, void *arg, uint8_t etype,
+        void *buffer, int buffer_len)
+{
+    int value;
+    uint16_t chr_val_handle;
+    int rc;
+
+    value = adc_read(buffer, buffer_len);
+    if (value >= 0) {
+        console_printf("Got %d\n", value);
+    } else {
+        console_printf("Error while reading: %d\n", value);
+        goto err;
+    }
+    gatt_adc_val = value;
+    rc = ble_gatts_find_chr(&gatt_svr_svc_adc_uuid.u, BLE_UUID16_DECLARE(ADC_SNS_VAL), NULL, &chr_val_handle);
+    assert(rc == 0);
+    ble_gatts_chr_updated(chr_val_handle);
+    return (0);
+err:
+    return (rc);
+} 
+```
+This is where we actually read the ADC value and then update the BLE Characteristic for that value. 
+
+But wait, we haven't defined those BLE services and characteristics yet! Right, so don't try to build and run this
+app just yet or it will surely fail. Instead, move on to the next section and get all of those services 
+defined.
 
 <br>
 
 ### Building the BLE Services
 
-The nrf52_adc app is a Bluetooth-enabled sensor app that will allow you to read the value of the eTape Water Level Sensor
-via Bluetooth. So let's go through some of the code.
+If the nrf52_adc app is going to be a Bluetooth-enabled sensor app that will allow you to read the value of the eTape Water Level Sensor
+via Bluetooth we'll need to actually define those Services and Characteristics.
 
 As with the [ble peripheral](bleprph/bleprph-app.md) app, we will advertise a couple of values from our app. The first is
-not strictly necessary, but it will help us build an iOS app later. We've defiined a service and the characteristics in
+not strictly necessary, but it will help us build an iOS app later. We've defined a service and the characteristics in
 that service in `bleadc.h` as follows:
 
 ```c
 /* Sensor Data */
 /* e761d2af-1c15-4fa7-af80-b5729002b340 */
-static const uint8_t gatt_svr_svc_sns_uuid[16] = {
-    0x40, 0xb3, 0x20, 0x90, 0x72, 0xb5, 0x80, 0xaf,
-    0xa7, 0x4f, 0x15, 0x1c, 0xaf, 0xd2, 0x61, 0xe7 };
+static const ble_uuid128_t gatt_svr_svc_adc_uuid =
+        BLE_UUID128_INIT(0x40, 0xb3, 0x20, 0x90, 0x72, 0xb5, 0x80, 0xaf,
+                         0xa7, 0x4f, 0x15, 0x1c, 0xaf, 0xd2, 0x61, 0xe7);
 #define ADC_SNS_TYPE          0xDEAD
-#define ADC_SNS_VAL           0xBEEF
-#define ADC_SNS_STRING "eTape Water Level Sensor"
-
+#define ADC_SNS_STRING "eTape Liquid Level Sensor"
+#define ADC_SNS_VAL           0xBEAD
 uint16_t gatt_adc_val; 
 ```
 
@@ -246,62 +648,57 @@ it will be a read-only characteristic. The second characteristic will be the sen
 itself, and we will allow connected devices to 'subscribe' to it in order to get 
 constantly-updated values.
 
+
+**Note:** You can choose any valid Characteristic UUIDs to go here. We're using these values
+for illustrative purposes only.
+
 The value that we'll be updating is also defined here as `gatt_adc_val`.
 
 If we then go look at `gatt_srv.c` we can see the structure of the service and
 characteristic offering that we set up:
 
 ```c
-
+static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
     {
-        /*** Alert Notification Service. */
+        /*** Service: Security test. */
         .type = BLE_GATT_SVC_TYPE_PRIMARY,
-        .uuid128 = BLE_UUID16(GATT_SVR_SVC_ALERT_UUID),
+        .uuid = &gatt_svr_svc_sec_test_uuid.u,
         .characteristics = (struct ble_gatt_chr_def[]) { {
-            .uuid128 = BLE_UUID16(GATT_SVR_CHR_SUP_NEW_ALERT_CAT_UUID),
-            .access_cb = gatt_svr_chr_access_alert,
-            .flags = BLE_GATT_CHR_F_READ,
+            /*** Characteristic: Random number generator. */
+            .uuid = &gatt_svr_chr_sec_test_rand_uuid.u,
+            .access_cb = gatt_svr_chr_access_sec_test,
+            .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
         }, {
-            .uuid128 = BLE_UUID16(GATT_SVR_CHR_NEW_ALERT),
-            .access_cb = gatt_svr_chr_access_alert,
-            .flags = BLE_GATT_CHR_F_NOTIFY,
-        }, {
-            .uuid128 = BLE_UUID16(GATT_SVR_CHR_SUP_UNR_ALERT_CAT_UUID),
-            .access_cb = gatt_svr_chr_access_alert,
-            .flags = BLE_GATT_CHR_F_READ,
-        }, {
-            .uuid128 = BLE_UUID16(GATT_SVR_CHR_UNR_ALERT_STAT_UUID),
-            .access_cb = gatt_svr_chr_access_alert,
-            .flags = BLE_GATT_CHR_F_NOTIFY,
-        }, {
-            .uuid128 = BLE_UUID16(GATT_SVR_CHR_ALERT_NOT_CTRL_PT),
-            .access_cb = gatt_svr_chr_access_alert,
-            .flags = BLE_GATT_CHR_F_WRITE,
+            /*** Characteristic: Static value. */
+            .uuid = &gatt_svr_chr_sec_test_static_uuid.u,
+            .access_cb = gatt_svr_chr_access_sec_test,
+            .flags = BLE_GATT_CHR_F_READ |
+                     BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC,
         }, {
             0, /* No more characteristics in this service. */
         } },
     },
     {
-        /*** Water Level Notification Service. */
+        /*** ADC Level Notification Service. */
         .type = BLE_GATT_SVC_TYPE_PRIMARY,
-        .uuid128 = gatt_svr_svc_sns_uuid,
+        .uuid = &gatt_svr_svc_adc_uuid.u,
         .characteristics = (struct ble_gatt_chr_def[]) { {
-            .uuid128 = BLE_UUID16(ADC_SNS_TYPE),
+            .uuid = BLE_UUID16_DECLARE(ADC_SNS_TYPE),
             .access_cb = gatt_svr_sns_access,
             .flags = BLE_GATT_CHR_F_READ,
         }, {
-            .uuid128 = BLE_UUID16(ADC_SNS_VAL),
+            .uuid = BLE_UUID16_DECLARE(ADC_SNS_VAL),
             .access_cb = gatt_svr_sns_access,
             .flags = BLE_GATT_CHR_F_NOTIFY,
         }, {
             0, /* No more characteristics in this service. */
         } },
     },
+
     {
         0, /* No more services. */
     },
 };
-
 ```
 
 You should recognize the first services from the [BLE Peripheral](bleprph/bleprph-intro.md)
@@ -320,16 +717,15 @@ gatt_svr_sns_access(uint16_t conn_handle, uint16_t attr_handle,
     uint16_t uuid16;
     int rc;
 
-    uuid16 = ble_uuid_128_to_16(ctxt->chr->uuid128);
-    assert(uuid16 != 0);
+    uuid16 = ble_uuid_u16(ctxt->chr->uuid);
 
     switch (uuid16) {
     case ADC_SNS_TYPE:
         assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
         rc = os_mbuf_append(ctxt->om, ADC_SNS_STRING, sizeof ADC_SNS_STRING);
-        BLEADC_LOG(INFO, "ADC SENSOR TYPE READ: %s\n", ADC_SNS_STRING);
+        BLEPRPH_LOG(INFO, "ADC SENSOR TYPE READ: %s\n", ADC_SNS_STRING);
         return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
-        
+
     case ADC_SNS_VAL:
         if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
             rc = gatt_svr_chr_write(ctxt->om, 0,
@@ -342,169 +738,32 @@ gatt_svr_sns_access(uint16_t conn_handle, uint16_t attr_handle,
                                 sizeof gatt_adc_val);
             return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
         }
+
     default:
         assert(0);
         return BLE_ATT_ERR_UNLIKELY;
-    }                              
+    }
 }
+
 ```
 
-You can see that when the `ADC_SNS_TYPE` is read, we return the
-Sensor Type we defined earlier. If the `ADC_SNS_VAL` we'll return the
+You can see that when request is for the `ADC_SNS_TYPE`, we return the
+Sensor Type we defined earlier. If the request if for `ADC_SNS_VAL` we'll return the
 `gatt_adc_val` value. 
 
 If you build, load and run this application now, you will see all those Services and Characteristics
 advertised, and you will even be able to read the "Sensor Type" String via the ADC_SNS_TYPE
-Characteristic, but when you subscribe to the ADC_SNS_VALUE Characteristic, you
-aren't getting any data. That's because we haven't set up the ADC Sensor yet, or
-created a task to update the value.
-
-<br>
-
-### Creating the ADC Task
-
-In order for the application to send new sensor readings to a connected device, we'll need
-to create a new OS Task to gather values and update them. If you've worked through the
-[Add tasks](task_lesson.md) tutorial, this should look familiar to you at this point.
-
-First, in `main.c` we'll define all the ADC-related things we'll need:
-
-```c
-/* ADC */
-#include "nrf.h"
-#include "app_util_platform.h"
-#include "app_error.h"
-#include <adc/adc.h>
-#include <adc_nrf52/adc_nrf52.h>
-#include <adc_nrf52/adc_nrf52.h>
-#include "nrf_drv_saadc.h"
-
-nrf_drv_saadc_config_t adc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
-```
-
-Next we need to add the task-related requirements:
-
-```c
-/* ADC Task settings */
-#define ADC_TASK_PRIO           5
-#define ADC_STACK_SIZE          (OS_STACK_ALIGN(336))
-struct os_task adc_task;
-bssnz_t os_stack_t adc_stack[ADC_STACK_SIZE];
-```
-
-We'll also need to define a task handler for that task:
-
-```c
-/**
- * Event loop for the ADC task.
- */
-static void
-adc_task_handler(void *unused)
-{
-    
-    gatt_adc_val = 0; 
-    int rc = 0;
-        
-    while (1) {
-        gatt_adc_val++;
-        uint16_t chr_val_handle;
-        
-        rc = ble_gatts_find_chr(gatt_svr_svc_sns_uuid,
-                                  BLE_UUID16(ADC_SNS_VAL),
-                                  NULL, &chr_val_handle);
-        assert(rc == 0);
-
-        ble_gatts_chr_updated(chr_val_handle);
-        
-        /* Wait 2 second */
-        os_time_delay(OS_TICKS_PER_SEC*2);
-        
-    }
-}
-```
-
-At this point you'll notice that we are just incrementing a value, not sending any actual 
-sensor data. Be patient, we'll get there. We're initializiing our 'sensor' data
-variable, `gatt_adc_val` and then heading into our task-loop. 
-
-Once in the task loop, we use `ble_gatts_find_chr()` to get the handle for the 
-characteristic we're updating. and then we let that characteristic know that
-we've updated it's value by calling ` ble_gatts_chr_updated()` with the
-handle for the characteristic. 
-
-Finally we set the update frequency of the characteristic's data via a call to 
-`os_time_delay()` though there are other meachanisms for doing this.
-
-Now that we have this all done, you can actually run this app and see the 
-'sensor' value increase when you're subscribed to it.
+Characteristic.
 
 <br>
 
-### Implementing an Analog to Digital Converter (ADC)
-
-So far we have a functioning BLE Peripheral device that will update a counter
-and send that counter's value to any connected device that asks for it. It's
-a lot, but it's still a far cry from useful. What we realy need is to add a
-real sensor! The sensor we're using, the eTape Liquid Level Sensor, is a
-pretty basic Analog Sensor. As the fluid level changes, the voltage output
-of the sensor changes. In order to read this value, we'll need to access
-the ADC on the nrf52dk, and that's going to take a bit of work. 
-
-If we look at the configuration for the project by running `newt target config nrf52_adc`
-you'll see the configuration of the ADC:
-
-```no-highlight
-* PACKAGE: hw/bsp/nrf52dk
-  * Setting: ADC_0
-    * Description: TBD
-    * Value: 1
-  * Setting: ADC_0_INTERRUPT_PRIORITY
-    * Description: TBD
-    * Value: SAADC_CONFIG_IRQ_PRIORITY
-  * Setting: ADC_0_OVERSAMPLE
-    * Description: TBD
-    * Value: SAADC_CONFIG_OVERSAMPLE
-  * Setting: ADC_0_RESOLUTION
-    * Description: TBD
-    * Value: SAADC_CONFIG_RESOLUTION
-  * Setting: BSP_NRF52
-    * Description: TBD
-    * Value: 1
-```
-
-Next we can look in `hw/bsp/nrf52dk/src/hal_bsp.c`
-and make sure the proper device-creation takes place:
-
-```c
-#if MYNEWT_VAL(ADC_0)
-static struct adc_dev os_bsp_adc0;
-static nrf_drv_saadc_config_t os_bsp_adc0_config = {
-    .resolution         = MYNEWT_VAL(ADC_0_RESOLUTION),
-    .oversample         = MYNEWT_VAL(ADC_0_OVERSAMPLE),
-    .interrupt_priority = MYNEWT_VAL(ADC_0_INTERRUPT_PRIORITY),
-};
-#endif
-```
-
-And also make sure that it gets properly initialized in the 
-`hal_bsp_init()` function:
-
-```
-#if MYNEWT_VAL(ADC_0)
-    rc = os_dev_create((struct os_dev *) &os_bsp_adc0, "adc0",
-            OS_DEV_INIT_KERNEL, OS_DEV_INIT_PRIO_DEFAULT,
-            nrf52_adc_dev_init, &os_bsp_adc0_config);
-    assert(rc == 0);
-#endif
-```
-
 
 ### Adding the eTape Water Sensor
 
 Now that we have a fully functioning BLE App that we can subscribe to sensor
-values from, it's time to turn that incrementing-counter into an actual sensor value!
+values from, it's time to actually wire up the sensor!
 
-As previous;y mentioned, we're going to be using an eTape Water Level Sensor. You can 
+As previously mentioned, we're going to be using an eTape Water Level Sensor. You can 
 get one from [Adafruit](https://www.adafruit.com/products/1786). 
 
 We're going to use the sensor as a resistive sensor, and the setup is very simple. 
@@ -512,135 +771,31 @@ I'll be using a 'breadboard` to put this all together for illustrative purposes.
 First, attach a jumper-wire from Vdd on the board to the breadboard.
 Next, attach a jumper wire from pin P0.03 on the board to the breadboard. This will be
 our ADC-in. The sensor should have come with a 560 ohm resistor, so plug that
-into the baord between Vdd and ADC-in holes. Finally, attach a jumper from
+into the board between Vdd and ADC-in holes. Finally, attach a jumper from
 GND on the board to your breadboard. At this point, your breadboard should look
 like this:
 
 ![Bread Board Setup](pics/breadboard.png)
 
-Now attach one of the middle 2 leads from the sensor to ground on the breadboad and 
+Now attach one of the middle 2 leads from the sensor to ground on the breadboard and 
 the other middle lead to the ADC-in on the breadboard. Your breadboard should now look
 like this:
 
 ![Bread Board Final](pics/adc-demo-1.png)
 
-And yhour eTape Sensor should look like this (at least if you have it mounted in a
+And your eTape Sensor should look like this (at least if you have it mounted in a
 graduated cylinder as I do).
 
 ![eTape Sensor Setup](pics/adc-demo-2.png)
 
 That concludes the hardware portion. Easy!
 
-<br>
-
-### Reading the eTape Water Sensor Values
-
-This is the meat of the application. We've got our BLE application broadcasting and we can connect
-to it and get notified when sensor values change. And we've got our sensor all wired
-up correctly. So let's now make sure the correct values get sent.
-
-First we'll make some changes to the `adc_task_handler()` function to properly initialize
-the ADC.
-
-```c
-    struct adc_dev *adc;
-    nrf_saadc_channel_config_t cc =
-        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
-    cc.gain = NRF_SAADC_GAIN1_6;
-    cc.reference = NRF_SAADC_REFERENCE_INTERNAL;
-    adc = (struct adc_dev *) os_dev_open("adc0", 0, &adc_config);
-    assert(adc != NULL);
-    
-    adc_chan_config(adc, 0, &cc);
-    
-    sample_buffer1 = malloc(adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
-    sample_buffer2 = malloc(adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
-    memset(sample_buffer1, 0, adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
-    memset(sample_buffer2, 0, adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
-    
-    adc_buf_set(adc, sample_buffer1, sample_buffer2,
-            adc_buf_size(adc, ADC_NUMBER_CHANNELS, ADC_NUMBER_SAMPLES));
-    adc_event_handler_set(adc, adc_read_event, (void *) NULL);
-```
-
-A few things need to be said about this part, as it is the most confusing. First, 
-we're using a **default** configuration for the ADC Channel via the `NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE`
-macro. The important part here is that we're actually using `AIN1`. I know what you're thinking, "But 
-we want ADC-0!" and that's true. The board is actually labelled 'A0, A1, A2' etc., and the actual pin 
-numbers are also listed on the board, which seems handy. At first. But it gets messy very
-quickly.
-
-If you try to use AIN0, and then go poke around in the registers while this is running, 
-
-```
-(gdb) p/x {NRF_SAADC_Type}0x40007000
-...
- CH = {{
-      PSELP = 0x1,
-      PSELN = 0x0,
-      CONFIG = 0x20000,
-      LIMIT = 0x7fff8000
-    }, 
-```
-
-You'll see that the pin for channel 0 is set to 1, which corresponts to AIN0, but that's **NOT**
-the same as A0 -- pin P0.03, the one we're using. For that, you use AIN1, which would set the
-pin value to 2. Messy. 
-
-
-The only other thing to note here is that we're using the internal reference voltage, rather than
-setting our own. There's nothing wrong with that, but since we are, we'll have to crank up
-the gain a bit by using `NRF_SAADC_GAIN1_6`.
-
-So, since that's all clear, our task-loop in the `adc_task_handler()` function is extremely simple:
-
-```c
-while (1) {
-    adc_sample(adc);
-    /* Wait 2 second */
-    os_time_delay(OS_TICKS_PER_SEC * 2);
-}
-```
-
-We'll just sample the ADC every 2 seconds or so.
-
-If you noticed above the call to `adc_event_handler_set()` then you'll also know that we'd 
-better define that callback function we set `adc_read_event()`
-
-```c
-int
-adc_read_event(struct adc_dev *dev, void *arg, uint8_t etype,
-        void *buffer, int buffer_len)
-{
-    int i;
-    int adc_result;
-    uint16_t chr_val_handle;
-    int rc;
-    for (i = 0; i < ADC_NUMBER_SAMPLES; i++) {
-        rc = adc_buf_read(dev, buffer, buffer_len, i, &adc_result);
-        if (rc != 0) {
-            goto err;
-        }
-        
-        gatt_adc_val = adc_result_mv(dev, 0, adc_result);
-        rc = ble_gatts_find_chr(gatt_svr_svc_sns_uuid, BLE_UUID16(ADC_SNS_VAL), NULL, &chr_val_handle);
-        assert(rc == 0);
-        ble_gatts_chr_updated(chr_val_handle);
-    }
-
-    adc_buf_release(dev, buffer, buffer_len);
-    return (0);
-err:
-    return (rc);
-}
-```
-
-Whenever the ADC has a sample for us in its buffer, we'll run through the samples available, convert them
-to millivolts, and then update the NOTIFY value so that any connected devices get the updated
-sensor values.
+At this point you should be able to build, create-image and load your application and see it properly 
+sending readings. 
 
 <br>
 
+
 ### Conclusion
 
 Congratulations, you've now completed both a hardware project and a software project by connecting a
@@ -652,6 +807,21 @@ appropriate mailing lists on our [Community Page](../../community.md).
 
 Keep on hacking and sensing!
 
+<br>
+
+### Note
+
+If you're wondering how to actually view these sensor readings via Bluetooth, you have a couple of
+options. On Mac OS or iOS you can download the [LightBlue app](https://itunes.apple.com/us/app/lightblue-explorer-bluetooth/id557428110?mt=8).
+This app lets you connect to, and interrogate, BLE devices like the one you just built. 
+
+If you used the BLE Service and Characteristic UUIDs used in this tutorial, you can also download
+and use a Mac OS [MyNewt Sensor Reader App](https://dragonflyiot.com/MyNewtSensorReader.zip) (Zip Archive) that allows 
+you to graph your data, etc. An iOS version is in Beta testing and should be available soon.
+
+![My Newt Sensor Reader](pics/MyNewtSensorReader006.jpg)
+
+Enjoy!
 
 
 


[3/5] incubator-mynewt-site git commit: Added missing photos

Posted by ad...@apache.org.
Added missing photos


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/9fc9992a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/tree/9fc9992a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/diff/9fc9992a

Branch: refs/heads/develop
Commit: 9fc9992aa00437b0470fbf733cad3d504a6c4909
Parents: 03cd817
Author: David G. Simmons <sa...@mac.com>
Authored: Wed Feb 8 15:25:05 2017 -0500
Committer: David G. Simmons <sa...@mac.com>
Committed: Wed Feb 8 15:25:05 2017 -0500

----------------------------------------------------------------------
 docs/os/tutorials/pics/adc-demo-1.png | Bin 0 -> 530153 bytes
 docs/os/tutorials/pics/adc-demo-2.png | Bin 0 -> 435709 bytes
 docs/os/tutorials/pics/breadboard.png | Bin 0 -> 546231 bytes
 3 files changed, 0 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/9fc9992a/docs/os/tutorials/pics/adc-demo-1.png
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/pics/adc-demo-1.png b/docs/os/tutorials/pics/adc-demo-1.png
new file mode 100644
index 0000000..6e5de58
Binary files /dev/null and b/docs/os/tutorials/pics/adc-demo-1.png differ

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/9fc9992a/docs/os/tutorials/pics/adc-demo-2.png
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/pics/adc-demo-2.png b/docs/os/tutorials/pics/adc-demo-2.png
new file mode 100644
index 0000000..be2cce7
Binary files /dev/null and b/docs/os/tutorials/pics/adc-demo-2.png differ

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-site/blob/9fc9992a/docs/os/tutorials/pics/breadboard.png
----------------------------------------------------------------------
diff --git a/docs/os/tutorials/pics/breadboard.png b/docs/os/tutorials/pics/breadboard.png
new file mode 100644
index 0000000..39a2b9d
Binary files /dev/null and b/docs/os/tutorials/pics/breadboard.png differ