×

Serial Studio:串口设备的仪表盘软件

消耗积分:2 | 格式:zip | 大小:0.00 MB | 2023-06-13

张浩

分享资料个

描述

您是否曾经需要在仪表板上显示来自微控制器的数据,并花更多的时间开发(和修复)您的仪表板软件,而不是实际处理您的 MCU 项目?

好吧,我做了很多次。让我介绍一下背景,我通过我大学的代表队KA'AN SAT参加了几个 CanSat 竞赛项目。CanSat 是“对真实卫星的模拟,集成在软饮料罐的体积和形状中”(欧洲航天局,更多信息)。这些比赛的主要任务之一是为地面站开发软件。地面站软件(GSS)通过串口设备(一般为XBee )实时接收CanSat的遥测数据,显示并导出为CSV/Excel文件,用于任务后分析。

从一开始,我们就使用Qt开发 GSS以支持多种操作系统(以防我们的一台计算机在比赛中遇到问题),并且因为 Qt/QML 非常便于开发引人注目的用户界面。

2019年地面站软件截图如下

poYBAGSAhEeANucdAAJBvM7h6fM287.png
 

以及 CUCEI CanSat 竞赛期间 GSS 运行和显示遥测的照片

pYYBAGSAhEmAHPbCAAES-_6PulE274.jpg
 

如果您有兴趣,可在此处获取 2019 GSS 的源代码该软件的所有意图和目的都运行良好(毕竟我们获得了第一名)。

半年后问题来了,当时我发现自己在处理多个项目,这些项目需要使用串行设备进行某种数据采集。例如,ROCH (我们大学的另一个代表团队,参加了NASA 人类漫游者探索挑战赛)的一些成员希望在隔离期间将我们的 GSS 与他们的漫游者整合为一个副项目。

结果是灾难性的;我在深夜接到一个电话,我们最终通宵达旦想出一种方法,使 GSS 适应他们接收到的遥测数据。最后,该软件可以运行,但 UI 集成很糟糕,数据导出功能也不是很好(请参阅下面的屏幕截图了解一下):

pYYBAGSAhFCAeC5TAAGCMmg6iKU410.jpg
 

这两个项目(CanSat 和流动站)都有相似的遥测格式(传感器读数和 OBC 状态数据以逗号分隔)。然而,信息本身有不同的顺序。

在那次经历之后,我决定我已经受够了为我参与的每个项目编写单独的仪表板软件。我需要想出一种方法来使用相同的仪表板/GSS 软件来处理所有项目,而无需在最后一刻修改 GSS 代码。

我最初想到的解决方案是在 GSS 和微控制器之间创建一个基于 JSON 的通信协议,于是Serial Studio诞生了(它的初始名称是SigLAB但后来我改变了主意)。

基本上,微控制器通过串行端口发送以下信息:

  • 项目名称。
  • 当前传感器读数和 OBC 状态。
  • 每个读数的含义、其测量单位以及 GSS 应如何处理该读数(例如,创建测量大气压力的实时图表)。

所有这些信息都可以很容易地在 JSON 文档中表示,例如:

{
   "t":"KAANSATQRO",
   "g":[
      {
         "t":"Mission Status",
         "d":[
            {
               "t":"Runtime",
               "v":"%value%",
               "u":"ms"
            },
            {
               "t":"Packet count",
               "v":"%value%"
            },
            {
               "t":"Battery voltage",
               "v":"%value%",
               "g":true,
               "u":"V"
            }
         ]
      },
      {
         "t":"Sensor Readings",
         "d":[
            {
               "t":"Temperature",
               "v":"%value%",
               "g":true,
               "u":"°C"
            },
            {
               "t":"Altitude",
               "v":"%value%",
               "u":"m"
            },
            {
               "t":"Pressure",
               "v":"%value%",
               "u":"KPa",
               "g":true
            },
            {
               "t":"External Temperature",
               "v":"%value%",
               "g":true,
               "u":"°C"
            },
            {
               "t":"Humidity",
               "v":"%9",
               "g":true,
               "u":"%value%"
            }
         ]
      }
   ]
}

如您所见,我们有以下结构:

  • 项目名称(字符串)
  • 数据组数组,对于每个组:
  • 组标题(字符串)
  • 数据集数组,对于每个数据集:
  • 标题(字符串)
  • 值(字符串)
  • 单位(字符串)
  • 图形请求(布尔值)

一个组由彼此密切相关的值组成,例如:

  • OBC 状态(我们示例中的第一组)
  • 传感器读数(我们示例中的第二组)
  • 加速度计读数(X、Y、Z)
  • GPS读数
  • ETC。

另一方面,数据集代表每个单独值的含义,以及我们应该如何处理它。

Serial Studio上,此信息以下列方式显示:

poYBAGSAhFOAbX_FAAD096xiNrA402.png
 

正如您可能推断的那样,每个“窗口”对应于我们 JSON 文档中的一个组(我隐藏了屏幕截图中的图形以避免混淆)。

这种方法非常适用于小型项目。然而,对于更复杂的项目,通过串行(或通过无线电信号,然后通过串口)创建和发送大型 JSON 文档就变得很成问题。解决方案?从您的计算机加载相同的 JSON 文档,指示微控制器仅发送传感器/数据读数,让Serial Studio通过使用逗号分隔的数据框中每个接收到的值的索引来计算其余部分。

这样做可以让您两全其美:

  • 您不需要为每个项目编写特定的仪表板/GSS 软件(并且您可以获得我们之前描述的所有不错的功能)。
  • 而且你不需要从你的微控制器创建和传输一个大的 JSON 文档(哎呀,微控制器软件的工作人员根本不需要知道 JSON 是什么或者它是如何工作的)。

JSON“地图”文档如下所示:

{
   "t":"%1",
   "g":[
      {
         "t":"Mission Status",
         "d":[
            {
               "t":"Runtime",
               "v":"%2",
               "u":"ms"
            },
            {
               "t":"Packet count",
               "v":"%3"
            },
            {
               "t":"Battery voltage",
               "v":"%4",
               "g":true,
               "u":"V",
               "w":"bar",
               "min":3.6,
               "max":4.3
            }
         ]
      },
      {
         "t":"Sensor Readings",
         "d":[
            {
               "t":"Temperature",
               "v":"%5",
               "g":true,
               "u":"°C",
               "w":"bar",
               "min":0,
               "max":80
            },
            {
               "t":"Altitude",
               "v":"%6",
               "u":"m",
               "w":"bar",
               "min":0,
               "max":3000
            },
            {
               "t":"Pressure",
               "v":"%7",
               "u":"KPa",
               "g":true,
               "w":"bar",
               "min":54,
               "max":102
            },
            {
               "t":"External Temperature",
               "v":"%8",
               "g":true,
               "u":"°C",
               "w":"bar",
               "min":0,
               "max":80
            },
            {
               "t":"Humidity",
               "v":"%9",
               "g":true,
               "u":"%",
               "w":"bar",
               "min":0,
               "max":100
            }
         ]
      },
      {
         "t":"GPS",
         "w":"map",
         "d":[
            {
               "t":"GPS Time",
               "v":"%10"
            },
            {
               "t":"Longitude",
               "v":"%11",
               "u":"°E",
               "w":"lon"
            },
            {
               "t":"Latitude",
               "v":"%12",
               "u":"°N",
               "w":"lat"
            },
            {
               "t":"Altitude",
               "v":"%13",
               "u":"m"
            },
            {
               "t":"No. Sats",
               "v":"%14"
            }
         ]
      },
      {
         "t":"Accelerometer",
         "w":"accelerometer",
         "d":[
            {
               "t":"X",
               "v":"%15",
               "u":"m/s^2",
               "g":true,
               "w":"x"
            },
            {
               "t":"Y",
               "v":"%16",
               "u":"m/s^2",
               "g":true,
               "w":"y"
            },
            {
               "t":"Z",
               "v":"%17",
               "u":"m/s^2",
               "g":true,
               "w":"z"
            }
         ]
      },
      {
         "t":"Gyroscope",
         "w":"gyro",
         "d":[
            {
               "t":"X",
               "v":"%18",
               "u":"°",
               "g":true,
               "w":"yaw"
            },
            {
               "t":"Y",
               "v":"%19",
               "u":"°",
               "g":true,
               "w":"roll"
            },
            {
               "t":"Z",
               "v":"%20",
               "u":"°",
               "g":true,
               "w":"pitch"
            }
         ]
      }
   ]
}

您可以猜到,Serial Studio会将%1 %2 %3 ... %20值替换为逗号分隔数据框中相应索引处的值。微控制器为给定的 JSON 映射发送的相应sprintf () 格式为:

/*KAANSATQRO,%s,%s,%s,%s,%s,%s,%,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s*/

您可能已经注意到某些地方有一些“w”键,这些键用于构建小部件在此处进行了解释)。最后,这是显示Serial Studio用法的强制性GIF

 

很酷,对吧?如果您有兴趣在您的项目中使用Serial Studio,请访问以下相关链接:

适用于 Windows、macOS 和 GNU/Linux 的预构建二进制文件/安装程序可通过 GitHub 发布获得: https: //github.com/Serial-Studio/Serial-Studio/releases/

最小的例子

假设我们想用 Arduino 绘制 ADC 读数并将数据导出到 CSV 表。这是 Arduino 代码:

#define ADC_PIN A0

void setup() {
   // Initialize Serial port at 9600 bauds
   Serial.begin(9600);
   
   // Configure analog input
   pinMode(ADC_PIN, INPUT);
}

void loop() {
   // Read voltage @ ADC_PIN
   int adc_value = analogRead(ADC_PIN);
   float voltage = adc_value * (5.0 / 1023.0);

   // Send current ms & reading through serial
   Serial.print("/*");        // Frame start sequence  [/*]
   Serial.print(millis());    // Add MCU runtime       [ms]
   Serial.print(",");         // Separator character   [,]
   Serial.print(voltage);     // Add voltage           [V]
   Serial.print("*/");        // Frame finish sequence [*/]
   
   // Wait 50 ms
   delay(50);
}

将此代码部署到您的 Arduino 并创建一个包含以下内容的 JSON 文件:

{
   "t":"Minimal Example",
   "g":[
      {
         "t":"MCU Status",
         "d":[
            {
               "t":"Runtime",
               "v":"%1",
               "u":"ms"
            },
            {
               "t":"ADC reading",
               "v":"%2",
               "g":true,
               "u":"V",
               "w":"bar",
               "min":0,
               "max":5
            }
         ]
      }
   ]
}

打开 Serial Studio 并通过选择应用程序左上角的“手动”单选按钮并单击“更改地图文件”按钮将 JSON 文件导入 Serial Studio。最后,选择合适的 COM 端口。如果一切顺利,您应该会看到与此类似的屏幕:

pYYBAGSAhF6ATOn3AAENWC4Yz7s340.png
 

如果单击“打开当前 CSV”按钮,您将能够在 Excel/Calc 表格中看到所有收到的信息:

poYBAGSAhGCAEkXMAACsxJ419Jc635.png
 

如果您有任何疑问、想法或错误报告,请随时添加评论、联系我或在 GitHub 上提出问题。希望互联网上的一些随机的人会发现这很有用:)


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !