Lämpötilaohjattu askelmoottori

Doddiin…

Arduino Uno + aloituspaketti tuli tilattua ja on tuossa nyt pyörinyt. Ledejä on vilkuteltu, potikan ja thermistorin arvoja luettu, servoja käännelty jne. yms. Youtuben varmaankin kaikki Arduino tutorialit on käyty läpi ja netistä löydettyjä “aloita tästä” oppaita on koodailtu ja selailtu. Kaikki ei tietenkään päässä pysy, mutta melkoisen hyvin perusteet hanskassa niin että tiedän mitä mikäkin kohta koodissa tekee / tarkoittaa.

Löysin erään toisen tekemän vastaavan projektin, otin siitä alustan ja muokkasin hieman. Sain nyt toimimaan servon liikkumisen lämpötilan mukaan + hienosäätö potikan avulla. Koodi ei vielä täysin aukene itselle, tutkiminen ja pohtiminen jatkuu.

Kyselenkin nyt seuraavaa…

Servo tuntuu helposti jäävän surisemaan koska ei pääse täysin haluamalleen kohdalle. Tämähän tietysti rasittaa servoa, joten olisiko askelmoottorin + potikan arvoa käyttäen asentotunnistus tässä kuitenkin kestävämpi / parempi ratkaisu? Mielipiteitä?

Koodi jolla nyt viimiseksi tullut kikkailtua ja jonka sisältöä selvittelen on tässä:

#include <Servo.h>

Servo myservo; 

unsigned char temps = 0;		
const unsigned char MAX_VAL = 10;
unsigned int T2 = 0;
unsigned int val = 0;			

unsigned int updateAvgtemp(){
	static int history[MAX_VAL]={0};
	static unsigned char lastHist=0;
	static unsigned char numHist=0;
	unsigned int temp=0;
	unsigned char counter=0;
	unsigned char arcount=0;
	history[lastHist] = analogRead(temps);
	if(numHist<MAX_VAL)
		++numHist;
	arcount=lastHist;
	++lastHist;
	if(lastHist>=MAX_VAL)
		lastHist=0;
	temp=0;
	counter=0;
	do{
		temp+=history[arcount];
		arcount--;
		if(arcount>MAX_VAL)
			arcount=(MAX_VAL-1);
		counter++;
	}while(counter < numHist);
	return (temp/numHist);
}

void setup()
{
  myservo.attach(9);			
  Serial.begin(9600);
}
void loop()
{
    val = updateAvgtemp();		
    T2 = val;
    val = map(val, 350, 700, 180, 0);	
    myservo.write(val);			
    Serial.print(val);
    Serial.print(" / ");
    Serial.print(T2);
    Serial.print(" \n ");
    delay(500);								
}

A0 liitännässä itsellä thermistori. Thermistorin maadoituksessa 2.2kOhm vastus sekä säätöpotikka (karkea hienosäätö).
Digipuolella pinnissä 9 servo.

Serial.printit otettu siksi, että näkee thermistorin arvon ja siihen suuntaavan servolle syötettävän arvon.

Tässä siis mennään tämän projektin suhteen…

Tuomo

Löysin tämmösen. En tiedä onko apua tai edes motivaatiota lisäävää, mutta videoitahan on aina hauska katsella :slight_smile:
self regulating waterheater

Morjesta ja kiitokset vastauksestasi.

Linkistä on hyötyä, tuosta sain uudenlaisen idean yhdistää tarvittava kampi tuohon säätönuppiin. Nyt edelleen googlen kanssa yritän etsiskellä tietoa mikä olisi paras anturi ulkoilmaa mittaamaan, sillä asteikko tulisi olla -40 -> +40.

Vesiputken kyljessä voin käyttää vaikka perus 10kOhm thermistoria, sillä lämpötilat kun ovat kokoajan vähintään +20c ja enintään varmasti siellä 65c tietämissä.


Tuomo

Eikö tuohon lie kykene mikä tahansa anturi, toteutustavasta riippuen esim. LM35, PT1000, DS18B20+…

Tutkittu ja hutkittu on…

Tuli tilailtua tuossa muutama päivä sitten 3kpl PT1000 jenkeistä (sieltä kun saa pilkkahinnalla). Tuli posteineen maksamaan 9.50€. Servon asennusrautoja (tässä tapauksessa kylläkin alumiinia) on tullut hommailtua ja nyt alkaa pikkuhiljaa hahmottumaan asennuskehys ja vipuvarsi.

Seuraavaksi täytyy alkaa tilailemaan sitä “juotospistelevyä” jotta saa tehtyä väliaikaisia-lopullisia kytkentöjä. Kaikki anturit ja servo tulee olemaan liittimellä irroitettavissa / kytkettävissä.

Projekti etenee hitaasti mutta hitaasti, ehkäpä tämä valmistunee ensi syksyn alkupakkasille ja talveksi tästä saadaan jo riemua.


Tuomo

Nostelua…

Nyt on piirilevyä pikkusen juoteltu tuollaiselle reikälevylle ja samalla ohjelmointia ajeltu pikkuhiljaa, siis todellakin hiljaa eteenpäin… Nyt ollaan siis siinä tilassa että kahdelle 7-segmenttiselle saadaan haluttua ruutua näkymään, mutta en saa kirveelläkään tuosta PT1000 muutettua lämpötilaa celcius asteiksi. Olen kikkaillut kaikkea ja testaillut, eli lukemat yms. toimii mutta ovat päin honkia. Koodi seuraava:

[code]float val = 0;
float analogInput = 0;

//ST_CP - 74HC595
int latchPin = 8;
//SH_CP 74HC595
int clockPin = 12;
//DS 74HC595
int dataPin = 11;

// Numerointi 0-9 LED-segment näytöille
byte digits[] = {
B00111111, B00000110, B01011011, B01001111, B01100110, B01101101,
B01111101, B00000111, B01111111, B01101111
};

// perussetuppia
void setup() {
Serial.begin(9600);
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}

// Peruslooppia
void loop() {
val = analogRead(analogInput);
float temp = map(val, 0, 1023, -200, 600.0);
displayNum(temp);
delay(5000);
Serial.println(temp);
Serial.println(val);
}

// LED-Segmenteille printtaus
void displayNum(int num)
{
// ykköset
int dig0 = num % 10;
// kympit
int dig1 = (num/10) % 10;

digitalWrite(latchPin, LOW); //pitää olla low jottei ledit välky kun lähetetään dataa
shiftOut(dataPin, clockPin, MSBFIRST, digits[dig1]); // lähetetään data kympit
shiftOut(dataPin, clockPin, MSBFIRST, digits[dig0]); // lähetetään data ykköset
digitalWrite(latchPin, HIGH); // nostetaan high jolloin määrätyt ledit syttyy[/code]

Koko koodia en tietenkään ole itse keksinyt, suotta sitä pyörää uudestaan keksimään, mutta olen tulkinnut sitä ja luulen ymmärtäväni tähän asti aikaansaamani tekeleen. Nyt jeesiä tarvitsisinkin tuon PT1000 anturin datan kanssa.

Anturi kytketty 5V linjasta 1k Ohm vastuksen kanssa maihin ja siitä vastuksen rinnalta otettu A0 linjaan. Eli siis: 5V - 1k Ohm - haaroitus anturille ja siittä A0 - Ground. Tämän kytkennän luin jostain netistä (olen selannut tolkuttomasti eri sivustoja etsien apuja). Monesti on löytynyt melkoisen monimutkaisia laskukaavoja joiden kanssa saisi asteet esille, ovatko nämä ainoat vaihtoehdot? Onko muuta keinoa?

Älkääpä ihmetelkö, tuossa on nyt vain “mapattu” nuo arvot jotta sain testailtua omia häröilyjä… Onko vinkkiä miten tästä edetä?


Tuomo

Koodiin en nyt mene mitään sanomaan.

Hommahan menee nyt niin, että nollassa saat sen kiloohmin pihalle NTC:stä. Tuolloin A/D muunnos näkee 2,5V jännitteen. Jos referenssi on Vcc ja A/D muunnoksen resolutio 10-bittiä, tulos on 512. Kun lämpötilaa lisätään saadaan satunnaisesta datasheetistä lunttaamani arvo: 265 asteta ja 2 kiloohmia. Tällöin A/D muunnin näkee 2/3 käyttöjännitteestä eli 683 (3,3V).

Jotta homma ei olisi aivan näin helppo, tarvitsee ottaa huomioon itselämmitys. Nollassa se on 5V/2kohm 2,5mA ja tehoksi siitä siirtyy anturissa 2,5V* 2,5mA = 6,25mW ja 265 asteessa 5,5mW

Tässä datalehdessä on kerrottu arvoksi ilmassa 4mW/C aste, joten mitattu tulos on asteen liian alhainen.

Tehdään libreofficella tai muulla vastaavalla taulukko, joka laskee A/D muunnoksen arvot C asteina ja ottaa huomioon itselämmityksen ja niin pois päin.

Kun arvataan miltä alueelta mittaus tulee niin: esimerkiksi 10 - 30 C astetta

Tästä voidaan sitten kirjoittaa esimerkiksi asteen tarkkuudella antavan häkkyrä:

#define MITTAUS_ALKU 10
#define MITTAUS_LOPPU 30
#define MITTAUS_ALUE MITTAUS_LOPPU - MITTAUS_ALKU
struct lampotila_tyyppi{
  uint16_t ala;
  uint16_t yla:
};
struct lampotila_tyyppi lampotilat[MITTAUS_ALUE] = {
  {
    .ala = ADC:n ala-arvo,
    .yla = ADC:n ylaarvo,
  },
  {
    ....
  }
}

int8_t adc_asteiksi(uint16_t adc_arvo){
  int i;
  for(i = 0; i < MITTAUS_ALUE; i++){
    if(lampotilat[i].ala >= adc_arvo && lampotilat[i].yla <= adc_arvo){
      return i + MITTAUS_ALKU;
    }
  }
}

Tarkoitukseni on sanoa, että tee laskenta ATK:lla ja anna kontrollerille valmiiksi pureksittu tieto.

Melkosta hepreaa…

Googlettelin ja koitin tulkita viestiäsi…

Syöttöjännite 5V, ja kun mittaukseen tarvitaan tuo 2.5mA niin siitä pystytään laskemaan se jännitehäviö joka on tuo 2.5V (käytin kaavaa R*I = U eli 1000kohm * 0.0025A = 2.5V).

Sitte tippu ja korkeelta… “Jos referenssi on Vcc ja A/D muunnoksen resolutio 10-bittiä, tulos on 512.”

Googlettelin A/D muunnoksesta ja löysin laskukaavan: tulojännitealue / (2^bittisyys -1) eli siis tässä tapauksessa käsittäisin sen olevan: 2.5V / (2^10 -1) josta vastaus on 0.00244… VÄÄRIN! eli ihan ulapalla ollaan…

Nojoo… Täytyypi jatkaa opiskelua… Jos tämä olis helppoa ja tietäisin mitä teen, kyseinen laite olisi jo tehty :smiley:


Tuomo

Aah.

0 on 0 V ja 10-bittisellä referenssijännite on 1023. Eli mittaus/referenssi * {maksimi A/D muunnoksen arvo ( 1023)}

Noin se tulee. Ja jos tämä olisi oikeasti helppoa, niin kaikkihan tätä tekisi :slight_smile:

Ongelma nyt lähinnä on että en osaa sijoittaa tuota 0 eli siis 0V mihinkään tuossa kaavassa… Nolla on nolla, se nyt on simppeliä, olkoon yksikkö perässä mitä vain… Mutta yleisesti siis täysin ulapalla… Onko tiedossa mitään hyvää sivua mistä tätä opiskella tätä asiaa, siis hyvin / perusteellisesti. Googlettamalla eri foorumeita ja guideja läpi kun tuntuu saavan tiedonmurusen sieltä ja toisen täältä, huonossa tapauksessa tieto tulee vielä väärässä järjestyksessä joka hieman hankaloittaa ymmärrystä.


Tuomo

Yritän vielä.

Mitattu jännite / Referenssi jännite on selkeästi osuus mittausalueesta. Tuo saa arvot nollasta ykköseen. referenssi / referenssi = 1 Ja jotta voidaan tuohon laskuun tunkea nolla, niin sen on tultava osoittajaan. Nimittäjässä näet tulisi musta aukko ja maailmanloppu. Sen jälkeen se vain kerrotaan sillä mistä halutaan osuus eli käytetyn resoluution maksimi arvosta. Nyt se sitten toimii. 0:lla tulee nolla. täydellä jännitteellä täsi arvo ja kaikki muut suoraan välistä. (Teoriassa)

Itse ainakin opettelin Atmelin datalehdestä koko ADC homman aikoinaan. Se kertoo myös liittenä olevan PDF:n ADC_arvot.pdf (37.4 KB)ja taulukkotiedoston (libreoffice) ADC_arvot.ods (25.8 KB)avulla, miten esimerkiksi 8-bittisen ADC:n kanssa syntyy virheitä. Näistä kvantisointi virheistä on myös kerrottu datalehdessä. Ja nyt mentiin vielä prosentin hyppäyksin. Voit muuten vaihtaa referenssijännitettä Referenssi kohdasta, missä lukee 5 nyt.

Toivottavasti auttaa.

Okeei no kiitokset ensinnäkin että jaksat neuvoa vaikka selvästi on tullut esille ettei täällä päässä näppäimistöä ole elektroniikan, ohjelmoinnin eikä matematiikan ammattilainen.

Ymmärsin nyt melkoisen selvästi että kaava menee näin: mitattu jännite jaettuna vertailujännitellää ja tämä kerrotaan resoluutiolla.

Eli ymmärtämäni tapaan jos 0c vastus on 1000ohm ja löytämäni taulukon mukaan vastus kasvaa 3,85ohm/c niin 20c lämpötilassa vastus pitäisi olla 1077ohm.

Tällöin kun virtaa käytetään mittaukseen 2.5mAh, vastus on 1077ohm ja referenssijännite 5V niin jännite joka on mitattavana pitäisi tulla kaavalla RI=U, 1077ohm0.0025A = 2.6925V

Kun pyöräytetään se sitten tuolla neuvomallasi kaavalla, mitattu jaettuna referenssillä ja kerrotaan resoluutiolla niin tulee: 2.6925V/5V*1023 = 550,8855. Tulosta kun vertailin tuohon liittämääsi taulukkoon niin näyttäisi osuvan kohdalleen, käytinkö oikeita kaavoja vai osuinko arvaamalla oikein?

Seuraavaksi siis tosiaan sisällyttämään lähettämääsi taulukkoon lämpöasteet ja ottaa huomioon itselämpeneminen. Sitten vain valitsemaan mittausalue jota käytän, eli esim. -50 ja +50 välillä täydentämään koodi jonka tarjosit esille tuossa muutama postaus takaisinpäin.

Olenko auttamattomasi ulapalla?

EDIT: Pitääkös tuo 10bit resoluutio sitten ympätä sihen valitsemaani tarkkuuten VAI koko anturin mittausalueeseen? Onko tuon mittausalueen valitsemisen ideana juuri se, että saadaan lisää tarkkuutta kun voidaankin saada 100c 10bit tarkkuudella verrattuna 850 asteen alue 10bit tarkkuudella?


Tuomo

Kyllä. Juuri näin.

Kyllä.

Does not Compute. 2.mAh on energiaa jollain tietyllä jännitteellä. Toisekseen, mistä tiedät, että mittaus tapahtui 2,5 mA virralla? Virta on jännite /( etuvastus + anturin resistanssi) Tuurilla arvoit oikein.

Virta on 5 / (1000 + 1077) = 2, 41mA
Anturin yli jäävä jännite on 5 V * 1077 / ( 1000 + 1077) = 2,59V
Anturin itselämmitysteho on 2,41mA * 2,59V = 6,2mW
ADC arvo 2,59/5 * 1023 = 530

Lasku sinällään oikein, mutta kuten jo huomautin, jännite on poskellaan.

Jotenkin noin.

Mielestäni mainitsit käyttäväsi 328 Atmelia. Siinä on tarjolla myös 1,1V sisäinen referenssi.Sillä pääsisi leikisti kolmasosa asteeseen. Ja miksi vain leikisti, niin konsultoi Atmelin datalehteä kohdasta ADC.

Tähän piirsin 1,1V referenssin kytennän.


Ja sitten taas taulukkoa.
ADC_laskentaa.ods (28.8 KB)
Ja ei-vapaan maailman kannattajille kuva:ADC_laskentaa.pdf (32.1 KB)

Jotenkin noin. Helposti ei saada mitattua, koska arvot ovat aina alueen yläpäässä 1,1V:lla Tai Vcc:tä käytettäessä skaalan puolessa välissä ja vain puolet alueesta käytössä. Tämän sanon väsyneenä ja seison korjattuna, kun joku kertoo hienon vastushäkkyrän, millä homma onnistuu. Jokin tarkka 5V linja ja kontrolleri 3:lla voltilla tai muuta vastaavaa, voisi tuoda jänniä mahdollisuuksia. Ongelmat olisivat silloin a) tarkka 5V ja tarkka 3V. 1,1V referenssiä käytettäessä 5V tarkkuus tuo haastetta… Sen lämpötilariippuvuus ja huojunta näkyy heti tuloksissa. 15 mV heilahdus 5V käyttöjännitteessä on noin aste sitten mittauksessa.

Ja päivitellääs taas…

Lämpötila-anturin vaihdoin LM35, koska netissä tutkimalla jotenkin jäin siihen käsitykseen että toteutus käyttämällä LM35 olisi helpompi. Lisäksi tossa hyllyssä löytyy Dallasin DS18S20 jos haluaa digitaaliseen siirtyä.

Tutorialeja on tehty monta ja lueskeltu / testailtu kaikkea. Nyt eri tutorialin tuloksia yhdistelemällä sain TODELLA rujolla koodilla homman toimimaan karkeasti (putsaillaan sitte joskus…):

[code]#define aref_voltage 3.3 // we tie 3.3V to ARef and measure it with a multimeter!
#include <Servo.h>

Servo myservo;

int tempPin = 0;
int servoPin = 1;

int tempReading; // the analog reading from the sensor
int val = 0;
int yhteis = 0;
int karvo = 0;
int asento = 0;

//ST_CP - 74HC595
int latchPin = 8;
//SH_CP 74HC595
int clockPin = 12;
//DS 74HC595
int dataPin = 11;

byte digits[] = {
B00111111, B00000110, B01011011, B01001111, B01100110, B01101101,
B01111101, B00000111, B01111111, B01101111
};

void setup() {
Serial.begin(9600);
analogReference(EXTERNAL);

pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);

myservo.attach(3);
}

void loop() {
for(int val = 0; val < 30; val++) {

tempReading = analogRead(tempPin);  
karvo = yhteis + tempReading;
//delay(1000);

}
Serial.print("Temp reading = ");
Serial.print(tempReading); // the raw analog reading
Serial.print(karvo);
// converting that reading to voltage, which is based off the reference voltage
float voltage = karvo * aref_voltage;
voltage /= 1024.0;

// print out the voltage
Serial.print(" - “);
Serial.print(voltage); Serial.println(” volts");

// now print out the temperature
int temperatureC = (voltage) * 100 ; //converting from 10 mv per degree
Serial.print(temperatureC); Serial.println(" degrees C");

int asento = map(temperatureC, 0, 40, 0, 180);
myservo.write(asento);
Serial.print("Servon asento ");
Serial.println(asento);
delay(3000);
}

// Display 2 digit number
void temperatureC(int num)
{
// get digit 0
int dig0 = num % 10;
// get digit 1
int dig1 = (num/10) % 10;

// shift out digits
digitalWrite(latchPin, LOW); //pitää olla low jottei ledit välky kun lähetetään dataa
shiftOut(dataPin, clockPin, MSBFIRST, digits[dig1]); // lähetetään data kympit
shiftOut(dataPin, clockPin, MSBFIRST, digits[dig0]); // lähetetään data ykköset
digitalWrite(latchPin, HIGH); // nostetaan high jolloin määrätyt ledit syttyy
}[/code]

Tuo “//Display 2 digit number” ei vielä toimi, en ole paneutunut siihen mutta servon liikkeet sain mapattua lämpötilaan (testilämpötilat nyt käytössä). Muutenkin tarvitsisi rakennella tuo 7-segmentti led-näyttöjen ohjaus tuolla servon ohjausperiaatteella, eli ottaisi ohjauskomennot tiedostona eikä syöttäisi niitä tuohon koodiin kuten on nyt.

Seuraavaksi tarvitsisi alkaa tekemään pientä laskutoimitusta jolla saisi tehtyä tuon “ulkona 0c -> lämmitysvesi 40c, jos pienempi kuin 40c käännä servoa 2 astetta, jos suurempi kuin 40c käännä servoa 2 astetta toiseen suuntaan, palaa alkuun…” tyylisen servo-ohjauksen. Tietysti lisätä täytyy tuo 0c = 40c --> -30c = 65c skaalaus myös tuohon kaavaan.

Ajatuksena oli myös sellainen, kun tuo servo kääntää sarvea ja vastusta tietysti on niin se jää helposti sirisemään. Olisiko järkevää miettiä lausetta joka tunnistaisi servon liikkumissuunnan tyylillä “vertaa uutta arvoa vanhaan arvoon” ja tämän mukaan osaisi ottaa vaikka yhden asteen “lähemmäksi edellistä arvoa” eli ns. pakkia. Käytännössä: jos servo kääntyy 5 astetta oikealle, tämän jälkeen 1 aste takaisin vasemmalle. Vai olisiko parempi skaalata koko servon 180 asteen liikerata käyttöön ja näinollen saada enempi voimaa jolloin servo ei välttämättä jäisi surisemaan?

Ei oo meitsin jälki nättiä, mutta näkeepä hyvin että oon aika alottelija. Toivottavasti näistä mun virheistä + mietteistä on jollekin apua / iloa.


Tuomo

Päivää iltaa…

Tuli kaivettua vanhat teokset esille kaapin nurkilta, ja lähdettyä tekemään jotain aivan erilaista…

Tein hätäseen raakavedoksen ohjelmasta joka mittaa lämpötilan LM35 anturilla 40 kertaa 250ms viiveellä ja laskee tämän jälkeen lämpötilojen keskiarvon. Keskiarvon perusteella käskytetään servoa asentoon X.

Ongelmaksi tulee nyt IF lause, josta ei ole päästy yli eikä ympäri. Olen jämähtänyt ajatukseeni ja polken paikoillaan… Potkaisisiko joku viisaampi vähän lisävauhtia jotta tästä kuopasta selvittäisiin?

#include <Servo.h>

Servo shuntti;

int ulkoMittaus = 0;
int asento;
double ulkolampoYHT = 0;
int ulkolampoKA = 0;

int ulkoanturi = 0;
int vikaled = 13;

void setup()
  {
    pinMode(vikaled, OUTPUT);
    pinMode(ulkoanturi, INPUT);
    shuntti.attach(9);
    Serial.begin(9600);
  }

void loop()
  {
    for (int toisto=0; toisto < 40; toisto++)
      {
        ulkoMittaus = analogRead(ulkoanturi);
        double ulkolampo = ulkoMittaus * (4720.00 / 1024);  // 4720 on mitattu jännite anturin nastoista, eli 4.72V
        ulkolampoYHT = ulkolampoYHT + ulkolampo;
                        
			
//      mittaa sisälämpö -> tallenna muuttujaan sisalampo
//      sisalampoYHT = sisalampoYHT + sisalampo
        delay(250);
      }

    ulkolampoKA =ulkolampoYHT / 10 / 40;    // ensimmäinen jako muuttaa asteiksi, toinen jako laskee keskiarvon
//  sisalampoKA =sisalampoYHT / 10	//pois kaytosta ensidemoissa

    if (ulkolampoKA > 20){
      shuntti.write(15); 		// shuntti säädetty niin että servon asennossa 5 patteriveden lämpö on 40c
      delay(500);}
    if (ulkolampoKA > 24){
      shuntti.write(39);		// shuntti säädetty niin että lämpö 45
      delay(500);}
    if (ulkolampoKA > 28){
      shuntti.write(73);		// shuntti säädetty niin että lämpö 50
      delay(500);}
    if (ulkolampoKA > 32){
      shuntti.write(107);		// shuntti säädetty niin että lämpö 55
      delay(500);}
    if (ulkolampoKA > 36){
      shuntti.write(141);		// shuntti säädetty niin että lämpö 60
      delay(500);}
    if (ulkolampoKA > 40){
      shuntti.write(175);		// shuntti säädetty niin että lämpö 65
      delay(500);}
    else
      {
        digitalWrite(13, HIGH);	// vikavalo
      }

    Serial.println(ulkolampoYHT);
    Serial.println(ulkolampoKA);
    ulkolampoYHT = 0;
    ulkolampoKA = 0;
  }

Ongelma siis tuolla lopussa, jossa käskytetään servoa.

Mitenkä rakennan IF lauseen jos haluan sen tekevän näin:
JOS lämpö yli 20 tarkista onko se yli 24
jos ei niin käännä servoa, jos on niin tarkista onko se yli 28
jos ei niin käännä servoa, jos on niin tarkista onko se yli 32
jos ei niin käännä servoa, jos on niin tarkista onko se yli 36
jos ei niin käännä servoa, jos on niin tarkista onko se yli 40
jos on niin käännä servoa.

Saattaa olla helppokin juttu, mutta nyt jotenkin silmät sokaistuneet…

ps. saa vinkata jos koodissa jotain muuta korjattavaa :slight_smile:

Tuomo

itse itselleni vastaten…

Piti siis kirjottaa, lukea ja tajuta…

Korjasin tilanteen näin

if (ulkolampoKA > 40){ shuntti.write(175); // shuntti säädetty niin että servon asennossa 5 patteriveden lämpö on 65c delay(500);} else if (ulkolampoKA > 36){ shuntti.write(141); // shuntti säädetty niin että lämpö 60 delay(500);} else if (ulkolampoKA > 32){ shuntti.write(107); // shuntti säädetty niin että lämpö 55 delay(500);} else if (ulkolampoKA > 28){ shuntti.write(73); // shuntti säädetty niin että lämpö 50 delay(500);} else if (ulkolampoKA > 24){ shuntti.write(39); // shuntti säädetty niin että lämpö 45 delay(500);} else if (ulkolampoKA > 20){ shuntti.write(15); // shuntti säädetty niin että lämpö 40 delay(500);} else digitalWrite(13, HIGH); // vikavalo

Pikaisella testillä tuntui auttavan, servo ei hyppinyt lainkaan niin kuin ensimmäisellä vedoksella.

Siltikin… Kommentteja?

Tällä karvalakkimallilla, vivuston mittoja ja servon asentoja muuttaen onnistuu automaattinen lämpötilasäätö ulkokelin mukaan… Käsittääkseni… Pitää rakentaa vivusto yms. ja testailla.

EDIT:
Lisäilin vähä vikavaloa ja “toimintamallin” jos lämpötila näyttää liian suurta (virhelaskenta TAI anturia ei tunnisteta)

HUOM! Koodin lämpötilat on testilämpötiloja jotta saa hiustenkuivaajalla demottua servon toimintaa.

Koodi nyt tällainen:

[code]#include <Servo.h>

Servo shuntti;

int ulkoMittaus = 0;
int asento;
double ulkolampoYHT = 0;
int ulkolampoKA = 0;

int ulkoanturi = 0;
int vikaled = 13;

void setup()
{
pinMode(vikaled, OUTPUT);
pinMode(ulkoanturi, INPUT);
shuntti.attach(9);
Serial.begin(9600);
}

void loop()
{
for (int toisto=0; toisto < 40; toisto++)
{
ulkoMittaus = analogRead(ulkoanturi);
double ulkolampo = ulkoMittaus * (4720.00 / 1024); // 4720 on mitattu jännite anturin nastoista, eli 4.72V
ulkolampoYHT = ulkolampoYHT + ulkolampo;

// mittaa sisälämpö -> tallenna muuttujaan sisalampo
// sisalampoYHT = sisalampoYHT + sisalampo
delay(250);
}

ulkolampoKA =ulkolampoYHT / 10 / 40;    // ensimmäinen jako muuttaa asteiksi, toinen jako laskee keskiarvon
if (ulkolampoKA > 45){
  digitalWrite(13, HIGH);	// vikavalo syttyy jos lämpötilamittaus totaalisen pielessä / anturia ei tunnisteta
  ulkolampoKA = 0;
}
  else
  digitalWrite(13, LOW);	// vikavalo ei pala kun kaikki OK
if (ulkolampoKA > 40){
  shuntti.write(175); 		// shuntti säädetty niin että servon asennossa 5 patteriveden lämpö on 65c
  delay(500);}
  else
    if (ulkolampoKA > 36){
    shuntti.write(141);		// shuntti säädetty niin että lämpö 60
    delay(500);}
    else
      if (ulkolampoKA > 32){
      shuntti.write(107);		// shuntti säädetty niin että lämpö 55
      delay(500);}
      else
        if (ulkolampoKA > 28){
        shuntti.write(73);		// shuntti säädetty niin että lämpö 50
        delay(500);}
        else
          if (ulkolampoKA > 24){
          shuntti.write(39);		// shuntti säädetty niin että lämpö 45
          delay(500);}
          else
          if (ulkolampoKA > 20){
          shuntti.write(15);		// shuntti säädetty niin että lämpö 40
          delay(500);}
          else
            digitalWrite(13, HIGH);	// vikavalo
            
Serial.println(ulkolampoYHT);
Serial.println(ulkolampoKA);
ulkolampoYHT = 0;
ulkolampoKA = 0;

}

[/code]

Tuomo

Varoitus. Ajatukseni eivät ole mukana. Sormet kirjoittelevat itsekseen.

Testaapa seuraavaksi anturit oikosena ja poikki. Tulee neljä testiä, että vikailmaisu toimii.

Mä edelleen suosittelen tutustumaan PID PHD artikkeliin. URL ekalla sivulla.

Sitten voisit miettiä miten säätö toimii ja miettiä tyyliin luetaan anturi. Mitäs jos luku ei onnistu. Millaiset luvut ovat hyväksyttäviä. Luonto on analogista ja jatkuvaa. törkeät pomput eivät ole todellisia. Aurinko paistaa mittariin tai muuta kummallista on sattunut.

Ohjelma voisi toimia näin:

Lue kerran anturit anturienArvoihin alustukseksi.

ja säädössä sitten…
tee silmukka:

for(mittauskerta=1; mittauskerta <= mittastenLukumaara; mittauskerta++){
  int mittaustulos = ADCArvo();
  anturinArvo += mittaustulos;
  if(mittaustulos * 0.85 < (anturinArvo/mittauskerta) || mittaustulos * 1.15 <
      (anturinArvo/mittauskerta)){
    vikatila(); //Ledi vilkkuun puhelin soimaan ja talo palamaan eikäku. 
  }
  viivesekunti();
}
anturinArvo /= mittaustenLukumaara;
jokuKivaTyyppiIntFloatDouble lampotila = muutaLampotilaksi(AnturinArvo);

Tän jälkeen logiikka voisi pärähtää ja laskea sitten tuon säädön.

Niin ja tuo koodihan tarttis tehä molemmille antureille.

Tuo mun vikatila() funktio tarvitsee sitten huolella miettiä. ottaako, se esimerkiksi anturien arvot ja viimeisen arvon ja päättelee jotain siitä. Heittääkö se sitten jotain vikalippuja päälleja havaitaan minne päin homma on menossa pieleen. Esimerkiksi kirjoitetaanko kompensaattorin ja P-säädön kautta servolle asentoa, jos sisälämpötila katoaa kokonaan ja jos ulkolämpötilatieto katoaa, niin ohjataanko sisälämmöllä pelkästään jne. jne.

Yksi tarkistus oisi myös jonkinnäiköinen ulkolämpötilan ja sisälämmön tila ja menoveden järkevyyden arviointi. Vai oliko noita tietoja tarjollakaan.

Oon väsynyt. En ole nyt ollenkaan varma asioista, mutta noin mä sen asian näkisin. Varaan oikeuden huomenna vaihtaa mielipidettä.

Moe.

Tuli tuolloin illalla vielä demottua laitosta hiustenkuivaajalla ja oikosuluilla, mittarin irroituksella jne. Totesin että tuo koodin lopussa oleva “else sytytä blinbling vikavalo” ei toimi oikein, ja vaikka toimisi niin kun/jos homma alkaa pelittämään kunnolla niin vikavalo ei automaattisesti sammu.

Tein siis muutoksia niin, että se mittaa nyt ne 600 mittausta, laskee keskiarvon. JOS keskiarvo on yli x niin syttyy vikavalo, jos ei niin jatkaa tuohon pitkään IF ketjuun. Jälkeenpäin on tullut asiaa vielä mietittyä ja ajattelin muuttaa asian vielä näin: JOS kieskiarvo on pienempi kuin “edellinen keskiarvo * 0.85” niin vikavalo, jos ei niin takistaa onko se suurempi kuin “edellinen keskiarvo * 1.15” jos niin vika valo, jos ei niin jatkaa pitkään if-listaukseen.

Tietysti muuttujia pyöritellään vähän ettei mene laskut sekaisin ja verrata juuri mitattua arvoa…

Mitä tuohon patteriveden lämpöön tulee yms, niin ne on tulossa. Ajattelin lähteä helposta, yksinkertaisesta “jos tämä niin tee tämä” ohjelmasta alkuun ja siitä sitten kehittää eteenpäin.

Tuohon on (ainakin ajatustasolla) helppo muokkailla sitten pätkä joka mittaa lämpötilan patteriveden lähtevästä putkesta, sitten vertaa ulkolämpötilaa ja while lauseella käskyttää servoa vaikka asteen kerrallaan kääntämään hanaa suuremmalle / pienemmälle. Siihen lisäksi sopivat viiveet jotta lämpötila ehtii tasottumaan putken ulkopinnassa “samaksi” kuin veden lämpötila.

Eilen olisi ollut hyvä hetki demota kun varaaja oli aluksi kylmä josta lämmitin sen n. 80c lämpöön. Patteriveden kierto oli pois päältä ja laitoin sen yöksi taas päälle. Shuntin ollessa normiasennossa patteriverkon veden lämpötila oli 30c tienoilla, koska koko putkisto oli kylmä ja shunttihan määrää prosenttuaalisen suhteen vanhaa vettä + kuumaa vettä. Kiersin hetkeksi shuntista reilusti isommalle jotta menovesi saatiin 40c paluuvedestä välittämättä. No… Sehän unohtui siihen… Illemmalla kävin katsomassa pannarissa ennen pehkuihin painumista niin lähtevän veden lämpötila oli siellä 70c tienoilla, koska putken lämmenneet ja paluuveden lämpötila noussut huomattavasti. Nykyinen ver.1 demo projekti ei tosin tuota olisi osannut korjata, mutta vastaavaa onglemaa ei silloin olekkaan kun eletään varsinaista lämmityskautta ja pellettipoltin pitää varaajan lähes tasalämpöisenä.


Tuomo

Tervehdys,

Olen mielenkiinnolla seurannut projektiasi. Jos olen ymmärtänyt oikein olet toteuttamassa aivan normaalia lämmityksen säätöä, joka toteutetaan ulkolämpötilan mukaan.

Siksi olenkin ihmtellyt mikset tee toteutustasi vastaamaan kaupallisia säätimiä, jotka ovat hyvinkin yksinkertaisia toteuttaa Arduinon avulla käyttäen hyväksi PID-kirjastoa.
http://arduino.cc/playground/Code/PIDLibraryConstructor

Säädinhän toimii siten että luodaan säätökäyrä talokohtaisesti.

PID-säätimelle sitten muutetaan asetusarvoa ulkolämpötilan mukaan säätökäyrää hyväksi käyttäen. Tällä tavalla saisit huomattavan tarkemman säädön aikaiseksi.

Tässä oma ideani näin nopeasti kirjoitettuna. Voin yrittää avata lisää asiaa jos kiinnostuit. :slight_smile:

-Jaso

Mulla ei mitään varsinaista syytä ole olla käyttämättä PID:iä. Sillä varmasti lopullisesti homma tullaankin toteuttamaan, mutta tähän asti on ollut lähinnä opiskelua. Mulla se huono puoli, että ehdin tässä elämässä istahtamaan koneelle muutamaksi tunniksi viikon aikana, ja sekään ei ole yhtämittaista aikaa. Ohjelmoinnit ja tutkimiset jää vähälle, asioiden miettiminen ja päässä pyörittely taas päinvastoin.

Mullahan tässä alunperin ollut ongelmaa mittailla lämpötilaa, nyt kun se on suunnilleen saatu hanskaan niin täytyy alkaa miettiä ja kehitellä lisää. Mukavaa tässä on se että virheistä toivottavasti oppii ja projektin edetessä oppii paljon hyödyllistä seuraavia ideoita varten.

Alanpa tästä kahvin kera opiskelemaan tuota PID käyttöä ja kikkailemaan perus ledin vilkutuksia sen avulla.


Tuomo