Spresense Header CodeSpresense Header Code

Spresense - 低功耗下的边缘计算

在干电池供电的Spresense板上体验正真的边缘计算

Spresense Arduino Library 的使用方法

本章将从如何获取Spresense Arduino Library到如何使LED亮灯,为大家介绍一个简单的APP开发。

Arduino 中把应用程序(Application Program)叫做Sketch程序。

1. Spresense Arduino Library 的安装方法

1.1. 可用平台

Spresense Arduino Library 可在以下平台上运行。

  • Windows 8.1/10

  • 64bit版 Linux Ubuntu 16.04

  • Mac OSX 10.12 Sierra

不支持32bit版Linux。

1.2. 事前准备

Arduino IDE バージョンは、1.8.x 以降を使用してください。
重新连接后以上设置生效。
未设置时,Arduino中编写的软件将无法上传到Spresense电路板上。

1.3. Spresense Arduino board package 的安装

下面说明一下Spresense Arduino board package的安装方法。

除了以下方法外,还可通过 git clone 或是下载安装包手动安装的方式手动安装。
  1. 启动Arduino IDE。

  2. 打开环境设置。

    arduino borad manager preference cn
    图表 1. Arduino IDE环境设定
  3. 在要添加的电路板管理程序URL地址中输入以下URL并单击 OK

    https://github.com/sonydevworld/spresense-arduino-compatible/releases/download/generic/package_spresense_index.json
    arduino borad manager add json url cn
    图表 2. 指定电路板管理程序 json文件
  4. 选择工具电路板电路板管理程序 并打开该程序。

    tutorial arduino open boardmanager cn
    图表 3. 电路板管理程序的打开方式
  5. 检索 Spresense 并单击 安装 完成安装。

    安装中约耗费*150MB*的下载流量,请在固定流量套餐等环境下安装。
    安装包检索出错时,请确认 文件 > 环境设置 > 网络 中代理相关的设置。
    tutorial arduino boardmanager spresense install cn
    图表 4. 检索并安装Spresense
    电路板管理程序中需要单击相应安装包后才显示安装按钮。

2. Spresense Arduino Library 编码环境的设置

2.1. USB串口检查

事前准备请参考,安装完USB驱动后,将USB数据线与Spresense主板连接。

如下图所示,蓝色LED亮灯表示已与PC连接。

spresense musb connect
图表 5. Connection to the Spresense main board USB connector with power LED on

各平台下USB端口的确认方法如下。

2.1.1. Windows上的USB串口驱动检查

  1. 设备管理器 打开。

  2. 确认 Silicon Labs CP210x USB to UART Bridge 的COM端口号。

    tutorial arduino windows device manager find port
    图表 6. 确认设备管理器中的COM端口

    这个例子中 COM9 为已连接状态。

    Spresense 主板在设备管理器中显示为 Silicon Labs CP210x USB to UART Bridge

2.1.2. Ubuntu 64bit上的USB串口驱动检查

Spresense 检索Spresense电路板所连接的COM端口。

  1. 打开终端。

  2. 在终端上输入以下命令。

    $ dmesg | grep "cp21.*attached"
    [12220.625979] usb 1-1: cp210x converter now attached to ttyUSB0

    这个例子中 ttyUSB0 为已连接状态。

2.1.3. Mac OSX上的USB串口驱动检查

检索Spresense 电路板所连接的COM端口。

  1. 打开终端。

  2. 在终端上输入以下命令。

    $ ls /dev/{tty,cu}.*
    /dev/cu.SLAB_USBtoUART  /dev/tty.SLAB_USBtoUART

    这个例子中 cu.SLAB_USBtoUART 为已连接状态。

2.2. Spresense Loader的安装

使用电路板前,需要在电路板中安装Loader。请按以下步骤安装Loader。

安装前提是Spresense Arduino board package 的安装已完成。

出厂时,Spresense 电路板为未安装Loader的状态。
Spresense主板与PC已通过micro USB数据线连接。
  1. Arduino IDE的启动。

  2. Spresense 电路板中选择 工具 > 电路板> Spresense

    tutorial arduino boardsmanager menu cn
    图表 7. Spresense 电路板被选择
  3. 连接USB数据线与Spresense的USB接口, 选择 工具 > 串口 ,选择COM端口。

    选择Spresense电路板图连接的COM端口。

    在不了解所要连接的com口时,请参考 USB串口检查一章。

    tutorial arduino select port cn
    图表 8. Spresense 选择电路板连接的COM端口
  4. 工具 > 写入装置 选择*Spresense Firmware Updater* 。

    tutorial arduino select programmer cn
    图表 9. Spresense Firmware Updater 的选择
  5. 选择 工具 > 写入BootLoader ,安装BootLoader与二进制库。

    tutorial arduino tools menu do burn cn
    图表 10. '写入BootLoader' 选择
  6. 确认 End User License Agreement 对话框中License内容,勾选 I Accept the terms in the license agreement 后点击 OK 按钮。

    tutorial arduino eula dialog
    图表 11. End User License Agreement的对话框
    Spresense的使用,需要同意End User License Agreement协议。
    之后只要电路板管理器未发生更新则不会再次显示出现。
  7. Arduino IDE(下面图片中的红框)中出现以下提示时表示安装结束。

    BootLoader写入完成。
    
    updater# Restarting the board ...
    reboot
    tutorial arduino fw update done cn
    图表 12. 安装结束时Arduino IDE上显示的提示消息

3. Spresense 上运行LED相关的Sketch程序

以上でSpresense Arduino board package 已经准备完成。下面我们来运行一下LED样例Sketch程序来确认下环境设置是否正确。

  1. 将以下LED样例Sketch程序复制到Arduino IDE中。

    void setup() {
        pinMode(LED0, OUTPUT);
        pinMode(LED1, OUTPUT);
        pinMode(LED2, OUTPUT);
        pinMode(LED3, OUTPUT);
    }
    
    void loop() {
        digitalWrite(LED0, HIGH);
        delay(100);
        digitalWrite(LED1, HIGH);
        delay(100);
        digitalWrite(LED2, HIGH);
        delay(100);
        digitalWrite(LED3, HIGH);
        delay(1000);
    
        digitalWrite(LED0, LOW);
        delay(100);
        digitalWrite(LED1, LOW);
        delay(100);
        digitalWrite(LED2, LOW);
        delay(100);
        digitalWrite(LED3, LOW);
        delay(1000);
    }
  2. 单击*Upload* 按钮,完成Sketch程序的编译和上传。

    tutorial arduino upload cn
    图表 13. Upload 按钮单击
  3. 上传成功结束时的提示消息。

    tutorial arduino sketch done uploading cn
    图表 14. 上传成功结束时的提示消息
  4. 确认程序动作。成功上传时,Spresense上的LED灯会闪烁。

    程序上传结束后,Spresense电路板会自动重置。
  5. 至此,环境设置完成。

4. 首次使用 Spresense 的Step Counter说明

4.1. Sensing程序库运行环境

请根据您要检测到的内容连接必要的传感器。

4.1.1. Step Counter运行环境

为了Step Counter程序库正常使用,以下是一些你需要事先准备好的事情。

这次提供的算法被调整为Bosch的BMI160和Rohm有限公司的传感器外接板。 SPRESENSE-SENSOR-EVK-701也可使用。

4.2. Sensing程序库示例

使用Step Counter (Sensing)的示例可从Arduino IDE File → Examples → Examples for Spresense Sensing → application 下获得。

4.2.1. Step Counter示例

自v1.3.0以来,索尼算法将随引导加载程序更新一起安装。最新版本的 请更新到引导加载程序。

Arduino IDE上通过 File → Examples → Examples for Spresense Audio → application → step_counter 运行示例程序。

启动程序后

"-----------------------------------------------------------" +
"      tempo,     stride,      speed,       step,  move-type"

继续显示。

Step Counter更改程序库中的物理传感器。

Rohm制造的传感器板 SPRESENSE-SENSOR-EVK-701 下面的示例演示如何更改。

  • 安装KX122程序库
    这里 下载程序库。
    「Clone or download」→「Download ZIP」并将其保存到任何文件夹。
    将下载的文件解压缩到任何文件夹。
    从Arduino的菜单中,单击「Sketch」→「Include Library」→「Add .ZIP Library…​」从您选择和展开的文件夹中选择「KX122」文件夹。

  • 修改示例

#include <BMI160Gen.h>

#include <Wire.h>
#include <KX122.h>
KX122 kx122(KX122_DEVICE_ADDRESS_1F);

如果要更改和初始化,

BMI160.begin(BMI160GenClass::I2C_MODE, i2c_addr);

Wire.begin();
kx122.init();

必须更改并获取数据

BMI160.readAccelerometerScaled(x, y, z);

kx122.get_val(acc);
/* acc 用 float acc[3] */

并将这些数据传递到逻辑传感器

AccelSensor.write_data(x, y, z);

AccelSensor.write_data(acc[0], acc[1], acc[2]);

可以更改。

kx122设置为50Hz,即使在程序库中也是如此。
Step Counter首次制造专有的逻辑传感器。

如果要在不使用当前提供的索尼算法Step Counter (AESM) 情况下,实现自己的步进计数器算法, 请创建逻辑传感器客户端, 如下所示:

创建从传感器客户端继承的逻辑传感器类。

例如,在MyCounter.h实现MyCounterClass类。根据需要包括头文件。例如,SensorClient.h是必要的,但只有当您要使用步进计数器的定义时,才需要使用sensing/logical_sensor/step_counter.h中StepCounter。

例如, 下图显示了常用代码的存储位置。

diag b936c6b05e866fd235bbb90a0fb0c932
图表 15. MyCounter代码存储位置示例

以上是Windows环境的一个示例,如果是Ubuntu环境,则为 ~/Arduino ; 如果是macOS环境,则为 ~/Documents/Arduino

class MyCounterClass : public SensorClient

其中 MyCounterClass

bool begin(int id,
           uint32_t subscriptions,
           int      rate,
           int      sample_watermark_num,
           int      size_per_sample));

int publish(FAR void* data,
            uint32_t  size_per_sample,
            uint32_t  freq,
            uint32_t  sample_watermark_num,
            uint32_t  timestamp);

int subscribe(sensor_command_data_mh_t& data);

在MyCounter.cpp中实现(重写)。

  • begin() 执行 :

    通过MyCounter初始设置,您需要注册callback函数以接收publish加速度计的数据。callback函数调用MyCounter的 subcribe() 并传递数据。

    描述示例
    unsigned char mycounter_cb(sensor_command_data_mh_t &data)
    {
      return MyCounter.subscribe(data);
    }
    
    bool MyCounterClass::begin(int      id,
                               uint32_t subscriptions,
                               int      rate,
                               int      sample_watermark_num,
                               int      size_per_sample)
    {
      return SensorClient::begin(id,
                                 subscriptions,
                                 rate,
                                 sample_watermark_num,
                                 size_per_sample,
                                 mycounter_cb);
    }
  • subscribe() 执行 :

    您可以通过订阅加速传感器数据创建自己的Step Counter计数器,并使用自己的算法进行处理。

    使用程序库提供的 AccelSensorClass 时,发送的数据50个频率50Hz的样本。在下面的示例中,x、y和z轴排列为 st_accel_axis 。 若要检索此数据,请在基类 ( SensorClient )中调用 Subscribe()

    描述示例
    int MyCounterClass::subscribe(sensor_command_data_mh_t& data)
    {
      struct st_accel_axis
      {
        float x;
        float y;
        float z;
      } *accel_axis;
    
      accel_axis = static_cast<accel_axis*>(SensorClient::subscribe(data));
      uint32_t  timestamp = data.time;
    
      SensorResultStepCounter output;
    
      /*
        实现您自己的算法。
        在输出中放置一个值。
       */
    
      publish(&output,
              sizeof(SensorResultStepCounter),
              1, /* 1Hz */
              1, /* 1sample */
             timestamp);
    }
    subscribe数据已成为 sensor_command_data_mh_t 。有关这个数据结构,请参阅 这里 此处。
  • publish() 执行 :

    publish() 将发出MyCounter计算的值。 Stepfindreader 作为读出应用程序客户端提供的数据结构,如果要按原样使用,则进行publish。

    SensorResultStepCounter

    必须发送。

    如果以上述 SensorResultStepCounter 类型通过,则按基类( SensorClient )进行使用 publish() 没有问题。

以下是 SensorResultStepCounter 类型介绍。

/*--------------------------------------------------------------------------*/
/**
 * @struct StepCounterStepInfo
 * @brief the structure of STEP_COUNTER results.
 */
typedef struct {

  float    tempo;     /**< Indicates tempo of walking / jogging calculated
                       *   from the input acceleration data.
                       *   The unit is [Hz].
                       */
  float    stride;    /**< Indicates stride calculated
                       *   from input acceleration data.
                       *   The unit is [cm].
                       */
  float    speed;     /**< Indicates speed of walking / jogging calculated
                       *   from the input acceleration data.
                       *   The unit is [m/s].
                       */
  float    distance;  /**< Indicates cumulative travel distance calculated
                       *   from the input acceleration data.
                       *   The unit is [m].
                       */
  uint32_t step;      /**< Indicates the number of steps calculated
                       *   from the input acceleration data.
                       * The unit is [step].
                       */
  StepCounterMovementType  movement_type; /**<
                                    * Indicates the walking type calculated
                                    * from the input acceleration data.
                                    */
  uint64_t          time_stamp;    /**< Indicates latest timestamp of the
                                    *   acceleration sensor data used.
                                    */
} StepCounterStepInfo;

/*--------------------------------------------------------------------------*/
/**
 * @struct SensorResultStepCounter
 * @brief the structure of sensor result on step counter commands.
 */
typedef struct
{
  SensorExecResult exec_result; /**< Execute resule.  */

  union
    {
      StepCounterStepInfo steps;        /**< Step count.         */
      SensorAssertionInfo assert_info;  /**< Assert information. */
    };
} SensorResultStepCounter;
尝试根据逻辑传感器更改数据。

当然,您可能希望根据自己的逻辑传感器更改传感器数据。在这种情况下

publish时,MyCounter会更改数据类型

int MyCounterClass::subscribe(sensor_command_data_mh_t& data)
{
  ..()..

  MyStepCounterResult output;

  publish(&output,
          sizeof(MyStepCounterResult),
          1, /* 1Hz */
          1, /* 1sample */
          timestamp);
}

在读取Application上( StepCountReaderClass )

subscribe()
{
  MyStepCounterResult* steps = reinterpret_cast<MyStepCounterResult*>(ApplicationSensorClass.subscribe(data));
}

并转换。

4.3. 尝试制造一种新的物理传感器

[T.B.D]

5. 初次搭建Spresense的Arduino多核环境

了解使用 Arduino IDE 的多核编程开发环境。

在 Arduino 多核环境中,使用 MultiCore MP 库。 应用程序 CPU 共有六个内核,包括一个 MainCore 和五个 SubCore 。 在典型的单核应用程序中,用户仅使用 MainCore 进行编程。 另一方面,通过使用此处描述的多核环境,用户负责包括 SubCore 在内的所有内核 您将能够编写和执行任何应用程序。

MainCore

MainCore将在通电时被激活。

SubCore(s)

SubCore将由MainCore控制推出。 总共有五个分核心。

在本教程中,您将移动 MultiCore MP 库附带的两个Example类型。

多核启动示例

启动四个次核心并使用多核执行L Chica。
通过使此示例工作,您可以了解启动SubCore的过程。

多核MessageHello示例

在MainCore和SubCore之间传达消息。
通过使此示例正常工作,您可以了解如何与 MainCore 和 SubCore 进行通信。

5.1. 初次使用多核引导示例

主要步骤

  1. 使用Arduino IDE打开示例

  2. 选择核心

  3. 编译和上传

重复任意数量的内核,以便使其正常工作。

请尝试执行以下步骤。

  • 从桌面启动 Arduino IDE
    (如果桌面上没有图标,请从 "开始" 菜单开始。)

    arduino multicore desktop
    在多核编程中启动多个 Arduino IDE 窗口时,需要考虑一些事项。
    例如,如果从Arduino IDE 菜单创建带有 File → New 的新窗口,例如,如果在一个窗口中切换 Core 选择菜单,则设置将链接到所有窗口 它将得到反映。
    作为一种解决方法,当您为每个 Core 打开多个Arduino IDE 窗口时,每次都从桌面上的图标启动Arduino IDE。通过这样做,菜单设置 (如 Core ) 选择不会链接到每个窗口 将能够独立设置
  • MainCore编程

    • 从Arduino IDE菜单中, File → Examples → Examples for Spresense → MultiCore MP → Boot → Main 打开示例

      arduino multicore boot0
      arduino multicore boot1 main
    • Main.ino示例描述

      MP.begin(subid) 启动子ID参数指定的子核心。
      在这种情况下,我们将总共启动四个子核心从 SubCore1 到 SubCore4。

      arduino multicore boot4 main
    • 从Arduino IDE菜单中,选择 Tools → Core → MainCore

      arduino multicore boot2 main

      您可以在下面的状态栏中验证是否选择了 MainCore

      arduino multicore boot3 main
      在Arduino IDE 1.8.9切换菜单时,
      有一个状态栏显示不正确的问题。
    • 按下Upload按钮Compile&Upload

      arduino multicore boot5 main
      不能同时从多个窗口上传多个核心程序。
      执行上传操作,以便每个内核避免同时运行。
    • 将显示编译结果日志中使用的内存大小

      MainCore 始终使用768 KByte内存。

      arduino multicore boot6 main

      如果上传成功完成,MainCore编程就完成了。

      • 尝试在缺少SubCore程序的情况下启动串行监视器。
        由于SubCore不存在,您可以看到 MP.begin(1~4) 调用返回时出现错误。

        arduino multicore boot7 serial err

        如果打开了串行监视器,则可能无法从其他窗口正确上传。
        完成验证后,关闭串行监视器。

下面是SubCore编程。

  • SubCore编程

    • 从Arduino IDE菜单 File → Examples → Examples for Spresense → MultiCore MP → Boot → Sub1 打开示例

      arduino multicore boot0
      arduino multicore boot1 sub1
    • Sub1.ino示例说明

      在setup()中调用 MP.begnin() ,通知 MainCore 启动已完成。
      loop()中LED0日志显示由 MPLog() 和闪烁控制。

      arduino multicore boot4 sub1
    • 从Arduino IDE菜单选择 Tools → Core → SubCore 1

      arduino multicore boot2 sub1

      您可以在下面的状态栏中验证是否选择了 SubCore1

      arduino multicore boot3 sub1
      在Arduino IDE 1.8.9中切换菜单时
      有一个状态栏显示不正确的问题。
    • 按下Upload按钮Compile&Upload

      arduino multicore boot5 sub1
      不能同时从多个窗口上载多个核心程序。
      执行上传操作,以便每个内核避免同时运行。
    • 将显示编译结果日志中使用的内存大小

      您可以看到,此处使用的子酷示例草图使用128 KByte 内存。
      此大小取决于用户程序,并增加或减少。

      arduino multicore boot6 sub1

      如果上传成功完成,SubCore1的编程就完成了

  • 在SubCore2、3、4 的相同过程中,请执行Compile & Upload

    • 打开Sub2示例并选择SubCore 2,Compile & Upload

    • 打开Sub3示例并选择SubCore 3,Compile & Upload

    • 打开Sub4示例并选择SubCore 4,Compile & Upload

  • 动作检查

    • Spresense主板闪光灯上的四个绿色LEDS

    • 当您打开串行监视器时,您将看到来自每个内核的日志输出。

      arduino multicore boot7 serial
  • 总结

    • 一个简单的示例用于解释如何启动SubCore。
      将现有草图移植到多核环境时,添加对 MP.begin() 的调用。

    • 在多核环境中,基本用法,如 Arduino IDE 的Compile & Upload方法,并没有变化。 主要区别在于,核心选择菜单已添加到 Tool → Core 中。

5.2. 初次使用多核MessgeHello示例

主要步骤与多核启动示例的步骤相同。
这个示例在MainCore和SubCore(s)中使用常见的草图。

  1. 使用Arduino IDE打开示例(仅一次)

  2. 选择核心

  3. 编译和上传

重复任意数量的内核,以便使其正常工作。 此示例移动所有SubCore(共5个)。

请尝试执行以下步骤。

  • 从桌面启动Arduino IDE
    (如果桌面上没有图标,请从 "开始" 菜单开始。)

    arduino multicore desktop
    在多核编程中启动多个Arduino IDE窗口时,需要考虑一些事项。
    如果从Arduino IDE菜单中点击 File → New 菜单,例如,如果在一个窗口中切换 Core 选择菜单,它将与该设置一起反映在所有窗口中。
    作为一种解决方法,当您为每个 Core 打开多个Arduino IDE窗口时,每次都从桌面上的图标启动Arduino IDE。 通过这样做,菜单设置 (如 Core ) 选择不会链接到每个窗口 可以独立设置。
  • MainCore编程

    • 从Arduino IDE菜单中 File → Examples → MultiCore MP → Messsage → MessageHello 打开示例

      arduino multicore boot0
      arduino multicore hello1
    • MessageHello.ino示例描述

      使用示例中的 #ifdef SUBCORE ~ #else ~ #endif 在主要核心和子核心实现之间切换。

      • MainCore源代码

        setup() 通过 MP.begin(subid) ,将启动五个子核心。
        在setup()最后, MP.RecvTimeout(MP_RECV_POLLING) 将接收设置为轮询模式。
        在loop() 中,MP.Recv() 接收来自各个SubCore的数据包地址,并在数据包printf()中输出消息。

        arduino multicore hello4 main
      • SubCore源代码

        在setup()中,调用 MP.begin() ,通知 MainCore 启动已完成。
        在loop()中,将"Hello"消息存储在数据包中,并使用其地址的 MP.Send() 到MainCore。

        arduino multicore hello4 sub
    • 在Arduino IDE菜单中,选择 Tools → Core → MainCore

      arduino multicore hello2 main

      在下面的状态栏中验证是否选择了 MainCore

      arduino multicore boot3 main
      在Arduino IDE 1.8.9切换菜单时
      有一个状态栏显示不正确的问题。
    • 按下Uplod按钮Compile & Uplod

      arduino multicore hello5 main
      不能同时从多个窗口上载多个核心程序。
      应执行上传操作,以便每个内核避免同时运行。
    • 将显示编译结果日志中使用的内存大小

      MainCore 始终使用768 KByte内存

      arduino multicore boot6 main

      如果上传成功完成,MainCore编程就完成了。

下面是SubCore执行

  • SubCore编程

    • 在Arduino IDE菜单中,选择 Tools → Core → SubCore 1

      arduino multicore hello2 sub1

      在下面的状态栏中验证是否选择了 SubCore 1

      arduino multicore boot3 sub1
      在Arduino IDE 1.8.9切换菜单时
      有一个状态栏显示不正确的问题。
    • 按下Upload按钮Compile & Upload

      arduino multicore hello5 main
      不能同时从多个窗口上载多个核心程序。
      执行上传操作,以便每个内核避免同时运行。
    • 将显示编译结果日志中使用的内存大小

      您可以看到,此处使用的子酷示例草图使用128 KByte内存。
      此大小取决于用户程序,并增加或减少。

      arduino multicore boot6 sub1

      如果上传成功完成,SubCore1的编程就完成了

  • 按照子核心2、3、4、5 Compile & Upload的相同过程

    • 选择SubCore 2,Compile & Upload

    • 选择SubCore 3,Compile & Upload

    • 选择SubCore 4,Compile & Upload

    • 选择SubCore 5,Compile & Upload

  • 动作检查

    • 请打开串行监视器

    • 每个SubCore发送的消息将由MainCore接收并显示在串行监视器上。

      arduino multicore hello7 serial
  • 总结

    • 讨论了如何使用示例与SubCore进行通信。

    • 由于内存在内核之间共享,因此可以传递地址并与消息进行通信。

    • 多核编程与共同的示例,而不分离每个核心的草图也是可能的。

5.3. 注意事项

  • 有关 MultiCore MP 的详细信息,请参阅 開発ガイド 文档。

  • 如果有一个已经上传到Spresense板上的SubCore二进制文件,并且想一次删除它们,Spresense Loader的安装 安装加载程序时,删除所有SubCore二进制文件,然后装载机安装开始。

    arduino multicore remove subcore

    请注意,除非从MainCore调用 MP.begin() ,否则 SubCore 将无法在未经允许的情况下工作。 因此,即使旧的SubCore仍在上传,也没有问题。

  • 在多核编程中,每个 Core 打开多个Arduino IDE窗口时,每次都可以从桌面上的图标启动Arduino IDE。请启动 Arduino IDE。 这样,可以为每个窗口单独设置菜单设置,如 Core 选择 。

  • 在Arduino IDE中的多个启动和Core之间切换是很麻烦的,但还可以使用命令行工具arduino-builder arduino-cli。上传也是可以使用flash_writer工具使用一个命令加载每个内核的二进制文件。命令行方法将在以后发布在文档中。