Selvvannende blomsterpotte

Her er min unødvendig avanserte og dyre selvvannende blomsterpotte. Det hele startet med at jeg fikk kommentar på at jeg hadde en «guttebule». Jeg var forøvrig helt enig i den kommentaren siden leiligheten var veldig steril med store høyttalere og stor tv. For å få den mindre sterilt og mer naturlig hadde jeg lyst på en plante med litt størrelse. Men pga av min daværende jobb og generelt sett ville jeg nok ikke greid å vanne den, slik at den til slutt ville dødd. Derfor kom jeg opp med ideen om å lage en selvvannende blomsterpotte av glassfiber, styrt av en microkontroller. Dette skulle vise seg å være vanskeligere og mer tidkrevende enn først antatt.

Ideen går ut på at jeg skal ha et reservoar i veggene på potta. Av og til skal det gå en pumpe som passer på å vanne blomsten med akkurat riktig mengde vann. Og hvis jeg føler for det, utvide med fuktsensor og vekstlys, alt styrt med Arduino microkontroller.

Jeg fikk tak i ett par gratis plastpotter av den tynne typen fra de lokale gartneriene. De brukte jeg som mal for mine potter. Jeg la 4 lag med glassfiber rundt og la epoxy mellom alle lag. Jeg hadde aldri lagt glassfiber før, så etter litt startproblemer og hodepine fikk jeg masken på og resultatet ble noenlunde OK. Pusset de lett ned og kuttet til kantene og la hvit topcoat slik at den skulle tåle vann.

Bunn- og topplaten ble etter mye om og men laget i trevirket. Jeg fikk avkapp fra en trappefabrikk på Senja. En kompis sa seg villig til å frese delene med sin nyinnkjøpte gamle CNC fres. Jeg designet de to delene i Fusion 360 og sendte de til kompisen min som skulle frese ut. Problemet var at han ikke kunne bruke fresen, så det tok LITT tid. Ett halvt år seinere fikk jeg de endelig i hendene. Disse ble grunnet og malt i matt svart.

Deler:
Biltema 12V nedsenkbar pentrypumpe
Arduino Uno
Veroboard fra ClasOhlson
Maling og topcoat fra den lokale maleren
Elektronikk fra Elfa
Arduino fra Ebay
3D-printer fra NTNU (Ultimaker 2+)
Yucca plante fra plantasjen
Avkapp fra en trappefabrikk på Senja
TEC7

Prosjektet kostet meg mer penger enn det jeg ønsker å tenke på. Prosjektet tok ca 4 år å gjennomføre da jeg prokrastinerte pga skole, jobb, dame, trening og giddesløshet. Valgte falt til slutt på en Yucca palme som skal tørkes skikkelig ut før den vannes. Etter litt tuning ble det 3.5dl per 10ende dag. Det fører til at jeg må fylle på reservoaret ca hver 50ende dag. Jeg ble fornøyd med sluttresultatet enda det tok litt vel lang tid å fullføre.

Målet med prosjektet var å lære, og det føler jeg at jeg har gjort. Jeg har 3D printet, CNC frest, laget to potter i glassfiber og toppet de med topcoat og programert i C++.

På fremsiden av potta har jeg to lysdioder. En rød og en grønn. Tilstandene er som vist under.

Tilstand 1
Potta er full av vann. Grønt lys indikerer at potta får strøm og at alt er ok.
Tilstand 2
Her indikeres det at det er på tide å fylle på vann. Pumpen går fortsatt med sine faste intervaller.
Tilstand 3
Solid rødt lys indikerer at potta er helt tom for vann. Den starter ikke igjen før den er full igjen.
SISTE
Et veldig forenkelet skisse/koblingsskjema

Kanskje jeg en dag utvider med fuktsensor.

Arduinokoden som måtte til finner du under. Takk til Vebjørn for god programeringshjelp.

/* I denne utgaven ha jeg trolig fikset buggen med at den henger seg opp når
* man fyller på vann i reservoaret i S_IDLE_LOW_WATER; Jeg har også introdusert PUMP_LEVEL for
* å PWM pumpa til en lavere hastighet
*/

const int LOWER_FLOATER = 9;
const int UPPER_FLOATER = 10;
const int PUMP = 11;
const int GREEN_LED = 12;
const int RED_LED = 13;
const int PUMP_LEVEL = 70; // Set pump level from 0 to 255

unsigned long waterCyclus = (6*1000); //in seconds
unsigned long waterBreak = (864000*1000); //in secounds
unsigned long nextTimeout = 0;

const int S_IDLE = 0;
const int S_WATERING = 1;
const int S_LOW_WATERING = 2;
const int S_IDLE_LOW_WATER = 3;
const int S_FILL_WATER = 4;

int state = S_IDLE;
void setup()
{
pinMode(LOWER_FLOATER, INPUT);
pinMode(UPPER_FLOATER, INPUT);
pinMode(PUMP, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
pinMode(RED_LED, OUTPUT);
setTimer(waterBreak);
Serial.begin(9600);
}

void loop()
{
switch(state)
{
case S_IDLE:
ledOff(RED_LED);
ledOn(GREEN_LED);
digitalWrite(PUMP, LOW);
if( timerHasExpired() == true && digitalRead(UPPER_FLOATER) == LOW && digitalRead(UPPER_FLOATER) == digitalRead(LOWER_FLOATER) )
{
//reservoar is full
Serial.println(«water is maxed, and switching to watering state»);
setTimer(waterCyclus);
state = S_WATERING;
}
else if (timerHasExpired() == true && digitalRead(UPPER_FLOATER) == HIGH && digitalRead(UPPER_FLOATER) != digitalRead(LOWER_FLOATER) )
{
//reservoar low
Serial.println(«detecting low water, and switching to low watering state»);
setTimer(waterCyclus);
state = S_LOW_WATERING;
}
else if (timerHasExpired() == true && digitalRead(UPPER_FLOATER) == HIGH && digitalRead(UPPER_FLOATER) == digitalRead(LOWER_FLOATER) )
{
//empty
Serial.println(«detcting no water, switching to fill water state»);
state = S_FILL_WATER;
}

break;

case S_WATERING:
ledOff(RED_LED);
ledOff(GREEN_LED);
ledOn(GREEN_LED);
analogWrite(PUMP, PUMP_LEVEL);
if(timerHasExpired() == true)
{
Serial.println(«switching case to IDLE»);
setTimer(waterBreak);
state = S_IDLE;
}
break;

case S_LOW_WATERING:
ledOff(RED_LED);
ledOff(GREEN_LED);
ledOn(GREEN_LED);
ledOn(RED_LED);
analogWrite(PUMP, PUMP_LEVEL);
if(timerHasExpired() == true)
{
Serial.println(«switching case to IDLE with low water»);
setTimer(waterBreak);
state = S_IDLE_LOW_WATER;
}
break;

case S_IDLE_LOW_WATER:
digitalWrite(PUMP, LOW);
if(timerHasExpired() == true && digitalRead(LOWER_FLOATER) == LOW && digitalRead(UPPER_FLOATER) != digitalRead(LOWER_FLOATER) )
{
//reservoar is low
Serial.println(«switching to low watering state»);
setTimer(waterCyclus);
state = S_LOW_WATERING;
}

else if (timerHasExpired() == true && digitalRead(UPPER_FLOATER) == HIGH && digitalRead(UPPER_FLOATER) == digitalRead(LOWER_FLOATER) )
{
//empty
Serial.println(«detecting no water, switching to fill water state»);
state = S_FILL_WATER;
}

else if (timerHasExpired() == true && digitalRead(UPPER_FLOATER) == LOW && digitalRead(UPPER_FLOATER) == digitalRead(LOWER_FLOATER) )
{
//refilled
Serial.println(«detecting water refill, switching to S_WATERING»);
setTimer(waterCyclus);
state = S_WATERING;
}
break;

case S_FILL_WATER:
ledOff(RED_LED);
ledOff(GREEN_LED);
ledOn(RED_LED);
digitalWrite(PUMP, LOW);
if( digitalRead(UPPER_FLOATER) == LOW && digitalRead(UPPER_FLOATER) == digitalRead(LOWER_FLOATER))
{
//filled
Serial.println(«reservoare filled! Switching to IDLE»);
setTimer(waterBreak);
state = S_IDLE;
}

break;
}
}

/////////////LED_FUNCTIONS/////////////////////

void ledOn(int led)
{
digitalWrite(led, HIGH);
}

void ledOff(int led)
{
digitalWrite(led, LOW);
}
////////////////////////////////////////////////////

////////////////////////TIMER_CONTROLL////////////////////
void setTimer(unsigned long timeout)
{
nextTimeout = millis() + timeout;
}

boolean timerHasExpired()
{
boolean hasExpired = false;
if(millis() > nextTimeout)
{
hasExpired = true;
}
else
{
hasExpired = false;
}
return hasExpired;
}
///////////////////////////////////////////////////////

 

Legg igjen en kommentar