Per chi non volesse scaricare l'allegato posto qui solo lo sketch, non l'ho potuto fare prima perché eccedevo nel numero di caratteri
/*Comando valvole proporzionali con modifica del duty cycle
Questo sketch serve per testare vavole proporzionali che hanno
un range di pressione da 0 a 10 Bar con un comando in
duty cycle che varia dal 4% al 100%.
Nello sketh la pressione massima è limitata a 8 Bar in quanto la pressione
di rete non supera gli 8.6 Bar.
Nello sketch è inserito un controllo sulla differenza di pressione tra set
e feedback, questo serve per evitare che venga impostata una pressione
troppo alta senza che la valvola sia effettivamente collegata. Questo controllo
è bypassabile utilizzando il jumper collegato al pin 9.
La libreria "I2C_graphical_LCD_display.h" è stata scaricata dal
link: http://www.gammon.com.au/forum/?id=10940 .
*/
int sensPres= 0; //sensore di pressione
int barGraph =0; //barra grafica
const int pinConf =10; //pin segnale di conferma valvola
int valConf = 0; //valore del pin 9
int bypass = 9; // pin per bypass protezione comando valvola
int valBy =0; //valore del pin 8
int state =0;
int encoderPin1 = 2; // pin per encoder (aumentare)
int encoderPin2 = 3; // pin per encoder (diminuire)
int ledPin = 17; // pin per uscita led sul risultato della comparazione
// tra set e feedback
volatile int lastEncoded = 0;
volatile long encoderValue = 0;
long lastencoderValue =0;
int lastMSB =0;
int lastLSB =0;
char buf [20];
char buf2 [20];
#include <Wire.h>
#include <SPI.h>
#include <I2C_graphical_LCD_display.h>
I2C_graphical_LCD_display lcd;
// preparazione dell'immagine legata al seganle di conferma della valvola
byte picture [] PROGMEM = {
0xF0, 0x0c, 0x02, 0x01, 0x19, 0x19, 0x01, 0x81,
0x81, 0x01, 0x19, 0x19, 0x01, 0x02, 0x0c, 0xF0,
};
byte picture2 [] PROGMEM = {
0x0F, 0x30, 0x40, 0x80, 0x84, 0x88, 0x90, 0x90,
0x90, 0x90, 0x88, 0x84, 0x80, 0x40, 0x30, 0x0F,
};
byte picture3 [] PROGMEM = {
0x0F, 0xf3, 0xfd, 0xfe, 0xe6, 0xe6, 0xfe, 0x7e,
0x7e, 0xfe, 0xe6, 0xe6, 0xfe, 0xfd, 0xf3, 0x0F,
};
byte picture4 [] PROGMEM = {
0xF0, 0xcf, 0xbf, 0x7f, 0x7b, 0x77, 0x6f, 0x6f,
0x6f, 0x6f, 0x77, 0x7b, 0x7f, 0xbf, 0xcf, 0xF0,
};
void setup(){
lcd.begin ();
lcd.gotoxy(0, 8);
lcd.string("Set :",true); //scritura Set sul display (evidenziata)
lcd.gotoxy(72, 8);
lcd.string("Bar",false); //scrittura Bar sul display
lcd.gotoxy(0, 40);
lcd.string("Feedback :",true); //scrittura Feedback sul display (evidenziata)
lcd.gotoxy(104, 40);
lcd.string("Bar",false); //scrittura Bar sul display
lcd.frameRect (7, 22, 115, 33, 1, 1); // crea un rettangolo sul display
pinMode(encoderPin1, INPUT);
pinMode(encoderPin2, INPUT);
pinMode(11, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(pinConf, INPUT);
pinMode(bypass, INPUT);
digitalWrite(encoderPin1, HIGH);
digitalWrite(encoderPin2, HIGH);
analogWrite(11, LOW);
attachInterrupt (0, updateEncoder, CHANGE); //interrupt sul pin 2, qualsiasi variazione di valore attiverà la funzione
attachInterrupt (1, updateEncoder, CHANGE); //interrupt sul pin 3, qualsiasi variazione di valore attiverà la funzione
}
// comandi per la preparazione dei pin PWM a lavorare con una frequenza
//differente da quella impostata di default
void setPwmFrequency(int pin, int divisor){
byte mode;
if(pin == 5 || pin == 6 || pin == 9 || pin == 10) {
switch(divisor) {
case 1: mode = 0x01; break;
case 8: mode = 0x02; break;
case 64: mode = 0x03; break;
case 256: mode = 0x04; break;
case 1024: mode = 0x05; break;
default: return;
}
if(pin == 5 || pin == 6) {
TCCR0B = TCCR0B & 0b11111000 | mode;
}else{
TCCR1B = TCCR1B & 0b11111000 | mode;
}
} else if(pin == 3 || pin == 11){
switch(divisor) {
case 1: mode = 0x01; break;
case 8: mode = 0x02; break;
case 32: mode = 0x03; break;
case 64: mode = 0x04; break;
case 128: mode = 0x05; break;
case 256: mode = 0x06; break;
case 1024: mode = 0x07; break;
default: return;
}
TCCR2B = TCCR2B & 0b11111000 | mode;
}
}
void loop(){
setPwmFrequency(11,256); //scelta del pin 11 a lavorare nel modo 0x06 (122Hz)
valBy= digitalRead(bypass); //lettura digitale del pin 8
valConf =digitalRead (pinConf); //lettura del segnale di conferma della valvola
if (valConf == LOW){
state = 1- state;
}
if (state == 1){
// ogni volta che il pin rileva un segnale basso cambia l'immagine visualizzata
lcd.clear(112,48,127,63,0);
lcd.gotoxy (112, 48);
lcd.blit (picture, sizeof picture);
lcd.gotoxy (112, 56);
lcd.blit (picture2, sizeof picture);
}else{
lcd.clear(112,48,127,63,0);
lcd.gotoxy (112, 48);
lcd.blit (picture3, sizeof picture);
lcd.gotoxy (112, 56);
lcd.blit (picture4, sizeof picture);
}
if( encoderValue > 190 ) { encoderValue = 190; } //viene dato un valore massimo a encoderValue
if( encoderValue < 10 ) { encoderValue = 10; } //viene dato un valore minimo a encoderValue
if ((encoderValue-sensPres < 35) || (valBy == LOW)){ //controllo della differenza di pressione o del pin 8,
//se una delle due condizioni fosse vera
analogWrite(11, encoderValue); //sul pin 11 si avrebbe un uscita PWM uguale al valore
//di encoderValue
}else{ // altrimenti
encoderValue = 10; //il valore di encodeValue viene portato a 10
}
sensPres= analogRead(1); //viene letto il valore del sensore di pressione
lcd.gotoxy (32, 8);
lcd.clear (32, 8, 63, 15);
float set = float(encoderValue-10); //encoderValue viene trasformato in un valore float
float x = (set*8)/180; //viene eseguito il calcolo per trasformare i bit in valore di pressione
dtostrf(x,2,2, buf); //viene preparata la stringa da visualizzare sul display
lcd.string (buf); //viene visualizzata la stringa sul display
lcd.clear (10,24,sensPres /10+10,29,0xFF); //visualizzazione della barra grafica
lcd.clear (sensPres /10+11,24,113,29,0); //visualizzazione della barra grafica
lcd.gotoxy (64, 40);
lcd.clear (64, 40, 95, 47);
float pressione = float (sensPres); //sensPres viene trasformato in un valore float
pressione= (pressione/4)*10/255; //viene eseguito il calcolo per trasformare i bit in Bar
dtostrf(pressione,2,2, buf2); //viene preparata la stringa da visualizzare sul display
lcd.string (buf2); //viene visualizzata la stringa sul display
if (((encoderValue - (sensPres/4)) >= -10) && ((encoderValue - (sensPres/4)) <= 10)){ //viene eseguita una comparazione, se il set ed il feedback sono all'interno
//di un determinato range
digitalWrite(ledPin, HIGH); //l'uscita del led sarà portata alta
} else { //altrimenti
digitalWrite(ledPin, LOW); //verrà portata bassa
}
delay(100);
}
// lettura del senso di rotazione dell'enoder e generazione del valore di encoderValue
void updateEncoder(){
int MSB = digitalRead(encoderPin1);
int LSB = digitalRead(encoderPin2);
int encoded = (MSB << 1) |LSB;
int sum = (lastEncoded << 2) |encoded;
if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)
encoderValue ++;
if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
encoderValue --;
lastEncoded = encoded;
}