[RISOLTO] Lettura erronea regime di rotazione

Buongiorno a tutti,

ho realizzato un prototipo con Arduino Uno, che legge tramite un DHT22 l'umidità relativa ed in base ad essa imposta il setpoint in termini di RPM di una ventolina a 4 terminali. Il sistema tramite un banale sistema PID insegue tale setpoint.

Il sistema funziona perfettamente ma... (e qui cominciano le stranezze) a patto che il pc portatile con cui carico il software tramite cavo USB rimanga collegato ad Arduino, anche a PC spento ma collegato con l'alimentatore alla rete. Preciso che Arduino è correttamente alimentato da un alimentatore 12 VDC... se io scollego suddetto PC, quando il setpoint si alza verso i 2500 rpm, il regime letto viene letto in modo erroneo verso il basso (2000 - 2100 RPM), di conseguenza il livello del PWM mi si alza verso il valore massimo.

Problema di assenza di filtri? A qualcuno è capitato qualcosa del genere?

Grazie a tutti.

Cioè aumentando la velocità impostata legge una velocità più bassa?

Sì... in pratica se l'umidità relativa aumenta, il software fa aumentare anche il setpoint. Se questo va oltre i circa 2500 rpm, la il valore letto comincia a diminuire verso i 2000 rpm circa. A qual punto il PID spinge al 100% il PWM (ovviamente il sistema legge un valore basso di regime di rotazione e cerca quindi di far si che venga raggiunto il setpoint...)... e ad orecchio sento che in realtà la ventola accelera, il rumore infatti sebbene lieve si fa più acuto.

A questo punto bisogna vedere il programma...

//parte dichiarativa per gestire il display con bus I2C
#include <Wire.h> //necessario per il funzionamento dell'I2C 
#include <LiquidCrystal_I2C.h> //necessario per il funzionamento dell'I2C 
LiquidCrystal_I2C lcd(0x27,20,4); //dichiarazione indirizzo e dimensioni del display

//parte dichiarativa per gestire il sensore DHT22
#include <SimpleDHT.h> //necessario per il funzionamento del DHT22
int pinDHT22 = 7; //pin ingresdo del DHT22
SimpleDHT22 dht22; //creazione oggetto dht22 
float TEMPERATURA;
float UMIDITA;

//parte dichiarativa per gestire PWM ventola e relativo sensore Hall (tachimetrico) 
int PWM = 10; //pin uscita PWM pilotaggio motore
int TACH = 2; //pin ingresso sensore Hall (tachimetrico)
float RPM; // velocità ventola in rpm
volatile int GIRI; // memorizza il numero di giri compiuti
int IMPULSI = 4; //numero di cambiamenti per giro
float SETPOINT;
float ERRORE = 0; 
float ERRORE_PRECEDENTE = 0;
float i, j;
float KP = 0.3; //costante proporzionale
float KI = 0; //costante integrativa
float KD = 0; //costante derivativa
int TEMPO = 1000;
float INTEGRALE = 0;
float DERIVATIVO = 0;

void incremento(){ //funzione chiamata dall'interrupt per il conteggio dei giri ed il calcolo del regime
 GIRI = GIRI+1;
}

void scrittura_dati_display(){
 lcd.home();
 lcd.setCursor(2,0);
 lcd.print(TEMPERATURA);
 lcd.setCursor(14,0);
 lcd.print(UMIDITA); 
 lcd.setCursor(11,1);
 lcd.print((int)SETPOINT);
 lcd.setCursor(11,2);
 lcd.print(i/253*100);
 lcd.print("  ");
 lcd.setCursor(11,3);
 lcd.print((int)RPM);
}

void setup() {
 Serial.begin (9600);
 pinMode(PWM, OUTPUT);
 pinMode(TACH, INPUT);
 attachInterrupt(1, incremento, CHANGE); //interrupt sul pin 2  
 i=100; //valore del PWM iniziale
 j=100;
 analogWrite (PWM,i);
 lcd.init(); //inizializzazione display 
 lcd.backlight(); //accensione retroilluminazione
 lcd.home();
 delay (3000);
 lcd.clear();
 lcd.home();
 lcd.print("T=");
 lcd.print("     ");
 lcd.print("^C  ");
 lcd.print("UR=");
 lcd.print("     ");
 lcd.print("%");
 lcd.setCursor(0,1);
 lcd.print("SETPOINT   ");
 lcd.print("    ");
 lcd.print("  rpm");
 lcd.setCursor(0,2);
 lcd.print("LIV. PWM   ");
 lcd.print("     ");
 lcd.print("   %");
 lcd.setCursor(0,3);
 lcd.print("REGIME     ");
 lcd.print("    ");
 lcd.print("  rpm");
}

void loop() {
 i=j;
 analogWrite (PWM,i);
 GIRI=0; //azzeramento della veriabile giri compiuti
 interrupts(); // attiva l'interrupt per la misurazione del regime
 delay (TEMPO); // tempo di misurazione regime di rotazione
 dht22.read2(pinDHT22, &TEMPERATURA, &UMIDITA, NULL);
 if (UMIDITA <=20){
   SETPOINT = 300;
   }
   else if (UMIDITA >=80){
     SETPOINT = 3000;
   }
     else SETPOINT = 45 * UMIDITA - 600; 
 //con questo if si fa in modo che per UR<=20% regime=300rpm, per UR>=80% regime=3000rpm, nel range intermedio si interpola linearmente tra 300 e 3000 rpm
 scrittura_dati_display();
 noInterrupts(); // disattiva l'interupt
 RPM = ((GIRI * 60)/IMPULSI); // il regime è dato dal numero di giri contati nel tempo di misurazione moltiplicati per il rapporto tra 60 secondi ed il tempo di misurazione
 ERRORE_PRECEDENTE = ERRORE;
 ERRORE = SETPOINT - RPM;
 INTEGRALE = INTEGRALE + ERRORE * TEMPO / 1000; //divisione per 1000 per usare KI espressa in secondi
 DERIVATIVO = (ERRORE - ERRORE_PRECEDENTE) / (TEMPO / 1000);  //divisione per 1000 per usare KD espressa in secondi
 j = i * (1 + KP * (ERRORE / RPM) + KI * INTEGRALE + KD * DERIVATIVO); // aliquota proporzionale del PID
 if (j > 253){
   j = 253;
 }
   else if (j < 25){
     j = 25;
 } // limitazione PWM min e max

}

Ok. Spero di esserci.

>JerryBurner: ti ricordo che in conformità al regolamento, punto 7, devi editare il tuo post qui sopra (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More -> Modify che si trova in basso a destra del tuo post) e racchiudere il codice all'interno dei tag CODE (... sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra).

In pratica, tutto il tuo codice dovrà trovarsi racchiuso tra due tag: [code] _il _tuo_ codice_ [/code] così da non venire interpretato e non dare adito alla formazione di caratteri indesiderati o cattiva formattazione del testo. Grazie.

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non avrai sistemato il codice come richiesto, nessuno ti potrà rispondere, quindi ti consiglio di farlo al più presto. :wink:

>JerryBurner: perfetto, però solo un'altra cosa ... leggi il REGOLAMENTO al punto 16.14 ... che deve esserti sfuggito ... ::slight_smile:

Guglielmo

Fatto... chiedo venia.

Risolto. Si trattava di interferenze. Con un anello di ferrite il problema è rientrato!