0

我对一些代码和奇怪的异常有疑问。此代码放置在Digispark上。Digispark 的代码大小限制为 6,010 字节。使用嵌套if语句时,文本不会输出到 LCD 屏幕(请参见下面的链接)。通过分别注释掉每个集合,我可以让它再次工作。

基本液晶功能:

  1. LCD 输出内部啤酒温度和环境空气温度。http://imgur.com/S0rYvaa
  2. LCD 清除
  3. LCD 输出目标温度和加热器(继电器)状态http://imgur.com/OtFXG1K

变量是浮点类型。

float inside_temp;
float outside_temp;
float target = 74.00;

//inside_temp and outside_temp are values from 2 ds18b20's
inside_temp = 70.70;
outside_temp = 70.81;

LCD 在使用此代码时工作,并像这样注释掉它。编译后的大小为 5,928 字节。

if(inside_temp < target){
    //Create a limit so heater isn't crazy hot as 5 gallons takes a while to change temperature.
    // float limit = target + 1;
    // if(outside_temp > limit){
    //     digitalWrite(RELAY_PIN, LOW);
    //     lcd.print("OFF");
    // }
    // else{
    digitalWrite(RELAY_PIN, HIGH);
    lcd.print("ON");
    // }
  }
  else{
      digitalWrite(RELAY_PIN, LOW);
      lcd.print("OFF");
  }

LCD 也可以使用此代码。编译后的大小为 5,590 字节。

// if(inside_temp < target){
    //Create a limit so the heater isn't crazy hot as 5 gallons takes a while to change temperature.
    float limit = target + 1;
    if(outside_temp > limit){
        digitalWrite(RELAY_PIN, LOW);
        lcd.print("OFF");
    }
    else{
       digitalWrite(RELAY_PIN, HIGH);
       lcd.print("ON");
    }
    // }
    // else{
    //     digitalWrite(RELAY_PIN, LOW);
    //     lcd.print("OFF");
    // }

未注释时 LCD 不工作。编译后的大小为 5,992 字节。它所做的只是坐在那儿,开着背光,没有文字。http://imgur.com/xPAzY0N,DdGdYoI

if(inside_temp < target){
    //create a limit so heater isn't crazy hot as 5 gallons takes a while to change temperature.
    float limit = target + 1;
    if(outside_temp > limit){
        digitalWrite(RELAY_PIN, LOW);
        lcd.print("OFF");
    }
    else{
        digitalWrite(RELAY_PIN, HIGH);
        lcd.print("ON");
    }
}
else{
    digitalWrite(RELAY_PIN, LOW);
    lcd.print("OFF");
}

我不明白为什么会这样。发生这种情况是因为我太接近最大尺寸限制了吗?我不能像这样构造代码吗?

4

2 回答 2

0

我认为很难以结论性的方式回答这个问题,而不能在本地进行测试。

听起来确实很可疑,当代码大小接近最大值时它会中断。另一方面,它似乎表明工具中的一个错误,如果超过某个限制,它不会“硬”破坏。

关于如何减少代码大小的一些提示:

  • 不要使用float,因为 CPU 必须模拟它。定点格式应该适合温度。
  • 分解出对 and 的函数调用digitalWrite()lcd.print()因为函数调用会生成大量代码。

排除这些调用的一种方法是执行以下操作:

uint8_t relay_pin = LOW;
const char *lcd_text = "OFF";
if(inside_temp < target) {
    float limit = target + 1;
    if(outside_temp > limit) {
    }
    else {
      relay_pin = HIGH;
      lcd_text = "ON";
    }
}
digitalWrite(RELAY_PIN, relay_pin);
lcd.print(lcd_text);

这利用了我们希望始终更新 LCD 和继电器的事实,因此我们始终可以调用这些函数。然后我们使用变量来保存所需的值,因为赋值通常比函数调用便宜(就代码大小而言,这里)。

于 2013-01-28T15:06:11.210 回答
0

不要忘记 RAM 的小尺寸,因为 Attiny85 只有 512 字节的 SRAM,而 328 的 2K。您可能只是用完了 RAM。我了解到,当它用完时,它只是坐在那里。

我建议从这个库中阅读自述文件以获取 FreeRAM。它提到了“.print”如何同时消耗 RAM 和 ROM。

我现在总是用

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

相对

Serial.print("HELLO"); 

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

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

在代码的开头,并注意。请注意,需要有空间来运行实际代码并递归到其中。

unwind 将 .print 分解为一个实例的示例是使用变量。它实际上与 F()(旧的 getPSTR())类似,因为它不再是 const 字符串。所以它实际上也使用了更少的内存。

于 2013-01-28T16:02:28.650 回答