Ensten bygger styrning till pelletsbrännare

Berätta om dina pågående projekt.
mstore
Inlägg: 81
Blev medlem: 22 november 2007, 00:42:20
Ort: Malmö/Österbotten i Finland

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av mstore »

Coolt projekt!

Har själv funderat på liknande projekt pga dåligt fungerande styrkort til en KMP Px-21.
Använder själv MTX lambdahttp://www.mrtuning.se/p/matare/innovat ... ambda.html
som jag använder för att logga förbränningen. Har noterat stora variationer i lambdavärde och kommit fram till att det
enklaste sättet kanske vore att kunna styra fläkthastigheten steglöst enligt lambda värdet. Kanske kontrollerat av en PI regulator. Har dock allt för dåliga programmeringskunskaper att göra något nu, men jag väntar med spänning och iver på nya framsteg i ditt projekt!

h, Martin
Användarvisningsbild
orvar-e
EF Sponsor
Inlägg: 5973
Blev medlem: 9 mars 2007, 09:01:32
Ort: Borlänge

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av orvar-e »

ensten skrev:Tänkte delge lite tankar kring Arduino nu när jag har labbat runt lite.
Finns det ingen ren arduino tråd? Så att din tråd slipper bli förstörd.
Användarvisningsbild
ensten
EF Sponsor
Inlägg: 3759
Blev medlem: 19 oktober 2004, 15:55:20
Ort: Hudiksvall

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av ensten »

Nu har jag nått en milstolpe i programmerandet. Jag har nu alla funktioner på plats utom möjligheten att välja effektläge via en rotationsencoder.

Alla "viktiga" larm såsom, fallschaktslarmet, pannans överhettningsskydd och brännarens överhettningsskydd går nu via en timer interrupt med 10Hz. Notera att pannans överhettningsskydd bryter strömmen till fläkten, skruven och tändelementet alltså den bryter helt oberoende av min hemmabyggda styrning. Det känns tryggt och säkert att använda den säkerhetsfunktionen som används i det befintliga systemet. Enda skillnaden är att i nuvarande system bryts strömmen även till styrboxen men det kommer den inte att göra i det nya systemet (finns egentligen ingen anledning). Övriga säkerhetsanordningar är också intakta.

Så snart jag fått till effektväljaren så kommer jag att gå över i betatestning (koppla in styrningen på pannan och köra den med personlig övervakning).

En annan detalj som blir mer som bling-bling är trådlös överföring via radio till en display uppe i själva bodelen av huset.

Här kommer koden:

Kod: Markera allt

// #include <MemoryFree.h>

#include <TimerOne.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 activityPin = 13;				// Used for indicate various activity (blinks led)
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
byte speedPin1 = 6;					// Set pin for fan speed control
byte speedPin2 = 5;					// Set pin for fan speed control
byte speedPin3 = 4;					// Set pin for fan speed control
byte speedPin4 = 3;					// Set pin for fan speed control
byte chutePin = 2;					// Set pin for chute sensor
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();
time_t f = now();					// Sets the variable 't' to now()
long timePlusFiveSec;				// Container for now + 5 seconds
long timePlusOneSec;				// Container for now + 1 second
long timePlusThirtySec;				// Container for now + 30 seconds
long timePlusTenSec;				// Container for now + 10 seconds
long timePlusTwentySec;				// Container for now + 20 seconds
long timePlusThreehundredSec;		// Container for now + 300 seconds (5 minutes)
long timePlusThirteenSec;			// Container for now + 13 seconds
long timePlusNineSec;				// Container for now + 9 seconds
int filledPellets;					// Is pellets filled (start feed)
int flameThreshold = 100;					// Contains threshold for when flame is detected
volatile int choosenEffect = 7;			// Volatile container makes it possible to change effect during run
int boilOH;							// Container for the boiler overheat state
int burnOH;							// Container for the burner overheat state
time_t chuteTimerStart;
long chuteTimerNow;
int chuteTime;
byte startCounting;
byte chuteMode;
byte chuteLarm = 0;


// Other settings
LiquidCrystal_I2C lcd(0x27,20,4);


void setup() 
{
  CreateSwedishChars();
  // Initiate some hardware 
  Timer1.initialize(100000);              // Set timer interrupt to 100 000 uS (10 Hz)
  Timer1.attachInterrupt(CheckChuteStatus);     // Attachthe service routine 

  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);
  pinMode(speedPin1, OUTPUT);
  pinMode(speedPin2, OUTPUT);
  pinMode(speedPin3, OUTPUT);
  pinMode(speedPin4, OUTPUT);
  pinMode(chutePin, INPUT);
  pinMode(activityPin, OUTPUT);
  setSyncProvider(RTC.get);

  // Decide if boiler is on at startup (ie after short power out).


}


void loop()
// Things that starts right away
// Check current boiler status
{
  if (chuteLarm == 1)
  {
    larmStop(4); 
  }
  
  if (boilOH == 0)
  {
    larmStop(3); 
  }
  
  if (burnOH == 1)
  {
    larmStop(2); 
  }
  
  
  FOn=getFlameStatus(); 			// Get flame status bool (on or off)/(True or False)
  k=CheckBoilerStatus();			// Get the status from boiler int 0-3
  /*
  lcd.clear();
  lcd.setCursor(0,1);				// Debug
  lcd.print(F("Pannstatus: "));
  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("Pannan v")); 	
    lcd.write(char(4));
    lcd.print(F("ntar"));  	
    lcd.setCursor(0,1);
    lcd.print(F("K")); 
    lcd.write(char(1));
    lcd.print(F("r dataunderh."));

    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; 
  }
/*
  lcd.setCursor(0,0);
  lcd.print(F("Pannstatus: "));
  lcd.print(FOn);
  lcd.setCursor(0,1);
  lcd.print(F(" Kallar: "));
  lcd.print(calling);
*/
}


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 == false)				// 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("Matar ...  "));
    }
    filledPellets = 1;					// Pellets has been filled
    digitalWrite(skruvPin, LOW);		// Turn off skruvPin (set to low)
    lcd.setCursor(0,0);
    lcd.print(F("Matning, klar!"));
    ignitePellets();					// Run the ignition routine
  }
  else{

  }
}

void ignitePellets() {					// Routine to ignite pellets
  
  if (getFlameStatus() == 0)
  {
  lcd.clear();
  lcd.setCursor(0,3);
  lcd.print(getFlameStatus());
  lcd.setCursor(0,0);
  lcd.print(F("T")); 
  lcd.write(char(4));
  lcd.print(F("nder pellets "));

  for (int c = 1; c < 11; c++) { 		// Try 10 times to ignite

    lcd.setCursor(0,1);
    lcd.print(F("T"));
    lcd.write(char(4));
    lcd.print(F("nder, nr: "));
    lcd.print(c);
    digitalWrite(heaterPin, HIGH);
    t = now();
    timePlusTenSec = t + 1;

    while (t < timePlusTenSec) {
      t = now();
      lcd.setCursor(0,2);
      lcd.print(F("Fl"));
      lcd.write(char(4));
      lcd.print(F("kt h"));
      lcd.write(char(0));
      lcd.print(F("g       "));
    //Run fan at high speed
    }
    t = now();
    timePlusTenSec = t + 1;
    while (t < timePlusTenSec) {
      t = now();
      lcd.setCursor(0,2);
      lcd.print(F("Fl"));
      lcd.write(char(4));
      lcd.print(F("kt l"));
      lcd.write(char(2));
      lcd.print(F("g       "));
      //Run fan at low speed

    }
    k = CheckBoilerStatus();
    if (k == 1)
    { 
      return;
    }

  }
  digitalWrite(heaterPin, LOW);

  if (k == 3)
  {
    larmStop(1); 
  }
  }
else if (getFlameStatus() == true)
{
}
else
{
}

}


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("Effektl"));
    lcd.write(char(4));
    lcd.print(F("ge: "));
    lcd.print(effect);

    timePlusTwentySec = q + 20;

    while (q < timePlusTwentySec)
    {
      lcd.setCursor(0,1);
      lcd.print(F("Matar om: "));
      lcd.print(timePlusTwentySec - q);
      lcd.write(char(1));
      lcd.print(F(" "));
      q = now(); 
    };

    digitalWrite(skruvPin, HIGH);
    delay(1000);
    digitalWrite(skruvPin, LOW);
     if (getFlameStatus() == 0)
    {
    larmStop(5);
    }
    CheckBoilerStatus();
    break;

  case 2:
    lcd.setCursor(0,0);
    lcd.print(F("Effektl"));
    lcd.write(char(4));
    lcd.print(F("ge: "));
    lcd.print(effect);

    timePlusThirteenSec = q + 13;

    while (q < timePlusThirteenSec)
    {
      lcd.setCursor(0,1);
      lcd.print(F("Matar om: "));
      lcd.print(timePlusThirteenSec - q);
      lcd.print(F(" "));
      q = now(); 
    };

    digitalWrite(skruvPin, HIGH);
    delay(1000);
    digitalWrite(skruvPin, LOW);
     if (getFlameStatus() == 0)
    {
    larmStop(5);
    }
    CheckBoilerStatus();
    break;

  case 3:
    lcd.setCursor(0,0);
    lcd.print(F("Effektl"));
    lcd.write(char(4));
    lcd.print(F("ge: "));
    lcd.print(effect);

    timePlusNineSec = q + 9;
    while (q < timePlusNineSec)
    {
      lcd.setCursor(0,1);
      lcd.print(F("Matar om: "));
      lcd.print(timePlusNineSec - q);
      lcd.print(F(" "));
      q = now(); 
    };

    digitalWrite(skruvPin, HIGH);
    delay(1000);
    digitalWrite(skruvPin, LOW);
     if (getFlameStatus() == 0)
    {
    larmStop(5);
    }
    CheckBoilerStatus();
    break;

  case 4:
    lcd.setCursor(0,0);
    lcd.print(F("Effektl"));
    lcd.write(char(4));
    lcd.print(F("ge: "));
    lcd.print(effect);

    timePlusNineSec = q + 7;
    while (q < timePlusNineSec)
    {
      lcd.setCursor(0,1);
      lcd.print(F("Matar om: "));
      lcd.print(timePlusNineSec - q);
      lcd.print(F(" "));
      q = now(); 
    };

    digitalWrite(skruvPin, HIGH);
    delay(1000);
    digitalWrite(skruvPin, LOW);
     if (getFlameStatus() == 0)
    {
    larmStop(5);
    }
    CheckBoilerStatus();

    // pause 7 sec
    effectValue = 4;

    break;

  case 5:
    lcd.setCursor(0,0);
    lcd.print(F("Effektl"));
    lcd.write(char(4));
    lcd.print(F("ge: "));
    lcd.print(effect);

    timePlusNineSec = q + 5;
    while (q < timePlusNineSec)
    {
      lcd.setCursor(0,1);
      lcd.print(F("Matar om: "));
      lcd.print(timePlusNineSec - q);
      lcd.print(F(" "));
      q = now(); 
    };

    digitalWrite(skruvPin, HIGH);
    delay(1000);
    digitalWrite(skruvPin, LOW);
     if (getFlameStatus() == 0)
    {
    larmStop(5);
    }
    CheckBoilerStatus();
    // pause 4.5 sec
    effectValue = 5;
    break;

  case 6:
    lcd.setCursor(0,0);
    lcd.print(F("Effektl"));
    lcd.write(char(4));
    lcd.print(F("ge: "));
    lcd.print(effect);

    timePlusNineSec = q + 3;
    while (q < timePlusNineSec)
    {
      lcd.setCursor(0,1);
      lcd.print(F("Matar om: "));
      lcd.print(timePlusNineSec - q);
      lcd.print(F(" "));
      q = now(); 
    };

    digitalWrite(skruvPin, HIGH);
    delay(1000);
    digitalWrite(skruvPin, LOW);
     if (getFlameStatus() == 0)
    {
    larmStop(5);
    }
    CheckBoilerStatus();
    // pause 3 sec
    effectValue = 6; 
    break;

  case 7:
    lcd.setCursor(0,0);
    lcd.print(F("Effektl"));
    lcd.write(char(4));
    lcd.print(F("ge: "));
    lcd.print(effect);

    timePlusNineSec = q + 2;
    while (q < timePlusNineSec)
    {
      lcd.setCursor(0,1);
      lcd.print(F("Matar om: "));
      lcd.print(timePlusNineSec - q);
      lcd.print(F(" "));
      q = now(); 
    };

    digitalWrite(skruvPin, HIGH);
    delay(1000);
    digitalWrite(skruvPin, LOW);
    if (getFlameStatus() == 0)
    {
    larmStop(5);
    }
    CheckBoilerStatus();
    // pause 2 sec 
    effectValue = 7;
    break;

  case 0:
    while (choosenEffect == 0)
    {
      effectValue = 0;			// Do nothing, boiler is off
      lcd.setCursor(0,0);
      lcd.print(F("Effektl"));
    lcd.write(char(4));
    lcd.print(F("ge: "));
      lcd.print(effect);
      lcd.setCursor(0,1);
      lcd.print(F("Pannan av"));
      CheckBoilerStatus();

      break;
    }
  }


}

void blowOut () {
  // Set fan high if status is 2, for 5 minutes (300 seconds)
  lcd.clear();
  time_t r = now();
  timePlusThreehundredSec = r + 10;
  while ((r < timePlusThreehundredSec) && (!k == 0))
  {
    lcd.setCursor(0,0);
    lcd.print(F("Bl"));
    lcd.write(char(2));    
    lcd.print(F("ser ut flamman"));
    lcd.setCursor(0,1);
    lcd.print(F("Kvar: "));
    lcd.print(timePlusThreehundredSec - r);
    lcd.print(F(" av 300 sek  "));
    r = now();
    k = CheckBoilerStatus();
    lcd.setCursor(0,2);
    lcd.print(k);
    // Fan speed high
  }

  k = CheckBoilerStatus();
  while (k == 0);
  {
    k = CheckBoilerStatus();
    lcd.setCursor(0,2);
    lcd.print(k); 
  }
  // 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("LARM!!!  Nr: "));
    lcd.print(larmMode);
    lcd.setCursor(0,1);
    lcd.print(F("Misslyckad start!"));
    lcd.setCursor(0,2);
    lcd.print(F("Starta om manuellt"));
    shutDown();
    break;

  case 2:
    // Burner fired overheat protection
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(F("LARM!!!  Nr: "));
    lcd.print(larmMode);
    lcd.setCursor(0,1);
    lcd.write(char(1));
    lcd.print(F("verhettad br"));
    lcd.write(char(4));
    lcd.print(F("nnare"));
    lcd.setCursor(0,2);
    lcd.print(F("V"));
    lcd.write(char(4));
    lcd.print(F("nta p"));
    lcd.write(char(2));
    lcd.print(F(" aut. "));
    lcd.write(char(2));
    lcd.print(F("terst."));
    shutDown();
    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("LARM!!!  Nr: "));
    lcd.print(larmMode);
    lcd.setCursor(0,1);
    lcd.write(char(1));
    lcd.print(F("verhettad panna"));
    lcd.setCursor(0,2);
    lcd.write(char(3));
    lcd.print(F("terst. manuellt"));
    shutDown();

    break;

  case 4:
    /* 
     Chute detector triggers a 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("LARM!!!  Nr: "));
    lcd.print(larmMode);
    lcd.setCursor(0,1);
    lcd.print(F("Fallschakt"));
    lcd.setCursor(0,2);
    lcd.print(F("Kontr. fallschakt"));
    shutDown();
    break;
    
   case 5:
    /* 
     Flame is lost during run. Probable cause is lack of pellets
     */
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(F("LARM!!!  Nr: "));
    lcd.print(larmMode);
    lcd.setCursor(0,1);
    lcd.print(F("Pannan slocknat"));
    lcd.setCursor(0,2);
    lcd.print(F("Pellets slut?"));
    lcd.setCursor(0,3);
    lcd.print(F("Fyll & starta om"));
    shutDown();
    break;


  }
  // Blink LCD background to get attention
  int s = 1;
  while (s < 10) {
    lcd.backlight();
    delay(200);
    lcd.noBacklight();
    delay(200);
  }  
}




int CheckOverheat()
{
  boilOH = digitalRead(boilerOverheatPin);
  burnOH = digitalRead(burnerOverheatPin);

  if  (burnOH == 1)
  {
    
    return 3;
  }
  
  else
  {
  }

  if (boilOH == 0)
  {
    return 2;
  }
  else
  {
  }
}

void CheckChuteStatus()
{
  if ((digitalRead(chutePin) == 1) && (startCounting == 0))
  {
    chuteMode=1;
    digitalWrite(activityPin, HIGH);  
  }

  else if ((digitalRead(chutePin) == 1) && (startCounting == 1))
  {
    chuteMode=2;
  }

  else
  {
    chuteMode=3;
  }

switch (chuteMode)
  {
  case 1:
    {
      chuteTimerStart = now() + 5;
      startCounting = 1;
    }
    break;

  case 2:
    {  
      f = now();
      chuteTime = chuteTimerStart - f;
      Serial.println(chuteTime);
    
    switch(chuteTime)      
      {
      case 1:
		{
        chuteLarm = 1;
        break;
        }
      default:
      {
        break;
      }
    }    
    break;

  case 3:
    {
      startCounting = 0;
    }
    break;
  }
 boilOH = digitalRead(boilerOverheatPin);
  burnOH = digitalRead(burnerOverheatPin);

  
}
}

void shutDown()
{
 
  digitalWrite(skruvPin, LOW);
  digitalWrite(heaterPin, LOW);
  digitalWrite(speedPin1, LOW);
  digitalWrite(speedPin2, LOW);
  digitalWrite(speedPin3, LOW);
  digitalWrite(speedPin4, LOW);

}

void CreateSwedishChars()
{
  byte versalOdots[8] = { // Ö
  B01010,
  B01110,
  B10001,
  B10001,
  B10001,
  B10001,
  B01110,
};

byte gemenOdots[8] = { // ö
  B01010,
  B00000,
  B01110,
  B10001,
  B10001,
  B10001,
  B01110,
};

byte gemenAring[8] = { // å
  B00100,
  B00000,
  B01110,
  B00001,
  B01111,
  B10001,
  B01111,
  
};

byte versalAring[8] = { // Å
  B00100,
  B01110,
  B10001,
  B10001,
  B11111,
  B10001,
  B10001,
  
};

byte gemenAdots[8] = { // ä
  B01010,
  B00000,
  B01110,
  B00001,
  B01111,
  B10001,
  B01111,
  
};

byte versalAdots[8] = { // Ä
  B01010,
  B01110,
  B10001,
  B10001,
  B11111,
  B10001,
  B10001,
  
};
lcd.createChar(0, gemenOdots); // ö
lcd.createChar(1, versalOdots); // Ö
lcd.createChar(2, gemenAring); // å
lcd.createChar(3, versalAring); // Å
lcd.createChar(4, gemenAdots); // ä
lcd.createChar(5, versalAdots); // Ä
}
mstore
Inlägg: 81
Blev medlem: 22 november 2007, 00:42:20
Ort: Malmö/Österbotten i Finland

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av mstore »

Hej,

Om jag har förstått ditt projekt rätt så är "effektväljaren" baserad på olika fläkthastighet?
Kör själv med Px-21 + lamdasensor i utblåset. Enligt mina observationer så är effekten i första hand beroende av matningsmängden. (det vet du väl ändå :v)
Tänkte försöka göra ett spjäll som regleras enligt lambdavärdet, men den ide´n visade sig vara dålig eftersom reaktionen av ett spjäll närmast var obefintlig.
Fast jag helt strypte luftintaget, är det åtminståne i mitt system otroligt högt drag i skorstenen så brännaren började suga luft genom matningsskruven istället.
På den bifogade bilden kan det noteras att lambdavädet rör sig mellan 1,2 och 1,8 lambda. Det verkar som om denna graf nästan direkt kan översättas till jämnheten i matningsskruven.
Bränslet verkar komma klumpvist.
Engligt egna observationer verkar skruven bete sig som att ifall det stundvis kommer mera pellets än vad det borde så kommer det i nästa stund komma mindre pellets än medelvärdet.
Kanske man eventuellt kunde reglera bränslemängden med någon slags PID regulator? Om jag har förstått dethär med förbränning så är man givetvist ute efter högsta systemverkningsgrad.
Man strävar efter att få brännaren att gå på den effekt där man får bästa förbränningverkningsgraden, men också där pannans systemverkningsgrad är högs.
Kort och gott så handlar det i såfall att hitta ett sätt att elektroniskt kontrollera matningen på ett så sätt att bränsleflödet är så jämnt som möjligt. Ifall man kontrollerar luftmängd kommer effekten att variera parallellt med luftmängden. Hoppas detta väcker tankar.

Detta är ett coolt projekt, Hoppas att det börjar fungera fint! följer det med spänning.

h, Martin
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
Icecap
Inlägg: 26628
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av Icecap »

Luftmängden bestämmer effekten! Doseringen ska anpassas till den luftmängd och då densiteten på pelletsen varierar med tillverkaren & produktionsdatum är en lamdbastyrning trevlig. Samtidig är denna variation anledningen till att man ska låta luften vara konstant och reglera doseringen istället.

Jag har utförd regleringen så att lambda-mätningen går genom ett rejält trögt lågpassfilter (mjukvara) och doseringen justeras var 3'dje dosering. Själva regleringen är en ren integrerande reglering.

Att försöka reglera under varje dosering är inte möjlig då rökgasen tar en viss tid på sig för att komma igenom pannan. Därmed sker regleringen efter att den behövs och en så snabbverkande reglering kommer helt enkelt att se till att värdet aldrig stämmer. Ja, jag har testat!

Justeringen för var 3'dje dosering har visat sig fungera ypperligt bra, regleringen av doseringen likaså. Doseringen justeras i steg om 1/100 sek. Har man en brännarkonstruktion med extern doseringsskruv är de ju ökända för att dosera lite hur som helst varför det i grunden är omöjligt att reglera något på ett vettigt sätt.

Har man inte heller dragbegränsare blir det ännu mer idiotisk att reglera med någon avancerat teknik.

Jag har kortat upp brännarens doseringsskruv lite för att få en jämnare dosering och det har hjälpt lite.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av blueint »

ensten skrev:Enda skillnaden är att i nuvarande system bryts strömmen även till styrboxen men det kommer den inte att göra i det nya systemet (finns egentligen ingen anledning). Övriga säkerhetsanordningar är också intakta.
Utom om det brinner i styrboxen ;)

Kanske det vore bra om överhettningsskyddet även strypte spjället? (lufttillförseln)
Användarvisningsbild
Icecap
Inlägg: 26628
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av Icecap »

Nej för allt i världen! Stryp inte spjället! Då kommer de gaser som finns kvar att ackumulera och plötsligt är det något som tänder dom och pannan desintegrerar!

Överhettningsskyddet i pannan är den siste säkring om t.ex. termostatsignalen blir fel och det räcker i grunden med att det bryter all driftström till doseringsmotorer osv medan själva elektronikboxen kan få köra vidare.

Men då överhettningsskyddet bara får kunde återställas manuellt kan styrningen som mest larma om fel.
Användarvisningsbild
ensten
EF Sponsor
Inlägg: 3759
Blev medlem: 19 oktober 2004, 15:55:20
Ort: Hudiksvall

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av ensten »

All återställning av larm kommer att kräva hands on från operatör. Detta för att inte äventyra säkerheten. Det är intressant med mer avancerad styrning och chansen att jag skall kunna låta bli att utveckla vidare är minimal, därmed uppskattar jag alla råd och tips och förslag.
mstore
Inlägg: 81
Blev medlem: 22 november 2007, 00:42:20
Ort: Malmö/Österbotten i Finland

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av mstore »

Icecap: Vilken brännare kör du med?
Användarvisningsbild
ensten
EF Sponsor
Inlägg: 3759
Blev medlem: 19 oktober 2004, 15:55:20
Ort: Hudiksvall

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av ensten »

Ursäkta att jag svarar i ditt ställe Icecap.
Han kör en Janfire eftersom han har jobbat som utvecklare av styrningen till dom brännarna.
Användarvisningsbild
Icecap
Inlägg: 26628
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av Icecap »

mstore: Just hemkommit. Janfire NH.
Användarvisningsbild
ensten
EF Sponsor
Inlägg: 3759
Blev medlem: 19 oktober 2004, 15:55:20
Ort: Hudiksvall

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av ensten »

Stötte på ett intressant problem igår (tog mig halva dagen att hitta felet). Efter att jag lagt larmfunktionerna i en timerinterrupt så slutade min flamvakt att fungera. Det hör till saken att jag inte kopplade ihop de två sakerna eftersom jag inte kört flamvakten på ett tag då jag hållit på med andra delar. Det som hände var att jag började få väldigt skumma data från flamvakten (borde i sämsta fall ligga mellan 0 och 1023). Värdena fladdrade mellan -40x till 4xxx.

Trodde jag hade hårdvarufel eftersom jag påbörjat permanent dragning av kabel i skåpet. Sedan misstänkte jag att jag hade bränt ADC. Började sedan fundera på hur det kunde bli minusvärden.

Jag har ju samplat sensorn 50ggr och sedan delat summan med 50. Det fungerade bra tills jag började med timerinterrupt, förklaringen verkar vara att den tappar samplingar och då blir så klart min division galen om den ens görs ordentligt. Tog bort den funktionen nu och det verkar som om det funkar bättre. Jag ska experimentera lite med färre samplingar och se om det funkar bättre.
Användarvisningsbild
Icecap
Inlägg: 26628
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av Icecap »

Jag har gjort så att det kommer en interrupt för varje omvandling. Jag tar sedan lambda-mätning och kör genom ett låg-pass filter i mjukvaran och sedan får det räcka. Slutvärdet är så pass trögt filtrerat att det duger alldeles fint och själva filter-funktionen är snabb och enkel.
Användarvisningsbild
ensten
EF Sponsor
Inlägg: 3759
Blev medlem: 19 oktober 2004, 15:55:20
Ort: Hudiksvall

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av ensten »

Dags för ett par bilder, det var ju ett tag sedan.
IMG 2014-02-03 20.12.06.jpg
Nätdelen med Kina-LCD'er.
IMG 2014-02-03 20.12.44.jpg
Styrbox med locket stängt och monterade intag för kablar. En akrylskiva skall monteras i hålet i locket.
IMG 2014-02-03 20.11.49.jpg
Styrboxen med öppet lock.
IMG 2014-02-03 20.13.42.jpg
AC Voltmeter 300V som skall visa ungefärligt hur fläkten körs
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
kawa
Inlägg: 1
Blev medlem: 22 mars 2014, 12:33:52

Re: Ensten bygger styrning till pelletsbrännare

Inlägg av kawa »

Har läst din tråd med intresse då jag själv har en gammal px21 liggandes som kortet är trasigt på.
Som jag skulle vilja göra något kul med.

Undrar hur det har gått för dig.

Samt testade att programera en arduino med din kod och den bara klagade på en massa fel eller så har jag gjort fel.

uppdatera oss som följer prodjektet
Skriv svar