Salve,
Innanzitutto vi ringrazio per le tante risposte ricevute. Ora ho parecchio materiale da studiare e da approfondire per poter modificare il codice del progetto.
Tengo a precisare che non ho ancora apportato alcuna modifica al codice, farò le eventuali modifiche nei prossimi giorni poiché al momento sono abbastanza impegnato.
Detto questo,
Ammetto di aver tralasciato il resto del programma perché a mio avviso non è influente nel problema delle oscillazioni e in secondo luogo per rendere più "sintetica" la descrizione del mio problema. In ogni caso ecco il codice completo
#include <SoftwareSerial.h>
//DEBUG ONLY
SoftwareSerial SWSERIAL(8, 0); // RX, TX
const byte tempPIN = A2;
const byte vadcPIN = A3;
const byte pwm_CTL = 1;
const byte PGS = 2;
float tempC;
float tempC_sum;
float VCC;
float VCC_sum;
byte PWM_val;
boolean STATUS_temp;
boolean STATUS_vcc;
const byte Tmin = 35;
const byte Tmax = 45;
const byte PWMmin = 114;
const byte PWMmax = 255;
const byte Vlow = 11;
const byte HIST = 1;
int RFSH = 1000;
//---------------------------------------
// --MAIN SETUP--
//---------------------------------------
void setup() {
//PWM freq.
TCCR1 = (TCCR1 & (0b11110000 | 0b0001));
pinMode(pwm_CTL,OUTPUT);
pinMode(PGS,OUTPUT);
//SERIAL BEGIN (DEBUG ONLY)
SWSERIAL.begin(4800);
}
//---------------------------------------
// --MAIN LOOP--
//---------------------------------------
void loop() {
//TEMPERATURE SENS.
getTEMP();
//FAN PWM / SPEED SET
setPWM();
//VCC SENS.
getVCC();
//POWER GOOD SIGNAL SET (P.G.S)
setPGS();
//ALARM SET
setALM();
//DEBUG
DATAMONITOR();
delay(RFSH);
}
//---------------------------------------
//FUNCTIONS DEFINITION
//---------------------------------------
//TEMPERATURE SENS.
void getTEMP() {
tempC = 0;
tempC_sum = 0;
for (byte i = 0; i < 20; i++){
tempC_sum += ((analogRead(tempPIN)/1023.00) * 498.10);
delay(20);
}
tempC = tempC_sum / 20.00;
}
//FAN PWM
void setPWM() {
//AVVIO CON VENTOLA A VELOCITA' MIN.
if((tempC > 0) && (tempC <= Tmin)){
PWM_val = PWMmin;
}
//VENTOLA MODULATA
if((tempC >= Tmin) && (tempC <= Tmax)){
PWM_val = map(tempC, Tmin, Tmax, PWMmin, PWMmax);
PWM_val = constrain(PWM_val, 0, 255);
}
// TEMP ALARM
// nessuna anomalia
if(tempC < Tmax){
STATUS_temp = false;
}
// TEMP ALARM
//temperatura troppo alta
if((tempC > Tmax) && (tempC > Tmax + HIST)){
PWM_val = 255;
STATUS_temp = true;
}
analogWrite(pwm_CTL,PWM_val);
}
//VCC SENS.
void getVCC() {
VCC = 0;
VCC_sum = 0;
for (byte i = 0; i < 20; i++){
VCC_sum += (((analogRead(vadcPIN)/1023.00) * 4.98) * 13.70);
delay(20);
}
VCC = VCC_sum / 20.00;
}
//POWER GOOD SIGNAL SET (P.G.S)
void setPGS(){
// STATO NORMALE , nessuna anomalia
if(VCC >= Vlow){
STATUS_vcc = false;
digitalWrite(PGS,HIGH);
}
//ALLARME TENSIONE BASSA
if((VCC <= Vlow) && (VCC < Vlow - HIST)){
STATUS_vcc = true;
digitalWrite(PGS,LOW);
}
}
//ALARM SET
void setALM(){
//STATO DI ALLARME
if ((STATUS_vcc == true) || (STATUS_temp == true)){
SWSERIAL.println("ALLARME TEMP.! / ALLARME TENSIONE BASSA!"); //DEBUG
}
//STATO NORMALE , nessuna allarme
if ((STATUS_vcc == false) && (STATUS_temp == false)){
//
}
}
//SERIAL DEBUG
void DATAMONITOR(){
//plot
SWSERIAL.print(tempC);
SWSERIAL.print(",");
SWSERIAL.println(PWM_val);
}
Oltre alla funzione che gestisce il PWM non c’è molto effettivamente ed in particolar modo sono presenti le funzioni che:
- rileva la temp.;
- setta il PWM;
- rileva la tensione di alimentazione;
- setta un pin allo stato alto o basso in base al valore della tensione;
- definisce cosa deve fare il sistema nella condizione di allarme (per ora lo scrive solo nella seriale);
- invia i dati nella seriale per debug;
Ammetto di esserci andato giù pesante con la definizione dei nomi delle variabili e dei pin questa volta
.
Ho dato poi il nome di STATUS_temp/STATUS_vcc perché sono le variabili che definiscono i due allarmi (lo stato appunto) della temperatura e dell’alimentazione, ho quindi ritenuto adatto chiamarli in questo modo per questo motivo.
In seguito comunque cambierò i nomi delle varie variabili e costanti.
Si è vero, ho già provveduto a rimediare l’errore. Grazie per avermelo fatto notare
Grazie per il link, ho visto che in questo caso fa uso anche di un buffer circolare per rendere più efficiente il programma, non ho ben capito come funziona ed è per questo che lo dovrò approfondire anche perché ho visto che in molte soluzioni, che ho trovato in rete, lo si utilizza.
Potrei comunque pensare in prima battuta di implementare un buffer "normale" e poi passare a quello circolare per ottimizzare il codice.
Forse mi sono espresso male
, con shiftare intendevo proprio lo scorrimento dei valori nel buffer proprio per eseguire la media mobile.
In questo caso non è un problema, infatti il sistema deve rispondere a cambiamenti di temperatura abbastanza lenti, non è un problema se si introducono ritardi nel filtraggio del segnale.
Un momento, ma un filtro passa basso non sarebbe utile per “eliminare” una determinata frequenza da un certo segnale?
In questo caso non andrei solo a “smussare” le creste dei picchi delle oscillazione del segnale invece di renderlo più stabile?
Forse potrebbe essere una possibile soluzione quella di implementare un sistema “ibrido” ovvero
una funzione a due stadi, nel quale il primo è costituito dalla media mobile o comunque la media classica di n valori e successivamente, come secondo stadio, un filtro passa basso per migliorare ancora di più la stabilità del segnale.
Anche il datasheet mi sembra che citi la possibilità di aggiungere un filtro al segnale in uscita. Ma come dicevo prima in questo caso non si ottiene uno “smusso” delle creste dei picchi delle oscillazione del segnale invece di renderlo più stabile?
In ogni caso vorrei proseguire con l’approccio software poiché mi piacerebbe approfondire meglio la questione.
Ringrazio ancora una volta tutti per le risposte fornite
Saluti