2024. április 19., péntek

Gyorskeresés

Útvonal

Cikkek » Akármi rovat

Arduino konyhapult világítás

Egy Arduino Nano, egy MOSFET meghajtó, led szalagok, alu profilok, kábelcsatornák, 20m vezeték és egy hét szabadidő.

[ ÚJ TESZT ]

Végszó

Szüleimnek nagyon tetszik az eredmény, előszeretettel használják a mennyezeten lévő spot lámpák helyett. Nem is csoda, hiszem sokkal barátságosabb és egyenletesebb fényt ad ott, ahol kell: a kezünk ügyében. Szerintem nem vagyok vele egyedül, de engem kifejezetten irritál a régimódi mennyezeti világítás, főleg egy konyhában, ahol körbe a falak mentén vannak a konyhapultok: biz' Isten a fény útjában állok és árnyékot vetek pont oda, ahol látnom kéne mit csinálok.
A mozgásérzékelő meg telitalálat, mivel a konyhán keresztül vezet az út a mellékhelyiségig és így éjjel bóklászva a sötétben is biztonsággal lehet tájékozódni.

Egyetlen hiányossága van a projektnek csupán: a kábelmenedzsment. Beáldoztam a gőzelszívó feletti kis szekrényt, amit kineveztünk "projekt doboznak" és a továbbiakban nem tárolnak benne semmit. A legközelebbi karbantartáskor ezt a kuplerájt szeretném majd szakszerűen beszerelni egy normális villanyszereléshez való kötődobozba.
Valamint még ki kell találnom valamit az időnkénti enyhe vibrációra.
Jah meg nem ártana ESD védelmet tenni a kapcsolóra... Néha megcsípi az ember ujját a statikus kisülés.
(Ez bánthatja amúgy a mikrovezérlőt is.)

A teljes programkód

#include <EEPROM.h>
#include <avr/wdt.h> //watchdog
#include <ADCTouch.h>
//#define DEBUG
#ifdef DEBUG
#define debug(x) Serial.print(x)
#define debugln(x) Serial.println(x)
#else
#define debug(x)
#define debugln(x)
#endif

#define top_left 5
#define top_right 10
#define bottom_left 9
#define bottom_right 6
#define PS_ON 3 //PSU ON signal
#define PS_GOOD 2 //PSU good signal
#define ldr A1 //input of photoresistor with internal pullup
#define ldr_gnd 7 //GND of photoresistor
#define touch A0 //touch sensor
#define pir_in 4 //Signal of PIR sensor
#define pir_pwr 8 //Vcc of PIR sensor

#define max_light 255 //max top brightness
#define max_b_light 180 //max bottom brightness
#define night_light 100 //auto light at night
#define dark 850 //photoresistor value at dusk

extern const uint8_t gamma[];
char message[14];
byte messageCount = 0, mode = 0, light_tl, light_tr, light_bl, light_br, shadow_tl, shadow_tr, shadow_bl, shadow_br, stepping, pressing;
bool button, ack, fade, shutdown, PIR = 1, night, dim;
int16_t report, touch_ref, touch_value;
unsigned long timer, shutdown_time, debug, eco;

void processMessage() {
byte com;
debug(messageCount);
debug(F(": "));
debugln(message);
for (byte i = 0; i <= messageCount; i++) {
if (isAlpha(message[i])) {
switch (message[i]) {
case 'c':
mode = atoi(& message[i + 1]);
debug(F("Mode: "));
debugln(mode);
break;
case 't':
light_tl = atoi(& message[i + 1]);
debug(F("Top Left: "));
debugln(light_tl);
break;
case 'b':
light_bl = atoi(& message[i + 1]);
debug(F("Bottom Left: "));
debugln(light_bl);
break;
case 'z':
light_tr = atoi(& message[i + 1]);
debug(F("Top Right: "));
debugln(light_tr);
break;
case 'n':
light_br = atoi(& message[i + 1]);
debug(F("Bottom Right: "));
debugln(light_br);
break;
}
}
}
}

void processSerialRead(const char inByte) {
switch (inByte) {
case '\n': // end of text
message[messageCount] = 0; // terminating null byte
// terminator reached! process input_line here ...
processMessage();
// reset buffer for next time
messageCount = 0;
break;
case '\r': // discard carriage return
break;
default:
if (messageCount < 13) message[messageCount++] = inByte;
break;
}
}

byte lightAdjustment(byte brightness) {
if (brightness != 255) {
return brightness = pgm_read_byte(&gamma[brightness]);
} else return brightness;
}

void updateLed() {
if (light_tl != shadow_tl) analogWrite(top_left, lightAdjustment(shadow_tl)); //analogWrite(top_left, lightAdjustment(shadow_tl));
//if (light_tr != shadow_tr) analogWrite(top_right, lightAdjustment(shadow_tr));
if (light_bl != shadow_bl) analogWrite(bottom_left, lightAdjustment(shadow_bl));
//if (light_br != shadow_br) analogWrite(bottom_right, lightAdjustment(shadow_br));
}

void dimming() {
digitalWrite(top_left, LOW);
delay(500);
analogWrite(top_left, light_tl);
if (PIR) {
delay(300);
digitalWrite(top_left, LOW);
delay(500);
analogWrite(top_left, light_tl);
}
}

void psu(bool state) {
if (state) {
pinMode(PS_ON, OUTPUT);
digitalWrite(PS_ON, LOW);
shutdown_time = millis(); //for power supply failing
while (digitalRead(PS_GOOD) != HIGH) { //when it fails
debugln(F("Waiting for power..."));
//wdt_reset();
if (millis() > shutdown_time + 1000) {
pinMode(PS_ON, INPUT);
delay(1000);
pinMode(PS_ON, OUTPUT);
digitalWrite(PS_ON, LOW);
shutdown_time = millis();
}
}
}
else {
if (digitalRead(PS_GOOD) == HIGH) {
if (shutdown == false) shutdown_time = millis();
shutdown = true;
//debugln(F("PS off"));
}
}

if ((millis() - shutdown_time) > 30000 && shutdown) {
pinMode(PS_ON, INPUT);
}
else if (mode != 0) shutdown = false;
}

ISR(WDT_vect, ISR_NAKED)
{
register uint8_t *upStack;
upStack = (uint8_t *)SP + 1;
report = (*upStack << 8) | *(++upStack);
eeprom_write_word((uint16_t *)500, report);
}

void setup() {
//watchdog config
byte resetflag = MCUSR; // save flags for debug
MCUSR = 0; // reset various flags
WDTCSR |= 0b00011000; // see docs, set WDCE, WDE
WDTCSR = 0b01101001; // set WDIE, WDE, and appropriate delay
wdt_reset();

Serial.begin(9600);
pinMode(PS_ON, INPUT);
pinMode(PS_GOOD, INPUT);
pinMode(top_left, OUTPUT);
//pinMode(top_right, OUTPUT);
pinMode(bottom_left, OUTPUT);
//pinMode(bottom_right, OUTPUT);
pinMode(pir_in, INPUT);
pinMode(ldr, INPUT_PULLUP);
pinMode(ldr_gnd, OUTPUT);
pinMode(pir_pwr, OUTPUT);
digitalWrite(ldr_gnd, LOW);
digitalWrite(pir_pwr, HIGH);

touch_ref = ADCTouch.read(touch, 4000);
debugln(touch_ref);

//watchdog report
EEPROM.get(500, report);
Serial.print(F("Froze at: 0x"));
Serial.println(report * 2, HEX);
if (resetflag != 0) Serial.print(F("Reset: "));
switch (resetflag) {
case 1:
Serial.println(F("Power-on"));
break;
case 2:
Serial.println(F("External"));
break;
case 4:
Serial.println(F("Brown-out"));
break;
case 8:
Serial.println(F("Watchdog"));
break;
}

EEPROM.get(1, PIR);
}

void loop() {
wdt_reset(); //reset wathdog timer

//touch sensing
if (stepping == 0) { //nyomvatartás esetén hamis
touch_value = ADCTouch.read(touch, 100) - touch_ref; //érintő szenzor
//if (touch_value < 0) touch_ref += touch_value;
if (touch_value > 25 && !button) { //megérintve
//debugln(touch_value);
timer = millis(); //időszámláló nullázása
button = true; //gomb megnyomva
ack = false; //nincs feldogozva
}
else if (touch_value <= 25) { //nem érintve
//debug(touch_value);
//debugln("\t false");
button = false; //gombnyomás nullázása
}
}

if ((millis() - timer) <= 700 && !button && !ack) { //gomb felengedése, feldolgozása előtt
if (mode != 1) {
mode = 1; //bekapcsolás
dim = false; //power saving alaphelyzetbe állítása
}
else pressing++; //minden egyéb esetben gombnyomás +1
debug(pressing);
debugln(F(": "));
timer = millis();
ack = true; //feldolgozva
}

if ((millis() - timer) > 500 && !button && ack) { //gomb felengedve és feldolgozva
if (pressing == 2) { //ha kétszer nyomták meg
light_tl = light_tl > 160 ? 150 : max_light;
light_bl = light_bl > 160 ? night_light : max_b_light;
if (light_tl == max_light) dim = false;
else dim = true;
}
else if (pressing == 1) mode = 0; //ha egyszer nyomták meg
else if (pressing >= 3 && PIR) {
PIR = false; //mozgásérzékelő kikapcsolása
EEPROM.put(1, PIR);
debug(F("PIR sensor: "));
debugln(PIR);
dimming();
}
else if (pressing >= 3 && !PIR) {
PIR = true; //-||- bekapcsolása
EEPROM.put(1, PIR);
debug(F("PIR sensor: "));
debugln(PIR);
dimming();
}
//debug(pressing);
//debugln(F(": "));
pressing = 0; //számláló nullázása
}
/*if ((millis() - timer) > 700 && button && mode == 1) { //nyomva tartás
if (light_tl >= max_light) fade = false;
if (light_tl == 80) fade = true;
if (fade) {
light_tl++;
light_tr++;
}
else {
light_tl--;
light_tr--;
}
ack = true; //feldolgozva
if (stepping-- == 0) stepping = 5;
}*/

//set fading
if (shadow_tl < light_tl) shadow_tl += 5; //shadow is the actual brightness, light is the target
else if (shadow_tl > light_tl) shadow_tl -= 5;
//if (shadow_tr < light_tr) shadow_tr += 5;
//else if (shadow_tr > light_tr) shadow_tr -= 5;
if (shadow_bl < light_bl) shadow_bl += 5;
else if (shadow_bl > light_bl) shadow_bl -= 5;
//if (shadow_br < light_br) shadow_br += 5;
//else if (shadow_br > light_br) shadow_br -= 5;

//night
if (analogRead(ldr) > dark) night = true;
else if (analogRead(ldr) <= dark - 100) night = false;

//PIR night
if (PIR && digitalRead(pir_in) && night && mode == 0) mode = 2;
else if (mode == 2) if (!PIR || !digitalRead(pir_in) || !night) mode = 0;

//PIR eco mode
if (PIR && mode == 1) {
if (millis() > eco + 1500000 && light_tl == max_light) { //Power saving after the timeout.
light_tl = 150;
light_bl = night_light;
debugln(F("Entering power saving mode."));
} else if (digitalRead(pir_in) && light_tl != max_light && !dim) {
light_tl = max_light;
light_bl = max_b_light;
eco = millis();
debugln(F("Movement detected."));
} else if (digitalRead(pir_in)) eco = millis();
}

while (Serial.available() > 0) processSerialRead((char)Serial.read());
//debugln(mode);

switch (mode) {
case 1: //felkapcsolás
psu(true); //turn psu on
if (light_tl == 0) {
light_tl = max_light;
//light_tr = max_light;
}
if (light_bl == 0) {
light_bl = max_b_light; //max bottom light brightness
//light_br = max_b_light;
}
updateLed();
break;
case 0: //lekapcsolás
psu(false); //turn psu off
light_tl = 0;
//light_tr = 0;
light_bl = 0;
//light_br = 0;
updateLed();
break;
case 2: //éjszakai üzemmód
psu(true); //turn psu on
//debug(F("Night: "));
light_bl = night_light;
//light_br = night_light;
//debugln(night_light);
updateLed();
break;
}

#ifdef DEBUG
if (millis() - debug > 1000) {
debug(F("PIR: "));
debugln(digitalRead(pir_in));
debug(F("Fény: "));
debugln(analogRead(ldr));
debug(light_tl);
debug(F(", "));
debug(light_tr);
debug(F(", "));
debugln(light_bl);
debug(F(", "));
debugln(light_br);
debug(shadow_tl);
debug(F(", "));
debug(shadow_tr);
debug(F(", "));
debug(shadow_bl);
debug(F(", "));
debugln(shadow_br);
debugln();
debug = millis();
}
#endif
}

const uint8_t PROGMEM gamma[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114,
115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142,
144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175,
177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213,
215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255
};

Azóta történt

Előzmények

Hirdetés

Copyright © 2000-2024 PROHARDVER Informatikai Kft.