Smart Appliance Switch (3 / 5 steg)
Steg 3: kodning
Först logik verkade enkelt: om det är mörkt och det finns rörelse - slå på apparaten (lampan i mitt fall), annars stänga av. Vänta n sekunder och kolla igen.
Men när jag testar och lägger till nya lägen på min enhet, ingen av ovan nämnda arbetade som enkel.
Du kan inte använda om (mörka == true & & rörelse == true) {och slå sedan på} annat {inaktivera}; fördröjning (n);
eftersom du kommer att få otäcka feedback effect: mörka? -Ja, rörelse? -ja då slår på; vänta; mörka? -Nej (eftersom vi har bara vände på lamporna), rörelse? -ja då stänga av; mörka? -Ja... Så blinkar med denna logik får du konstant.
Det är därför i förfarande light_on() kontrollera vi först om det är mörkt och sedan gå till loop, tända ljus och ständigt kontrollera om förslaget är närvarande. Vi kontrollerar inte dessa två villkor samtidigt.
Som för kommandot fördröjning (n), som Pausar körning för n millisekunder, vi kan inte använda det eftersom under dröjsmål, om du trycker på permanent eller manuell läge knappar, Arduino inte kommer att märka det, eftersom det sover. Det är därför vi använder i samma slingan, som kontroller för rörelser i light_on () förfarande, fungerar millis() och tilldela dess värde till variabel "nu". Millis() returnerar antalet millisekunder som gått sedan Arduino var påslagen. Detta sätt är vi kunna få ut av loop när nu + delay_time > millis().
Så, alla villkor för att få ut av loop i light_on() procedur:
- Det finns ingen rörlighet;
- delay_time har passerat sedan senast rörelse upptäcktes;
- enhetsläge ändrades genom att trycka på en av knapparna.
Andra kommentarer som jag ingår i själva koden.
Jag gjorde två klasser: fotocell och pir.
För knappen debouncing använder jag Bounce2 bibliotek som du kan ladda ner från här. Ladda ner biblioteket och packa upp innehållet i ~/Documents/Arduino/libraries (på en Mac) eller My Documents\Arduino\libraries (på en Windows maskin).
< p > //#define __DEBUG__ / / avkommentera detta definierar för felsökningsinformation i följetong monitor < br > #include "Bounce2.h"
#include "photocell.h"
#include "pir.h" < /p >< p > //SETUP
CONST unsigned int PHOTOCELL_PIN = A0;
CONST unsigned int RELAY_PIN = 10;
CONST unsigned int PERMANENT_LED_PIN = 13.
CONST unsigned int PERMANENT_MODE_PIN = 12;
CONST unsigned int MANUAL_MODE_PIN = 11;
CONST unsigned int PIR_INPUT_PIN = 2;
CONST unsigned int BAUD_RATE = 9600;
CONST unsigned int LIGHT_DELAY = 5000;
CONST unsigned int DEBOUNCE_DELAY = 20;
CONST int DEFAULT_THRESHOLD = 130;
SETUP < /p >< p > int tröskel = 0;
Bounce permanent_mode_button, manual_mode_button;
booleska button_state = false;
fotocell p_cell(PHOTOCELL_PIN);
PIR ir_sensor(PIR_INPUT_PIN);
enum lägen {default_, permanent, manual, threshold_changed}; Vi måste också kunna avgöra, när under manuellt läge, manuellt lägesknappen trycktes igen
int prev_mode = default_;
int läge = default_; < /p >< p > //check tillstånd av knappen
booleska button_pressed (studs & knappen, boolean och staten) {
om (button.update() & & button.read() == 1) {
State =! statligt;
}
returnera staten.
} < /p >< p > //determine nuvarande läge
int check_mode() {
om (button_pressed (permanent_mode_button, button_state))
läge = permanent; permanent lägesknappen intryckt < /p >< p > annars om (manual_mode_button.update() & & manual_mode_button.read() == 1) {
tröskel = p_cell.value(); < /p >< p > #ifdef __DEBUG__
Serial.println ("tröskel:" + String(threshold));
#endif < /p >< p > läge = threshold_changed; tröskeln har ändrats
} < /p >< p > annars om (tröskelvärde > 0) {
läge = manuell; manuellt läge
} < /p >< p > annat
läge = default_; standardläget < /p >< p > återvända läge;
} < /p >< p > / / Kontrollera, wheter mode ändrades
bool mode_changed() {
om (prev_mode! = check_mode()) {
prev_mode = check_mode(); < /p >< p > #ifdef __DEBUG__
Serial.println ("sant, tidigare läge:" + String(prev_mode));
#endif
return true;
}
annat {
#ifdef __DEBUG__
Serial.println ("falska, tidigare läge:" + String(prev_mode));
#endif
returnera false;
}
} < /p >< p > //turn på ljus
void light_on (int tröskel, const unsigned int & pin, const unsigned int & delay_time) {
digitalWrite (PERMANENT_LED_PIN, 0);
om (p_cell.value() < = tröskelvärde) {< /p >< p > osignerade länge nu = 0;
booleska mode_change = mode_changed(); < /p >< p > för (; ((ir_sensor.motion_detected() & &! mode_change) & & (nu = millis())) || ((millis() < (nu + delay_time)) & &! mode_change); mode_change = mode_changed()) {
digitalWrite (pin, 1); Vi får ut av denna loop när det finns ingen rörlighet eller enhetsläge ändrades eller delay-tiden har gått
#ifdef __DEBUG__
Serial.println ("inuti loop, rörelse:" + String(ir_sensor.motion_detected()));
Serial.println ("nu:" + String(now));
#endif
}
digitalWrite (pin, 0);
}
digitalWrite (pin, 0);
} < /p >< p > void setup() {
#ifdef __DEBUG__
Serial.BEGIN(BAUD_RATE);
#endif
permanent_mode_button.attach(PERMANENT_MODE_PIN);
permanent_mode_button.Interval(DEBOUNCE_DELAY);
pinMode (PERMANENT_MODE_PIN, indata);
manual_mode_button.attach(MANUAL_MODE_PIN);
manual_mode_button.Interval(DEBOUNCE_DELAY);
pinMode (MANUAL_MODE_PIN, indata);
pinMode (RELAY_PIN, OUTPUT);
pinMode (PERMANENT_LED_PIN, OUTPUT);
} < /p >< p > void loop() {
om (läge == permanent) {
digitalWrite (RELAY_PIN, 1);
digitalWrite (PERMANENT_LED_PIN, 1);
#ifdef __DEBUG__
Serial.println ("permanent läge på");
#endif
} < /p >< p > annars om (läge == manual) {
#ifdef __DEBUG__
Serial.println ("manuellt läge på");
#endif
light_on (tröskel, RELAY_PIN, LIGHT_DELAY);
} < /p >< p > annars om (läge == default_) {
#ifdef __DEBUG__
Serial.println ("standardläge på");
Serial.println ("värde:" + String(p_cell.value()));
#endif
light_on (DEFAULT_THRESHOLD, RELAY_PIN, LIGHT_DELAY);
}
check_mode();
} < /p >
photocell.h
< p > #include "arduino.h" < /p >< p > klass fotocell {
privat:
unsigned int _pin;
int buffer_size; < /p >< p > offentliga:
fotocell (const unsigned int pin) {
_pin = pin;
buffer_size = 10;
} < /p >< p > int värde () {
float summan = 0;
för (int jag = 1; jag < = buffer_size; i ++) {//we använda buffert för att få fin medelvärdet
summa += analogRead(_pin);
}
återvända round(sum / buffer_size);
}
}; < /p >
pir.h
< p > #ifndef __PIR__ < br > #define __PIR__
#include "arduino.h" < /p >< p > klass PIR {
int _input_pin; < /p >< p > offentliga:
PIR (const unsigned int input_pin) {
_input_pin = input_pin;
pinMode (_input_pin, ingång);
} < /p >< p > bool motion_detected() {
återgå digitalRead(_input_pin) == hög;
}
};
#endif < /p >
Det är all kod som du behöver. Nu kan du överföra den till din Arduino och test, om allt fungerar som det ska, innan med hög spänning och montering för enheten.
Också bifogade jag filer med koder. På min maskin sammanställer allt utan problem.