УФ сушка лака для ногтей
- Войдите на сайт для отправки комментариев
в общем, решил я своей мамзели сворганииь таке.
корпус будет из пластиковой коробки(полно подходящих в посудных лавках), светодиоды нашел в Китае(тут важно подобрать их не только по мощности, но и по длине волны - разный гель требует своей).
разработал ТЗ:
1. нужен таймер с дискретностью 5 сек и выдержкой до 10 мин.
2. регулировка яркости свечения УФ диодов.
3. отключаемый(переодически включаемый) маленький вентилятор, теплый воздух от диодов гнать на ногти, с регулировкий скорости.
4. индикация на двух 3-х сегментниках - один время, второй шим диодов и вентилятора.
5. управление - энкодер или три кнопки(мамзель блондинка, боюсь больше не осилит).
и тут я плотно завис - пока разобрался с управлением семисегментниками и нашел скетч таймера совершенно не понимаю как до кучи всё это собрать.
по сему вопрос - если есть нароботки по данной(или смежной) теме - делитесь, плз :)
Люди наоборот из ламп для ногтей что-то делают...
http://m.instructables.com/id/Printed-Circuit-Board-Production-using-UV-...
ну... такие темы видел. каждому своё(с)
управление светодиодами и вентилятором - по типу как в соседних ветках паяльные станции.
вот, в сети нашел код таймера(правда он на два сегмента с несколько странной индикацией)
#include <EEPROM.h> void setup() { ind_setup(); kbd_setup(); out_setup(); config_setup(); } void loop() { ind_refresh(); ind_update(); kbd_update(); timer_update(); out_update(); config_update(); beep_update(); delay(10); } //Config/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// struct { unsigned long time; byte crc; } config; #define CONFIG_WRITE_DELAY 500 unsigned int config_timer; void config_setup() { config_read(); if (config.time > (3600 * 99)) config.time = 1; } void config_update() { if (config_timer > 0) { config_timer--; if (config_timer == 0) { config_write(); } } } void config_read() { byte *b = (byte *)&config; for (byte i=0; i<sizeof(config); i++) *b++ = EEPROM.read(i); } void config_write() { byte *b = (byte *)&config; for (byte i=0; i<sizeof(config); i++) EEPROM.write(i, *b++); } void config_write_reset() { config_timer = CONFIG_WRITE_DELAY; } //Timing/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// enum {SEC,MINSEC,MIN,HR}; //time mode const unsigned int timer_inc[] = {1,10,60,3600}; const unsigned long timer_mode_min[] = {0,60,10*60,60*60}; unsigned long timer = 0; byte timer_div = 0; //check if timer is loaded and counting byte timer_counting() { return (timer > 0); } //get timer mode (0-seconds, 1-min.sec, 2-min, 3-hr) byte timer_mode(unsigned long t) { if (t < 60) return SEC; else if (t < 10 * 60) return MINSEC; else if (t < 60 * 60) return MIN; else return HR; } //get 2-digit value for timer byte timer_to_byte(unsigned long t) { switch (timer_mode(t)) { case SEC: return t; case MINSEC: return ((t / 60) * 10) + ((t % 60) / 10); case MIN: return (t / 60); case HR: return (t / 3600); } } //update timer void timer_update() { if (timer_counting()) { if (++timer_div >= 100) { timer_div = 0; timer--; if (timer == 0) { //play stop sound beep_timer_end(); } else { if (timer <= 10) beep_timer_ending(); } } } } //set and start timer void timer_start(unsigned long t) { timer = t; timer_div = 0; } //Indication/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// enum {SEGA=1,SEGB=2,SEGC=4,SEGD=8,SEGE=16,SEGF=32,SEGG=64,SEGH=128}; //segments masks enum {SEGApin=2,SEGHpin=9}; //segments pins //HEX 7-seg digits const byte ind_digits[]={ SEGA | SEGB | SEGC | SEGD | SEGE | SEGF, //0 SEGB | SEGC, //1 SEGA | SEGB | SEGD | SEGE | SEGG, //2 SEGA | SEGB | SEGC | SEGD | SEGG, //3 SEGB | SEGC | SEGF | SEGG, //4 SEGA | SEGC | SEGD | SEGF | SEGG, //5 SEGA | SEGC | SEGD | SEGE | SEGF | SEGG, //6 SEGA | SEGB | SEGC, //7 SEGA | SEGB | SEGC | SEGD | SEGE | SEGF | SEGG, //8 SEGA | SEGB | SEGC | SEGD | SEGF | SEGG, //9 SEGA | SEGB | SEGC | SEGE | SEGF | SEGG, //A SEGC | SEGD | SEGE | SEGF | SEGG, //b SEGA | SEGD | SEGE | SEGF, //C SEGB | SEGC | SEGD | SEGE | SEGG, //d SEGA | SEGD | SEGE | SEGF | SEGG, //E SEGA | SEGE | SEGF | SEGG, //F }; const byte ind_com[] = {10,A1}; //common anode pins //number of digits #define IND_SIZE 2 byte ind_buf[IND_SIZE]; //indication buffer byte ind_cnt; //current digit counter //setup indication void ind_setup() { //segment pins for (byte pin=SEGApin; pin<=SEGHpin; pin++) { pinMode(pin, OUTPUT); digitalWrite(pin, HIGH); } //common anodes pins for (byte pin=0; pin<IND_SIZE; pin++) { pinMode(ind_com[pin], OUTPUT); digitalWrite(ind_com[pin], HIGH); } //clear buffer for (byte i=0; i<IND_SIZE; i++) ind_buf[i] = 0; } byte ind_digit(byte digit) { return ind_digits[digit]; } //set segments void ind_set_segs(byte digit) { byte mask = 1; for (byte pin=SEGApin; pin<=SEGHpin; pin++) { digitalWrite(pin, !(digit & mask)); mask <<= 1; } } //select digit (0xFF to deselect all) void ind_set_com(byte num) { if (num == 0xFF) { //all OFF for (byte com=0; com<IND_SIZE; com++) digitalWrite(ind_com[com], HIGH); } else { digitalWrite(ind_com[num], LOW); } } //convert lower half-byte to 7-segment HEX byte to_hex(byte data) { return ind_digit(data & 0xF); } //convert decimal 0..99 to BCD 0..0x99 byte to_bcd(byte data) { byte result = data % 10; data /= 10; result += (data % 10) << 4; return result; } //write 8-bit HEX to indication buffer void ind_wr_H8(byte data, byte pos) { ind_buf[pos] = to_hex(data >> 4); ind_buf[pos + 1] = to_hex(data); } //refresh indication void ind_refresh() { ind_set_com(0xFF); if (++ind_cnt >= IND_SIZE) ind_cnt = 0; ind_set_segs(ind_buf[ind_cnt]); ind_set_com(ind_cnt); } void ind_update() { unsigned long t = (!timer_counting()) ? config.time : timer; ind_wr_H8(to_bcd(timer_to_byte(t)), 0); if (ind_buf[0] == ind_digits[0]) ind_buf[0] = 0; if (timer_div < 50) { switch (timer_mode(t)) { case SEC: break; case MINSEC: ind_buf[0] |= SEGH; break; case MIN: ind_buf[1] |= SEGH; break; case HR: ind_buf[0] |= SEGH; ind_buf[1] |= SEGH; break; } } } //Keyboard///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// byte kbd_buf[2]; //current/previous keyboard states byte kbd_cnt; //keypress counter enum {KBD_UP=1, KBD_DOWN=2, KBD_SET=3}; //key codes enum {KBD_CNT_SHORT=5, KBD_CNT_LONG=100, KBD_CNT_START=250, KBD_REPEAT=10}; //key press counter values #define KBD_CNT_REPEAT (KBD_CNT_LONG - KBD_REPEAT) void kbd_setup() { pinMode(12, INPUT_PULLUP); digitalWrite(12, HIGH); pinMode(13, INPUT_PULLUP); digitalWrite(13, HIGH); } byte kbd_read() { return (!digitalRead(12) << 1) | !digitalRead(13); } byte kbd_press(byte code, byte cnt) { return (kbd_buf[1] == code) && (kbd_cnt == cnt); } byte kbd_press2(byte code, byte cnt1, byte cnt2) { return (kbd_buf[1] == code) && ((kbd_cnt == cnt1) || (kbd_cnt == cnt2)); } void kbd_update(void) { kbd_buf[0] = kbd_read(); if (kbd_buf[1] != kbd_buf[0]) { kbd_cnt = 0; kbd_buf[1] = kbd_buf[0]; } else { if (kbd_cnt < 255) kbd_cnt++; if (!timer_counting()) { if (kbd_press2(KBD_UP, KBD_CNT_SHORT, KBD_CNT_LONG)) { if (kbd_cnt == KBD_CNT_LONG) kbd_cnt = KBD_CNT_REPEAT; else beep_key_press(); config.time += timer_inc[timer_mode(config.time)]; if (config.time > (3600UL * 99)) config.time = (3600UL * 99); config_write_reset(); beep_stop(); } else if (kbd_press2(KBD_DOWN, KBD_CNT_SHORT, KBD_CNT_LONG)) { if (kbd_cnt == KBD_CNT_LONG) kbd_cnt = KBD_CNT_REPEAT; else beep_key_press(); if (config.time > 1) { byte m = timer_mode(config.time); if ((m > 0)&&(config.time == timer_mode_min[m])) m--; config.time -= timer_inc[m]; config_write_reset(); } beep_stop(); } //start timer else if (kbd_press(KBD_SET, KBD_CNT_SHORT)) { timer_start(config.time); beep_stop(); beep_timer_start(); } } else { //stop timer if (kbd_press(KBD_SET, KBD_CNT_SHORT)) { timer = 0; beep_timer_stop(); } } } } //Out///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #define OUT_PIN A0 void out_setup() { pinMode(OUT_PIN, OUTPUT); digitalWrite(OUT_PIN, LOW); } void out_update() { if (timer_counting()) digitalWrite(OUT_PIN, HIGH); else digitalWrite(OUT_PIN, LOW); } //Beeper////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #define BEEP_FREQ 2500 unsigned int beep_cnt; void beep(byte len) { if (len == 0) noTone(11); else if (len == 1) tone(11, BEEP_FREQ); else tone(11, BEEP_FREQ, len); } void beep_stop() { beep_cnt = 0; beep(0); } void beep_update() { if (beep_cnt > 0) { beep_cnt--; if (beep_cnt == 0) beep(0); else { // beep((beep_cnt & 0x20) && (beep_cnt & 0x4) && (beep_cnt & 0x02)); beep((beep_cnt & 0x40) && (beep_cnt & 0x08)); } } } void beep_timer_end() { beep_cnt = 1000; } void beep_timer_start() { beep(100); } void beep_timer_stop() { beep(100); } void beep_timer_ending() { beep(50); } void beep_key_press() { beep(30); }У моей на лампе одна кнопка включает, вторая устанавливает таймер отключения 2мин, правда лампа заводская.
Вы планируете столько опций, а нужны ли они все?
ИМХО
вот такую лампу я и хочу переделать(это один вариант). ну или с "0" сделать на светодиодах.
тут основное это таймер с гибкой настройкой - что б руки не пожечь и что б разные лаки(точнее гели) гарантировано сохли.
индикация времени и мощности излучения диодов - тож вроде нужно, циферки запомнить проще(какой лак да при какой мощности и времени).
вентилятор - тот да, можно включать кнопочкой а ШИМ на 555 таймере заорганизовать.
вроде особо лишнего нет.
если уже ставите контроллер тогда таймер не555 не нужен ардуино легко два шима потянет один на диоды второй на вентилятор.
Семисигментники гемор еще тот(((
да, геморр тот, но у меня есть трёхразрядный индикатор и он места меньше LCD занимает.
ну и в первом приближении понятно как работает =)
кароч, прикинул что к чему:
- будет таймер с выдержкой 9 мин 59 сек;
- два ШИМ (один на вентилятор, второй на светики);
- три кнопки управления (select, uр, down);
есть вопросы, если кто сталкиваолся подскажите плз:
1. вот, нарыл скетч таймера (он для четырёх разрядного и без сдвигового регистра). вопрос в том, что пока не стал указывать сегмент "F" с двумя буквами, вылетало с ошибкой "незадекларировано".
почему так?
/* Arduino 4 digits 7 segments LED countdown timer with buzzerm from electronicsblog.net. If You share/use this code elsewhere on the internet please meantion this code source. */ // segment | Arduino board PIN number #define A 2 #define B 3 #define C 4 #define D 5 #define E 6 #define FF 7 #define G 8 #define DP 9 // Commonn cathodes control #define GND1 10 #define GND2 11 #define GND3 12 #define GND4 13 // buttons /* Button_start - start/pause timer and in setup mode inreases minutes and seconds values Button_set - if timer is paused it resets timer to start. Long press activates setup mode in which button is for going through minutes, seconds setup and leaving setup mode. */ #define Button_start A1 #define Button_set A2 #define Buzzer A3 #define LED A0 // or relay insted int i=0; char run=0; // shows if timer is runnig int b=0; //for buttons int c=0; int d=0; // for buzzer char set_mode=0; // shows if timer is in setup mode char alarm =0; // if "1" buzzer is on //timer variables // user setted and "turn on" values int default_Sec=59; int default_Min=99; // current values int Sec; int Min; //timer interrupt ISR(TIMER1_OVF_vect) { Sec--; // timer values decreases TCNT1=0x0BDC; } // functions to display digits void digit0 () { digitalWrite(A, HIGH); digitalWrite(B, HIGH); digitalWrite(C, HIGH); digitalWrite(D, HIGH); digitalWrite(E, HIGH); digitalWrite(FF, HIGH); digitalWrite(G, LOW); }; void digit1 () { digitalWrite(A,LOW); digitalWrite(B, HIGH); digitalWrite(C, HIGH); digitalWrite(D, LOW); digitalWrite(E, LOW); digitalWrite(FF, LOW); digitalWrite(G, LOW); }; void digit2 () { digitalWrite(A,HIGH); digitalWrite(B, HIGH); digitalWrite(C, LOW); digitalWrite(D, HIGH); digitalWrite(E, HIGH); digitalWrite(FF, LOW); digitalWrite(G, HIGH); }; void digit3 () { digitalWrite(A,HIGH); digitalWrite(B, HIGH); digitalWrite(C, HIGH); digitalWrite(D, HIGH); digitalWrite(E, LOW); digitalWrite(FF, LOW); digitalWrite(G, HIGH); }; void digit4 () { digitalWrite(A,LOW); digitalWrite(B, HIGH); digitalWrite(C, HIGH); digitalWrite(D, LOW); digitalWrite(E, LOW); digitalWrite(FF, HIGH); digitalWrite(G, HIGH); }; void digit5 () { digitalWrite(A,HIGH); digitalWrite(B, LOW); digitalWrite(C, HIGH); digitalWrite(D, HIGH); digitalWrite(E, LOW); digitalWrite(FF, HIGH); digitalWrite(G, HIGH); }; void digit6 () { digitalWrite(A,HIGH); digitalWrite(B, LOW); digitalWrite(C, HIGH); digitalWrite(D, HIGH); digitalWrite(E, HIGH); digitalWrite(FF, HIGH); digitalWrite(G, HIGH); }; void digit7 () { digitalWrite(A,HIGH); digitalWrite(B, HIGH); digitalWrite(C, HIGH); digitalWrite(D, LOW); digitalWrite(E, LOW); digitalWrite(FF, LOW); digitalWrite(G, LOW); }; void digit8 () { digitalWrite(A, HIGH); digitalWrite(B, HIGH); digitalWrite(C, HIGH); digitalWrite(D, HIGH); digitalWrite(E, HIGH); digitalWrite(FF, HIGH); digitalWrite(G, HIGH); }; void digit9 () { digitalWrite(A, HIGH); digitalWrite(B, HIGH); digitalWrite(C, HIGH); digitalWrite(D, HIGH); digitalWrite(E, LOW); digitalWrite(FF, HIGH); digitalWrite(G, HIGH); }; //function to display digit from inputed int void showdigit (int digit) { switch (digit) { case 0: digit0 (); break; case 1: digit1 (); break; case 2: digit2 (); break; case 3: digit3 (); break; case 4: digit4 (); break; case 5: digit5 (); break; case 6: digit6 (); break; case 7: digit7 (); break; case 8: digit8 (); break; case 9: digit9 (); break; default: break; }; }; // showing 4 digits // not only shows 4 digit number, but also there is option to turn on //only selected digits and decimal point. void showdigits (int number, char digit_on, char decimal_point) { digitalWrite(GND4, LOW); // e.g. we have "1234" showdigit(number/1000); // segments are set to display "1" if (decimal_point&8) {digitalWrite(DP, HIGH);} else {digitalWrite(DP, LOW);}; if (digit_on&8) { digitalWrite(GND1, HIGH); // first digit on, digitalWrite(GND2, LOW); // other off digitalWrite(GND3, LOW); } delay (1); number = number%1000; // remainder of 1234/1000 is 234 digitalWrite(GND1, LOW); // first digit is off showdigit(number/100); //// segments are set to display "2" if (decimal_point&4) {digitalWrite(DP, HIGH);} else {digitalWrite(DP, LOW);}; if (digit_on&4) { digitalWrite(GND2, HIGH); // second digit is on } delay (1);// and so on.... number =number%100; digitalWrite(GND2, LOW); showdigit(number/10); if (decimal_point&2) {digitalWrite(DP, HIGH);} else {digitalWrite(DP, LOW);}; if (digit_on&2) { digitalWrite(GND3, HIGH); } delay (1); number =number%10; digitalWrite(GND3, LOW); showdigit(number); if (decimal_point&1) {digitalWrite(DP, HIGH);} else {digitalWrite(DP, LOW);}; if (digit_on&1) { digitalWrite(GND4, HIGH); } delay (1); }; void setup() { pinMode(A, OUTPUT); pinMode(B, OUTPUT); pinMode(C, OUTPUT); pinMode(D, OUTPUT); pinMode(E, OUTPUT); pinMode(FF, OUTPUT); pinMode(G, OUTPUT); pinMode(DP, OUTPUT); pinMode(GND1, OUTPUT); pinMode(GND2, OUTPUT); pinMode(GND3, OUTPUT); pinMode(GND4, OUTPUT); pinMode(Button_start, INPUT); digitalWrite(Button_start, HIGH); //pull up resistor pinMode(Button_set, INPUT); digitalWrite(Button_set, HIGH); //pull up resistor pinMode(Buzzer, OUTPUT); pinMode(LED, OUTPUT); TIMSK1=0x01; // enabled global and timer overflow interrupt; TCCR1A = 0x00; // normal operation 148 page (mode0); TCNT1=0x0BDC; TCCR1B = 0x00; // stop hardware timer // loading default timer values Sec = default_Sec ; Min = default_Min ; }; void loop () { //////////// button_start////////// if (!digitalRead(Button_start)&&!b) { if (!set_mode) { if (run) {TCCR1B=0x00; run=0;} else {TCCR1B=0x04; run=1;}} if (set_mode==1) {Min++;} if (set_mode==2) {Sec++;} if (set_mode) {b=25;} else b=100; }; if (!digitalRead(Button_start)&&b==1) { }; if (!b==0) b--; //////////// button_set///////// if (!digitalRead(Button_set)&&!c) { if(!run&&!set_mode) {Min=default_Min; Sec=default_Sec;} if (set_mode>0) set_mode++; if (set_mode==3) {set_mode=0; default_Sec = Sec ; default_Min = Min; } c=100; }; if (!digitalRead(Button_set)&&c==1&&!run) { set_mode=1; c=100; }; if (!c==0) c--; //////////////////////////// if (set_mode) {if (Sec==60) {Sec=00;} if (Min==100) {Min=0;} } else { if (Sec==-1) {Min--;Sec=59;} } //decimal point indication control if (!set_mode) { if (!(Sec%2)) { showdigits (Min*100+Sec,0x0F,0x04); } //0X00 else { showdigits (Min*100+Sec,0x0F,0x00); }; //0000 } else { if (set_mode==1) { showdigits (Min*100+Sec,0x0F,0x0C); //XX00 } else { showdigits (Min*100+Sec,0x0F,0x03); } //00XX } if (run) { // to do while timer is running; e.g. control relay digitalWrite(LED, HIGH); } else digitalWrite(LED, LOW); if ((Min==0)&&(Sec==0)&&run) { run=0; TCCR1B=0x00; //stop timer //// to do after count down is finished e.g. start alarm as in this example alarm=1; d=500; } // Alarm part if (alarm) { if (!(d%100)) { // sound 500/100= 5 times ; tone(Buzzer, 440, 200); } d--; if (d==0) {alarm=0; Sec = default_Sec ; Min = default_Min ; // After alarm is off, timer goes to start } } };2. второй вопрос - как организовать меню? в смысле выбор что кнопками регулируется.
например, при нажатии на кнопку select один раз - мигают разряды секунд (двумя другими кнопками в этот момент можно менять значение), второй раз - разряд минут. при длительном нажатии - старт отсчёта.
а когда отсчёт идёт, кнопка select(при однократном нажатии) позволяет устанавливать ШИМ для светодиодов(в первом разряде "d", в двух других от 0 до 99), при втором нажатии - в первом разряде появится символ "t", в двух других регулировка от 0 до 99.
длинное нажатие - возврат к отображению времени с сохранением настроек ШИМ.
как-то так.