Arduino(C ++)sketc定期冻结或重置:可疑溢出

时间:2018-09-28 12:33:05

标签: c++ arduino

我无法确定一些arduino代码导致重复出现问题的原因。下面的代码读取两个温度传感器,将结果发送到PID库,并使用输出来控制冰箱上的一些继电器(基本上是对冰箱添加精确的温度控制)。

代码冻结或Arduino定期重置。这是定期发生的,但时间会有所变化-每隔30分钟冻结一次,最多冻结30个小时。

我怀疑有一个溢出或者我正在写超出数组范围的内容,但是我找不到问题。不太可能出现电源问题-arduino使用10A 12v电源和专用5v稳压器供电,因此我对此表示怀疑。

对于这一切我还是很陌生,非常感谢您提供任何指示或建议-甚至对于如何解决此不可预测的错误的一些提示,也将不胜感激!

代码如下:

设置和主回路,还会检查模拟输入的设定温度:

// Call libraries for display, sensor, I2C, and memory. Library setup included as well.
#include <avr/pgmspace.h>
char buffer[20];

#include <Time.h>
#include <TimeLib.h>
#include <OneWire.h> 
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3f,20,4); 
#include <DallasTemperature.h>
#include <PID_v1.h>

// Special Characters for the display and display animations
#if defined(ARDUINO) && ARDUINO >= 100
#define printByte(args)  write(args);
#else
#define printByte(args)  print(args,BYTE);
#endif
#define ONE_WIRE_BUS 5  //DS18S20 Signal pin on digital 2
uint8_t heart[8] = { 0x0,0xa,0x1f,0x1f,0xe,0x4,0x0};
uint8_t deg[8] = { 0x1c,0x14,0x1c,0x0,0x3,0x4,0x4,0x3};
uint8_t Pv[8] = { 0x1c,0x14,0x1c,0x10,0x10,0x5,0x5,0x2};
uint8_t Sv[8] = { 0xc,0x10,0x8,0x4,0x18,0x5,0x5,0x2};
// end special chars 


//************* Begin Variables Setup ***************//

//Sensors (ds18s20 needs additional chatter)

  byte addr1[8]= {0x28, 0x3F, 0xB5, 0x3C, 0x05, 0x00, 0x00, 0x25};
  byte addr2[8]= {0x28, 0xC7, 0xCD, 0x4C, 0x05, 0x00, 0x00, 0x0D};
  byte data1[12];
  byte data2[12];
  byte MSB = 0;
  byte LSB = 0; 
  float tempRead = 0;
  float TemperatureSum = 0;
  OneWire ds(ONE_WIRE_BUS);
  OneWire oneWire(ONE_WIRE_BUS); 
  DallasTemperature sensors(&oneWire);


//controller outputs
int ControlCpin = 6; // control to fridge
int ControlTpin = 8; // control to temperature/heater  (get aquarium heater)
int ControlLpin = 7; // control to light
int ControlApin = 9; // control to airflow

//operational vars (the button)
//int buttonPushCounter = 0;   // counter for the number of button presses DEPRACATED
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button
boolean buttonstate = false; // calculastate of the button (includes timer delay. use this in menus)
int buttontime = 0;          // press length measure 
int buttontimeon = 0;        // necessary for press length measure 

//operational vars (sensors and timing)
unsigned int sensorInterval = 20000;         // time between readings
unsigned long int sensorTime = 0;           // current time 
unsigned long int sensorTime2 = 0;          // time of last sensor reading

// fans, lights, and timers
unsigned long int fanONmillis = 0;
unsigned long int fanOFFmillis = 0;
byte fanON = 0;
byte fanOFF = 0;
boolean fanstate = false;
unsigned long int Time = 0;
unsigned long int TimeAdjust = 0;

unsigned long int LightON = 0;
unsigned long int LightOFF = 0;
unsigned int Hours = 0;
unsigned int Minutes = 0;
unsigned int Days = 0;
byte daysAdj = 0; //not implemented yet
float tempDiff = 0;

//key var storage
float PvH = 0; 
double PvT = 0;
float SvH = 0; 
double SvT = 12; 
float SvTdisplay = 5.5;
float SvTdisplayOld = 5.5;

float Temp1;                   //Current readings
float Temp2;                   //Current readings
float Temp3;                   //Current readings

// Fridge limits
unsigned int safetyRest = 5; // off this long every hour (minimum) to let the compressor rest in minutes
int minCool = 10; // minimum cooling period in minutes
int coolStart = 0;
byte coolON = 0;  // PID attached to this

// Heat limits
byte heatON = 0;  // PID attached to this

//cool
double Kp = 0.5;
double Ki = 0.5;
double Kd = 0.5;
double Output;
PID coolPID(&PvT, &Output, &SvT ,Kp,Ki,Kd, REVERSE);
unsigned coolWindowSize = 600;  // minutes*10
unsigned long coolWindowStartTime;
unsigned long coolOffElapsed = 0;
long unsigned PIDpos = 0; 

  unsigned long Outputx = 0;
  unsigned long PIDposx = 0;
  unsigned long safetyRestx = 0;

// ensure setpoint, input, and outpit are defined

//************* End Variables Setup ***************//


void setup(){

//Sensor start

  sensors.begin();


//Pin declarations  
  pinMode(ControlTpin, OUTPUT); //set outputs
  pinMode(ControlLpin, OUTPUT);
  pinMode(ControlApin, OUTPUT);
  pinMode(ControlCpin, OUTPUT);
  digitalWrite(ControlTpin, HIGH); // write outputs HIGH (off in this case) FIRST to prevent startup jitters.
  digitalWrite(ControlLpin, HIGH); 
  digitalWrite(ControlApin, HIGH); 
  digitalWrite(ControlCpin, HIGH); 

//LCD and special chars
  Serial.begin(9600);
  lcd.begin();                      
  lcd.backlight();
  lcd.createChar(0, heart);
  lcd.createChar(1, deg);
  lcd.createChar(2, Pv);
  lcd.createChar(3, Sv);
  lcd.clear();
  LoadScreen();
  HomeSetup();
  //PID setup
  coolPID.SetOutputLimits(0, coolWindowSize);
  coolPID.SetMode(AUTOMATIC);
  coolOffElapsed = millis();
}

void loop(){
  //if interval has passed, check the sensors, update the triggers, and update the screen
  if (millis() - sensorTime2 > sensorInterval){ 
     sensorTime2 = millis();
     SensorCheck();
     Triggers();
     HomeSetup ();
  }

  SvTdisplay = (float)analogRead(A0);
  SvTdisplay = SvTdisplay/40+5;
  if(abs(SvTdisplay-SvTdisplayOld) > 0.2){
    SvTdisplayOld = SvTdisplay;
    lcd.setCursor(2,0);
    lcd.print(SvTdisplayOld,1);     //svt
    lcd.printByte(1);
    lcd.print(" ");
    SvT = analogRead(A0)/4+50;
    }
  PIDpos = ((millis()/60000) % (coolWindowSize/10));
 }

以下代码对加载屏幕进行编码,并使用当前值更新屏幕:

void LoadScreen (){
  lcd.clear();
  lcd.home();
  lcd.setCursor(0,0);
  lcd.print(" LaggerLogger "); 
  lcd.printByte(0);
  lcd.setCursor(0,1);
  lcd.print(" V2.0 Beepboop!"); 
  delay(3000);
  lcd.clear();
 }

//write the home screen to the LCD with current data 

void HomeSetup(){
  lcd.setCursor(0,0);
  lcd.printByte(3);
  lcd.print(" ");
  lcd.print(SvTdisplayOld,1);     //svt
  lcd.printByte(1);
  lcd.print(" ");
  lcd.setCursor(0,1);
  lcd.printByte(2);
  lcd.print(" "); 
  lcd.print(PvT/10,1);   //pvt
  lcd.printByte(1);
  lcd.print(" ");
  lcd.setCursor(8,1);
  lcd.print(day()-1);
  lcd.print("/");
  lcd.print(hour());
  lcd.print(":");
  lcd.print(minute());
  lcd.print(" ");
  lcd.setCursor(8,0);
  lcd.print(Output/10,1);
  lcd.print("m/h ");    
}

以下内容将检查输出值,并在适当的情况下“触发”继电器:

void Triggers () {
  coolPID.Compute();

  // Check PID
  if ((Output/10) > (coolWindowSize/10-PIDpos) && PIDpos > safetyRest ) {  //
    coolON = 1;
    coolStart = millis();
  }
  else if ((millis() - coolStart) > (minCool * 60000)){
    coolON = 0;
  }
  else {}

  // Write to temp relay pins
  if (coolON == 1) {
    digitalWrite(ControlCpin, LOW);
  }
  else {
    digitalWrite(ControlCpin, HIGH);
  }

  // Control fans
  if (coolON == 1 || heatON == 1 || tempDiff > 1) {
    fanOFFmillis = millis();
    fanONmillis = millis();
    fanstate = true;
    digitalWrite(ControlApin, LOW);
  }
  else {
    fanstate = false;
    digitalWrite(ControlApin, HIGH);
  }
}

以下内容检查温度传感器并进行一些时钟计算:

void SensorCheck(){ 

     Temp1 = getTemp1();
     Temp2 = getTemp2();

    //average readings and note the difference
    if(Temp1 > 0 && Temp2 >0) { 
      PvT = (Temp1 + Temp2) / .2;
      tempDiff = abs(Temp1 - Temp2);
    }

    //... unless there's only one thermometer...
    else if (Temp1 > 0){  
      PvT = Temp1*10;
      tempDiff = 0;
    }
    else {
      PvT = 999;
      tempDiff = 0;
    }

    //clock update
    Time = millis() + TimeAdjust;
    Hours = hour();
    Minutes = minute();
    Days = day();  
}

float getTemp1(){
 sensors.requestTemperatures();
 float z = sensors.getTempCByIndex(0);
 return z;
 }

float getTemp2(){
 sensors.requestTemperatures();
 float z = sensors.getTempCByIndex(1);
 return z;
}

1 个答案:

答案 0 :(得分:0)

问题在于,后来更新了一个整数(声明为int coolStart)以容纳millis()的值。

Millis()可能比int可用的16位要大得多-产生了溢出。

将变量声明更改为“ unsigned long coolStart = 0;”似乎已经解决了问题。

感谢大家提供故障排除建议。