资料介绍
功能性
该设备易于客户使用,也易于旅游公司设置,只需几分钟,设备即可启动并准备运行。在下雨或晴天时,CityGuide 将引导任何人穿过城市。
该设备操作非常简单;使用 Sony Spresense 的机载 GNSS 模块,它可以检索个人的当前位置并对其进行处理,以查看他们是否位于地图上的某个地标处。如果用户在标记的位置;将播放地标的适当录音,简要告知客户他们所看到的背景。下图显示了功能概述。
设置概述
供应商,在我们的例子中是旅游公司,必须在使用设备之前设置设备(在构建项目部分中找到设置项目的分步指南)。他们必须规划用户可以访问的地标地图,并记录用户到达所选地标时将播放的曲目。所有这些数据都必须放在 SD 卡上,然后输入到设备中。
设备启动
该设备需要在 SD 卡中输入启动时所需的所有数据。在这里,设备将读取给定的数据,提取每个地标的位置,以及用户在给定位置时要播放的名称和 mp3 文件,并将数据保存到变量中。
然后设备将在所有提供的位置周围创建一个网格,该网格将用于将用户的当前地理位置与地标的位置进行比较,以便查看用户是否位于地标处。
播放文件
如果设备可以确认用户在地标处,它会播放该地标的文件并将音频输出到耳机插孔。如果两个网格共享相同的位置,设备将播放它遇到的第一个地标的文件。
代码概述
下图说明了项目的代码概述。
-
Get File Data
从设备管理器提供的 SD 文件中检索数据并进行处理。 -
Get GPS
从 GNSS 模块读取当前地理位置。 -
If(GPS)
检查是否已从连接的卫星接收到新的 GPS 数据,以及卫星是否已修复。 -
Compare with Locations
将接收到的地理位置与用户输入的地标的地理位置进行比较。 -
If(atLandmark)
如果当前地理位置位于围绕输入的地理位置生成的网格内,则触发。 -
Play Audio
为客户端所在的地标播放适当的音频文件。
调试 LED
Spresense 板配备了 4 个调试 LED,其中 3 个被该应用程序用于调试目的。
- LED 1是上图顶部的第一个 LED。它用于指示设备的当前状态。它在设备设置时闪烁,然后在算法运行时保持亮起。
- LED 2为 GNSS 状态 LED,用于指示当前 GNSS 状态。当设备正在搜索卫星且尚未接收 GPS 数据时,LED 会闪烁;当设备锁定到卫星并正在接收可靠的地理定位数据时,LED 会保持亮起;如果设备未使用 GNSS,则 LED 会熄灭。
- LED 3指示当前是否正在播放 mp3 文件。它会在播放设置时闪烁,并在播放文件时保持亮起,在没有播放时熄灭。
播放概述
当音频文件正在运行时,设备必须停止 GNSS 模块,因为 GNSS 和音频库不能一起运行,在所有卫星连接的情况下播放完文件后,GNSS 将恢复。
用户可以使用提供的电位器来切换设备的音量。
。但是也可以浏览这些图像,因为它们非常好。
该设备的设计方式使得一个位置只能访问一次。到达该位置后,将播放该文件并将该位置标记为已看到,这可以防止该文件在客户端第二次到达同一位置时播放。
好处
改用 CityGuide 的公司将受益于:
- 更大的自主权和易于设置
- 降低成本
- 快速部署
- 吸引客户的专业方式
使用 CityGuide 的个人将受益于:
- 更快速地游览这座城市
- 以他们的速度观光
- 选择要参观的地标
- 集体或单独参观
构建项目
第1 步:所需设备
该项目不需要很多组件,因为大部分所需的传感器和模块都内置在 Spresense 板中,材料清单如下。
- 1、索尼Spresense板
- 1、电位器
- 1、面包板
- 1、SD卡
- 耳机/耳机
- 跳线
第 2 步:连接电路
所要做的就是将电位计连接到 Spresense 板上,原理图如下所示。
焊接电位器
由于用户不会随身携带面包板,因此必须将电位器焊接到 Spresense 板上。下面是一些焊接图片。
第 3 步:安装 Arduino Spresense 库
首先,我们需要包含使用 Arduino IDE 操作 Spresense 板所需的库。使用板管理器可以轻松完成此操作。按照以下步骤指导您完成设置环境的步骤。
第 4 步:安装端口实用程序
下面的指南将显示下载和安装所需的端口实用程序所需的步骤,以便从您的 Spresense 或向您的 Spresense 发送命令,反之亦然。本指南专为 Mac 用户设计,使用此链接可帮助您在 PC 上安装 Port Utility。
首先,为您的操作系统下载合适的实用程序。
请注意,Arduino 板无法在安装实用程序的情况下运行,卸载它以在您的计算机上编程和使用 Arduino 或类似的板是至关重要的。
为了卸载VPC驱动程序。在 .dmg 文件中找到uninstaller.sh shell 脚本,然后使用Mac 上的终端运行它。这样做;打开Terminal ,然后键入uninstaller.sh文件并将其ssh
拖放到 Terminal 窗口中。可能会要求您输入密码。
第 5 步:更新 Spresense 的固件
为了在您的 Spresense 开发板上运行项目;它需要更新到最新的固件。下面的指南说明了更新设备固件所需的步骤。
第 6 步:安装 MP3 解码器
为了在 Spresense 板上播放 MP3 文件,设备上需要一个 MP3 解码器。该解码器可以安装在设备的 SPI 闪存或 SD 卡上。我们将把它安装在闪存上,这样我们就不需要特定的 SD 卡来运行该项目。下面的步骤说明了安装解码器的步骤。
第 7 步:设置 SD 卡
为了在您的项目中使用 SD 卡,必须将其适当格式化为 FAT。下面的步骤显示了如何在 Mac 上完成此操作。
第 8 步:准备文件
现在我们必须在 SD 卡上设置文件,这些文件将用于识别设备的地标并为其提供声音文件以在特定地标处播放。SD 卡上需要以下文件。
- Datalog.txt是管理员输入地标和相关数据的文本文件
- mp3文件用作设备到达适当地标时将播放的文件。
datalog.txt文件是设备的核心,项目运行所需的所有数据都包含在该文件中。经理可以在地图上添加任意数量的地标,他们所要做的就是在文件中为该地标添加一行。下图说明了必须格式化专用于地标的线的方式。
-
GPO
是线上表示的地标的名称。它可以是任何东西,但不能包含空格。 -
53.349430,-6.260235
是地标的地理位置,获取这个位置在下面的指南中有描述。纬度和经度由分号分隔,没有空格。 -
fileA.mp3
是当用户位于特定位置时播放的文件,在我们的例子中是 GPO。请注意,名称中不允许有空格,.mp3必须包含在末尾并且名称不能包含数字。 - 每个部分之间包含一个空格。
记住上图,我们可以开始自定义datalog.txt文件。下面的图片将指导您完成整个过程。
第 9 步:确认代码
代码有 3 个主要部分,每个部分都很大。
- 获取标清设置
- 获取和处理 GPS
- 播放音频文件
它们都在下面详细介绍。
获取标清设置
void getData()
{
Serial.println("Getting Data");
Serial.println("________________________________________");
Serial.println("Locating File");
Serial.println(" OK - Preparing Variables");
int space = 0;
int comma = 0;
String localName[10];
String localSound[10];
String localRawLocation[10];
String localLatitude[10];
String localLongitude[10];
Serial.println(" OK - Opening File 'datalog.txt'");
myFile = SD.open("datalog.txt");
Serial.println(" OK - Verifying Presence");
if(myFile)
{
Serial.println(" Success - File Loaded");
Serial.println("");
Serial.println("Extracting Data");
Serial.println(" OK - Beginning Final Extraction");
while(myFile.available())
{
char c = myFile.read();
if(c == '\n')
{
newLine++;
}
else if(c == ' ')
{
space++;
}
else
{
if(space == 0)
{
localName[newLine] += c;
}
else if(space == 1)
{
if(c == ',')
{
comma++;
}
else if(comma == 0)
{
localLatitude[newLine] += c;
}
else
{
localLongitude[newLine] += c;
}
localRawLocation[newLine] += c;
}
else if(space == 2)
{
localSound[newLine] += c;
if(c == '3')
{
space = 0;
comma = 0;
}
}
}
}
// parse the local data into the struct
for(int i = 0; i < (newLine + 1); i++)
{
landmark[i].name = localName[i];
landmark[i].sound = localSound[i];
landmark[i].rawLocation = localRawLocation[i];
landmark[i].latitude = localLatitude[i].toFloat();
landmark[i].longitude = localLongitude[i].toFloat();
}
}
else
{
Serial.println(" Error - File not Present");
Serial.println(" OK - Terminating Algorithm");
Serial.println("________________________________________");
Serial.println("");
terminateLEDS();
while(1) {};
}
myFile.close();
Serial.println(" Success - Data Loaded Locally");
Serial.println("");
feedback();
drawGrid();
}
void feedback()
{
Serial.println("Data Feedback");
Serial.println(" OK - Dumping All Data");
Serial.println("");
for(int i = 0; i < (newLine + 1); i++)
{
Serial.print("Struct "); Serial.println(i);
Serial.print(" location name "); Serial.println(landmark[i].name);
Serial.print(" sound file "); Serial.println(landmark[i].sound);
Serial.print(" raw location "); Serial.println(landmark[i].rawLocation);
Serial.print(" latitude "); Serial.println(landmark[i].latitude, 4);
Serial.print(" longitude "); Serial.println(landmark[i].longitude, 4);
}
Serial.println("");
Serial.println(" Success - Data Dumped");
Serial.println("________________________________________");
Serial.println("");
}
void drawGrid()
{
Serial.println("Generating Grids");
Serial.println("________________________________________");
Serial.println("Mapping Grid Around Co-ordinates");
Serial.println(" OK - Looping through landmarks");
for(int i = 0; i < (newLine + 1); i++)
{
landmark[i].maxLat = landmark[i].latitude + 0.001;
landmark[i].minLat = landmark[i].latitude - 0.001;
landmark[i].maxLng = landmark[i].longitude + 0.001;
landmark[i].minLng = landmark[i].longitude - 0.001;
}
Serial.println(" Success - Grids Generated");
Serial.println("");
Serial.println("Dumping Grid Data");
Serial.println(" OK - Dumping Grid Data");
Serial.println("");
for(int i = 0; i < (newLine + 1); i++)
{
Serial.print("Struct "); Serial.println(i);
Serial.print(" max lat "); Serial.println(landmark[i].maxLat, 4);
Serial.print(" min lat "); Serial.println(landmark[i].minLat, 4);
Serial.print(" max lng "); Serial.println(landmark[i].maxLng, 4);
Serial.print(" min lng "); Serial.println(landmark[i].minLng, 4);
}
Serial.println("");
Serial.println(" Success - Data Dump Complete");
Serial.println("________________________________________");
Serial.println("");
}
这部分代码由3个循环组成。总的来说,这部分从datalog.txt中读取数据并进行处理。
-
getData()
读取文件并从中提取数据,计算输入的位置数以及所有这些位置的详细信息。 -
feedback()
将接收到的数据打印到串行监视器以允许用户调试数据文件 -
drawGrid()
在所有输入的地理位置周围绘制一个网格,如果客户端位于这些网格之一内,则设备会播放适当的声音文件。
获取和处理 GPS
void startGPS(bool hot)
{
Serial.println("");
digitalWrite(LED0, HIGH);
Serial.println("Initialising GNSS");
Serial.println(" OK - Setting Debug");
gnss.setDebugMode(PrintInfo); // set the mode to print info
Serial.println("Initialising Module");
if(gnss.begin() != 0)
{
Serial.println(" Error - Module Failed to Initialise");
digitalWrite(LED0, LOW);
while(1) {};
}
else
{
Serial.println(" OK - Setting Elements");
gnss.select(QZ_L1CA);
gnss.select(QZ_L1S);
Serial.println(" OK - Starting Positioning");
if(hot)
{
if(gnss.start(HOT_START) != 0)
{
Serial.println(" Error - Start Failed");
digitalWrite(LED0, LOW);
while(1) {};
}
else
{
Serial.println(" Success - GNSS Setup Complete");
}
}
else
{
if(gnss.start(COLD_START) != 0)
{
Serial.println(" Error - Start Failed");
digitalWrite(LED0, LOW);
while(1) {};
}
else
{
Serial.println(" Success - GNSS Setup Complete");
}
}
}
digitalWrite(LED0, HIGH);
delay(500);
}
void processGPS(SpNavData *pNavData)
{
char dataBuffer[STRING_BUFFER_SIZE];
// print number of satellites
snprintf(dataBuffer, STRING_BUFFER_SIZE, "numSat:%2d, ", pNavData->numSatellites);
Serial.print(dataBuffer);
// print the location data
Serial.print(" ");
if(pNavData->posFixMode == FixInvalid)
{
Serial.print("NO FIX ");
}
else
{
Serial.print("FIX ");
}
if(pNavData->posDataExist == 0)
{
Serial.println("No Geolocation");
}
else
{
gpsLatitude = pNavData->latitude;
gpsLongitude = pNavData->longitude;
Serial.print(gpsLatitude, 6); Serial.print(","); Serial.println(gpsLongitude, 6);
checkLocation();
}
}
void checkLocation()
{
for(int i = 0; i < (newLine + 1); i++)
{
if(gpsLatitude <= landmark[i].maxLat && gpsLatitude >= landmark[i].minLat &&
gpsLongitude <= landmark[i].maxLng && gpsLongitude >= landmark[i].minLng )
{
if(landmark[i].visited)
{
Serial.println(" [1/2] Already Visited");
delay(500);
}
else
{
Serial.println(" [1/2] First Visit");
delay(1000);
Serial.println(" OK - Checking Data");
Serial.print(" landmark name "); Serial.println(landmark[i].name);
Serial.print(" landmark sound file "); Serial.println(landmark[i].sound);
Serial.println(" [2/2] Calling 'playFile' with audio file");
Serial.println(" OK - Calling Function");
Serial.println("");
attachFile(landmark[i].sound);
landmark[i].visited = true;
break;
}
}
}
}
这一段也是由3个循环组成。它负责设置和启用 GNSS 模块以及连接和检索来自卫星的数据。
-
startGPS()
初始化 GNSS 模块,这不是在setup()
循环中完成的,因为 GNSS 模块在播放音频之前被禁用并且必须再次启用。 -
processGPS()
在void()
循环中进行读取后处理 GNSS 模块返回的数据并提取地理位置。 -
checkLocation()
根据先前生成的网格检查 GNSS 模块接收到的地理位置,以检查客户端是否位于地标处。
播放音频文件
void attachFile(String fileName)
{
Serial.println("");
Serial.println("Setting Up File");
Serial.println("________________________________________");
Serial.println("Finalising Setup");
digitalWrite(LED2, HIGH);
delay(500);
digitalWrite(LED2, LOW);
Serial.println("");
Serial.println("Locating File");
Serial.println(" OK - Opening File");
Serial.print(" OK - Locating "); Serial.println(fileName);
soundFile = SD.open(fileName);
if(!soundFile)
{
Serial.println(" Fatal Error - File Not Present");
Serial.println("________________________________________");
Serial.println("");
delay(500);
return;
}
else
{
Serial.println(" Success - File Located");
}
Serial.println("");
Serial.println("Analysing Format");
Serial.println(" OK - Getting Frames to Analyse");
int err = theAudio->writeFrames(AudioClass::Player0, soundFile);
Serial.println(" OK - Analysing Data");
if(err != AUDIOLIB_ECODE_OK)
{
Serial.println(" Fatal Error - File Formatation is Bad");
soundFile.close();
Serial.println("________________________________________");
}
else
{
Serial.println(" Success - Formatation is Good");
}
Serial.println("________________________________________");
Serial.println("");
playFile(fileName);
}
void playFile(String fileName)
{
Serial.println("Playing File");
Serial.println("________________________________________");
Serial.println(" OK - Pausing GNSS");
gnss.stop();
Serial.print("Playing "); Serial.println(fileName);
theAudio->startPlayer(AudioClass::Player0);
digitalWrite(LED2, HIGH);
while(1) // main playback loop
{
Serial.print(".");
int rawPot = analogRead(A0);
int volume = map(rawPot, 0, 1024, -700, 0);
theAudio->setVolume(volume); // set the volume to the position of the potentiometer
int err = theAudio->writeFrames(AudioClass::Player0, soundFile);
if(err == AUDIOLIB_ECODE_FILEEND) // end of file record
{
Serial.println("");
break;
}
if(err)
{
Serial.println("");
Serial.println(" Error - Playback Error");
Serial.print(" OK - Error ID "); Serial.println(err);
break;
}
usleep(40000);
}
theAudio->stopPlayer(AudioClass::Player0);
soundFile.close();
digitalWrite(LED2, LOW);
Serial.println(" OK - Playback Terminated");
delay(500);
Serial.println(" OK - Restarting GNSS");
startGPS(true);
Serial.println("________________________________________");
Serial.println("");
delay(500);
}
这部分代码控制mp3文件的播放,设置文件然后播放。
-
attachFile()
设置播放,它开始播放程序,检查文件是否存在并验证以确保 mp3 文件格式正确且帧可读。 -
playFile()
通过禁用 GNSS 模块开始播放,完成设置,然后实际播放文件,直到完成,用户可以在文件播放时使用电位器控制播放音量。
设置变量
现在已经描述了代码,一些变量必须个性化,以便从项目中获得最佳体验。要编辑的第一个变量是proDebug
,此变量控制串行打印。如果启用(设置为true
),则设备需要连接到计算机并启用串行监视器。默认设置为false
,因为必须将其设置为false
才能在字段上操作。
第二个变量不需要实际编辑,但必须调整索引。名为的结构Landmark
用于保存所有与地标相关的数据,下面包含具有该结构的代码片段。
struct Landmark
{
// strings
String name;
String sound;
String rawLocation;
// actual location
float latitude;
float longitude;
// grid co-ordinates
float maxLat;
float minLat;
float maxLng;
float minLng;
// extras
bool visited;
};
Landmark landmark[10];
如上所示,包括从名称到是否已经访问过该位置的所有内容。必须更改的是下面的声明,它创建了一个结构实例数组。目前,我有 10 个地标的索引,经理必须将此数字更改为他们已包含在文件中的地标数量。如果少于 10 个,则可以保留原样。就是这样。
图书馆
- SDHCI - Copyright (c)2018 Sony Semiconductor Solutions Corporation根据GNU Lesser General PublicLicense这个库在公共领域
- GNSS - Copyright (c)2018 Sony Semiconductor Solutions Corporation根据GNU Lesser General PublicLicense这个图书馆在公共领域
- 音频- Copyright (c)2018 Sony Semiconductor Solutions Corporation根据GNU Lesser General PublicLicense这个图书馆在公共领域
最后
最后一步是将设备插入计算机并上传草图。功耗方面,我已经将 Spresense 板连接到移动电源,它应该可以使用几次,然后才需要充电。
然后最后一步是封装项目以使其可移植且美观。我为该项目的外壳设计了一些快速示意图,附在下面。
我制作了外壳并完成得很好。我最终得到了一个看起来像这样的盒子。
所以在我完成原始盒子之后,是时候对其进行编辑并为电位器钻一些孔并访问板载 SD 卡模块和板载耳机插孔。下面的步骤显示了如何完成外壳并将设备安装到其中。
所以现在,您已准备好在现场使用该设备。请注意,在冷启动时,设备需要大约 10 分钟才能锁定足够多的卫星来收集地理定位数据。就是这样!
背景
我花了一段时间思考使用 Spresense 开发板的伟大项目。问题是你可以用 Spresense 板做任何东西,所以很难想出完美的想法。但我认为我实现了一个伟大项目的想法。旅游方式的彻底改变。建立在你进入博物馆的设备上,当你插入你正在看的东西的 ID 时,那个带耳机的设备会告诉你你正在看的东西。
它剥离了这个想法,用一个自动系统代替手动按钮选择,当客户到达一个位置时播放。按照您的节奏创造未来的观光。
- 《江苏省城市照明智慧灯杆建设指南》 2019
- GBT_城市与社区可持续发展模型指南
- 船舶电气设备维修指南.pdf 0次下载
- 开关电源设计指南.pdf 0次下载
- 基于开关电源的离线反激变换器设计指南 11次下载
- USB例程指南电子版下载 0次下载
- 传感器系统的构建与设计技巧资料下载
- 常用USB设备结构分析资料下载
- SoMachine Basic软件操作指南电子版 0次下载
- 如何设计一个网络爬虫程序进行智慧城市研究的获取与分析 9次下载
- LabView相机采集图像指南 100次下载
- TMS320F28x 控制和中断参考指南 6次下载
- TMS320x280x增强型脉宽调制器ePWM模块参考指南 44次下载
- 面向便携设备的白光LED驱动应用指南 0次下载
- my-rio构建工程指南_英版 0次下载
- 使用PyTorch构建神经网络 412次阅读
- 自动化设备的伺服电机选型指南 490次阅读
- X-RAY检测设备操作指南 385次阅读
- 交换芯片的构建方式 336次阅读
- 《RT-Thread设备驱动开发指南》基础篇--以先楫bsp的hwtimer设备为例 930次阅读
- 镜像构建Dockerfile的介绍 1004次阅读
- 如何利用ATmega328P构建一个可靠的LoRa设备 5274次阅读
- 一个易于构建且成本极低的电子设备保护器电路图 1025次阅读
- 如何使用 Compose 进行构建 1667次阅读
- Material Design指南中更新的相关内容 1858次阅读
- 什么是城市大脑?城市大脑是怎么破案的? 8955次阅读
- 智慧城市包括哪些方面(智慧城市领域与内容详解) 17.2w次阅读
- 如何打造智慧城市_发展智慧城市的意义何在 6.6w次阅读
- 六道防线构建平安城市新篇章 1628次阅读
- 如何让现代城市如何更智慧 585次阅读
下载排行
本周
- 1山景DSP芯片AP8248A2数据手册
- 1.06 MB | 532次下载 | 免费
- 2RK3399完整板原理图(支持平板,盒子VR)
- 3.28 MB | 339次下载 | 免费
- 3TC358743XBG评估板参考手册
- 1.36 MB | 330次下载 | 免费
- 4DFM软件使用教程
- 0.84 MB | 295次下载 | 免费
- 5元宇宙深度解析—未来的未来-风口还是泡沫
- 6.40 MB | 227次下载 | 免费
- 6迪文DGUS开发指南
- 31.67 MB | 194次下载 | 免费
- 7元宇宙底层硬件系列报告
- 13.42 MB | 182次下载 | 免费
- 8FP5207XR-G1中文应用手册
- 1.09 MB | 178次下载 | 免费
本月
- 1OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 2555集成电路应用800例(新编版)
- 0.00 MB | 33566次下载 | 免费
- 3接口电路图大全
- 未知 | 30323次下载 | 免费
- 4开关电源设计实例指南
- 未知 | 21549次下载 | 免费
- 5电气工程师手册免费下载(新编第二版pdf电子书)
- 0.00 MB | 15349次下载 | 免费
- 6数字电路基础pdf(下载)
- 未知 | 13750次下载 | 免费
- 7电子制作实例集锦 下载
- 未知 | 8113次下载 | 免费
- 8《LED驱动电路设计》 温德尔著
- 0.00 MB | 6656次下载 | 免费
总榜
- 1matlab软件下载入口
- 未知 | 935054次下载 | 免费
- 2protel99se软件下载(可英文版转中文版)
- 78.1 MB | 537798次下载 | 免费
- 3MATLAB 7.1 下载 (含软件介绍)
- 未知 | 420027次下载 | 免费
- 4OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 5Altium DXP2002下载入口
- 未知 | 233046次下载 | 免费
- 6电路仿真软件multisim 10.0免费下载
- 340992 | 191187次下载 | 免费
- 7十天学会AVR单片机与C语言视频教程 下载
- 158M | 183279次下载 | 免费
- 8proe5.0野火版下载(中文版免费下载)
- 未知 | 138040次下载 | 免费
评论
查看更多