PWM Pulse
[sketchbook_andrea] / libraries / common / common.cpp
1 /*  Common
2  *
3  *  Oggetti di uso comune
4  *  Autore: Andrea Manni
5  *
6  *  Link: http://git.andreamanni.com/
7  *  Licenza:    GPLv3
8  */
9
10 #include "Arduino.h"
11 #include "common.h"
12
13 #define DEBUG
14
15 //////////////////////
16 // RGB LED
17 // Common anode / cat
18
19 RGBLed::RGBLed(byte pinR, byte pinG, byte pinB) {
20     // Per un common catodo, valore max / min invertiti
21     redPin    = pinR ;
22     greenPin  = pinG ;
23     bluePin   = pinB ;
24     common    = 0 ;
25
26     // Equvalente del Setup() per inizializzare i PIN
27     pinMode(redPin, OUTPUT);
28     pinMode(greenPin, OUTPUT);
29     pinMode(greenPin, OUTPUT);
30 };
31
32 RGBLed::RGBLed(byte pinR, byte pinG, byte pinB, byte com) {
33     // Per un common anode, valore max / min normali
34     redPin    = pinR ;
35     greenPin  = pinG ;
36     bluePin   = pinB ;
37     common    = com ;
38
39     // Equvalente del Setup() per inizializzare i PIN
40     pinMode(redPin, OUTPUT);
41     pinMode(greenPin, OUTPUT);
42     pinMode(greenPin, OUTPUT);
43 };
44
45 void RGBLed::SetColor (byte r, byte g, byte b) {
46 // Imposta il colore di un LED RGB
47   if (common == 0) {
48     analogWrite(redPin,    r);
49     analogWrite(greenPin,  g);
50     analogWrite(bluePin,   b);
51   } else {
52     analogWrite(redPin,   255 - r);
53     analogWrite(greenPin, 255 - g);
54     analogWrite(bluePin,  255 - b);
55   }
56
57
58 // Debug
59 #ifdef DEBUG
60    Serial.print(r);
61    Serial.print("-");
62    Serial.print(g);
63    Serial.print("-");
64    Serial.print(b);
65    while(1);
66 #endif
67
68 };
69
70 void RGBLed::Rand () {
71 // Imposta il colore di un LED RGB
72     analogWrite(redPin, random(0,256));
73     analogWrite(greenPin, random(0,256));
74     analogWrite(bluePin, random(0,256));
75 };
76
77 void RGBLed::Red () {
78 // Accende il LED di rosso
79     SetColor(255,0,0);
80 };
81
82 void RGBLed::Green () {
83 // Accende il LED di verde
84     SetColor(0,255,0);
85 };
86
87 void RGBLed::Blue () {
88 // Accende il LED di blu
89     SetColor(0,0,255);
90 };
91
92 void RGBLed::Magenta () {
93 // Accende il LED di magenta
94     SetColor(255,0,255);
95 };
96
97 void RGBLed::Cyano () {
98 // Accende il LED di Cyano
99     SetColor(0,255,255);
100 };
101
102 void RGBLed::Yellow () {
103 // Accende il LED di giallo
104     SetColor(255,255,0);
105 };
106
107 void RGBLed::White () {
108 // Accende il LED
109     SetColor(255,255,255);
110 };
111
112 void RGBLed::Off () {
113 // Spegne il LED
114     SetColor(0,0,0);
115 };
116
117
118
119 /////////////////////////////////////
120 // Lampeggiatore
121 // Constructor
122 //
123 // Esempi incrementali: https://lab.piffa.net/sketchbook_andrea/multitasking/
124 Lampeggiatore::Lampeggiatore(int pin)
125 {
126     ledPin = pin;
127     pinMode(ledPin, OUTPUT);
128     ledState = LOW;
129     previousMillis = 0;
130     interval = 500;
131 };
132
133 // Una funzione facente parte di una classe prende il nome di "metodo" della stessa:
134 void Lampeggiatore::Invert() {
135     // Inverte il lampeggio
136     ledState = HIGH ;
137 }
138
139 void Lampeggiatore::Blink() {
140     // Illumina il led a 500ms
141
142     if(millis() + shift - previousMillis > interval) {
143
144         // if the LED is off turn it on and vice-versa:
145         ledState = !ledState ; // Inverti il LED
146         // set the LED with the ledState of the variable:
147         digitalWrite(ledPin, ledState);
148         // save the last time you blinked the LED
149         previousMillis += interval;
150     }
151 };
152
153 void Lampeggiatore::Blink(long time, long drift ) {
154     // Illumina il led secondo un intervallo passato come argomento
155
156     shift = drift;
157     if(millis() + shift - previousMillis > time) {
158         // if the LED is off turn it on and vice-versa:
159         ledState = !ledState ; // Inverti il LED
160     // set the LED with the ledState of the variable:
161     digitalWrite(ledPin, ledState);
162         // save the last time you blinked the LED
163         previousMillis += time;
164     }
165 };
166
167 void Lampeggiatore::Blink(long up, long down, long drift ) {
168     // Illumina il ledB precisando ontime e downtime
169
170     shift = drift;
171     if((ledState == HIGH)&& (millis() + shift - previousMillis > up)) {
172         // save the last time you blinked the LED
173         previousMillis += up;
174         ledState = LOW  ;
175     }
176     else if((ledState == LOW)&& (millis() + shift - previousMillis > down)) {
177         previousMillis += down;
178         ledState = HIGH  ;
179     }
180
181     // set the LED with the ledState of the variable:
182     digitalWrite(ledPin, ledState);
183 };
184
185 void Lampeggiatore::High() {
186     // Accende il LED
187     digitalWrite(ledPin, HIGH);
188 }
189
190 void Lampeggiatore::Low() {
191     // Spegne  il LED
192     digitalWrite(ledPin, LOW);
193 }
194
195 void Lampeggiatore::Swap() {
196     // Inverte lo stato del LED
197     digitalWrite(ledPin, !digitalRead(ledPin));
198 }
199
200 /////////////////////////////////////
201 // Pwm
202 // Constructor
203 Pwm::Pwm(int pin)
204 // Gestione del PWM utilizzando millis
205 // per non bloccare il processore con delay
206 // Warning: serialWrite puo' interferire con i tempi.
207 {
208     ledPin = pin;
209     pinMode(ledPin, OUTPUT);
210     previousMillis = 0;
211     byte brightness = 0 ;
212     increment = 1;
213     int step = 0;              // Pulse: stato del loop PWM
214     int interval = 1;
215 };
216
217 void Pwm::Up(long speed, long drift) {
218     // Aumenta linearmente la luminosita' usanndo millis()
219     // quindi senza bloccare il processore
220     // Viene usato un float, in alternativa un coseno
221
222     if (millis() != previousMillis)  { // si potrebbe togliere
223         shift = drift;
224         brightness = 255.0 /(float)speed * (millis() + shift);
225         analogWrite(ledPin, brightness);
226
227         previousMillis = millis();
228     };
229 }
230
231 void Pwm::lUp(long speed, long drift) {
232     // Aumenta usanndo millis() con correzione luminosita' LED
233     // quindi senza bloccare il processore
234     // Viene usato un float, in alternativa un coseno
235
236     if (millis() != previousMillis)  { // si potrebbe togliere
237         shift = drift;
238         brightness = 255.0 /(float)speed * (millis() + shift);
239         analogWrite(ledPin, lum(brightness));
240
241         previousMillis = millis();
242     };
243 }
244
245 void Pwm::Down(long speed, long drift) {
246     // Riduce linearmente la luminosita' usanndo millis()
247     // quindi senza bloccare il processore
248
249     if (millis() != previousMillis)  {
250         shift = drift;
251         brightness = 255 - 255.0 /(float)speed * (millis() + shift) ;
252         analogWrite(ledPin, brightness);
253
254         previousMillis = millis();
255     };
256 }
257
258 void Pwm::lDown(long speed, long drift) {
259     // Riduce  usanndo millis() con correzione della luminosita'
260     // quindi senza bloccare il processore
261
262     if (millis() != previousMillis)  {
263         shift = drift;
264         brightness = 255 - 255.0 /(float)speed * (millis() + shift) ;
265         analogWrite(ledPin, lum(brightness));
266
267         previousMillis = millis();
268     };
269 }
270
271 void Pwm::UD(long speed, long drift ) {
272     // Aumenta e riduce in sequenza la luminosita' usanndo millis()
273     shift = drift;
274     brightness = 128 + 127 * cos(2 * PI / speed * (millis() + shift));
275     analogWrite(ledPin, brightness);
276 }
277
278 void Pwm::Set(byte brightness) {
279     // Imposta il valore del PWM
280     analogWrite(ledPin, brightness);
281 }
282
283
284 void Pwm::Pulse(int interval, int pausa) {
285     // PWM up/down + un ciclo di pausa
286     // Interval e' la pausa tra uno step di 255 e l'altro
287
288     if ((millis() - previousMillis) >= interval) {
289       previousMillis = millis();
290       if (step < 256) { //UP
291         analogWrite(ledPin, lum(step));
292         step++ ;
293       } else if (step < 512 ) { // Down
294         analogWrite(ledPin, lum(511 - step));
295         step++ ;
296       } else if (step < 512 + pausa ){ // Pausa
297         analogWrite(ledPin, lum(0));
298         step++ ;
299       } else if (step >= 512 + pausa) { // Reset 
300       step = 0 ;
301       }
302     }
303
304
305 void Pwm::RandomPulse(int min , int max, int pausa ) {
306     // PWM up/down + un ciclo di pausa
307     // L'intervallo e' random a ogni nuovo ciclo, 
308     // compreso tra un min - max passato come argomento
309
310     if ((millis() - previousMillis) >= interval) {
311       previousMillis = millis();
312       if (step < 256) { //UP
313         analogWrite(ledPin, lum(step));
314         step++ ;
315       } else if (step < 512 ) { // Down
316         analogWrite(ledPin, lum(511 - step));
317         step++ ;
318       } else if (step < (512 + pausa )){ // Pausa
319         analogWrite(ledPin, lum(0));
320         step++ ;
321       } else if ((step >= 512 + pausa )) {
322       step = 0 ;
323       interval = random(min,max);
324       }
325     }
326
327
328 void Pwm::lSet(byte brightness) {
329     // Imposta il valore del PWM con correzione luminosita' LED
330     analogWrite(ledPin, lum(brightness));
331 }
332
333
334 /////////////////////////////////////
335 // Sequenza
336 // Constructor
337 Sequenza::Sequenza (byte passed[], byte dim) {
338     ledPins = passed ;
339     size = dim ;
340     for (int thisPin = 0; thisPin < size; thisPin++) {
341         pinMode(ledPins[thisPin], OUTPUT);
342     }
343     previousMillis = millis();
344     digitalWrite(ledPins[0], HIGH);
345 }
346
347 void Sequenza::Update(long value) {
348     // Incrementa dal primo all'ultimo valore dell'array
349     interval = value;
350     if (millis() - previousMillis >= interval) {
351         previousMillis = millis();
352
353         if ( i < size - 1 ) {
354             // Spegni precedente led
355             digitalWrite(ledPins[i], LOW);
356
357             // Accendi successivo led
358             digitalWrite(ledPins[++i], HIGH);
359         }
360
361         else if  (i == size - 1 )   {
362             // Ultimo caso
363             i = 0;
364             previousMillis = millis();
365             digitalWrite(ledPins[i], HIGH);
366             digitalWrite(ledPins[ size - 1 ], LOW);
367         }
368     }
369 }
370
371
372 void Sequenza::Reverse(long value) {
373     interval = value;
374     if (millis() - previousMillis >= interval) {
375         previousMillis = millis();
376
377         if  (i == 0)   { // Entry point, ultimo LED
378             digitalWrite(ledPins[size -1],HIGH);
379             digitalWrite(ledPins[0],LOW);
380             i = size -1 ;
381         }
382         else {
383             digitalWrite(ledPins[i],LOW);
384             digitalWrite(ledPins[--i],HIGH);
385         }
386     }
387 }
388
389 void Sequenza::UD(long value) {
390     interval = value;
391     if (millis() - previousMillis >= interval) {
392         previousMillis = millis();
393         // Spegni precedente led
394         digitalWrite(ledPins[i], LOW);
395         i = i + inc ;
396         // Accendi successivo led
397         digitalWrite(ledPins[i], HIGH);
398
399         if (i == 0 || i == size -1) {
400             inc = -inc ;
401         }
402     }
403 }
404
405
406 //////////////////
407 // Funzioni
408
409
410 void brilla(byte pin, int velocita ) { // Defalt value di velocita' solo nell'Header
411     // Accende e spegne il LED accetando un argomento
412     // per impostare la velocita'.
413
414     pinMode(pin, OUTPUT);
415     // sequenze di istruzione: accendere e spegnere il LED
416     digitalWrite(pin, HIGH);   // turn the LED on (HIGH is the voltage level)
417     delay(velocita);               // wait for a second
418     digitalWrite(pin, LOW);    // turn the LED off by making the voltage LOW
419     delay(velocita);               // wait for a second
420 };
421
422
423 byte lum(byte val) {
424     // Mappatura dell'intervallo 0-255 con correzione di luminosita.
425     // storata in SRAM
426     return pgm_read_byte_near(BCORRECT + val);
427 };
428
429
430 int calibraTrim(int pin, const byte ledPin) {
431     /* START Calibrazione TRIM canale:
432        Lettura di 10 smaple
433        calcolo del valore medio esclusi gli 0
434
435        I canali come alettoni / elevatore possono avere un TRIM
436        (generalmente il throttle non ha un TRIM impostato),
437        questa funzione nel setup serve per trovare il punto medio
438        all'avvio dello sketch.
439      */
440     pinMode(ledPin,OUTPUT);
441     byte a              = 0;
442     int servoValue      = 0;
443     int middle = 0; 
444 #ifdef DEBUG
445     Serial.println(">> Calibrazione: ");
446 #endif 
447     while (a < 10) {
448         if (millis() > 10000) {
449 #ifdef DEBUG
450             Serial.println(">> Calibrazione annullata a causa di assenza di seganle. \nAssicurarsi di accendere radio e ricevente \ne ripetere la procedura.");
451 #endif 
452             middle = 15000; // Return value is divided by 10
453             break;
454         };
455         servoValue = pulseIn(pin, HIGH, 25000);
456         if (servoValue != 0 && servoValue > 950 && servoValue <2000)  {
457             middle = middle + servoValue ;
458             a++ ;
459 #ifdef DEBUG
460             Serial.print(servoValue);
461             Serial.print(": ");
462             Serial.println(middle / a);
463 #endif 
464             digitalWrite(ledPin, !digitalRead(ledPin));
465             delay(50);
466         }
467     }
468 #ifdef DEBUG
469     Serial.print(">> Fine Calibrazione, media: ");
470     Serial.println(middle / 10 + 10);
471     Serial.flush() ;
472 #endif 
473     return(middle / 10 ) ;
474 // END calibrazione
475 };
476