interactivly change LDR samping size and noise rejection
[Arduino] / Desk_LED_dimmer / Desk_LED_dimmer.ino
1 /*
2     Over complicated desk LED dimmer
3     2016-01-10 Dobrica Pavlinusic <dpavlin@rot13.org>
4 */
5
6 #include <EEPROM.h>
7
8 const int led_pin = 13;
9 const int buzzer_pin = 4;
10 const int mosfet_pins[] = { 9, 10, 6 }; // PWM pins: 3,5,6,9,10,11
11 const int ldr_pin = A3; // LDR +5 -- A3 -[10K]- GND
12 const int pir_pin = A2;
13
14
15 #define TOUCHPAD 1 // set this to 0 if debugging without touchpad
16
17 int LDR_SIZE = 1;       // 1 number of LDR reading to average
18 int LDR_NOISE = 6;      // 6 calibrate LDR noise level 
19 int LDR_CHANGE = 1;     // do we report LDR changes?
20
21 #define PIR_TIMEOUT 10 // s
22
23 #if TOUCHPAD
24 #include <ps2.h>
25 PS2 mouse(8, 7); // PS2 synaptics clock, data
26 #endif
27 #define TP_LANDSCAPE 0
28
29
30 int mosfet_pwm[] = { 1, 1, 1 }; // initial and current state of mosfet pwm
31
32 void MOSFET_PWM(int i, int pwm) {
33         analogWrite(mosfet_pins[i], pwm);
34         Serial.print("MOSFET=");
35         Serial.print(i);
36         Serial.print(":");
37         Serial.println(pwm);
38 }
39
40
41 void setup() {
42   Serial.begin(115200);
43   Serial.println("setup");
44
45   pinMode(led_pin, OUTPUT);
46   digitalWrite(led_pin, HIGH); // signal reset
47
48   pinMode(buzzer_pin, OUTPUT);
49
50   for(int i=0; i<=2; i++) {
51     pinMode(mosfet_pins[i], OUTPUT);
52     analogWrite(mosfet_pins[i], 0);
53   }
54
55   pinMode(ldr_pin, INPUT);
56
57   pinMode(pir_pin, INPUT);
58
59 #if TOUCHPAD
60   Serial.println("Synaptics touchpad init");
61
62   mouse.write(0xff);  // reset
63   mouse.read();  // ack byte
64   mouse.read();  // blank */
65
66   mouse.read();  // blank */
67   mouse.write(0xf0);  // remote mode -- send motion data only on $EB (read data) command
68   mouse.read();  // ack
69   delayMicroseconds(100);
70   mouse.write(0xe8); // set resolution
71   mouse.read();  // ack byte
72   mouse.write(0x03); // rr  ( rr * 64  +  ss * 16  +  tt * 4  +  uu  == modebyte )
73   mouse.read();  // ack byte
74   mouse.write(0xe8);
75   mouse.read();  // ack byte
76   mouse.write(0x00); // ss
77   mouse.read();  // ack byte
78   mouse.write(0xe8);
79   mouse.read();  // ack byte
80   mouse.write(0x01); // tt
81   mouse.read();  // ack byte
82   mouse.write(0xe8);
83   mouse.read();  // ack byte
84   mouse.write(0x00); // uu
85   mouse.read();  // ack byte
86   mouse.write(0xf3); // set samplerate 20 (stores mode) 
87   mouse.read();  // ack byte
88   mouse.write(0x14);
89   mouse.read();  // ack byte
90   delayMicroseconds(100); 
91
92 #endif
93
94   Serial.print("Commands: b - beep, qwe/asd/zxc - MOSFETs, hjkl - single step fade, ui/op/[/] - LDR size-+/noise-+/read/changes, P - PIR\nLDR = ");
95   int ldr = analogRead(ldr_pin);
96   Serial.println(ldr);
97
98   for(int i=0; i<=2; i++) {
99     analogWrite(mosfet_pins[i], 1);
100     delay(100);
101     int ldr = analogRead(ldr_pin);
102     Serial.println(ldr);
103     analogWrite(mosfet_pins[i], 0);
104   }
105
106   // recall startup values
107   for(int i=0; i<=2; i++) {
108     int pwm = EEPROM.read(i);
109     mosfet_pwm[i] = pwm;
110     analogWrite(mosfet_pins[i], pwm);
111   }
112
113   digitalWrite(led_pin, LOW);
114
115 }
116
117 void mosfet(int nr, int value) {
118   int pwm = mosfet_pwm[nr];
119   if ( pwm == value ) {
120     Serial.println("ignored");
121     return;
122   }
123   int sleep = 200 / abs(pwm - value); // changes bigger than 200 (on/off) will be instant
124   int step = pwm < value ? 1 : -1;
125   for(int i=pwm + step; i != value; i += step) {
126     //MOSFET_PWM(nr, i);
127     analogWrite(mosfet_pins[nr], i);
128     delay(sleep);
129   }
130   MOSFET_PWM(nr, value);
131   mosfet_pwm[nr] = value;
132 }
133
134
135 unsigned int last_cx = 0;
136 unsigned int last_cy = 0;         
137
138 int last_ldr = 0;
139 static int ldr_sum = 0;
140 static int ldr_count = 0;
141
142 int last_pir = 0;
143 long int pir_millis = millis();
144
145 int vi_nr = 0; // mosfet to fade with vi binadings
146
147
148 void loop() {
149
150 #if TOUCHPAD
151   byte mstat1;
152   byte mstat2;
153   byte mxy;
154   byte mx;                    //x coordinate
155   byte my;                    //y coordinate
156   byte mz;                    //z pressure value
157
158   unsigned int cx,cy;
159
160   mouse.write(0xeb); // read data
161   mouse.read();
162   
163   mstat1 = mouse.read();
164   mxy = mouse.read();
165   mz = mouse.read();
166   mstat2 = mouse.read();
167   mx = mouse.read();
168   my = mouse.read();
169
170
171   // collect the bits for x and y
172   cx = (((mstat2 & 0x10) << 8) | ((mxy & 0x0F) << 8) | mx ); // 1100-5800
173   cy = (((mstat2 & 0x20) << 7) | ((mxy & 0xF0) << 4) | my ); // 800-5000
174
175   if ( last_cx != cx || last_cy != cy ) {
176     last_cx = cx;
177     last_cy = cy;
178     Serial.print("X=");
179     Serial.print(cx, DEC);
180     Serial.print("\tY=");
181     Serial.print(cy, DEC);
182     Serial.print("\tZ=");
183     Serial.print(mz, DEC);
184     if ( cx > 1100 && cy > 800 ) {
185 #if TP_LANDSCAPE
186       int nr  = ( cx - 1100 ) / (( 5800 - 1100 ) / 3);
187       int pwm = ( cy - 800  ) / (( 5000 - 800  ) / 255);
188 #else
189       int pwm = ( cx - 1100 ) / (( 5800 - 1100 ) / 255);
190       int nr  = ( cy - 800  ) / (( 5000 - 800  ) / 4);
191       if ( nr > 2 ) nr -= 1;  // 0 [ 1 2 ] 3 -> 0 1 2
192 #endif
193       pwm -= 1; // allow off
194       Serial.print("\tmosfet = ");
195       Serial.print(nr);
196       Serial.print("\tpwm = ");
197       Serial.print(pwm);
198       if ( nr >= 0 && nr <= 2 && pwm >= 0 && pwm <= 255 ) {
199         Serial.println("\tOK");
200         MOSFET_PWM(nr, pwm);
201         mosfet_pwm[nr] = pwm;
202       } else {
203         Serial.println("\tIGNORED");
204       }
205     }
206   }
207 #endif
208
209
210   int ldr = analogRead(ldr_pin);
211   ldr_sum += ldr;
212   ldr_count++;
213   if ( ldr_count > LDR_SIZE ) {
214     ldr = ldr_sum / ldr_count;
215     ldr_count = 0;
216     ldr_sum = 0;
217
218     if ( abs(ldr-last_ldr) > LDR_NOISE && LDR_CHANGE ) {  
219       Serial.print("LDR = ");
220       Serial.println(ldr);
221       last_ldr = ( last_ldr + ldr ) / 2;
222     }
223   }
224
225
226   int pir = digitalRead(pir_pin);
227   if ( pir != last_pir) {
228     last_pir = pir;
229     Serial.print("PIR = ");
230     Serial.println(pir);
231   }
232
233   long int ms = millis();
234   if ( pir == 0 ) {
235     if (pir_millis > 0 && ms - pir_millis > PIR_TIMEOUT * 1000 ) {
236       Serial.println("PIR timeout, fade-out");
237       pir_millis = -1; // mark that we are in timeout
238       for(int i=0; i<=2; i++) {
239         MOSFET_PWM(i, 0);
240       }
241     }
242   } else {
243     if (pir_millis < 0) {
244       Serial.println("PIR fade-in after timeout");
245       for(int i=0; i<=2; i++) {
246         MOSFET_PWM(i, mosfet_pwm[i]);
247       }
248     }
249     pir_millis = ms;
250   }
251
252
253   if (Serial.available()) {
254     digitalWrite(led_pin, HIGH);
255     int in = Serial.read();
256     switch (in) {
257       case 'b':
258         tone(buzzer_pin, 1800, 100);
259         delay(200);
260         tone(buzzer_pin, 2200, 100);
261         delay(500);
262         break;
263       case 'q': mosfet(0, 255); break;
264       case 'a': mosfet(0, 127); break;
265       case 'z': mosfet(0, 0); break;
266       case 'w': mosfet(1, 255); break;
267       case 's': mosfet(1, 127); break;
268       case 'x': mosfet(1, 0); break;
269       case 'e': mosfet(2, 255); break;
270       case 'd': mosfet(2, 127); break;
271       case 'c': mosfet(2, 0); break;
272
273       // vi mappings
274       case 'h': vi_nr = ( vi_nr - 1 + 3 ) % 3; Serial.println(vi_nr); break;
275       case 'j': mosfet(vi_nr, (mosfet_pwm[vi_nr]-1+255)%255 ); break;
276       case 'k': mosfet(vi_nr, (mosfet_pwm[vi_nr]+1)%255 ); break;
277       case 'l': vi_nr = ( vi_nr + 1 ) % 3; Serial.println(vi_nr); break;
278
279       // LDR
280       case 'u': LDR_SIZE -= 1; Serial.println(LDR_SIZE); break;
281       case 'i': LDR_SIZE += 1; Serial.println(LDR_SIZE); break;
282       case 'o': LDR_NOISE -= 1; Serial.println(LDR_NOISE); break;
283       case 'p': LDR_NOISE += 1; Serial.println(LDR_NOISE); break;
284       case '[': Serial.println(ldr); break;
285       case ']': LDR_CHANGE = ! LDR_CHANGE; break;
286
287       case 'P': Serial.println(pir); break;
288
289       case 'S':
290         for(int i=0; i<3; i++) EEPROM.write(i, mosfet_pwm[i]);
291         Serial.println("EEPROM store brightness");
292         break;
293
294       /*
295               m1 = (m1 + 10) % 255;
296               analogWrite(mosfet1_pin, m1);
297               Serial.print("MOSFET 1 = ");
298               Serial.println(m1);
299               break;
300             case 'a':
301               m1 = (m1 - 10) % 255;
302               analogWrite(mosfet1_pin, m1);
303               Serial.print("MOSFET 1 = ");
304               Serial.println(m1);
305               break;
306       */
307       default:
308         Serial.print("unknown command ");
309         Serial.println(in);
310     }
311     digitalWrite(led_pin, LOW);
312   }
313
314 }