Hallo Foristen,
ich hätte einige Fragen zu meinem aktuellen Projekt, einer automatischen
Pflanzenbewässerung:
1. An meinem Attiny13 sind 2 Schalter, ein Feuchtigkeitssensor (2 Nägel
und 1MOhm Widerstand als Spannungsteiler) und eine Pumpe über ein Mosfet
angeschlossen. Wenn der erste Taster (an PB2) gedrückt wird, wird der
aktuelle Messwert des Feuchtigkeitssensors in die Variable "Trocken"
geschrieben. Wenn der zweite Taster (an PB1) gedrückt wird, soll das
selbe passieren, bloß eben in die Variable "Feucht". So habe ich die
Maximale Trockenheit und die Maximale Feuchtigkeit.
Das Programm soll jetzt so funktionieren, dass wenn die Maximale
Trockenheit erreicht ist, die Pumpe solange läuft bis die Maximale
Feuchtigkeit erreicht ist. Und soweiter und so fort. Meine Frage lautet,
ob dass der Pflanze so gut tut.
2. Ist mein Programm soweit richtig?
1
/*
2
* Bewässerungssystem.c
3
*
4
* Created: 12.04.2013 17:33:44
5
* Author: Benedikt_2
6
*/
7
8
#define F_CPU 1200000 //Clockspeed 1,2 MHz
9
#include<avr/io.h>
10
#include<util/delay.h>
11
12
intTrocken=100;//speichert die maximale Trockenheit
13
intFeucht=0;//speichert die maximale Feuchtigkeit
14
intADCResultVoid=0;//speichert den Messwert der Funktion adcGet
15
intADCResult=0;//speichert den Messwert in der Loop Funktion
16
17
intadcGet(void){//Funktion zur Erfassung des Messwertes
18
ADCSRA|=(1<<ADSC);//starte Konvertierung
19
while(ADCSRA&0b01000000)//warte bis Konvertierung abgeschlossen
oooOooo schrieb:> Ein Eimer mit Wasser und Baumwollfäden sind besser.>> 'vorraus' = Augenkrebs
Schön, dass du weder eine meiner Fragen beantwortet hast und meinen
einzigen Rechtschreibfehler im Text gefunden hast.
Glückwunsch
Ich würde in Intervallen Messen. Die Pumpe laufen lassen bzw.
Wassermenge zuführen. Warten und wieder messen. Wenn die Erde die
Wassermenge nicht sofort aufnimmt könnte es sonst in einem Wasserschaden
enden.
Grüsse
Benedikt K. schrieb:> Schön, dass du weder eine meiner Fragen beantwortet hast und meinen> einzigen Rechtschreibfehler im Text gefunden hast.
Ich habe noch sieben weitere Fehler gefunden. ;-)
Benedikt K. schrieb:> Meine Frage lautet, ob dass der Pflanze so gut tut.
Die Art und Menge der Bewässerung hängt von vielerlei Faktoren ab und
gestaltet sich pflanzenspezifisch. Ich denke, in einem entsprechenden
Fachforum bekommst du kompetenten Rat.
Benedikt K. schrieb:> Meine Frage lautet,> ob dass der Pflanze so gut tut.
NEIN! Warum? Ganz einfach.
Du bist fast am verdursten (trocken) und säufst plötzlich wie ein Loch
Wasser in dich hinein (nass), dann hast du sicher Magenschmerzen. Das
ist sicher angenehm, oder nicht?
Jetzt zufrieden?
Jörg Esser schrieb:> Adcresult is immer 0??? Und bei den anderen Problemen habe ich dann> erstmal aufgehört.
Wo siehst du das denn? Der adcResult wird nur am Anfang auf Null
gesetzt...
oooOooo schrieb:> Benedikt K. schrieb:>> Meine Frage lautet,>> ob dass der Pflanze so gut tut.>> NEIN! Warum? Ganz einfach.>> Du bist fast am verdursten (trocken) und säufst plötzlich wie ein Loch> Wasser in dich hinein (nass), dann hast du sicher Magenschmerzen. Das> ist sicher angenehm, oder nicht?>> Jetzt zufrieden?
Naja die Pflanze wird ja erst bewässert wenn ein bestimmter
Trockenheitsgrad erreicht ist.
Evtl. wäre es sinnvoller, einen Wert zu nehmen, bei dem das Substrat
noch eine geringe Restfeuchte hat. Wenn dieser Wert unterschritten wird,
kannst du dann deine Pumpe für eine bestimmte Zeit einschalten. Die
Messung kannst du dann vier mal am Tag durchführen. So schnell wird Erde
ja nicht trocken, wenn du überhaupt Erde benutzt.
Einen Überschwemmungsschutz solltest du dir aber noch überlegen. Bei mir
habe ich einen normalen Überlauf. Ist allerdings auch ein Ebbe und Flut
System, also ganz anderes Prinzip.
also ich habe mir soetwas auch gebaut, mein gerät funktioniert wie
folgt:
der benutzer steckt die sensoren in den blumentopf
dann wird die pflanze gegossen
nun wird der stecker in die steckdose gesteckt.
Nun misst der Atmega den Widerstand und merkt sich den.
einmal pro Stunde überprüft er ob der widerstand größer geworden ist,
sollte das so sein wird die pumpe für 5 sekunden eingeschaltet, 5min
gewartet und wieder gemessen ist der widerstand kleiner als vorgegeben
wird wieder 1 stunde in den schlafmodus gegangen.
So funktioniert das ganze bei mir schon seit rund 1 jahr und die pflanze
ist weder vertrocknet noch ertrunken ;)
Alexander R. schrieb:> Evtl. wäre es sinnvoller, einen Wert zu nehmen, bei dem das Substrat> noch eine geringe Restfeuchte hat. Wenn dieser Wert unterschritten wird,> kannst du dann deine Pumpe für eine bestimmte Zeit einschalten. Die> Messung kannst du dann vier mal am Tag durchführen. So schnell wird Erde> ja nicht trocken, wenn du überhaupt Erde benutzt.>> Einen Überschwemmungsschutz solltest du dir aber noch überlegen. Bei mir> habe ich einen normalen Überlauf. Ist allerdings auch ein Ebbe und Flut> System, also ganz anderes Prinzip.
Danke für deine Antwort. Kann ich für die Messungen einen Timer
Interrupt hernehmen? Was meinst du mit Überschwemmungsschutz bzw. wie
kann ich das implementieren?
while (ADCSRA & 0b01000000) //warte bis Konvertierung abgeschlossen
{
;
}
ADCResultVoid = ADCH; //setzen der Variable
return ADCResult; //Messwert ausgeben
Adcresultvoid und adcresult haben nix miteinader zu tun....
Wenn der Behälter für das Gießwasser mehr Wasser fasst als deine Töpfe,
wäre mir das persönlich zu riskant, ohne einen Schutz. Wenn was schief
läuft und die Pumpe nicht abschaltet läuft das Wasser irgendwann aus den
Töpfen.
Zu dem Timer Interrupt: Wenn am Controller keine Uhr dran ist, würde ich
den nehmen. Vielleicht kennt aber jemand noch eine elegantere
Möglichkeit. Sind ja doch große Zeitabstände.
Der gesunde Bauer schaut seinen Pflanzen zu,wie sie wachsen !
Die Anlage funktioniert solange du sie ueberwachen kannst....
...bei deiner ersten Abwesenheit schlaegt das Schicksal zu !
Die Naegel funktionieren 4 Wochen lang; dann passiert etwas....!
Alexander R. schrieb:> Zu dem Timer Interrupt: Wenn am Controller keine Uhr dran ist, würde ich> den nehmen. Vielleicht kennt aber jemand noch eine elegantere> Möglichkeit. Sind ja doch große Zeitabstände.
Nein eine Uhr ist nicht dran. Hat jemand eine Idee, solche großen
Zeitabstände zu messen?
Benedikt K. schrieb:> Alexander R. schrieb:>> Zu dem Timer Interrupt: Wenn am Controller keine Uhr dran ist, würde ich>> den nehmen. Vielleicht kennt aber jemand noch eine elegantere>> Möglichkeit. Sind ja doch große Zeitabstände.>> Nein eine Uhr ist nicht dran. Hat jemand eine Idee, solche großen> Zeitabstände zu messen?
Ja.
Mit einem Timer eine Uhr aufbauen.
Du weisst schon: tritt ein Ereigniss alle 1/100 Sekunde auf, dann ist
nach 100 Ereignissen 1 Sekunde vergangen. Nach 60 Sekunden 1 Minute,
nach 60 Minuten 1 Stunde, etc. etc. Sind alles nur Variablen, die bei
Bedarf um 1 hochgezählt werden und bei bestimmten Zählerständen die
nächste Variable hochzählen und dann wieder auf 0 gesetzt werden.
FAQ: Timer
schreib solche Dinge
> if (!(PINB & 0b00000100)) //wurde Taster 2 an PB2 gedrückt?
so
if( !(PINB & (1<<PB2) )
dann sieht man gleich viel besser, dass es hier um PB2 geht.
Und wenn du dem ganzen dann noch per #define ein paar schöne Namen
verpasst, dann kannst du dir auch den Kommentar sparen
#define MIN_TASTER PB2
...
if( !(PINB & (1<< MIN_TASTER ) )
jetzt brauchst du den ganzen Kommentar nicht mehr und siehst trotzdem im
Programmtext mehr als dein ganzer Kommentar je ausgesagt hat. Denn jetzt
sieht man im Code selber, dass es hier um den Taster geht, mit dem du
deinen minimalen Wert feststellst.
So, wirds dann noch mal eine Spur schöner und besser lesbar
#define IS_PRESSED(x) (!(PINB & (1<<(x))))
...
if( IS_PRESSED( MIN_TASTER ) )
Herz was willst du mehr? Das kann sogar jemand lesen und verstehen, der
noch nie programmiert hat.
Hier dasselbe
> ADCSRA |= (1<<ADSC); //starte Konvertierung> while (ADCSRA & 0b01000000) //warte bis Konvertierung abgeschlossen
zum Bit setzen hast du wunderbar den Bitnamen benutzt. Da gibt es nichts
daran auszusetzen. Aber warum hast du ihn nicht für die Abfrage benutzt?
ADCSRA |= (1<<ADSC); //starte Konvertierung
while (ADCSRA & (1<<ADSC)) //warte bis Konvertierung abgeschlossen
jetzt könnte man sogar sehen, dass zwischen diesen beiden Dingen ein
Zusammenhang besteht. Du setzt das ADSC Bit per Programm, woraufhin der
ADC zu arbeiten anfängt, und wenn der ADC fertig ist, nimmt er das Bit
wieder zurück auf 0.
Dealer schrieb:> Bei so einem Aufwand kann es sich nur um Hanfpflanzen handeln.
nö das zeugs ist n unkraut das wächst auch ohne aufwändige
bewässerung;-)).
Karl Heinz Buchegger schrieb:> Ja.> Mit einem Timer eine Uhr aufbauen.> Du weisst schon: tritt ein Ereigniss alle 1/100 Sekunde auf, dann ist> nach 100 Ereignissen 1 Sekunde vergangen. Nach 60 Sekunden 1 Minute,> nach 60 Minuten 1 Stunde, etc. etc. Sind alles nur Variablen, die bei> Bedarf um 1 hochgezählt werden und bei bestimmten Zählerständen die> nächste Variable hochzählen und dann wieder auf 0 gesetzt werden.>> FAQ: Timer
PS. Um Zeiten abzustoppen, bewährt es sich ganz gut, wenn man dann
diesen Teil umgekehrt macht, also von einer Zahl runterzählt.
zb. wenn das deine normale Uhr ist
1
volatileuint8_tSeconds,Minutes,Hours;
2
3
ISR(...)
4
{
5
count++;
6
7
if(count==....)// je nachdem wie oft dann die ISR wirklich
8
// aufgerufen wird -> Timereinstellung
9
{
10
count=0;
11
Seconds++;
12
13
if(Seconds==60)
14
{
15
Seconds=0;
16
Minutes++;
17
18
if(Minutes==60)
19
{
20
Minutes=0;
21
Hours++;
22
23
if(Hours==24)
24
Hours=0;
25
}
26
}
27
}
28
}
und du willst mit Sekundenauflösung was stoppen, dann führst du dir eine
weitere Variable ein und zählst sie in der ISR runter, wenn sie grösser
als 0 ist
1
volatileuint8_tSeconds,Minutes,Hours;
2
volatileint16_tWaittime=-1;
3
4
ISR(...)
5
{
6
count++;
7
8
if(count==....)// je nachdem wie oft dann die ISR wirklich
9
// aufgerufen wird -> Timereinstellung
10
{
11
count=0;
12
Seconds++;
13
14
if(Waittime>0)
15
Waittime--;
16
17
if(Seconds==60)
18
{
19
Seconds=0;
20
Minutes++;
21
22
if(Minutes==60)
23
{
24
Minutes=0;
25
Hours++;
26
27
if(Hours==24)
28
Hours=0;
29
}
30
}
31
}
32
}
Was hast du damit erreicht.
Im Normalfall tut sich nichts mit dieser Variablen. Sie ist -1 und wenn
das so ist, dann macht auch der Code in der ISR nichts damit.
Aber.
Im Hauptprogramm kannst du jetzt, wenn die Bedingungen richtig sind,
diese Variable auf einen Wert setzen
1
if(irgendwasliegtvor)
2
{
3
cli();
4
Waittime=300;
5
sei();
6
}
und in dem Moment beginnt die 'Wartezeit' zu ticken. Durch die ISR wird
die Variable im Sekundentakt wieder runtergezählt. Nach 1 Sekunde 299,
nach 2 Sekunden 298, etc. etc. bis die Variable nach 300 Sekunden wieder
bei 0 angelangt ist. Und das kann man abfragen!
1
if(irgendwasliegtvor)
2
{
3
cli();
4
Waittime=300;
5
sei();
6
}
7
8
cli();
9
NochZuWarten=Wartezeit;
10
sei();
11
12
if(NochZuWarten==0)
13
{
14
// Ha! Die 300 Sekunden sind um. Mach was!
15
16
....
17
18
// und schalte die Wartezeit wieder auf inaktiv, damit bei
19
// der nächsten Abfrage die 0 nicht nochmal auftauchen und
20
// den Schaltvorgang erneut auslösen
21
cli();
22
Wartezeit=-1;
23
sei();
24
}
25
26
....
was mit einer derartigen Variablen geht, geht auch mit 2 oder 10 oder
100.
Und wenn der Teil 'Mach was' kurz genug ist, dann braucht man das auch
nicht so kompliziert in die Hauptschleife auslagern, wo man jedesmal den
Interrupt abschalten muss, wenn man mit dieser Variablen arbeitet,
sondern man legt den Teil einfach gleich in die ISR.
Karl Heinz Buchegger schrieb:> Ja.> Mit einem Timer eine Uhr aufbauen.> Du weisst schon: tritt ein Ereigniss alle 1/100 Sekunde auf, dann ist> nach 100 Ereignissen 1 Sekunde vergangen. Nach 60 Sekunden 1 Minute,> nach 60 Minuten 1 Stunde, etc. etc. Sind alles nur Variablen, die bei> Bedarf um 1 hochgezählt werden und bei bestimmten Zählerständen die> nächste Variable hochzählen und dann wieder auf 0 gesetzt werden.>> FAQ: Timer
Danke für die Erklärung und den Link! Sehr Hilfreich.
MfG Benedikt
Das mit den Nägeln als Feuchtigkeitssensor wird so nicht gehen. Es baut
sich bald ein elektrochemisches Potential auf, deine Messwerte sind bald
unbrauchbar und ein Nagel rostet.
Du müsstest mit dem µC eine Rechteckspannung (> 10Hz) ausgeben und den
Nagel über einen entsprechend großen Kondensator anschließen, damit er
Wechselspannung abbekommt. Den Messeingang schließt du vor dem
Kondensator an. Natürlich ist dadurch die Auswertung etwas
komplizierter, aber machbar.
DIe Wartenfunktion habe ich einfach mit ein Timer gemacht.
Zum Schutz vor überschwämmung ist die schaltung auch so das er nur die
wasserpumpe einschaltet wenn das signal plausibel ist.
z.b wenn der widerstand unendlich ist ( wenn die messonden aus den
behälter gefallen sind ) oder wenn der widerstand fast 0 ( wenn die
sonden sich ausversehen berühren ) oder wenn der wert nach den 5
sekunden pumpen sich garnicht ändert dann wird immer gestoppt bis
schaltung resetet wird.