Developer World Spresense
English 日本語
目录

1. Audio 教程

Audio库提供各种示例sketch,包括播放和录制音频。

利用Spresense的多核特征,诸如音频编码/解码的处理在与用户应用操作的主核不同的核(以下称为DSP)中执行。 这允许用户轻松开发使用音频功能的应用程序,而无需复杂的控制。

音频教程说明如何安装DSP文件以及如何使用各种示例sketch。

1.1. 安装DSP文件

运行示例前,必须根据播放/录制的格式预先安装DSP文件。 本节介绍如何安装DSP文件。

1.1.1. DSP文件类型

表格 1. DSP类型
DSP文件名 DSP安装程序 说明

MP3DEC

mp3_dec_installer

用于MP3音频播放

MP3ENC

mp3_enc_installer

用于MP3录音

WAVDEC

wav_dec_installer

用于WAV(PCM)音频播放

SRC

src_installer

用于WAV(PCM)录音

1.1.2. DSP安装方法

有两种方法可以安装DSP:

  • 下载DSP文件并将其直接复制到microSD卡

  • 使用DSP安装程序sketch

往microSD卡上安装的方法没有特别限制。 使用DSP安装程序时,除了扩展板上的microSD卡外,还可以安装到主板上的SPI-Flash。

注意:除非更新DSP文件,否则一次安装后不需要每次都执行DSP文件安装过程。

1.1.2.1. 将DSP文件复制并安装到microSD卡
  1. 在这里下载最新的DSP文件。

  2. 在FAT32格式的microSD卡上创建BIN目录并复制下载的文件。

arduino dsp copy cn
图表 1. DSP文件复制
  1. 运行音频示例时请将此microSD卡插入扩展板。

1.1.2.2. 使用DSP安装程序安装

为每个DSP文件都提供了DSP安装程序。

  1. 运行Arduino IDE, 选择 File→ Sketch Example→ Spresense Sketch Example Audio→ dsp_installer

    arduino dsp installer cn
    图表 2. 启动DSP安装程序
  2. 选择 Tools→ Serial Port 下的Spresense COM端口,执行写入操作。

  3. 编译和写入(上载)完成后,启动Serial monitor。

  4. 选择波特率115200 bps时,将显示如下所示的消息。

  5. 选择安装编号,然后按“发送”按钮。
    安装到microSD卡时,将FAT32格式的microSD卡插入扩展板上的microSD卡插槽。

    arduino dsp installer monitor1 cn
    图表 3. 选择DSP安装位置
  6. 如果安装成功,将显示以下消息。

    arduino dsp installer monitor2 cn
    图表 4. DSP安装执行
在音频播放/录制应用程序中,使用 initPlayer()initRecorder() 函数的参数指定安装DSP文件的位置。 默认为microSD卡( /mnt/sd0/BIN )。使用SPI-Flash时,将其更改为 /mnt/spif/BIN

1.2. 播放蜂鸣音

1.2.1. 摘要

此示例使用音频硬件的功能输出蜂鸣声。

指定频率的声音由音频库的setBeep()函数输出。 此功能与Arduino tone()功能非常相似,但不需要准备压电蜂鸣器。 声音从Spresense扩展板的耳机插孔输出。

在此示例中,不需要安装DSP文件。

1.2.2. 运行环境

  • Spresense主板和扩展板

  • 播放耳机或扬声器

将耳机或有源扬声器连接到扩展板上的耳机插孔。

1.2.3. 操作程序

  1. 运行Arduino IDE,选择 File→ Sketch Example→ Spresense Sketch Example Audio→ application→ beep 打开示例sketch。

    arduino audio examples beep
  2. Tools→ Serial Port 中选择Spresense COM端口并写入微控制器板。

    arduino audio examples beep2
  3. 耳机输出音阶音。

1.2.4. 程序说明

  • 使用 setPlayerMode() 函数设置播放器模式。

    theAudio->setPlayerMode(device,          (1)
                            player0bufsize,  (2)
                            player1bufsize); (3)
    1 device :选择输出设备,输出到扬声器耳机( AS_SETPLAYER_OUTPUTDEVICE_SPHP ),I2S( AS_SETPLAYER_OUTPUTDEVICE_I2SOUTPUT )。
    此示例使用 AS_SETPLAYER_OUTPUTDEVICE_SPHP
    使用I2S时,请参阅输出到I2S
    2 player0bufsize :指定播放器0的缓冲区大小。
    3 player1bufsize :指定播放器1的缓冲区大小。 有关详情,请参见关于播放器缓冲区大小
    如果仅输出蜂鸣声,则不使用缓冲区,因此在此示例中指定了0。
  • 要输出蜂鸣声,请使用 setBeep() 函数。

    theAudio->setBeep(enable,     (1)
                      volume,     (2)
                      frequency); (3)
    1 enable 设置为 1 时,蜂鸣声输出开始,当 enable 设置为 0 时停止。
    2 volume :音量可以改变(-90到0[dB])。
    3 frequency :输出指定频率的声音。

1.3. 播放MP3音乐

1.3.1. 摘要

播放microSD卡上的MP3音乐文件。

1.3.2. 运行环境

  • Spresense主板和扩展板

  • microSD卡

  • 播放耳机或扬声器

此示例使用microSD卡和耳机。 将耳机或有源扬声器连接到扩展板上的耳机插孔。

1.3.3. 操作程序

  1. 在microSD卡上安装MP3解码DSP文件 MP3DEC (参见安装DSP文件)。

  2. 将要播放的MP3文件放在microSD卡的根目录中,文件名为“Sound.mp3”。

  3. 将microSD卡插入扩展板上的microSD卡插槽。

  4. 运行Arduino IDE,选择 File→ Sketch Example→ Spresense Sketch Example Audio→ application→ player 打开示例sketch。

    arduino audio examples player
  5. Tools→ Serial Port 中选择Spresense COM端口并写入微控制器板。

  6. 上传并执行sketch时,耳机将播放放置在microSD卡上的MP3文件。
    当文件播放到最后时停止。

1.3.4. 程序说明

  • 使用 setRenderingClockMode() 函数设置时钟模式。

    theAudio->setRenderingClockMode(mode); (1)
    1 mode :选择正常( AS_CLKMODE_NORMAL ),高分辨率( AS_CLKMODE_HIRES )时钟模式。
    MP3播放时指定“AS_CLKMODE_NORMAL”。
  • 使用 setPlayerMode() 函数设置播放器模式。

    theAudio->setPlayerMode(device,  (1)
                            sp_drv); (2)
    1 device :选择输出设备,输出到扬声器耳机( AS_SETPLAYER_OUTPUTDEVICE_SPHP ),I2S( AS_SETPLAYER_OUTPUTDEVICE_I2SOUTPUT )。
    此示例使用 AS_SETPLAYER_OUTPUTDEVICE_SPHP
    使用I2S时,请参阅输出到I2S
    2 sp_drv :设置输出驱动器。
    在此示例中,指定“AS_SP_DRV_MODE_LINEOUT”。
    有关详细信息,请参阅使用扩展板上的扬声器端子时
  • 使用 initPlayer() 函数初始化播放器。

    theAudio->initPlayer(id,         (1)
                         codec,      (2)
                         codec_path, (3)
                         fs,         (4)
                         channel);   (5)
    1 id :选择播放器ID。
             此示例使用 AudioClass::Player0
    2 codec :指定MP3( AS_CODECTYPE_MP3 )作为编解码器类型。
    3 codec_path :指定安装DSP文件的位置。
          为microSD卡指定 / mnt/sd0/BIN ,为SPI-Flash指定 /mnt/spif/BIN
    4 fs :指定采样率。
          MP3支持32kHz( AS_SAMPLINGRATE_32000 ),44.1kHz( AS_SAMPLINGRATE_44100 ),48kHz( AS_SAMPLINGRATE_48000 )。 如果指定 AS_SAMPLINGRATE_AUTO ,则自动确定采样率。
    5 channel :指定单声道( AS_CHANNEL_MONO )或立体声( AS_CHANNEL_STEREO )。
  • 使用 writeFrames() 函数将MP3文件的内容写入解码器。

    theAudio->writeFrames(id,      (1)
                          myFile); (2)
    1 id :选择播放器ID。
         此示例使用 AudioClass::Player0
    2 可以使用参数中指定的myFile更改播放文件。
        此示例使用名为“Sound.mp3”的文件。
        周期性地执行该函数以将流提供给解码器,从而不中断解码。     当函数写入文件末尾时,返回 AUDIOLIB_ECODE_FILEEND 作为函数的返回值。
  • 使用 startPlayer() 函数启动播放器。

    theAudio->startPlayer(id); (1)
    1 id :选择播放器ID。
         此示例使用 AudioClass::Player0
         使用 writeFrames() 函数写入解码器后调用该函数。
  • 使用 stopPlayer() 函数停止播放器。

    theAudio->stopPlayer(id,    (1)
                         mode); (2)
    1 id :选择播放器ID。
         此示例使用 AudioClass::Player0
    2 可以选择是立即停止( AS_STOPPLAYER_NORMAL )还是等到已经提供给解码器的流完成播放( AS_STOPPLAYER_ESEND )。 如果没有指定 mode ,则缺省为 AS_STOPPLAYER_NORMAL
  • 使用 setVolume(volume) 功能调节音量。

    theAudio->setVolume(volume); (1)
    1 volume :您可以更改音量。 (-1020至120)
    指定值的1/10是实际音量[dB]。 例如,当指定15时,音量为1.5 [dB]。

1.3.5. 关于播放器缓冲区大小

默认情况下,每个播放器用于从microSD卡读取的缓冲区大小为160kByte。 此大小是可以读取高分辨率WAV音频的大小,以及播放48 kHz MP3文件等的大小。 您可以通过设置 setPlayerMode 函数参数以减少缓冲区大小。 作为示例,当播放192kHz高分辨率WAV文件时,默认为160kByte 播放大约128kbps的MP3文件时,建议设置为大约24kByte。

注意:尺寸仅供参考。 请根据microSD卡性能,应用吞吐量等进行调整。 如果缓冲区太小,从microSD卡读取时会发生错误。 如果发生读取数据下溢,请增加缓冲区大小。

1.3.6. 输出到I2S

如果要将输出设备切换到I2S,请将 setPlayerMode 中的输出设备切换到 AS_SETPLAYER_OUTPUTDEVICE_I2SOUTPUT 。 I2S的工作模式仅支持从模式,I2S格式模式,48000Hz和立体声。

1.3.7. 使用扩展板上的扬声器端子时

在使用扩展板的耳机端子作为音频输出的情况下,作为音频信号的驱动能力设置, setPlayerModesp_drv 指定为 AS_SP_DRV_MODE_LINEOUT (默认值)。

从扩展板的扬声器端子输出时,参数 sp_drv 指定为 AS_SP_DRV_MODE_4DRIVER

使用扬声器端子时,需要修改电路板。 有关详细信息,请参阅: 如何使用扬声器

1.4. 播放WAV音乐

1.4.1. 摘要

播放microSD卡上的WAV音乐文件。

1.4.2. 运行环境

  • Spresense主板和扩展板

  • microSD 卡

  • 播放耳机或扬声器

此示例使用microSD卡和耳机。。 将耳机或有源扬声器连接到扩展板上的耳机插孔。

1.4.3. 操作程序

  1. 在microSD卡上安装WAV解码DSP文件 WAVDEC (参见安装DSP文件)。

  2. 将要播放的WAV文件放在microSD根目录中,名称为“Sound.wav”。

  3. 将microSD卡插入扩展板上的microSD卡插槽。

  4. 运行Arduino IDE,选择 File→ Sketch Example→ Spresense Sketch Example Audio→ application→ player_wav 打开示例sketch。

    arduino audio examples player wav

Tools→ Serial Port 中选择Spresense COM端口并写入微控制器板。

上传并执行sketch时,将从耳机播放放置在microSD卡上的WAV文件。
当文件播放到最后时,它将停止。

1.4.4. 程序说明

  • 使用 setRenderingClockMode() 函数设置时钟模式。

    theAudio->setRenderingClockMode(mode); (1)
    1 模式:选择正常( AS_CLKMODE_NORMAL )或高分辨率( AS_CLKMODE_HIRES )时钟模式。
    在这个例子中,我们将使用 AS_CLKMODE_NORMAL
    只有在调用 setPlayerMode() 函数前或处于ReadyMode状态时才可以调用此函数。
    要动态切换正常分辨率和高分辨率,请在切换 AS_CLKMODE_NORMALAS_CLKMODE_HIRES 之前调用 setReadyMode() 并切换到Ready状态。
  • 使用 setPlayerMode() 函数设置播放器模式。

    theAudio->setPlayerMode(device,  (1)
                            sp_drv); (2)
    1 device :选择输出设备,输出到扬声器耳机( AS_SETPLAYER_OUTPUTDEVICE_SPHP ),I2S( AS_SETPLAYER_OUTPUTDEVICE_I2SOUTPUT )。
    此示例使用 AS_SETPLAYER_OUTPUTDEVICE_SPHP
    使用I2S时,请参阅输出到I2S
    2 sp_drv :设置输出驱动器。
    在此示例中,指定 AS_SP_DRV_MODE_LINEOUT
    有关详细信息,请参阅使用扩展板上的扬声器端子时
  • 使用 initPlayer() 函数初始化播放器。

    theAudio->initPlayer(id,         (1)
                         codec,      (2)
                         codec_path, (3)
                         fs,         (4)
                         channel);   (5)
    1 id :选择播放器ID。
                此示例使用 AudioClass::Player0
    2 codec :指定MP3( AS_CODECTYPE_MP3 )作为编解码器类型。
    3 codec_path :指定安装DSP文件的位置。
          为microSD卡指定 /mnt/sd0/BIN ,为SPI-Flash指定 / mnt/spif/BIN
    4 fs :指定采样率。
          MP3支持32kHz( AS_SAMPLINGRATE_32000 ),44.1kHz( AS_SAMPLINGRATE_44100 ),48kHz( AS_SAMPLINGRATE_48000 )。 如果指定 AS_SAMPLINGRATE_AUTO ,则自动确定采样率。
    5 channel :指定单声道( AS_CHANNEL_MONO )或立体声( AS_CHANNEL_STEREO )。
  • 使用 writeFrames() 函数将WAV文件的内容写入解码器。

    theAudio->writeFrames(id,          (1)
                          data,        (2)
                          write_size);
    1 id :选择播放器ID。
         此示例使用 AudioClass::Player0
    2 可以通过更改从microSD卡读取的文件来更改播放文件。
    在此示例中,指定了从文件“Sound.wav”读取的缓冲区。
    周期性地执行该函数以将流提供给解码器,从而不中断解码。
  • 使用 startPlayer() 函数启动播放器。

    theAudio->startPlayer(id); (1)
    1 id :选择播放器ID。
         此示例使用 AudioClass::Player0
         使用 writeFrames() 函数写入解码器后调用该函数。
  • 使用 stopPlayer() 函数停止播放器。

    theAudio->stopPlayer(id,    (1)
                         mode); (2)
    1 id :选择播放器ID。
         此示例使用 AudioClass::Player0
    2 可以选择是立即停止( AS_STOPPLAYER_NORMAL )还是等到已经提供给解码器的流完成播放( AS_STOPPLAYER_ESEND )。 如果没有指定 mode ,则缺省为 AS_STOPPLAYER_NORMAL
  • 使用 setVolume(音量) 功能调节音量。

    theAudio->setVolume(volume); (1)
    1 volume :您可以更改音量。 (-1020至120)
    指定值的1/10是实际音量[dB]。 例如,当指定15时,音量为1.5 [dB] です。

1.5. 播放高分辨率音频

1.5.1. 摘要

播放microSD卡上的高分辨率声源的WAV音乐文件。

1.5.2. 运行环境

  • Spresense主板和扩展板

  • microSD 卡

  • 播放耳机或扬声器

此示例使用microSD卡和耳机。。 将耳机或有源扬声器连接到扩展板上的耳机插孔。

1.5.3. 操作程序

  1. 在microSD卡上安装WAV解码DSP文件 WAVDEC (参见安装DSP文件)。

  2. 将要播放的WAV文件放在microSD卡的根目录中,文件名为“HiResSound.wav”。

  3. 将microSD卡插入扩展板上的microSD卡插槽。

  4. 运行Arduino IDE,选择 File→ Sketch Example→ Spresense Sketch Example Audio→ application→ player_hires 来启动示例sketch。

    arduino audio examples player hires
  5. Tools→ Serial port 中选择Spresense COM端口并写入微控制器板。

  6. 上传并执行sketch时,放置在microSD卡上的高分辨率WAV文件将从耳机播放。
    文件播放结束时停止。

1.5.4. 程序说明

  • 使用 setRenderingClockMode() 函数设置时钟模式。

    theAudio->setRenderingClockMode(mode); (1)
    1 模式:选择正常( AS_CLKMODE_NORMAL )或高分辨率( AS_CLKMODE_HIRES )时钟模式。
    在这个例子中,我们使用 AS_CLKMODE_HIRES
    只有在调用 setPlayerMode() 前或处于ReadyMode状态时才可以调用此函数。
    要动态切换正常分辨率和高分辨率,请在切换“AS_CLKMODE_NORMAL”或“AS_CLKMODE_HIRES”之前调用 setReadyMode() 并切换到Ready状态。
  • 使用 setPlayerMode() 函数设置播放器模式。

    theAudio->setPlayerMode(device,  (1)
                            sp_drv); (2)
    1 device :选择输出设备,输出到扬声器耳机( AS_SETPLAYER_OUTPUTDEVICE_SPHP ),I2S( AS_SETPLAYER_OUTPUTDEVICE_I2SOUTPUT )。
    在这个示例中,我们使用 AS_SETPLAYER_OUTPUTDEVICE_SPHP
    使用I2S时,请参阅输出到I2S
    2 sp_drv :设置输出驱动器。 在此示例中,指定 AS_SP_DRV_MODE_LINEOUT
    有关详细信息,请参阅使用扩展板上的扬声器端子时
  • 使用 initPlayer() 函数初始化播放器。

    theAudio->initPlayer(id,         (1)
                         codec,      (2)
                         codec_path, (3)
                         fs,         (4)
                         bitlen,     (5)
                         channel);   (6)
    1 id :选择播放器ID。
    此示例使用 AudioClass::Player0
    2 codec :将编解码器类型指定为WAV( AS_CODECTYPE_WAV )。
    3 codec_path :指定DSP文件的安装位置。
    为microSD指定 /mnt/sd0/BIN ,为SPI-Flash指定 /mnt/spif/BIN
    4 fs :指定采样率。
    此示例指定96kHz( AS_SAMPLINGRATE_96000 )。
    5 bitlen :指定位长度。
    在此示例中,指定了24位( AS_BITLENGTH_24 )。
    6 channel :指定单声道( AS_CHANNEL_MONO )或立体声( AS_CHANNEL_STEREO )。
  • 调用 writeFrames() 将从WAV文件读取的内容写入解码器。

    theAudio->writeFrames(id,      (1)
                          myFile); (2)
    1 id :选择播放器ID。
    此示例使用 AudioClass::Player0
    2 您可以通过指定myFile参数来更改播放文件。
    此示例使用名为“HiResSound.wav”的文件。
    周期性地执行该函数以将流提供给解码器,从而不中断解码。。 当函数写入文件末尾时,返回 AUDIOLIB_ECODE_FILEEND 作为函数的返回值。
  • 使用 startPlayer() 函数启动播放器。

    theAudio->startPlayer(id); (1)
    1 id :选择播放器ID。
    此示例使用 AudioClass::Player0
    使用 writeFrames() 函数写入解码器后调用。
  • 使用 stopPlayer() 函数停止播放器。

    theAudio->stopPlayer(id,    (1)
                         mode); (2)
    1 id :选择播放器ID。
    此示例使用 AudioClass::Player0
    2 可以选择是立即停止( AS_STOPPLAYER_NORMAL )还是等到已经提供给解码器的流完成播放( AS_STOPPLAYER_ESEND )。 如果没有指定 mode 参数,则缺省为 AS_STOPPLAYER_NORMAL
  • 使用 setVolume(音量 功能调节音量。

    theAudio->setVolume(volume); (1)
    1 volume : 您可以更改音量。(-102 ~ 120 [dB])
    对于音量,指定一个乘以10的整数值,例如,15表示1.5 [dB]。

1.6. 播放播放列表

1.6.1. 摘要

此示例是使用播放列表播放音乐的示例sketch。

按顺序播放microSD卡中的多个音乐文件。 您可以执行播放,停止,下一首歌曲,返回,重复播放和随机播放等操作。

1.6.2. 运行环境

  • Spresense主板和扩展板

  • microSD 卡

  • 播放耳机或扬声器

此示例使用microSD卡和耳机。。 将耳机或有源扬声器连接到扩展板上的耳机插孔。

1.6.3. 操作程序

为了使用播放列表功能,需要在PC上预先创建播放列表文件并将其复制到microSD。 此示例sketch使用的microSD目录结构如下所示。

  `  `  `
microSD 卡根目录
|-- BIN/
|   |-- MP3DEC
|    ` -- WAVDEC
|-- AUDIO/
|   |-- Sound1.mp3
|   |-- Sound2.mp3
|   |--   :
|   |-- Sound1.wav
|   |-- Sound2.wav
|   |--   :
 ` -- PLAYLIST/
     ` -- TRACK_DB.CSV
 `  `  `
  • BIN/ 目录中安装 MP3DECWAVDEC DSP二进制文件(参见安装DSP文件)。

  • 将播放列表播放的音乐文件复制到 AUDIO/ 目录。

  • 将播放列表文件( TRACK_DB.CSV )复制到 PLAYLIST/ 目录。

1.6.3.1. 如何创建播放列表文件

播放列表文件 TRACK_DB.CSV 的格式如下所示。 这是CSV(逗号分隔值)格式的文本文件,其中每个文件的信息以行为单位写入。

[filename],[artist],[album],[channel number],[bit length],[sampling rate],[file format]
[filename],[artist],[album],[channel number],[bit length],[sampling rate],[file format]
[filename],[artist],[album],[channel number],[bit length],[sampling rate],[file format]
 :

写入音乐文件名,艺术家姓名,专辑名称和编解码器信息(通道数,位长,采样率Hz)。 这是一个 TRACK_DB.CSV 的例子。

Sound1.mp3,Artist1,Album1,2,16,44100,mp3
Sound2.mp3,Artist1,Album1,2,16,44100,mp3
Sound1.wav,Artist2,Album2,2,16,48000,wav
Sound2.wav,Artist2,Album2,2,24,192000,wav

这里提供了一个简单的脚本工具mkplaylist.py,用于创建播放列表文件。 右键单击链接:这里 下载并使用该文件。 由于此脚本使用ffmpeg-python,请在已安装ffmpeg和ffmpeg-python的环境中使用它。

mkplaylist.py的用法如下所示。

python mkplaylist.py
usage: python mkplaylist.py dirname [dirname2] [dirname3] ...
usage: python mkplaylist.py -f filename

Generate an audio playlist file named as TRACK_DB.CSV

指定包含音乐文件的目录路径作为参数。 正常执行时,TRACK_DB.CSV文件将输出到当前目录。 如果TRACK_DB.CSV文件已存在,则将其添加到文件末尾。

python mkplaylist.py MyMusic
  • 音乐文件扩展名必须为.mp3或.wav。

  • 不支持包含2字节代码(如日语)的文件名。 将文件名更改为ASCII代码字符串。

  • 由于播放列表文件是以CSV格式编写的,因此请勿使用文件名,艺术家,专辑名称中包含逗号的字符串。

  1. 将microSD卡に插入扩展板上的microSD卡插槽。

  2. 运行Arduino IDE , 选择 File→ Sketch Example→ Spresense Sketch Example Audio→ application→ play_playlist 打开示例sketch。

    arduino audio examples player playlist
  3. Tools→ Serial port 中选择Spresense COM端口并写入微控制器板。

  4. 启动Serial monitor时,将显示以下菜单。 根据来自串口的键输入执行各种操作。

    === MENU (input key ?) ==============
    p: play  s: stop  +/-: volume up/down
    l: list  n: next  b: back
    r: repeat on/off  R: random on/off
    a: auto play      m,h,?: menu
    =====================================
使用EEPROM库,将诸如音量值,随机/重复/自动播放等信息保存在非易失性存储器中。 下次启动时,基于先前预设的信息运行。 创建自己的音乐播放器时请参考。

1.7. MP3双解码播放

1.7.1. 摘要

同时播放microSD卡上的两个MP3音乐文件。

1.7.2. 运行环境

  • Spresense主板和扩展板

  • microSD 卡

  • 播放耳机或扬声器

此示例使用microSD卡和耳机。。 将耳机或有源扬声器连接到扩展板上的耳机插孔。

1.7.3. 操作程序

  1. 在microSD上安装MP3解码DSP文件 MP3DEC (参见安装DSP文件)。

  2. 将要播放的两个MP3文件放在microSD卡的根目录中,文件名为“Sound0.mp3”和“Sound1.mp3”。

  3. 将microSD卡插入扩展板上的microSD卡插槽。

  4. 运行Arduino IDE, 选择 文件 - >sketch示例 - > Spresensesketch示例选择Audio→ application→ dual_players 打开示例sketch。

    arduino audio examples dual players
  5. Tools→ Serial port 中选择Spresense COM端口并写入微控制器板。

  6. 编译sketch后烧写至开发板,程序运行时,microSD上的两个MP3会被混合在一起循环播放。

1.7.4. 程序说明

  • 使用 setRenderingClockMode() 函数设置时钟模式。

    theAudio->setRenderingClockMode(mode); (1)
    1 模式:选择正常( AS_CLKMODE_NORMAL )或高分辨率( AS_CLKMODE_HIRES )时钟模式。
    为MP3播放指定“AS_CLKMODE_NORMAL”。
  • 使用 setPlayerMode() 函数设置播放器模式。

    theAudio->setPlayerMode(device,  (1)
                            sp_drv); (2)
    1 device :选择输出设备,输出到扬声器耳机( AS_SETPLAYER_OUTPUTDEVICE_SPHP ),I2S( AS_SETPLAYER_OUTPUTDEVICE_I2SOUTPUT )。
    こ在我们的示例中,我们使用 AS_SETPLAYER_OUTPUTDEVICE_SPHP
    使用I2S时,请参阅输出到I2S
    2 sp_drv :设置输出驱动器。
    在此示例中,指定“AS_SP_DRV_MODE_LINEOUT”。
    有关详细信息,请参阅使用扩展板上的扬声器端子时
  • 对于每个播放器0,1使用 initPlayer() 函数初始化。

    theAudio->initPlayer(id,         (1)
                         codec,      (2)
                         codec_path, (3)
                         fs,         (4)
                         channel);   (5)
    1 id :选择播放器ID。
    一个指定 AudioClass::Player0 ,另一个指定 AudioClass::Player1
    2 codec : 指定编解码器类型MP3( AS_CODECTYPE_MP3 )。
    3 codec_path :指定DSP文件的安装位置。
    为microSD指定 /mnt/sd0/BIN ,为SPI-Flash指定 /mnt/spif/BIN
    4 fs :指定采样率。
    MP3 支持32kHz ( AS_SAMPLINGRATE_32000 ), 44.1kHz ( AS_SAMPLINGRATE_44100 ), 48kHz ( AS_SAMPLINGRATE_48000 )。 指定AS_SAMPLINGRATE_AUTO 将自动选择采样率。
    5 channel :指定单声道( AS_CHANNEL_MONO )或立体声( AS_CHANNEL_STEREO )。
  • 使用每个播放器0和1的 writeFrames() 函数将MP3文件的内容写入解码器。

    theAudio->writeFrames(id,      (1)
                          myFile); (2)
    1 id :选择播放器ID。
    一个指定 AudioClass::Player0 ,另一个指定 AudioClass::Player1
    2 您可以通过指定myFile参数来更改播放文件。
    此示例使用文件“Sound0.mp3”和“Sound1.mp3”。
    周期性地执行该函数以将流提供给解码器,从而不中断解码。 当函数写入文件末尾时,返回 AUDIOLIB_ECODE_FILEEND 作为函数的返回值。
  • 对于每个播放器0,1使用 startPlayer() 函数。

    theAudio->startPlayer(id); (1)
    1 id :选择播放器ID。
    一个指定 AudioClass::Player0 ,另一个指定 AudioClass::Player1
    使用 writeFrames() 函数写入解码器后调用。
  • 对于每个播放器0,1使用 stopPlayer() 函数停止播放器。

    theAudio->stopPlayer(id,    (1)
                         mode); (2)
    1 id :选择播放器ID。
    一个指定 AudioClass::Player0 ,另一个指定 AudioClass::Player1
    2 您可以选择是立即停止( AS_STOPPLAYER_NORMAL )还是等到已经提供给解码器的流完成播放( AS_STOPPLAYER_ESEND )。 如果没有指定 mode 参数,则缺省为 AS_STOPPLAYER_NORMAL
  • 使用 setVolume(master,player0,player1) 函数调整音量。

    theAudio->setVolume(master,   (1)
                        player0,  (2)
                        player1); (3)
    1 master : 更改两个播放器音量。(-1020 ~ 120)
    2 player0 更改播放器0音量。(-1020 ~ 120)
    3 player1 更改播放器1音量。(-1020 ~ 120)
    指定值的1/10是实际音量[dB]。 例如,当指定15时,音量为1.5 [dB] 。 您可以使用 master 调整整体音量,使用 player0player1 调整单个音量。。

1.8. 聆听麦克风输入的声音

1.8.1. 摘要

从麦克风输入的声音从耳机插孔输出。

使用音频硬件的路径设置功能,可以将来自I2S的数字音频输出到模拟通道,还可以将从麦克风的输入输出到I2S, 实现具有低功耗和非常低延迟的输出。

1.8.2. 运行环境

  • Spresense主板和扩展板

  • 播放耳机或扬声器

  • 录音麦克风

此示例使用耳机和麦克风。 将耳机或有源扬声器连接到扩展板上的耳机插孔。 有关麦克风连接,请参阅:如何使用麦克风

在此示例中,不需要安装DSP文件。

1.8.3. 操作程序

  1. 运行Arduino IDE , 选择 File→ Sketch Example→ Spresense Sketch Example Audio→ application→ through 打开示例sketch。

    arduino audio examples through
  2. 示例sketch将从I2S输入的声音输出到耳机插孔。
    修改sketch以便将从麦克风输入的声音输出到耳机插孔。
    通过 File→ Save As 将其保存到可编辑的位置。

  3. setThroughMode() 函数的参数 inputAudioClass::I2sIn 更改为 AudioClass::MicIn 并保存。

  4. Tools→ Serial port 中选择Spresense COM端口并写入微控制器板。

  5. 上传并执行sketch时,将从耳机听到麦克风输入的声音。

1.8.4. 程序说明

  • 使用 setThroughMode() 函数设置through模式。。

    theAudio->setThroughMode(input,      (1)
                             i2s_out,    (2)
                             sp_out,     (3)
                             input_gain, (4)
                             sp_drv);    (5)
    1 input 选择输入系统。
    2 i2s_out 选择要输出到I2S的信号源。
    3 sp_out 选择是否输出到耳机扬声器。
      例如,如果要将麦克风的音频输入输出到I2S,
    input 指定 AudioClass::MicIn
    i2s_out 指定 AudioClass::Mic
    sp_out 指定 false
    4 input_gain 设置麦克风增益。
    可以为模拟麦克风设置-78.5至21 [dB],为数字麦克风设置-78.5至0 [dB]。
    对于input_gain,指定一个乘以100的整数值,例如为-0.05 [dB]设置5。 <5>对于 sp_drv ,请参阅使用扩展板上的扬声器端子时

1.9. 以MP3格式录制

1.9.1. 摘要

录制麦克风的声音并将其作为MP3文件存储在microSD卡上。

1.9.2. 运行环境

  • Spresense主板和扩展板

  • microSD 卡

  • 录音麦克风

此示例使用microSD卡和麦克风。 有关麦克风连接,请参阅: 如何使用麦克风

1.9.3. 操作程序

  1. 在microSD上安装MP3编码DSP文件 MP3ENC ((参见安装DSP文件)。

  2. 运行Arduino IDE , 选择 File→ Sketch Example→ Spresense Sketch Example Audio→ application→ recorder 打开示例sketch。

    arduino audio examples recorder
  3. Tools→ Serial port 中选择Spresense COM端口并写入微控制器板。

  4. 上传并执行sketch时,录制开始并在一定时间后停止录制。

  5. 记录的数据保存在microSD卡中,文件名为“Sound.mp3”。
    取出microSD卡并在PC上检查记录的数据。

1.9.4. 程序说明

  • 使用 setRecorderMode() 函数设置录音机模式。

    theAudio->setRecorderMode(input_device, (1)
                              input_gain,   (2)
                              bufsize,      (3)
                              is_digital);  (4)
    1 input_device :指定麦克风( AS_SETRECDR_STS_INPUTDEVICE_MIC )为输入设备。
    2 input_gain :设置麦克风增益。
    对于模拟麦克风,设置范围为-78.5dB至21dB。对于数字麦克风,设置范围为-78.5dB至0dB。
    对于input_gain,指定一个乘以100的整数值,例如为-0.05 dB设置5。
    3 bufsize :指定录音机的缓冲区大小。
    有关详细信息,请参阅关于录音机缓冲区大小
    4 如果连接的麦克风是数字麦克风,请将参数 is_digital 设置为 true
  • 使用 initRecorder() 函数初始化录音机。

    theAudio->initRecorder(codec,      (1)
                           codec_path, (2)
                           fs,         (3)
                           channel);   (4)
    1 codec 指定编解码器类型MP3( AS_CODECTYPE_MP3 )。
    2 codec_path 指定DSP文件的安装位置。
    为microSD指定 /mnt/sd0/BIN ,为SPI-Flash指定 /mnt/spif/BIN
    3 fs 指定采样率。
    MP3 支持32kHz ( AS_SAMPLINGRATE_32000 ), 44.1kHz ( AS_SAMPLINGRATE_44100 ), 48kHz ( AS_SAMPLINGRATE_48000 )。
    4 channel :指定单声道( AS_CHANNEL_MONO )或立体声( AS_CHANNEL_STEREO )。
  • 使用 readFrames() 函数读取MP3编码数据以记录到文件。

    theAudio->readFrames(myFile); (1)
    1 您可以通过指定myFile来更改录制文件。
    此示例使用名为“Sound.mp3”的文件。
    定期执行该函数以读出编码结果,以便编码缓冲区不会溢出。。
  • 使用 startRecorder() 函数启动录音机。

  • 使用 stopRecorder() 函数停止录音机。

1.9.5. 关于录音机缓冲区大小

写入microSD所需的缓冲区大小默认为160k字节。 这个尺寸足以读取高分辨率WAV音频,当播放48kHz MP3文件等时,将会消耗额外的内存。

默认情况下,160kByte是用于写入microSD卡的缓冲区大小。。 此大小是可以写入高分辨率WAV音频的大小,录制48 kHz MP3文件时, 通过setRecorderMode ,您可以更改要使用的缓冲区大小。 作为参考,当播放192kHz高分辨率WAV文件时,默认为160kByte, 录制48kHz MP3文件时,建议将其设置为大约8kByte。

注意: 大小仅供参考。请根据microSD卡性能,应用吞吐量等进行调整。 如果缓冲区太小,写入microSD时会出错。 如果发生溢出,请增加缓冲区大小。

注意:即使可以获取音频,由于诸如microSD的写入性能和正在运行的应用程序等因素,也可能无法写入所有数据。 对于当前的扩展板,上限为8ch / 48kHz或2ch / 192kHz。 此外,microSD的速度等级也有影响,请使用尽可能快传输速度的microSD卡。

1.10. 以WAV格式录制

1.10.1. 摘要

记录麦克风的声音并将其记录为microSD卡上的WAV文件。

1.10.2. 运行环境

  • Spresense主板和扩展板

  • microSD 卡

  • 录音麦克风

此示例使用microSD卡和麦克风。 有关麦克风连接,请参阅 如何使用麦克风

1.10.3. 操作程序

  1. 在microSD卡上安装用于WAV(PCM)编码的DSP文件 SRC (参见安装DSP文件)。

  2. 运行Arduino IDE , 选择 File→ Sketch Example→ Sample Spresense Audio→ application→ recorder_wav 打开示例sketch。

    arduino audio examples recorder wav
  3. 在 ` Tools→ Serial port ` 中选择Spresense COM端口并写入微控制器板。

  4. 上传并执行sketch时,录制开始并在一定时间后停止录制。 记录的数据保存在microSD上,文件名为“Sound.wav”。
    取出microSD卡并在PC上检查记录的数据。

1.10.4. 程序说明

  • 使用 setRecorderMode() 函数设置为录音机模式。

    theAudio->setRecorderMode(input_device, (1)
                              input_gain,   (2)
                              bufsize,      (3)
                              is_digital);  (4)
    1 input_device : 指定麦克风( AS_SETRECDR_STS_INPUTDEVICE_MIC )为输入设备。
    2 input_gain : 您可以设置麦克风增益。
    对于模拟麦克风,设置范围为-78.5dB至21dB。对于数字麦克风,设置范围为-78.5dB至0dB。。
    对于input_gain,请指定一个乘以100的整数值。例如指定5以设置-0.05 dB。。
    3 bufsize : 指定录音机的缓冲区大小。
    有关详细信息,请参阅关于录音机缓冲区大小。。
    4 如果连接的麦克风是数字麦克风,请将参数“is_digital”设置为“true”。
    ※在以高分辨率(192kHz)录制时,在调用 setRecorderMode() 函数之前, 您需要在 setRenderingClockMode() 函数中指定 AS_CLKMODE_HIRES
  • 使用 initRecorder() 函数初始化录音机。

    theAudio->initRecorder(codec,      (1)
                           codec_path, (2)
                           fs,         (3)
                           channel);   (4)
    1 codec 指定编解码器类型为WAV( AS_CODECTYPE_WAV )。
    2 codec_path 指定DSP文件的安装位置。
    为microSD指定 /mnt/sd0/BIN ,为SPI-Flash指定 /mnt/spif/BIN
    3 fs 指定采样率。
    4 channel 指定通道数。
    ※以高分辨率(192kHz,24bit)录制时,设置 fsASSAMPLINGRATE_192000 , bitlen 设置为 AS_BITLENGTH_24
  • 录制WAV文件时,在执行录音前调用 writeWavHeader() 函数创建WAV header。

    theAudio->writeWavHeader(myFile); (1)
    1 指定记录的文件。
    此示例使用名为“Sound.wav”的文件。
  • 使用 readFrames() 函数读取WAV(PCM)编码数据以记录到文件。

    theAudio->readFrames(myFile); (1)
    1 您可以通过指定myFile来更改录制文件。。
    此示例使用名为“Sound.wav”的文件。
    定期执行此函数以读取编码结果,以便编码缓冲区不会溢出。
  • startRecorder() 开始录音。

  • stopRecorder() 停止录音。

1.11. 获取PCM数据

1.11.1. 摘要

捕获从麦克风输入的PCM数据。

在该示例中,仅显示PCM数据最前部,但是通过改进,可以执行诸如PCM原始数据的频率分析和各种滤波器等信号分析。。

1.11.2. 运行环境

  • Spresense主板和扩展板

  • 录音麦克风

此示例使用麦克风。 有关麦克风连接,请参阅: 如何使用麦克风

在此示例中,不需要安装DSP文件。

1.11.3. 操作程序

  1. 运行Arduino IDE , 选择 File→ Sketch Example→ Spresense Sketch Example Audio→ application→ pcm_capture 打开示例sketch。

    arduino audio examples pcm capture
  2. 示例sketch从麦克风中提取语音输入作为PCM数据。

  3. Tools→ Serial port 中选择Spresense COM端口并写入微控制器板。

  4. 启动Serial monitor时,将显示从麦克风输入的语音的PCM数据。

1.11.4. 程序说明

  • 使用 initRecorder() 函数初始化录音机。

    theAudio->initRecorder(codec,      (1)
                           codec_path, (2)
                           fs,         (3)
                           channel);   (4)
    1 codec 编解码类型指定 PCM ( AS_CODECTYPE_PCM )。
    2 codec_path 指定DSP文件的安装位置。
    为microSD指定 /mnt/sd0/BIN ,为SPI-Flash指定 /mnt/spif/BIN
    3 fs 指定采样率。
    对于48kHz( AS_SAMPLINGRATE_48000 ),没有必要安装DSP文件。
    4 channel 指定通道数。
    在此示例中,指定了 AS_CHANNEL_4CH
  • 使用 readFrames() 函数读取PCM数据。

    theAudio->readFrames(p_buffer,    (1)
                         buffer_size, (2)
                         read_size);  (3)
    1 将PCM数据读入 p_buffer
    2 指定要读取的大小。
    3 返回实际读取的大小。
    定期执行此功能以读取PCM数据,以便捕获缓冲区不会溢出。

1.12. 重复录制和播放

1.12.1. 摘要

重复从耳机播放麦克风输入的声音的操作。

1.12.2. 运行环境

  • Spresense主板和扩展板

  • microSD 卡

  • 播放耳机或扬声器

  • 录音麦克风

此示例使用microSD卡和耳机。。 将耳机或有源扬声器连接到扩展板上的耳机插孔。 有关麦克风连接,请参阅: 如何使用麦克风

1.12.3. 操作程序

  1. 在microSD卡上安装MP3解码DSP文件 MP3ENCMP3DEC (参见安装DSP文件)。

  2. 将microSD卡插入扩展板上的microSD卡插槽。

  3. 运行Arduino IDE , 选择 File→ Sketch Example→ Spresense Sketch Example Audio→ application→ rec_play 打开示例sketch。

    arduino audio examples rec play
  4. Tools→ Serial port 中选择Spresense COM端口并写入微控制器板。

  5. 当上传并执行sketch后,以约20秒的周期记录来自麦克风的声音,并播放记录的数据。
    录制和播放重复5次,然后结束。

1.12.4. 程序说明

  • 录制和播放功能与其他单功能示例相同。

  • 通过调用 setRecorderMode()setReadyMode()setPlayerMode() 函数来切换模式,您可以在录制和回放操作之间动态切换。

1.13. Object接口层

所有前面的示例都使用了High Level API中的顶层抽象API。

此外,还提供了功能块单位的Object层示例用以操作音频功能。

  • player_ObjIf

  • recorder_objif

  • recorder_wav_objif

  • recorder_with_rendering

  • pcm_capture_objif

  • voice_effector

这些示例可以通过include FrontEnd.h,MediaPlayer.h,MediaRecorder.h和OutputMixer.h来使用。

例如,通过使用Object层,可以获取解码和播放MP3之间的中间数据。

请尝试运行这些示例代码。

2. GPS 教程

在本教程中,我们将基于示例草图,使用Spresense GPS功能的简单应用程序, 并了解如何自定义示例以添加和扩展功能。

2.1. GPS 示例草图

2.1.1. 简介

了解基于GNSS库示例草图gnss.ino的GNSS库的基本功能。

2.1.2. 操作环境

下面是操作此草图所需的环境。
主板上装有GPS芯片天线,只需主板即可移动GPS功能。

  • Spresense 主板

2.1.3. 操作说明

从 Arduino IDE 菜单中,打开 File → Examples → GNSS → gnss

gnss example1
gnss example2

将此示例写入Spresense板。

gnss example3

打开串行监视器时,将显示定位信息。在定位过程中,LED0每隔一秒闪烁一次。

gnss example4
  • 时间从初始时间 1980/01/06 00:00:00 开始计数。
    从卫星获取精确时间后,切换到当前 UTC 时间显示。

  • numSat:表示找到的卫星数

  • 在非定位状态下,将显示"无修复,无位置"。
    定位后,显示"修复"和"Lat=纬度、Lon=经度"。
    此外,获得位置信息后,LED1会亮起。

gnss example5

每分钟显示有关卫星的详细信息。

  • Type: 卫星类别、Id: 卫星编号、Elv: 仰角、Azm: 方位角、CN0: 信号强度。

2.1.4. 程序说明

  • 使用setup()函数初始化GNSS库。

    enum ParamSat {
      eSatGps,            /**< GPS                     World wide coverage  */
      eSatGlonass,        /**< GLONASS                 World wide coverage  */
      eSatGpsSbas,        /**< GPS+SBAS                North America        */
      eSatGpsGlonass,     /**< GPS+Glonass             World wide coverage  */
      eSatGpsQz1c,        /**< GPS+QZSS_L1CA           East Asia & Oceania  */
      eSatGpsGlonassQz1c, /**< GPS+Glonass+QZSS_L1CA   East Asia & Oceania  */
      eSatGpsQz1cQz1S,    /**< GPS+QZSS_L1CA+QZSS_L1S  Japan                */
    };
    /* Set this parameter depending on your current region. */
    static enum ParamSat satType =  eSatGps; (3)
    
    void setup() {
       :
      /* Activate GNSS device */
      result = Gnss.begin();           (1)
    
      Gnss.select(XXX);                (2)
    
      /* Start positioning */
      result = Gnss.start(COLD_START); (4)
       :
    }
    1 使用Gnss.begin()函数初始化。调用此函数以加载GNSS专用固件。 如果无法正常工作,请安装最新版本的引导加载程序 arduino_set_up_zh.html
    2 选择要用于Gnss.select()函数的卫星。
    3 多个卫星的组合可用于卫星选择。
    例如,如果使用QZSS Mhibhi,请将"satType"更改为"eSatGpsQz1cQz1S"。
    4 使用Gnss.start()函数开始定位。 这里会冷启动。
  • 使用loop()函数定期获取 GNSS 定位结果。

    void loop()
    {
       :
      /* Check update. */
      if (Gnss.waitUpdate(-1)) (1)
      {
        /* Get NaviData. */
        SpNavData NavData;
        Gnss.getNavData(&NavData); (2)
    1 在 Gnss.waitUpdate()函数中等待 GNSS 接收。
    2 使用Gnss.getNavData()函数获取定位结果。根据此处获得的 NavData ,使用 print_pos()print_condition() 函数输出定位信息。 有关详细信息,请参阅 SpNavData
  • 作为功能使用的示例,此示例在5分钟的周期内停止/恢复GNSS定位。

      if (LoopCount >= RESTART_CYCLE)
      {
    
        /* Restart GNSS. */
        if (Gnss.stop() != 0)                (1)
        {
          Serial.println("Gnss stop error!!");
          error_flag = 1;
        }
        else if (Gnss.end() != 0)            (2)
        {
          Serial.println("Gnss end error!!");
          error_flag = 1;
        }
        else
        {
          Serial.println("Gnss stop OK.");
        }
    
        if (Gnss.begin() != 0)               (3)
        {
          Serial.println("Gnss begin error!!");
          error_flag = 1;
        }
        else if (Gnss.start(HOT_START) != 0) (4)
        {
          Serial.println("Gnss start error!!");
          error_flag = 1;
        }
        else
        {
          Serial.println("Gnss restart OK.");
        }
    1 使用Gnss.stop()函数停止定位。
    2 使用Gnss.end()函数执行终止处理。 调用此函数可卸载GNSS专用固件。
    3 使用Gnss.begin()函数再次初始化。
    4 Gnss.start()函数使用HOT_START。通过热启动而不关闭电源,可以使用上次定位获取的时间信息、位置信息和卫星启动信息,并立即获取位置信息。

2.2. GPS 跟踪器

2.2.1. 简介

GNSS库示例中的GPS跟踪器示例草图 gnss_tracker 。+ 此草图称为GPS数据记录器, 定期从GPS获取的位置信息记录在microSD卡上。 然后,通过检索存储在microSD卡上的文件,并使用专用工具(如 PC)。 这样可以在地图上叠加移动轨迹以浏览它们。

2.2.2. 操作环境

下面是操作此草图所需的环境。

  • Spresense主板

  • Spresense扩展板

  • microSD卡

2.2.3. 操作说明

连接Spresense主板和扩展板,并将microSD卡插入扩展板。
从Arduino IDE菜单中,打开 File → Examples → GNSS → gnss_tracker

gnss tracker1
gnss tracker2

将此示例写入Spresense板。

gnss tracker3

打开串行监视器时,首先打印应用程序的配置信息,然后开始输出定位结果。

gnss tracker4

2.2.4. 操作规范

电源通电后,首先读取microSD卡中的 tracker.ini 文件中写入的设置。 根据此文件中写入的设置初始化应用程序后,将启动GPS定位操作。 在操作过程中,主板上的LED表示应用程序的操作状态。

  • LED 规格

    当应用程序启动时,所有四个LED指示灯仅闪烁一次。
    在定位停止期间,所有LED都熄灭。 单个LED的操作规范如下:

    LED 说明

    LED0

    定位操作期间亮起/重复关闭

    LED1

    获取当前位置(FIX)后亮起

    LED2

    文件访问期间亮起

    LED3

    当发生某些错误(如无法访问 microSD 卡)时亮起

  • microSD 卡中的文件配置

    microSD 卡中的文件配置如下所示。如果该文件不存在,则不需要提前准备该文件,因为程序将创建新文件。

    文件名 说明

    tracker.ini

    包含应用程序设置信息的文本文件。后面将介绍每个设置。如果此文件不存在,则会创建一个具有默认设置的文件。

    index.ini

    包含索引号的文本文件。此数字表示GPS数据的目标文件名。例如,如果写入 " 00000018 ",请将GPS数据输出到文件名" 0000018.txt "。重复操作时,现有此数字递增1,以避免覆盖。如果文件不存在,则会创建一个名为"00000001"的新文件。

    00000001.txt
    00000002.txt
      :

    要写入GPS数据的文本文件。此文件包含NMEA 0183格式的GPGGA语句。用户将此文件导入PC等,以生成GPS跟踪数据。

  • tracker.ini 设置信息

    可以通过更改此处定义的设置参数来切换应用程序的行为。默认值有效,此处可以忽略。

    参数 说明 参数值

    SatelliteSystem

    (GPS/GLONASS/SBAS/QZSS_L1CA/QZSS_L1S)
    从以下选项中选择卫星系统(组合)。
    GPS+GLONASS+QZSS_L1CA
    GPS+QZSS_L1CA+QZSS_L1S
    GPS+QZSS_L1CA
    GPS+GLONASS
    GLONASS
    GPS+SBAS
    GPS

    SatelliteSystem=GPS+GLONASS+QZSS_L1CA

    NmeaOutUart

    (TRUE/FALSE)
    选择是否在串行监视器上显示NMEA输出。

    NmeaOutUart=TRUE

    NmeaOutFile

    (TRUE/FALSE)
    选择是否将NMEA输出保存到文件中。这里是TRUE。

    NmeaOutFile=TRUE

    BinaryOut

    (TRUE/FALSE)
    选择是否保存GNSS二进制数据。通常,可以保留FALSE。

    BinaryOut=FALSE

    IntervalSec

    (1-300)
    设置定位间隔(秒)。

    IntervalSec=1

    ActiveSec

    (60-300)
    设置定位的刷新时间(秒)。在ActiveSec中定位一秒钟后,SleepSec秒将定期重复停止定位的行为。

    ActiveSec=60

    SleepSec

    (0-240)
    设置停止定位的时间段(秒)。在ActiveSec中定位一秒钟后,SleepSec秒将定期重复停止定位的行为。如果睡眠周期没有,要求始终定位,请指定0。

    SleepSec=240

    UartDebugMessage

    (NONE/ERROR/WARNING/INFO)
    设置要输出到串行监视器的调试级别。

    UartDebugMessage=NONE

2.2.5. GPS 记录数据验证步骤

查看GPS记录数据的方法有很多种。不过,这里可以将NMEA转换为KML格式,并使用Google地球在地图上显示。

  • Google Earth 安装

    Google Earth 下载页面 下载Google Earth并安装。

  • NMEA到KML/KMZ转换器

    存储在microSD卡上的00000001.txt到9999999.txt文件的内容以NMEA格式(仅限GPGGA语句)编写。将其转换为KML/KMZ格式,可通过Google Earth处理。如果源数据被划分为多个文本文件,请将该文件合并为一个文件。

    1. 打开 https://www.h-schmidt.net/NMEA/

    2. 通过" 选择文件 " 指定输入文件,然后按" 发送 "按钮

    3. 下载转换为KML的文件

      gnss nmea2kml1
      gnss nmea2kml2
      另外, https://www.gpsvisualizer.com 这个网站也可以转换成Google Earth和其它格式的数据。网络上有各式各样的转换工具,在PC上运行而不通过网站转换的方式,如: NMEA to KMZ Utility
  • Google Earth 打开 KML 文件

    移动的轨迹将在地图上映射并显示,如下所示:

    gnss google earth

现在,已经了解如何使示例代码正常工作。

下面,将讨论自定义和使用GPS跟踪器的应用。

2.3. GPS 移动跟踪器

2.3.1. 简介

在上一章中,尝试应用GPS跟踪器的示例gnss_tracker.ino。此示例将GPS记录器数据存储在microSD卡上,并对其进行修改以将其保存到主板上的Flash内存中。主板只使用更小、更省电的GPS跟踪器。

2.3.2. 操作环境

下面是操作此示例所需的环境。

  • Spresense 主板

2.3.3. 代码修改

打开gnss_tracker.ino示例。

gnss tracker1
gnss tracker2

从Arduino IDE的菜单,选择 File → Save as…​ 将示例保存到任何文件夹。复制示例以进行编辑。

gnss tracker5

打开gnss_file.cpp并进行修改。

  • 添加#include <Flash.h>这行

  • 删除 “ SDClass theSD; "这行

  • 替换 " theSD " → " Flash "

    • 更改为使用Flash。由于Flash库具有与SD相同的接口配置,因此只需更改对象名称即可。

    • 参考下面修改的示例。

      gnss tracker7

2.3.4. 操作说明

操作过程与 SD 相同。将刚刚编辑的示例写入Spresense板并运行。

2.3.5. GPS 数据验证步骤

有几种方法可以检索存储在Flash内存中的结果。(除了这里介绍的方法外,您还可以使用 Add-on 等通过网络传输文件)。

  • 转存文件方法

    GPS记录器数据存储在Flash中作为文本文件。将内容转储到串行终端,并将显示结果另存为文件。 这是一个非常原始的方法,但快速和容易。

    由于 Arduino IDE 的串行监视器无法将串行显示结果保存到文件中,因此建议使用其他终端(如 TeraTerm 或 minicom)。
    1. 下载示例 nuttx_shell

      写入并运行草图时,串行终端将显示" NuttShell nsh> "提示。

    2. 使用命令 ls 查看Flash中的文件列表。

      nsh> ls -l /mnt/spif
      gnss tracker8
    3. 使用 cat 命令显示目标日志文件。 将日志结果设置为在运行命令之前保存到文件中。

      nsh> cat /mnt/spif/00000003.txt
      gnss tracker9

      能够搜索GPS记录器数据。
      如果不再需要Flash中的文件,可以使用 rm 命令将其删除。

      nsh> rm /mnt/spif/00000003.txt
  • Flash → microSD 复制方法

    如果有扩展板,则可以使用扩展板从Flash复制到microSD并检索文件

    1. 而且使用示例 nuttx_shell

      写入并运行示例时,串行终端将显示" NuttShell nsh> " 提示。

    2. ls 命令查看Flash上的文件列表。

      nsh> ls -l /mnt/spif
      gnss tracker8
    3. cp 命令复制目标日志文件到microSD。

      nsh> cp /mnt/spif/00000003.txt /mnt/sd0
      gnss trackerA

      通过microSD可以检索GPS记录器数据。
      如果不再需要Flash中的文件,可以使用 rm 命令将其删除。

      nsh> rm /mnt/spif/00000003.txt
  • Zmodem 传输文件方法

    可以使用Spresense SDK环境使用Zmodem传输功能检索文件。
    详细信息,请参考 Zmodem 传输文件

有关如何根据提取的 GPS 记录器数据在地图上映射的信息,请参考 这里

2.4. GPS 跟踪器节能

2.4.1. 简介

通过将LowPower库与GPS跟踪器相结合,节省能源。 即使在正常工作时,Spresense 的功能是低功耗的。如果使用LowPower库,还可以显著降低功耗。 为了延长电源/电池的使用时间,请尝试根据本教程更改源代码。

此处使用LowPower库的以下功能。 有关LowPower库的详细信息,请参考 LowPower 程序库

  • 更改时钟模式

  • 使用睡眠模式

2.4.2. 更改时钟模式

通常,将运行在156MHz下的系统范围的时钟降至32MHz可降低功耗。 GNSS定位功能在32MHz时钟操作模式下运行时也有效。 更改GPS跟踪器,如下所示:

#include <LowPower.h> (1)

void setup()
{
  :
  LowPower.begin();                     (2)
  LowPower.clockMode(CLOCK_MODE_32MHz); (3)
  :
}
1 引用LowPower库。
2 在setup()函数中调用LowPower.begin()函数。
3 将时钟模式设置为32MHz。

只需添加对LowPower.clockMode(CLOCK_MODE_32MHz)的调用即可切换时钟模式。

2.4.3. 使用睡眠模式

当定位功能间歇性地运行时,在非定位期间将系统置于睡眠状态,从而降低待机功率。 在进入睡眠状态之前,将最终定位位置和卫星轨道信息存储在闪存中,以便在从睡眠 唤醒后通过热启动立即继续定位操作。

更改源代码以使用睡眠模式,如下所示:

#include <LowPower.h> (1)
#include <Flash.h>    (2)
1 引用LowPower库。
2 引用Flash库。
void setup()
{
  LowPower.begin();                      (1)
  bootcause_e bc = LowPower.bootCause(); (2)

  if ((bc == POR_SUPPLY) || (bc == POR_NORMAL)) {
    /* Remove backup file if power-on-reset */
    Flash.remove("gnss_backup.bin");     (3)
  }
1 在setup()函数中调用LowPower.begin()函数。
2 获取系统启动的因素。 可以确定是电源打开重置(如上电或按下复位开关)还是从睡眠状态唤醒。
3 如果启动因素(如首次启动时)是Power-On-Reset,请删除Flash上的备份文件。 当从Deep Sleep中醒来时,请使用Flash上的备份文件进行热启动定位。
static void SleepIn(void)
{
  /* Turn off the LED. */
  APP_PRINT("Sleep ");
  ledOff(PIN_LED0);
  /* Save backup data to flash */
  Gnss.saveEphemeris(); (1)
  Gnss.stop();
  Gnss.end();
1 在SleepIn()函数中退出Gnss之前,将备份数据存储在Flash中。
void loop() {
    :
  /* Check state. */
  if (State == eStateSleep)
  {
    /* Deep sleep */
    Serial.print("Go to Deep sleep...");
    LowPower.deepSleep(Parameter.SleepSec); (1)
1 在loop()函数中执行睡眠时调用LowPower.deepSleep()函数。 Parameter.SleepSec后,会自动从深度睡眠中唤醒。 当Deep Slep唤醒时,从setup()开始操作,其顺序与按下重置时的顺序相同。

2.5. NMEA 打印输出

2.5.1. 简介

将GPS接收器中常用的NMEA数据输出到串行监视器。

2.5.2. 示例代码

下面是用于输出NMEA数据的示例。

#include <GNSS.h>
#include <GNSSPositionData.h>
#include <gpsutils/cxd56_gnss_nmea.h>

SpGnss Gnss;
char   PositionData[sizeof(GnssPositionData)];

/* output NMEA */
static char nmea_buf[NMEA_SENTENCE_MAX_LEN];

static char *reqbuf(uint16_t size)
{
  if (size > sizeof(nmea_buf)) {
    return NULL;
  }
  return nmea_buf;
}

static void freebuf(char *buf)
{
  return;
}

static int outbin(char *buf, uint32_t len)
{
  return len;
}

static int outnmea(char *buf)
{
  return printf("%s", buf);
}

void setup()
{
  /* Initialize Serial */
  Serial.begin(115200);

  /* Initialize GNSS */
  if (Gnss.begin()) {
    Serial.println("begin error!");
  }

  /* select satellite system */
  Gnss.select(GPS);
  Gnss.select(GLONASS);
  Gnss.select(QZ_L1CA);
  //Gnss.select(QZ_L1S);
  //Gnss.select(SBAS);

  /* set interval */
  Gnss.setInterval(1);

  if (Gnss.start(COLD_START)) {
    Serial.println("start error!");
  }

  /* use NMEA library */
  NMEA_InitMask();
  //NMEA_SetMask(0x5); // only GGA+GSA (1)
  NMEA_OUTPUT_CB  funcs;
  funcs.bufReq  = reqbuf;
  funcs.out     = outnmea;
  funcs.outBin  = outbin;
  funcs.bufFree = freebuf;
  NMEA_RegistOutputFunc(&funcs);
}

void loop()
{
  SpNavData NavData;

  /* Check update. */
  if (Gnss.waitUpdate(1000)) {
    /* Get NavData. */
    Gnss.getNavData(&NavData);

    /* Output NMEA */
    Gnss.getPositionData(PositionData);
    NMEA_Output(&(((GnssPositionData*)PositionData)->Data));
  }
}
1 可以通过NMEA_SetMask()函数输出NMEA语句。 例如,如果仅输出 GGA 或 GSA,请指定 0x5。 有关 NMEA 掩码值的详细信息,请参阅下文。

运行此示例时,NMEA数据将输出到串行监视器。

gnss nmea log

2.5.3. NMEA 掩码值

在NMEA 0183(ver 4.00)标准中定义的 NMEA 句子中, 输出NMEA语句是NMEA_SetMask()函数的参数,具有位掩码值。 最初,NMEA掩码设置为0xef。

NMEA Bit Description

$xxGGA

0

基本信息,如时间、纬度和经度、高程、定位状态和DGPS基站编号

$xxGLL

1

GGA的简单版本,如时间、纬度和经度、定位状态等

$xxGSA

2

不使用每颗卫星,DOP值

$xxGSV

3

可见卫星的卫星编号、高程、方位角和信号强度

$xxGNS

4

时间、纬度和经度、定位状态

$xxRMC

5

时间、纬度和经度、速度和时间偏差

$xxVTG

6

了解有关行驶速度的详细信息

$xxZDA

7

时间信息,包括日期

$QZQSM

14

灾害危机管理报告服务消息(QZSS 专有语句)

xx 表示以下内容:

  • GP:使用GPS卫星定位时

  • GL:使用GLONASS卫星进行定位时

  • QZ:使用QZS卫星定位

  • GN:使用多个卫星系统进行定位时

2.5.4. NMEA 监视器

各种工具可用于使用NMEA数据。

这里使用 NMEA Monitor for windows 尝试实时查看解码 NMEA 数据的结果。

选择串行监视器输出的COM端口并启动它。

gnss nmea monitor com ja

除了纬度和经度信息之外,您还可以看到许多信息,如海拔和天空图,如下所示。

gnss nmea monitor ja

2.6. GPS 移动时钟

2.6.1. 简介

在RTC库的Examples下,应用移动示例rtc_gnss.ino。
本示例将来自GNSS的时间信息设置为内置Spresense 的RTC(实时时钟)。

2.6.2. 操作环境

下面是操作此草图所需的环境。
主板上装有GPS芯片天线,只需主板即可移动GPS功能。

  • Spresense 主板

2.6.3. 操作说明

在Arduino IDE, 选择菜单 File → Examples → RTC → rtc_gnss

rtc gnss1
rtc gnss2

将此示例写入Spresense板。

rtc gnss3

打开串行监视器时,打印时间信息。

rtc gnss4

2.6.4. 程序说明

#include <RTC.h>
#include <GNSS.h>

SpGnss Gnss;

#define MY_TIMEZONE_IN_SECONDS (9 * 60 * 60) // JST (1)
1 通过在示例上定义时差,UTC时间将转换为本地时间并输出到串行。 有关RTC库的详细信息,请参考 RTC库

3. Camera 教程

3.1. Camera 简单示例

3.1.1. 简介

将使用Spresense相机拍摄的JPEG图像保存到microSD卡。

像延时相机一样,大约每秒钟关闭一次快门,并拍摄100张JPEG图像的照片。

3.1.2. 操作环境

  • Spresense主板和扩展板

  • Spresense相机板

  • microSD卡

将Spresense主板连接到相机板,请参考 如何连接Spresense 主板和Spresense 相机板

相机功能无需扩展板即可工作,但此示例使用扩展板将相机拍摄的照片保存到microSD卡。

3.1.3. 操作说明

  1. 将卡插入扩展板上的microSD卡插槽。

  2. 在Arduino IDE中,选择菜单 File → Examples for Spresense Camera → camera

    arduino camera examples1
    arduino camera examples2
  3. Tools → Serioal Port 中选择Spresense COM端口以写入微控制器板。

    arduino camera examples3
  4. 刻录完成后,程序将工作并开始拍照。
    打开串行监视器时,将显示预览图像的日志信息,以及拍摄静止图像时的日志。

    arduino camera examples4
  5. microSD 卡上保存 ”PICT00.JPG" ~ "PICT099.JPG" 文件。
    请尝试从microSD卡中取出JPEG图像。

3.1.4. 程序说明

详细的注释位于开发指南 示例代码说明 示例代码中。

3.2. LCD 上显示 Camera 预览图像

3.2.1. 简介

更改之前的camera示例草图,以便在LCD上显示预览图像。

预览图像的大小为QVGA(320 x 240)。

LCD 使用配备ILI9341的2.2英寸LCD模块。

3.2.2. 操作环境

  • Spresense 主板和扩展板

  • Spresense 相机板

  • microSD 卡

  • LCD 板(ILI9341 2.2 英寸LCD模块)

3.2.2.1. LCD 和扩展板连接

下面是与ILI9341 2.2英寸LCD模块的连接示例。

connect ili9341
ILI9341 CXD5602 pin name Arduino compatible pin name

VCC

3.3V

3.3V / IOREF / AREF

GND

GND

GND

CS

SPI4_CS_X

D10

RESET

GPIO

D8

DC/RS

GPIO

D9

SDI/MOSI

SPI4_MOSI

D11

SCK

SPI4_SCK

D13

LED

3.3V

3.3V / IOREF / AREF

SDO/MISO

SPI4_MISO

D12

  • 参考 Spresense 扩展板 ,在扩展板的JP1跳线上将I/O端子参考电压设置为3.3V。

  • 为ILI9341的 VCC 端子提供3.3V。 连接到Spresense的 3.3V、IOREF或AREF。
    此示例始终为ILI9341的 LED 端子提供3.3V。

  • 与ILI9341通信使用SPI(SPI4)。

  • RESETDC/RS 引脚使用D8、D9作为GPIO。
    参考 LCDSP001板 也具有相同的引脚分配, 可以按原样使用本教程中的代码。

3.2.2.2. 安装 Adafruit ILI9341 库

演示如何安装Adafruit ILI9341的Arduino库。

  1. 下载下面两个库的zip文件。

  2. 选择Arduino IDE中 Sketch → Include Library → Add .ZIP Library 菜单。

    arduino camera examples5
  3. 使用下载的 zip 文件进行安装。

  4. 如果安装成功,将显示以下消息:
    (请分别安装 Adafruit-GFX-库和 Adafruit_ILI9341)

    arduino camera examples6

3.2.3. 操作顺序

  1. 选择Arduino IDE上 Files → Examples → Examples for Spresense Camera → camera 菜单。

  2. 当编辑示例之后,选择 File → Save AS 来保存示例文件。

  3. 将以下代码添加到草图

    1. 将Adafruit_ILI9341对象的定义添加到示例的开头。

      #include <SPI.h>
      #include <Adafruit_GFX.h>
      #include <Adafruit_ILI9341.h>
      
      #define TFT_CS -1 (1)
      #define TFT_RST 8 (2)
      #define TFT_DC  9 (3)
      
      Adafruit_ILI9341 tft = Adafruit_ILI9341(&SPI, TFT_DC, TFT_CS, TFT_RST); (4)
      1 SPI CS使用硬件自动控制,需指定-1
      2 RST 引脚指定8
      3 DC 引脚指定9
      4 tft 生成对象。
    2. setup()函数中初始化tft。

      void setup(void) {
          :
        tft.begin(40000000); (1)
        tft.setRotation(3);  (2)
          :
      1 使用40 MHz的SPI通信速率初始化tft。
      2 将LCD显示屏旋转270度。
    3. 通过CamCB()函数,在LCD上绘制预览图片。

      void CamCB(CamImage img)
      {
      
        /* Check the img instance is available or not. */
      
        if (img.isAvailable())
          {
            /* If you want RGB565 data, convert image data format to RGB565 */
      
            img.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565);
      
            tft.drawRGBBitmap(0, 0, (uint16_t *)img.getImgBuff(), 320, 240); (1)
          }
      }
      1 使用drawRGBBitmap()函数从坐标(0, 0)绘制QVGA大小的RGB565图像。
  4. Tools → Serial Port 中选择Spresense COM端口以写入微控制器板。

  5. 上传并运行草图后,在拍摄照片时,LCD上将显示预览图像。

3.2.4. 程序说明

有关开发指南,请参考 示例代码说明

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"

继续显示。

4.2.1.1. 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,即使在程序库中也是如此。
4.2.1.2. Step Counter首次制造专有的逻辑传感器。

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

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

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

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

diag b936c6b05e866fd235bbb90a0fb0c932
图表 5. 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;
4.2.1.3. 尝试根据逻辑传感器更改数据。

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

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. AI 教程

5.1. 手写识别

Arduino IDE中 Files → Examples → Examples for Spresense DNNRT → number_recognition 提供简单的数字识别示例。

有关详细信息,请参阅开发指南中的 DNNRT 程序库 。 如何使用Neural网络控制台创建学习模型,以及描述了在Spresense板上实际作为识别器运行的步骤。

其它示例也会不时添加到本教程中。

6. 初次搭建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 进行通信。

6.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 中。

6.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进行通信。

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

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

6.3. 注意事项

  • 有关 MultiCore MP 的详细信息,请参阅 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工具使用一个命令加载每个内核的二进制文件。命令行方法将在以后发布在文档中。