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

时间:2018-10-03 14:58:25

标签: c++ arduino

完整代码:Pastebin

启用了注释的完整代码(Google云端硬盘):SerialGrapherV0.9

正在执行的代码位于底部附近。

运行图形代码的youTube示例:Grapher

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

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

到目前为止: 实际的图形工作正常,并且只要graphAdd(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崩溃并重新启动。

流量:

  • 被叫方无限期地等待连接
  • 呼叫者发送就绪字节
  • Callee的袜子
  • 呼叫者发送了想要的图
  • 不工作:重新初始化图形
  • 图形通过调用的函数添加数据
  • NYI:通过序列发送图形编号和新值

我的问题是现在从函数内部实例化一个可全局访问的结构数组,因为我不想将图的数量预先编码到被调用方中,也不需要在内部分配缓冲区数组的大小。结构。

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

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

已实施:

  • 绘图系统
  • 简单的串行“呼叫-响应”系统和确认系统。 (刚刚发现了Arduino IDE附带的流函数,当前重写了几节以使用Serial.parseInt()而不是修改后的serialEvent()。
  • 基本错误处理
  • 循环/秒计数器

1 个答案:

答案 0 :(得分:0)

一些可能有用的想法。

显示为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);

请参阅Arduino map()函数。

接下来,您是否真的需要图形的y_pos和高度?您计划有多于1行的图形吗?如果不是,请摆脱那些struct成员。同样,您也可以摆脱x_pos和width字段。这些可以根据索引进行计算。

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字段即可。

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