从函数中全局删除并重新实例化数组结构,而无需在编译时知道数组的大小

Deleting and re instantiating an arrayed struct globally from within a function without knowing the size of the array at compile

本文关键字:数组 编译 删除 全局 函数 结构 实例化      更新时间:2023-10-16

完整代码:Pastebin

启用评论的完整代码(谷歌云端硬盘(:SerialGrapherV0.9

正在进行的代码接近底部。

youTube 图形代码运行示例:Grapher

背景:我的目标是编写一个库,允许调用方Arduino通过串行驱动被调用方Arduino,并在SSD1306 I2C显示器上打印到主定义的图形或图形(没有SPI版本可供测试(。图形代码已完成。目前我可以有 4 个可以同步或异步更新的图形,没有空白,只写入需要更新的部分。

两个 arduinos 目前运行相同的草图,并通过与地面绑定的pullup_input确定它们的角色,但是在更高版本中,草图将使用带有 #defined 布尔值的 if 语句进行编译,以大大节省调用方 arduino 的程序空间。

迄今: 实际的图形正在工作,并且每当图形添加(graphNumber,newVal(时图形都会更新;被称为。 每个图的 xpos、ypos、xlength 和 ylength 可以在调用方定义如下:

#define masterGraphNum 4                  //Set this to the number of Graphs you want. 
graphStruct graph[masterGraphNum] = {             //Each set of brackets is an instance of a graph, one for each specified in graphNum, set the array number on the receiver to the max number of graphs you can use.
//Graph 1                           //Usage: {LeftX, TopY, width, height}
{0, 0, 31, 32},
//Graph 2
{32, 0, 31, 32},
//Graph 3
{64, 0, 31, 32},
//Graph 4
{96, 0, 31, 32},
};

目前我正在尝试使用delete[] (graph);后跟graphStruct *graph = new graphStruct[incomingGraphNum];其中 incomingGraphNum 是由调用方发送并由被调用方接收的 int,这似乎一开始有效,但是在短时间绘制 ~15 秒后,arduino 崩溃并重新启动。

流:

  • 被叫方无限期等待连接
  • 调用方发送就绪字节
  • 被叫方确认
  • 调用方发送所需的图形数
  • 不起作用:重新初始化图形
  • 图形通过调用函数添加数据
  • NYI:通过串行发送图形编号和新值

我的问题是现在从函数中实例化全局可访问的结构数组,因为我不想将图形的数量预先编码到被调用者中,以及在结构中分配缓冲区数组的大小。

要使函数工作 图[] 需要全局声明。我想在被调用方设置期间在函数中全局声明 graph[图数],因为我想将其变成我未来项目的即插即用诊断工具。

后续步骤: 设置数据包以发送图形数据。不太难,基本上发送两个整数,如(graph#,graphData( 添加图表"标题"(如"ACC"或"光强度"(

实现:

  • 绘图系统
  • 简单的串行"呼叫 - 响应"系统和确认系统。(刚刚发现了Arduino IDE中包含的流函数,目前正在重写一些部分以使用Serial.parseInt((而不是修改后的serialEvent((。
  • 基本错误处理
  • 循环/秒计数器

一些可能会有所帮助的想法。

显示为 128 像素,因此您需要一个不超过该值的缓冲区。我建议你把它做成一个单一的全局缓冲区(而不是每个结构都有自己的缓冲区(。这永远不需要用new/delete重新调整大小,无论你有多少图表。

uint8_t global_graph_buffer[128];

请注意,我已将其从int更改为byte。显示器的高度只有 30 或 40 像素 (?(,因此无需存储任何大于此的数字。只需在端口上输入时缩小值即可。

graph_buffer[x] = map(incoming_data, 0, max_input, 0, height_of_graph);

请参阅 Arduinomap()函数。

接下来,你真的需要图表的y_pos和高度吗?您是否打算使用超过 1 行图表?如果没有,请删除这些结构成员。此外,您还可以摆脱x_pos和宽度字段。这些可以根据指数计算。

struct graphStruct {
uint8_t gx;  // Removed
uint8_t gy;  // Removed
uint8_t gw;  // Removed
uint8_t gh;  // Removed
int gVal;              // What is this for?
//int graphBuffer[graphBufferSize]; This is gone
uint8_t start_index;   // First index in the global array
uint8_t end_index;     // Last index
bool isReady;          // What is this for?
};

要计算x_pos和宽度:

x_pos = start_index
width = end_index - start_index

要处理传入的数据,请仅移动给定图形的缓冲区部分并添加值:

int incoming_data = some_value_from_serial;
// Shift
for (byte i = graph[graphNumber].start_index+1; i < graph[graphNumber].end_index; i++) {
global_graph_buffer[i] = global_graph_buffer[i-1]
}
// Store
global_graph_buffer[i] = map(incoming_data, 0, graphMax, 0, 128);

最后,您需要考虑:一次可以实际显示多少个图形?设置一个最大值,并在开始时只创建那么多结构。如果您使用全局缓冲区,正如我建议的那样,您可以多次重用结构(不必使用new/delete(。只需更改start_indexend_index字段即可。

不确定这些是否有帮助,但也许您可以从中获得一些想法。