Hulp bij schoolopdracht - Timer in douche

Hi!

Ik hoop dat jullie mij willen helpen, omdat ik een beginner ben en ik een opdracht móét halen voor school, maar ik heb er zo verdomd veel moeite mee. De opdracht luidt als volgt:

Zorg ervoor dat een persoon, nadat de douche 10 minuten aan staat, de douche uit wilt zetten. Er brandt standaard een groen lampje en na 10 minuten wil ik dat er een alarm (piezo) afgaat en het groene lampje rood wordt. Ook moet er elke minuut een piepje te horen zijn. Ik heb een watersensor, piezobuzzer en ledlampje.

Ik moet het zelfs filmen om te laten zien dat het allemaal werkt.

Ik ben behoorlijk wanhopig en hoop dat iemand mij wilt helpen, ik ben zelfs bereidt om iemand te betalen om deze code voor mij te schrijven.

Alsjeblieft?! Alvast bedankt.

Hoi Kimmie,

Als je door de basic voorbeelden van de Arduino gaat zoals blink, dan zie je daarin alle bouwstenen die je nodig hebt.

Het moeilijkste is meestal "getting started" dus hier alvast een paar tips.

Je hebt 1 input - watersensor en twee outputs.
Die hebben allemaal een pin nodig.
Met pinMOde definieer je of ze input of output zijn.
Dit doe je in setup().

In de loop ga je iedere iteratie kijken of je wat moet doen.

void loop()
{
noteer hoe laat het nu is

is er 60 seconden verstreken sinds laatste piepje ==> piep + onthoud de tijd van laatste piepje

is er water gedetedteert? ==> onthoud de begintijd

is er 600 seconden verstreken sinds water detectie? ==> piep continue en zet groen led uit en rode aan

is er 700 seconden verstreken sinds water detectie? ==> sluit warm water af :wink:

}

de tijd meet je met millis()

Iedere vraag is een if ( )

wat je moet onthouden doe je met variabelen
(hint gebruik type long daar kunnen voldoende grote getallen in.)

De watersensor kun je met analogRead(A0) uitlezen (moet je hem wel daaraan verbinden natuurlijk.

Leds stuur je aan met digitalWrite()

Buzzer kan met digitalWrite() maar ook met analogWrite()

Probeer nu eens een opzet te maken van een programma dat (voorlopig) alleen detecteert of er water is of niet. Werkt dat niet, post het en zet je vragen erbij.

Success

Prachtig Rob in 20 regels het begin van arduino uitleggen.

kim ben iets duidelijker in wat je al gedaan hebt, zoals een schema van de hardware en de software.

Mee eens, shooter.

Alles wat je weg laat is een obstakel en zal eerder tegenwerken als meewerken.
Zoveel mogelijk informatie dus.
Als je bijvoorbeeld op 1 februari (of nog eerder) klaar moet zijn, dan ben je rijkelijk laat met je vraag.
En dat komt veel vaker voor, dat het te laat is om goed te helpen.
Want het leerproces is heel anders als iemand anders het voor je gaat maken, dus dan leer je niet wat de bedoeling van de opdracht was.

Ik zeg niet dat dat allemaal van toepassing is, want dat kan ik niet weten.
Dus geef zoveel mogelijk informatie als je een vraag stelt, en begin maar eens met Rob's voorstel.

robtillaart:
Hoi Kimmie,

Als je door de basic voorbeelden van de Arduino gaat zoals blink, dan zie je daarin alle bouwstenen die je nodig hebt.

Het moeilijkste is meestal “getting started” dus hier alvast een paar tips.

Je hebt 1 input - watersensor en twee outputs.
Die hebben allemaal een pin nodig.
Met pinMOde definieer je of ze input of output zijn.
Dit doe je in setup().

In de loop ga je iedere iteratie kijken of je wat moet doen.

void loop()
{
noteer hoe laat het nu is

is er 60 seconden verstreken sinds laatste piepje ==> piep + onthoud de tijd van laatste piepje

is er water gedetedteert? ==> onthoud de begintijd

is er 600 seconden verstreken sinds water detectie? ==> piep continue en zet groen led uit en rode aan

is er 700 seconden verstreken sinds water detectie? ==> sluit warm water af :wink:

}

de tijd meet je met millis()

Iedere vraag is een if ( )

wat je moet onthouden doe je met variabelen
(hint gebruik type long daar kunnen voldoende grote getallen in.)

De watersensor kun je met analogRead(A0) uitlezen (moet je hem wel daaraan verbinden natuurlijk.

Leds stuur je aan met digitalWrite()

Buzzer kan met digitalWrite() maar ook met analogWrite()

Probeer nu eens een opzet te maken van een programma dat (voorlopig) alleen detecteert of er water is of niet. Werkt dat niet, post het en zet je vragen erbij.

Success

Hi Rob,

Enorm bedankt!! Je hebt me flink op weg geholpen.

Voor mijn doen ben ik een stuk verder gekomen, alleen snap ik het nog niet helemaal en mijn code klopt dan ook nog lang niet. Hoe zorg ik ervoor dat de watersensor pas gaat meten ná 10 minuten? En tegelijkertijd elke minuut een piepje laat horen? Ik heb mijn code bijgevoegd en hoop dat je me weer een aantal tips wilt geven:).

watersensor.ino (1.46 KB)

We gaan eerst de minuut biepjes goed krijgen

tip 1: toekenning versus vergelijking

currentTime = 6000 is een toekenning

currentTime == 6000 is een vergelijking

tip 2: repetende acties met lastTime en millis constructie

Omdat je iedere 6000 msec iets wil doen kun je dat als volgt:

if (currentTime - lastTimeIDidBeep >= 6000)
{
lastTimeIDidBeep = currentTime;
beep();
}

door dit in de loop te zetten kun je een heleboel if(...) opruimen
in je code.

Voor iedere aktie die repeterend moet gebeuren gebruik je een eigen
lastTimeIdid_whatever variabele. Dus als je bv tegelijk ledjes wil laten
knipperen kan dat op deze manier.
Verder kun je bij iedere actie een eigen interval gebruiken door de 6000
aan te passen voor die akite.

Omdat millis() van jet type unsigned long is, moet je deze lastTime.... variabelen
van hetzelfde type maken. Dan gaat er geen (milli)seconde verloren.

Tip 3: header boven je programma

Ik gebruik bijna altijd een header boven mijn programma ter informatie.
Voegt functioneel niets toe maar toch
//
// FILE: watersensor.ino
// AUTHOR: Kimmie
// VERSION: 0.0.1
// PURPOSE:
//
// HISTORY:

KIjk of je nu een stap verder komt

robtillaart:
We gaan eerst de minuut biepjes goed krijgen

tip 1: toekenning versus vergelijking

currentTime = 6000 is een toekenning

currentTime == 6000 is een vergelijking

tip 2: repetende acties met lastTime en millis constructie

Omdat je iedere 6000 msec iets wil doen kun je dat als volgt:

if (currentTime - lastTimeIDidBeep >= 6000)
{
lastTimeIDidBeep = currentTime;
beep();
}

door dit in de loop te zetten kun je een heleboel if(…) opruimen
in je code.

Voor iedere aktie die repeterend moet gebeuren gebruik je een eigen
lastTimeIdid_whatever variabele. Dus als je bv tegelijk ledjes wil laten
knipperen kan dat op deze manier.
Verder kun je bij iedere actie een eigen interval gebruiken door de 6000
aan te passen voor die akite.

Omdat millis() van jet type unsigned long is, moet je deze lastTime… variabelen
van hetzelfde type maken. Dan gaat er geen (milli)seconde verloren.

Tip 3: header boven je programma

Ik gebruik bijna altijd een header boven mijn programma ter informatie.
Voegt functioneel niets toe maar toch
//
// FILE: watersensor.ino
// AUTHOR: Kimmie
// VERSION: 0.0.1
// PURPOSE:
//
// HISTORY:

KIjk of je nu een stap verder komt

Hi Rob! Bedankt voor de tips:) Ik heb alle beep stappen verwijderd en eentje toegevoegd, alleen nu begint hij meteen te beepen en elke 10 seconden ongeveer. Mijn code is nu als volgt:

//
//    FILE: watersensor.ino
//  AUTHOR: Kimmie
// VERSION: 0.0.1
// PURPOSE: Douchegedrag veranderen
//
// HISTORY:

const int read = A0;
int water;
const int greenLEDPin = D3;
const int redLEDPin = D4;
const int piezoPin = D1;
unsigned long currentTime = 0;
unsigned long lastTimeIDidBeep = 0;

void setup(){
 
  Serial.begin(9600); //Begin serial communication
  pinMode(greenLEDPin, OUTPUT);
  pinMode(redLEDPin, OUTPUT);
  pinMode(piezoPin, OUTPUT);
  beep(); //begonnen met meten
}
 
void loop(){
  
 currentTime = millis();
 water = analogRead(read);

 if (water<=700){
  digitalWrite(greenLEDPin, HIGH);
  digitalWrite(redLEDPin, LOW);
  digitalWrite(piezoPin, LOW);
 }

if (currentTime - lastTimeIDidBeep >= 6000) //na elke minuut een beep
{
   lastTimeIDidBeep = currentTime;
   beep();
}

 else if (water>700 && currentTime > 60000) //na 10 minuten
 
 {
  digitalWrite(greenLEDPin, LOW);
  digitalWrite(redLEDPin, HIGH);
  alarm();
 }

 }

 void alarm(){
        tone(piezoPin, 698);
        delay(600);
        noTone(piezoPin);
        delay(400);
  }

 void beep(){
        tone(piezoPin, 100);
        delay(100);
        noTone(piezoPin);
        delay(1000);
  
}

if (currentTime - lastTimeIDidBeep >= 6000)

==>

if (currentTime - lastTimeIDidBeep >= 60000)

Als je code post gebruik aub [code]....[/code] tags

else if (water>700 && currentTime > 60000) //na 10 minuten

60000 milliseconden is 1 minuut, geen 10 …

TIP CTRL-T in de IDE zorgt dat je code automatisch inspringt.
ziet er netter uit voor leesbaarheid.

robtillaart:
else if (water>700 && currentTime > 60000) //na 10 minuten

60000 milliseconden is 1 minuut, geen 10 …

TIP CTRL-T in de IDE zorgt dat je code automatisch inspringt.
ziet er netter uit voor leesbaarheid.

Het waren dus 6 seconden ipv 60 seconden… got it!

De minuut biepjes doen het nu, maar alles begint meteen te lopen zodra ik het upload. Hoe zorg ik ervoor dat dit pas gebeurt zodra de watersensor in contact komt met water?

//
//    FILE: watersensor.ino
//  AUTHOR: Kimmie
// VERSION: 0.0.1
// PURPOSE: Douchegedrag veranderen
//
// HISTORY:

const int read = A0;
int water;
const int greenLEDPin = D3;
const int redLEDPin = D4;
const int piezoPin = D1;
unsigned long currentTime = 0;
unsigned long lastTimeIDidBeep = 0;

void setup() {

  Serial.begin(9600); //Begin serial communication
  pinMode(greenLEDPin, OUTPUT);
  pinMode(redLEDPin, OUTPUT);
  pinMode(piezoPin, OUTPUT);
  beep(); //begonnen met meten
}

void loop() {

  currentTime = millis();
  water = analogRead(read);

  if (water <= 700) {
    digitalWrite(greenLEDPin, HIGH);
    digitalWrite(redLEDPin, LOW);
    digitalWrite(piezoPin, LOW);
  }

  else if (currentTime - lastTimeIDidBeep >= 60000) //na elke minuut een beep
  {
    lastTimeIDidBeep = currentTime;
    beep();
  }

  else if (water > 700 && currentTime > 600000) //na 10 minuten

  {
    digitalWrite(greenLEDPin, LOW);
    digitalWrite(redLEDPin, HIGH);
    alarm();
  }

}

void alarm() {
  tone(piezoPin, 698);
  delay(600);
  noTone(piezoPin);
  delay(400);
}

void beep() {
  tone(piezoPin, 100);
  delay(100);
  noTone(piezoPin);
  delay(1000);

}

Het gaat goed Kimmie!

De minuut biepjes doen het nu, maar alles begint meteen te lopen zodra ik het upload. Hoe zorg ik ervoor dat dit pas gebeurt zodra de watersensor in contact komt met water?

Daarvoor gaan we een nieuwe variabele introduceren. Deze variabele zetten we de startTijd van het ondekken van water.

Omdat het een tijd weergeeft maken ook daarvan een uint32_t

uint32_t WaterDetectionTime = 0;

NU spreken we zelf af dat zolang de waarde 0 is de tijd nog niet gezet is. OK?

De variabele WaterDetectionTime wordt gezet op het moment dat ..... (goed zo :wink:

In Nederlands

Als analogRead water aangeeft ==> WaterDetectionTime = millis();

Daarna kunnen we in de loop ook een conditie toevoegen of er 10 minuten = (?? milliseconden ??)
verstreken zijn,

In Nederlands

Als millis() - WaterDetectionTime >= 10 minuten ==> laat alle alarmen rinkelen

Echter als WaterDetectionTime == 0 mag het weer niet

Dus de regel wordt wat langer

Als (millis() - WaterDetectionTime >= 10 minuten) && (WaterDetectionTime != 0)
==> laat alle alarmen rinkelen

de && if de logische AND operatie, dan moeten beide delen waar zijn.


Als dit werkt moet er nog wat verfijnd worden. Namelijk als er geen water meer gedetecteerd wordt moet
de variabele WaterDetection weer op 0 gezet worden.

In Nederlands zou je nu zelf moeten kunnen formuleren

Success!

Ik dacht dat ik het goed had gedaan, maar nu gaat het alarm niet aan na 10 minuten en ik snap niet zo goed waarom.

En je zei omdat de nieuwe variabele een tijd weergeeft maak ik hier ook een uint32_t van. Moet ik de andere variabelen die ook tijd weergeven veranderen of staan deze goed?

//
//    FILE: watersensor.ino
//  AUTHOR: Kimmie
// VERSION: 0.0.3
// PURPOSE: Douchegedrag veranderen
//
// HISTORY:

const int read = A0;
int water;
const int greenLEDPin = D3;
const int redLEDPin = D4;
const int piezoPin = D1;
unsigned long currentTime = 0;
unsigned long lastTimeIDidBeep = 0;
uint32_t WaterDetectionTime  = 0;

void setup() {

  Serial.begin(9600); //Begin serial communication
  pinMode(greenLEDPin, OUTPUT);
  pinMode(redLEDPin, OUTPUT);
  pinMode(piezoPin, OUTPUT);
}

void loop() {

  currentTime = millis();
  water = analogRead(read);

  if (water <= 700) {
    digitalWrite(greenLEDPin, HIGH);
    digitalWrite(redLEDPin, LOW);
    digitalWrite(piezoPin, LOW);
  }

  else if (currentTime - lastTimeIDidBeep >= 60000) //na elke minuut een beep
  {
    lastTimeIDidBeep = currentTime;
    beep();
  }

  else if (water => 700) // Als analogRead water aangeeft ?? Doe ik dit goed of moet ik deze variabele ergens anders zetten?
{
    WaterDetectionTime  = millis();
}
  
  else if (millis() - WaterDetectionTime  >=  600000 && WaterDetectionTime  !=  0)  

  {
    digitalWrite(greenLEDPin, LOW);
    digitalWrite(redLEDPin, HIGH);
    alarm();
  }


}

void alarm() {
  tone(piezoPin, 698);
  delay(600);
  noTone(piezoPin);
  delay(400);
}

void beep() {
  tone(piezoPin, 100);
  delay(100);
  noTone(piezoPin);
  delay(1000);

}

Waarom zo moeilijk met al die else-ifs?

Je kan de vraag opdelen in deelvragen:
a) loopt er water
b) is er een minuut voorbij
c) zijn er 10 minuten voorbij

Ad a: Loopt er water
Als er water loopt en er is nog geen timer gestart ( je hebt dus een boolean nodig die aangeeft dat de timer loopt) dan start je de timer EN je reset een eenvoudige counter (tot 10). Eventueel zet je wat LEDS oid aan of uit).

Als er GEEN water loopt zet je die bool op false. Wederom wat ledjes aan of uit.

Meer hoef je dus niet te doen in deze stap

Ad b: Is er een minuut voorbij
Dit hoef je alleen maar te doen als de timer loopt (de bool is true)
Zo ja dan controleer je of millis() - timer > 60000
Zo ja
dan zet je de timer weer (timer = millis())
dan verhoog je de counter
dan laat je een beep() horen

Meer hoef je niet te doen

Ad c: zijn er 10 minuten verlopen
Dit hoef je alleen te doen als de timer loopt (bool is true)
Als de counter >= 10
Dan gaat je alarm af
en wat je nog meer wilt doen

Meer hoef je niet te doen

samenvattend:
Trek het probleem uit elkaar en maak er eenvoudige controles van.

Bedankt voor de hulp, alleen ik vind het erg moeilijk en snap niet veel van booleans. Het klinkt heel makkelijk, maar geen idee hoe ik het moet uitvoeren. Ga ik zo de goede kant op?

//
//    FILE: watersensor.ino
//  AUTHOR: Kimmie
// VERSION: 0.0.3
// PURPOSE: Douchegedrag veranderen
//
// HISTORY:

const int read = A0;
int water;
const int greenLEDPin = D3;
const int redLEDPin = D4;
const int piezoPin = D1;
unsigned long currentTime = 0;
unsigned long lastTimeIDidBeep = 0;
uint32_t WaterDetectionTime  = 0;
boolean runTimer;

void setup() {

  Serial.begin(9600); //Begin serial communication
  pinMode(greenLEDPin, OUTPUT);
  pinMode(redLEDPin, OUTPUT);
  pinMode(piezoPin, OUTPUT);
}

void loop() {

  currentTime = millis();
  water = analogRead(read);
  WaterDetectionTime  = millis();

  if (water <= 700) // Als analogRead water aangeeft ?? Doe ik dit goed of moet ik deze variabele ergens anders zetten?{
    digitalWrite(greenLEDPin, HIGH);
  digitalWrite(redLEDPin, LOW);
  digitalWrite(piezoPin, LOW);
  runTimer = false;
}

else if (currentTime - lastTimeIDidBeep >= 6000) //na elke minuut een beep
{
  lastTimeIDidBeep = currentTime;
  beep();
}

else if (millis() - WaterDetectionTime  >=  60000 && WaterDetectionTime  !=  0)

{
  digitalWrite(greenLEDPin, LOW);
  digitalWrite(redLEDPin, HIGH);
  alarm();
  runTimer = true;
}


}

void alarm() {
  tone(piezoPin, 698);
  delay(600);
  noTone(piezoPin);
  delay(400);
}

void beep() {
  tone(piezoPin, 100);
  delay(100);
  noTone(piezoPin);
  delay(1000);

}

@nico: die If dingen komen van Rob , is ook een goede manier van beginnen, hij houd het simpel, en dat lijkt mij hier ook de beste.
@Kim er missen wat haken {} na de if
zoek een cheatsheet, waar alle instructies op staan, en ja dat water is goed.

@shooter: wat je wilt.....

@shooter: Dankje voor je bericht. Dat water zorgt ervoor dat mn beeps per minuut het niet meer doen. Enig idee hoe dat kan?

En ook het alarm en het rode lampje gaan niet aan na 10 minuten in het water (of uberhaupt na 10 minuten).

//
//    FILE: watersensor.ino
//  AUTHOR: Kimmie
// VERSION: 0.0.3
// PURPOSE: Douchegedrag veranderen
//
// HISTORY:

const int read = A0;
int water;
const int greenLEDPin = D3;
const int redLEDPin = D4;
const int piezoPin = D1;
unsigned long currentTime = 0;
unsigned long lastTimeIDidBeep = 0;
uint32_t WaterDetectionTime  = 0;

void setup() {

  Serial.begin(9600); //Begin serial communication
  pinMode(greenLEDPin, OUTPUT);
  pinMode(redLEDPin, OUTPUT);
  pinMode(piezoPin, OUTPUT);
}

void loop() {

  currentTime = millis();
  water = analogRead(read);
  WaterDetectionTime  = millis();

  if (water <= 700)
  {
    digitalWrite(greenLEDPin, HIGH);
    digitalWrite(redLEDPin, LOW);
    digitalWrite(piezoPin, LOW);
  }

  else if (currentTime - lastTimeIDidBeep >= 6000) //na elke minuut een beep
  {
    lastTimeIDidBeep = currentTime;
    beep();
  }

  else if (water > 700)
  {
    WaterDetectionTime  = millis();
  }

  else if (millis() - WaterDetectionTime  >=  60000 && WaterDetectionTime  !=  0)

  {
    digitalWrite(greenLEDPin, LOW);
    digitalWrite(redLEDPin, HIGH);
    alarm();

  }


}

void alarm() {
  tone(piezoPin, 698);
  delay(600);
  noTone(piezoPin);
  delay(400);
}

void beep() {
  tone(piezoPin, 100);
  delay(100);
  noTone(piezoPin);
  delay(1000);

}

De teller start onder bepaalde voorwaarden.
Schijnbaar worden die voorwaarden niet bereikt.
Wanneer de eerste voorwaarde wel word bereikt, dan zullen de andere voorwaarden niet meer behandeld worden.
Dat kun je wel of niet zo laten gebeuren door wel of niet het woordje ‘else’ te gebruiken.
Dus ‘else’ betekent dat wat er daarna gebeuren moet, alleen moet worden uitgevoerd als het voorgaande niet waar was.
En dus ook dat wat daarna staat, niet zal worden uitgevoerd als het voorgaande wel waar was.
Ik hoop dat dat duidelijk genoeg is.

Ik zie dat het woord ‘read’ een kleurtje krijgt in de IDE.
Dat betekent volgens mij dat dat een woord is dat al gedefinieerd is.
Daarom is dat volgens mij niet het beste woord om te kiezen hiervoor.
Ik stel voor om daarvoor in de plaats het woord ‘sensor’ te gebruiken.
Zodat je geen vreemde en ongewenste dingen veroorzaakt.
Die kleurtjes die spontaan (of toch niet…) in je code verschijnen, zijn hints van de IDE die je moeten helpen tijdens het programmeren.

Bedankt! Dit is nu mijn code:

//
//    FILE: watersensor.ino
//  AUTHOR: Kimmie
// VERSION: 0.0.3
// PURPOSE: Douchegedrag veranderen
//
// HISTORY:

const int sensor = A0;
int water;
const int greenLEDPin = D3;
const int redLEDPin = D4;
const int piezoPin = D1;
unsigned long currentTime = 0;
unsigned long lastTimeIDidBeep = 0;
uint32_t WaterDetectionTime  = 0;

void setup() {

  Serial.begin(9600); //Begin serial communication
  pinMode(greenLEDPin, OUTPUT);
  pinMode(redLEDPin, OUTPUT);
  pinMode(piezoPin, OUTPUT);
}

void loop() {

  currentTime = millis();
  water = analogRead(sensor);
  WaterDetectionTime  = millis();

  if (water <= 700) // geen water
  {
    digitalWrite(greenLEDPin, HIGH);
    digitalWrite(redLEDPin, LOW);
    digitalWrite(piezoPin, LOW);
  }

  if (water >= 700 && currentTime - lastTimeIDidBeep >= 60000) //water staat aan + na elke minuut een beep
  {
    lastTimeIDidBeep = currentTime;
    beep();
  }

  if (water >= 700) //is er water gedetecteerd? Onthoud de begintijd 
  {
    WaterDetectionTime = millis();
  }

  if (water >= 700 && millis() - WaterDetectionTime >= 600000 && WaterDetectionTime  !=  0) //zijn er 10 minuten verstreken? Zet rode led aan + alarm
  {
    digitalWrite(greenLEDPin, LOW);
    digitalWrite(redLEDPin, HIGH);
    alarm();
  }
}

void alarm() {
  tone(piezoPin, 698);
  delay(600);
  noTone(piezoPin);
  delay(400);
}

void beep() {
  tone(piezoPin, 100);
  delay(100);
  noTone(piezoPin);
  delay(1000);

}

Toch gaat het alarm niet aan na 10 minuten. Wat doe ik precies fout? En hoe zet ik de waterdetectietimer weer op 0 zodra de watersensor niet meer in contact is met water.

if (water <= 700) // doe ik dit zo?
{
WaterDetectionTime = 0;
}

Of kan ik ‘WaterDetectionTime = 0;’ in de eerste if statement zetten?

Ik heb het gevoel dat deze if statement niet klopt;

if (water >= 700 && millis() - WaterDetectionTime >= 60000 && WaterDetectionTime != 0)

Wie kan mij vertellen wat er precies fout gaat? :smiley: