När det står tex Time.h eller MemoryFree.h är det en fil man inkluderar som heter så, vart ligger lägger man den filen i arduino projektet?
Hoppas att det är okej att jag kommer med frågor fast det inte precis för ditt projekt framåt.


Kod: Markera allt
lcd.clear()Kod: Markera allt
#include <MemoryFree.h>
#include <Time.h>              // For the clock
#include <DS1307RTC.h>         // For the RTC
#include <Wire.h>              // For serial communication
#include <LiquidCrystal_I2C.h> // For running thel i2c LCD
// Declare variables
// Set pin numbers
byte skruvPin = 12;        			// Set pin for feeder
byte boilerOverheatPin = 11;		// Set pin for overheated boiler 
byte heaterPin = 10;       			// Set pin for heater
byte burnerOverheatPin = 9;			// Set pin for overheated burner
byte resetPin = 8;					// Reset program (Not Arduino)
byte callingForHeat = 7;   			// Set pin for listening on boiler calling for heat
int flameInput = A0;				// Analog pin for flame
// Set other variables
int flameVisible;					// Is there a flame?
int calling;						// Does boiler call for heat?
boolean FOn;						// Is there a flame
int k;								// What is the boiler status?
time_t t = now();					// Sets the variable 't' to now()
long timePlusFiveSec = 5;			// Container for now + 5 seconds
long timePlusOneSec = 1;			// Container for now + 1 second
long timePlusThirtySec = 30;		// Container for now + 30 seconds
long timePlusTenSec = 10;			// Container for now + 10 seconds
long timePlusTwentySec = 20;		// Container for now + 20 seconds
long timePlusThreehundredSec = 300; // Container for now + 300 seconds (5 minutes)
long timePlusThirteenSec = 13;		// Container for now + 13 seconds
long timePlusNineSec = 9;			// Container for now + 9 seconds
int filledPellets = 0;				// Is pellets filled (start feed)
int flameThreshold = 100;			// Contains threshold for when flame is detected
volatile int choosenEffect = 2;		// Volatile container makes it possible to change effect during run
// Other settings
LiquidCrystal_I2C lcd(0x27,20,4);
void setup() 
{
  // Initiate some hardware 
  lcd.init();
  lcd.backlight();
  Wire.begin();
  Serial.begin(9600);
  pinMode(skruvPin, OUTPUT);
  pinMode(callingForHeat, INPUT);
  pinMode(heaterPin, OUTPUT);
  pinMode(boilerOverheatPin, INPUT);
  pinMode(burnerOverheatPin, INPUT);
  pinMode(resetPin, INPUT);
  setSyncProvider(RTC.get);
}
void loop()
	// Things that starts right away
  	// Check current boiler status
{
  
FOn=getFlameStatus(); 			// Get flame status bool (on or off)/(True or False)
k=CheckBoilerStatus();			// Get the status from boiler int 0-3
lcd.setCursor(0,1);				// Debug
lcd.print(F("Boiler Status: "));
lcd.print(k);					// Debug
  
  switch (k) {					// Act on boiler status
  case 0:						// 0 Boiler is idling, nothing to do but sending log data
  	lcd.clear();
  	lcd.setCursor(0,0);
  	lcd.print(F("Boiler idle")); 	  	
  	lcd.setCursor(0,1);
  	lcd.print(F("Running data maint."));
  	
  	break;
  	
  case 1:						// 1 Boiler should run with set effect mode
  	runBoiler(choosenEffect);
  	break;
  
  case 2:
  	blowOut();					// 2 Blow out flame, boiler is done
  	break;
  	
  case 3:
  	fillPellets();				// 3 Start by feed and ignite pellets
	break;
  
  }
  	
}
int CheckBoilerStatus()			// Checking boiler status and set it as an int 0-3
/* 
 Controls the status of the boiler
 0 = Boiler is hot enough, no need to start, flame is out
 1 = Boiler has flame and wants more heat, run pellet feed and fan
 2 = Boiler has flame but is hot enough, run fan until flame is out
 3 = Boiler has no flame and is not hot enough, start from beginning with feeding pellet and start heating
 */
{  
  FOn =  getFlameStatus(); 					// Get flame status 
  calling = digitalRead(callingForHeat);	// Does boiler ask for heat?
  
  if ((FOn == 1) && (calling == 1))			// Set proper status according to info 
  {	
    return 1; 
  }
  
  else if ((FOn == 1) && (calling == 0))
  {
    return 2;
  }
  
  else if ((FOn == 0) && (calling == 1))
  {
    return 3;
  }
  
  else
  {
    return 0; 
  }
 }
int getFlameStatus() {					// Determents the flame status
  int flameValue;						// Int to hold the avg flame value
  int avgFlame;							// Int variable to hold the sums of flame level
  for (int i = 1; i < 51; i++) {		// Take 50 samples of the flame value
    avgFlame = analogRead(flameInput)+avgFlame; 
  }
  
  flameValue = avgFlame / 50;			// Divide the result by 50
  if (flameValue < flameThreshold)		// Determent if flame is on or off
  {
    return false;
  }
  else if (flameValue >= flameThreshold)
  {
    return true;
  }
}
void fillPellets() {					// Routine to fill pellets ans start ignition
lcd.clear();
  if (filledPellets == 0)				// Check that pellets has not all ready been filled
  {
    t=now();
    timePlusThirtySec = t + 2;			// Calculate the 30 second feeding time
   
    while (t < timePlusThirtySec){		// Fill pellets for 30 seconds
      t = now();
      lcd.setCursor(0,0);
      lcd.print(timePlusThirtySec - t);
      lcd.print(F(" "));
      digitalWrite(skruvPin, HIGH); 	// Sets the skruvPin high
      lcd.print(F("Feeding ...  "));
    }
    filledPellets = 1;					// Pellets has been filled
    digitalWrite(skruvPin, LOW);		// Turn off skruvPin (set to low)
    lcd.setCursor(0,0);
    lcd.print(F("Feeding, done!"));
    ignitePellets();					// Run the ignition routine
  }
  else{
  
  }
}
void ignitePellets() {					// Routine to ignite pellets
  lcd.clear();
  lcd.setCursor(0,1);
  lcd.print(F("Ignites pellets "));
  
  for (int c = 1; c < 11; c++) { 		// Try 10 times to ignite
 
  lcd.setCursor(0,0);
  lcd.print(F("Igniting, try no: "));
  lcd.print(c);
    digitalWrite(heaterPin, HIGH);
    t = now();
    timePlusTenSec = t + 1;
    while (t < timePlusTenSec) {
      t = now();
      lcd.setCursor(0,1);
      lcd.print(F("Fan high    "));
      //Run fan at high speed
    }
    t = now();
    timePlusTenSec = t + 1;
    while (t < timePlusTenSec) {
      t = now();
      lcd.setCursor(0,1);
      lcd.print(F("Fan low     "));
      //Run fan at low speed
      
    }
    k = CheckBoilerStatus();
    if (k == 1)
    { 
      runBoiler(choosenEffect);
    }
  }
  digitalWrite(heaterPin, LOW);
  
  if (k == 3)
  {
   larmStop(1); 
  }
}
void runBoiler(int effect) {
  lcd.clear();
  digitalWrite(heaterPin, LOW);
  time_t q = now();
  int effectValue;
  
  
  switch (effect)
  {
  case 1:
  	lcd.setCursor(0,0);
  	lcd.print(F("Effect mode: "));
  	lcd.print(effect);
  	
  	timePlusTwentySec = q + 20;
  	
    while (q < timePlusTwentySec)
    {
      lcd.setCursor(0,3);
      lcd.print(F("Feeds in: "));
      lcd.print(timePlusTwentySec - q);
      lcd.print(F(" "));
      q = now(); 
    };
    
    digitalWrite(skruvPin, HIGH);
    delay(1000);
    digitalWrite(skruvPin, LOW);
  	CheckBoilerStatus();
	break;
  
  case 2:
  	lcd.setCursor(0,0);
  	lcd.print(F("Effect mode: "));
  	lcd.print(effect);
    
    timePlusThirteenSec = q + 13;
    
    while (q < timePlusThirteenSec)
    {
      lcd.setCursor(0,3);
      lcd.print(F("Feeds in: "));
      lcd.print(timePlusThirteenSec - q);
      lcd.print(F(" "));
      q = now(); 
    };
    
    digitalWrite(skruvPin, HIGH);
    delay(1000);
    digitalWrite(skruvPin, LOW);
  	CheckBoilerStatus();
	break;
  
  case 3:
  	lcd.setCursor(0,0);
  	lcd.print(F("Effect mode: "));
  	lcd.print(effect);
  	
    timePlusNineSec = q + 9;
      while (q < timePlusNineSec)
    {
      lcd.setCursor(0,3);
      lcd.print(F("Feeds in: "));
      lcd.print(timePlusNineSec - q);
      lcd.print(F(" "));
      q = now(); 
    };
    
    digitalWrite(skruvPin, HIGH);
    delay(1000);
    digitalWrite(skruvPin, LOW);
  	CheckBoilerStatus();
    break;
  
  case 4:
    effectValue = 4;
    break;
  
  case 5:
    effectValue = 5;
    break;
  
  case 6:
    effectValue = 6; 
    break;
  
  case 7: 
    effectValue = 7;
    break;
  
  case 0:
    effectValue = 0;			// Do nothing, boiler is off
    lcd.setCursor(0,0);
  	lcd.print(F("Effect mode: "));
  	lcd.print(effect);
  	lcd.setCursor(0,1);
  	lcd.print(F("Boiler is off"));
    break;
  }
}
void blowOut () {
	// Set fan high if status is 2, for 5 minutes (300 seconds)
	lcd.clear();
	time_t r = now();
	timePlusThreehundredSec = r + 300;
	while (r < timePlusThreehundredSec) {
	lcd.setCursor(0,0);
	lcd.print(F("Blowing out flame"));
	lcd.setCursor(0,1);
	lcd.print(F("Left: ");
	lcd.print(timePlusThreehundredSec - r);
	lcd.print(F(" of 300");
	r = now();
	// Fan speed high
	}
	
	
	CheckBoilerStatus();
	
}
void larmStop(int larmMode) {
  lcd.clear();
  digitalWrite(skruvPin, LOW);
  digitalWrite(heaterPin, LOW);
  switch (larmMode)
  {
  case 0:
  // larmMode 0 = no alarm fired
  break;
  
  case 1:
  // Set fan to High for five minutes
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(F("L A R M ! ! !  "));
  lcd.print(larmMode);
  lcd.setCursor(0,1);
  lcd.print(F("Start failed!"));
  lcd.setCursor(0,2);
  lcd.print(F("Restart manually"));
  break;
  
  case 2:
  // Burner fired overheat protection
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(F("L A R M ! ! !  "));
  lcd.print(larmMode);
  lcd.setCursor(0,1);
  lcd.print(F("Burner overheat!"));
  lcd.setCursor(0,2);
  lcd.print(F("Wait for aut reset"));
  
  break;
  
  case 3:
  /* 
  Boiler fired overheat protection (Mains power for fan and screw is off) 
  Manual reset of boiler required 
  */
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(F("L A R M ! ! !  "));
  lcd.print(larmMode);
  lcd.setCursor(0,1);
  lcd.print(F("Boiler overheat!"));
  lcd.setCursor(0,2);
  lcd.print(F("Reset manually"));
  
  break;
  
  case 4:
  /* 
  Chute detector fires alarm. Chute is full of pellets or smoke is coming 
  up the chute. Clean glass and clear chute.
  */
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(F("L A R M ! ! !  "));
  lcd.print(larmMode);
  lcd.setCursor(0,1);
  lcd.print(F("Chute alarm!"));
  lcd.setCursor(0,2);
  lcd.print(F("Check chute"));
  
  break;
  
  }
  // Blink LCD background to get attention
  int s = 1;
  while (s < 10) {
  lcd.backlight();
  delay(200);
  lcd.noBacklight();
  delay(200);
  }  
}
 Jag hade fått för mig att dom var snuskigt dyra, men det där var ju klart överkomligt. Och som sagt, det är ju inget som påverkar säkerheten om relät fallerar eftersom dess uppgift är att tala om för arduinon att något hänt.
  Jag hade fått för mig att dom var snuskigt dyra, men det där var ju klart överkomligt. Och som sagt, det är ju inget som påverkar säkerheten om relät fallerar eftersom dess uppgift är att tala om för arduinon att något hänt.