Arduino的内存限制

11

我最近购买了一个Arduino Uno,现在正在进行一些实验。我连接了几个18B20传感器和一个ENC28J60网络模块,然后编写了一个草图,使我能够从浏览器连接到它并读取温度,无论是作为简单的网页还是JSON。制作网页的代码如下:

client.print("Inne: ");
client.print(tempin);
client.println("<br />");
client.print("Ute: ");
client.print(tempout);
client.print("<br /><br />");
client.println(millis()/1000);
//    client.print("<a href=\"/json\">j</a>");

奇怪的是:如果我取消最后一行的注释,代码可以编译成功,上传也没有问题,但我无法连接到板子。如果我在其他输出中添加更多字符,也会出现相同的情况。因此,看起来我遇到了某种内存限制(代码的总大小约为15 KB,在代码的其他地方还使用了一些字符串 - 是的,我知道,我将重写它以使用数组来存储临时数据,我只是从一个示例中借用了一些代码)。

在Arduino中,我可以使用多少内存来存储字符串?有没有办法绕过这个限制?(在Debian PC上使用GUI v1.0.1,GCC-AVR 4.3.5和AVR Libc 1.6.8)

4个回答

17

由于UNO的328仅有2K,所以RAM相对较小。你可能正在使用完RAM后导致程序停滞不前。我发现当RAM用尽时,程序就会卡在那里。

我建议阅读这个库的readme来获取可用RAM。它提到了如何使用“.print”同时消耗RAM和ROM的问题。

我现在总是使用(适用于Arduino IDE 1.0.+)

Serial.print(F("HELLO"));

对抗

Serial.print("HELLO");

由于它节省了RAM,这对于lcd.print应该是正确的。我总是放一个

Serial.println(freeMemory(), DEC);  // print how much RAM is available.

在代码的开头,请注意需要留出空间来运行实际代码并递归进入其子程序。

对于IDE 1.0.0之前的版本,该库提供getPSTR()函数。

IDE 1.0.3现在开始在编译结束时显示预期的RAM使用情况。不过,我发现它经常会低估,因为它只是一个估计值。


我也建议您查看 Webduino ,因为它有一个支持JSON的库。它的例子非常容易上手。但是它不直接支持ENC28J60。


“just kind of sit there” 对,没错。谢谢!我会查看你的建议。 - MortenSickel
“F”技巧非常聪明,已经修复了许多串行打印的奇怪错误。 - jjz

2
我使用以下代码来获取可用的免费RAM。
int getFreeRam()
{
  extern int __heap_start, *__brkval; 
  int v;

  v = (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);

  Serial.print("Free RAM = ");
  Serial.println(v, DEC);

  return v;
}

1
你可以使用一个名为memoryFree的小型库来检查内存使用情况。
当剩余内存较多时,你可能会达到串行缓冲区限制而不是内存限制。如果是这样,你可以在HardwareSerial.cpp中增加SERIAL_BUFFER_SIZE。(在Windows机器上,路径为C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino
但请注意,RAM和串行缓冲区都存储在SRAM上。增加串行缓冲区将导致可用于变量的内存减少。
对于在Arduino上使用JSON,有一个非常好的库,叫做aJson

这个人对于硬件串行缓冲区了解更多。 - mrv

0

在编程中,添加这个函数并在设置中调用它,然后在循环中的某些时候调用它,以确保RAM不被耗尽。

// Private function: from http://arduino.cc/playground/Code/AvailableMemory  
int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

你需要在print函数内调用它,例如: Serial.println(freeRam());


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接