Select Git revision
FanLoop.ino
Forked from
SistemiEmbedded / 2019-2020
Source project has a limited visibility.
FanLoop.ino 4.33 KiB
//#define SENSORE 4 // sulla board Arduino UNO solo 2,3
#define SENSORE 2
#define ATTUATORE 3
#define RUMORE 50 // soglia minima interrupt
// TODO 'volatile' (vedere se si può creare un esperimento ad-hoc, non banale)
volatile long timestamp=0;
volatile long durata=0;
volatile long durataMedia=0; // media mobile (molto corta, a 2 elementi)
volatile boolean updated=false;
long durataDesiderata=100; // inverso velocità
float duty=.7; // %
int periodpwm=2000; //millis
//boolean fai=true; // per il "monitor"
// TaskScheduler
#include <TaskScheduler.h>
Scheduler runner;
///////////////////////////////////////////////////////
// I soluzione
void onLED(){
digitalWrite(LED_BUILTIN,HIGH);
}
void offLED(){
digitalWrite(LED_BUILTIN,LOW);
}
Task accendiLEDTask(TASK_SECOND, TASK_FOREVER, onLED);
Task spegniLEDTask(TASK_SECOND, TASK_FOREVER, offLED);
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
// II soluzione
boolean acceso=false;
void blink(){
Serial.println("blink");
Serial.println(acceso);
if(acceso) digitalWrite(LED_BUILTIN,LOW);
else digitalWrite(LED_BUILTIN,HIGH);
acceso=!acceso;
//delay(20000); // BLOCCA TASK SCHEDULER!!!
}
Task blinkTask(2*TASK_SECOND, TASK_FOREVER, blink);
///////////////////////////////////////////////////////
boolean dutyOn=false;
Task pwmDeiPoveryTask(periodpwm*(1-duty), TASK_FOREVER, pwmDeiPovery);
void pwmDeiPovery(){
//Task pwmDeiPoveryTask(periodpwm*(1-duty), TASK_FOREVER, [](){
Serial.println("pwm");
Serial.println(dutyOn);
noInterrupts(); // non compila in fn anonima
if(dutyOn){
digitalWrite(ATTUATORE,HIGH);
pwmDeiPoveryTask.setInterval(periodpwm*duty);
}
else{
digitalWrite(ATTUATORE,LOW);
pwmDeiPoveryTask.setInterval(periodpwm*(1-duty));
}
interrupts(); // non compila in fn anonima
//delay(periodpwm*(duty));
//delay(periodpwm*(1.0-duty));
dutyOn=!dutyOn;
duty+=(durataMedia-durataDesiderata)*.001;
if(duty>=1) duty=1.0;
//});
}
void setup() {
Serial.begin(115200);
pinMode(SENSORE,INPUT_PULLUP);
pinMode(ATTUATORE,OUTPUT);
pinMode(LED_BUILTIN,OUTPUT);
// CONFIGURAZIONE
attachInterrupt(
digitalPinToInterrupt(SENSORE),
lap,
RISING);
// Tasks
runner.init();
runner.addTask(blinkTask); // qui usare il task non la callback!
blinkTask.enable();
runner.addTask(pwmDeiPoveryTask); // qui usare il task non la callback!
pwmDeiPoveryTask.enable();
}
void loop() {
runner.execute(); // TaskScheduler
//boolean scattato=digitalRead(SENSORE); // non serve più
if(updated) {
//Serial.print(timestamp);
//Serial.print(F("durata:"));
//Serial.print(durata);
Serial.print(F("media:"));
Serial.print(durataMedia);
Serial.print(F(",desiderata:"));
Serial.print(durataDesiderata);
Serial.print(F(",duty:"));
Serial.println(duty*100);
//Serial.print(",");
//Serial.println(scattato);
updated=false;
}
// a questo punto posso permettermi tranquillamente di "dormire" anche a lungo... o no?
/* TRASFORMARE IN TASK
digitalWrite(ATTUATORE,HIGH);
delay(periodpwm*(duty));
digitalWrite(ATTUATORE,LOW);
delay(periodpwm*(1.0-duty));
*/
/* versione "grande"
LOW 800
HIGH 250 non meno, se no non fa nemmeno in tempo a partire
minima durata circa 20ms, max circa 60
versione "piccola", ad esempio
LOW 500
HIGH 500
*/
}
void lap() {
//noInterrupts(); // non si può invocare da dentro, non ha effetto, va usata fuori per marcare sezioni critiche, qui dentro parte già a interrupt disabilitati
/* versione "monitor" (dei poveri)
if (fai) {
fai=false;
durata=millis()-timestamp;
timestamp=millis();
//scattato=true;
fai=true;
}
*/
//Serial.println("int!"); //da non fare...
long m=millis();
if((m-timestamp)>RUMORE) { // per eliminare gli interrupt spuri
durata=m-timestamp;
durataMedia=(durataMedia+durata)/2;
timestamp=m;
updated=true;
}
//interrupts(); // questa invece si può invocare (e in automatico vengono cmq riabilitati all'uscita), potrebbe avere senso riabilitarli anche prima di uscire se si deve solo fare qualcosa di non critico
}