Pra facilitar a inclusão de barras de progresso em displays LCD, criei uma classe chamada LCDProgressBar, que com poucas linhas é possível incluir uma ou mais barras de progresso, que podem, inclusive, serem mostradas ao mesmo tempo.
A ideia foi criar uma barra customizável, onde o programador indica a posição (linha e coluna) no display e o tamanho que a barra de progresso terá.
A Classe possui um método chamado setPerc(), o qual irá receber um valor que deverá estar entre 0 e 100. A barra será gerada de acordo com o valor passado como parâmetro, sendo que em 0 a barra não aparece e em 100 ela é completamente preenchida.
Vídeo da primeira versão:
vídeo da segunda versão:
código da primeira versão:
/* Fabiano A. Arndt - 2015 www.youtube.com/user/fabianoallex www.facebook.com/dicasarduino fabianoallex@gmail.com */ #include <LiquidCrystal.h> /************************************************************************************************************* *******************************CLASSE LCD PROGRESS BAR******************************************************** **************************************************************************************************************/ byte c1[8] = {B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000}; byte c2[8] = {B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000}; byte c3[8] = {B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100}; byte c4[8] = {B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110}; byte c5[8] = {B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111}; class LCDProgressBar { private: LiquidCrystal * _lcd; int _row; int _col; int _len; int _perc; /*0..100*/ public: void createChars() { _lcd->createChar(0, c1); _lcd->createChar(1, c2); _lcd->createChar(2, c3); _lcd->createChar(3, c4); _lcd->createChar(4, c5); } LCDProgressBar(LiquidCrystal * lcd, int row, int col, int len) { _lcd = lcd; _row = row; _col = col; _len = len; } void setPerc(int perc){ _perc = perc; if (perc > 100) { _perc = 100; } if (perc < 000) { _perc = 000; } _lcd->setCursor(_col, _row); for (int i=0; i<(_len);i++) { _lcd->print(" "); } _lcd->setCursor(_col, _row); int bars = 5 * _len * _perc / 100; int div = bars / 5; //divisao int resto = bars % 5; //resto for (int i=0; i<div; i++) { _lcd->write((byte)4); } //pinta todo o quadro if (resto > 0 ) { _lcd->write((byte)(resto-1)); } //pinta o quadro com a quantidade de barras proporcional } }; /************************************************************************************************************* *******************************FIM CLASSE LCD PROGRESS BAR**************************************************** **************************************************************************************************************/ LiquidCrystal lcd(12, 11, 5, 4, 3, 2); LCDProgressBar lcdBar1(&lcd, 0, 8, 8); //inclui uma barra no lcd, primeira linha, coluna 8. tamanho 8 LCDProgressBar lcdBar2(&lcd, 1, 12, 4); //inclui outra barra no lcd, segunda linha, coluna 12. tamanho 4 void setup() { Serial.begin(9600); lcdBar1.createChars(); pinMode(44, OUTPUT); analogWrite(44, 255/6); //utilizado para aumentar o contraste lcd.begin(16, 2); } int i = 0; int perc; void loop() { lcd.setCursor(0, 0); int value = i % 100; perc = value/100.0 * 100; if (value < 010) {lcd.print("00");} else { if (value < 100) {lcd.print("0");} } lcd.print(value); lcd.print("/"); lcd.print(100); lcdBar1.setPerc(perc); //atualização da primeira barra de progresso lcd.setCursor(0, 1); value = (i++) % 200; perc = value/200.0 * 100; if (value <= 010) {lcd.print("00");} else { if (value < 100) {lcd.print("0");} } lcd.print(value); lcd.print("/"); lcd.print(200); lcdBar2.setPerc(perc); //atualização da segunda barra de progresso delay(100); }
Código 01 da segunda versão :
/* Fabiano A. Arndt - 2015 www.youtube.com/user/fabianoallex www.facebook.com/dicasarduino fabianoallex@gmail.com */ #include <LiquidCrystal.h> /************************************************************************************************************* *******************************CLASSE LCD PROGRESS BAR******************************************************** **************************************************************************************************************/ byte c1[8] = {B00000, B00000, B00000, B00000, B00000, B00000, B00000, B11111}; byte c2[8] = {B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111}; byte c3[8] = {B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111}; byte c4[8] = {B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111}; byte c5[8] = {B00000, B00000, B00000, B11111, B11111, B11111, B11111, B11111}; byte c6[8] = {B00000, B00000, B11111, B11111, B11111, B11111, B11111, B11111}; byte c7[8] = {B00000, B11111, B11111, B11111, B11111, B11111, B11111, B11111}; byte c8[8] = {B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111}; class LCDProgressBar { private: LiquidCrystal * _lcd; int _row; int _col; int _len; int _perc; /*0..100*/ public: void createChars() { _lcd->createChar(0, c1); _lcd->createChar(1, c2); _lcd->createChar(2, c3); _lcd->createChar(3, c4); _lcd->createChar(4, c5); _lcd->createChar(5, c6); _lcd->createChar(6, c7); _lcd->createChar(7, c8); } LCDProgressBar(LiquidCrystal * lcd, int row, int col, int len) { _lcd = lcd; _row = row; _col = col; _len = len; } void setPerc(int perc){ _perc = perc; if (perc > 100) { _perc = 100; } if (perc < 000) { _perc = 000; } _lcd->setCursor(_col, _row); for (int i=0; i<(_len);i++) { _lcd->print(" "); } _lcd->setCursor(_col, _row); int bars = (8+1) * _len * _perc / 100; int div = bars / 8; //divisao int resto = bars % 8; //resto for (int i=0; i<div; i++) { _lcd->write((byte)7); } //pinta todo o quadro if (resto > 0 ) { _lcd->write((byte)(resto-1)); } //pinta o quadro com a quantidade de barras proporcional } }; /************************************************************************************************************* *******************************FIM CLASSE LCD PROGRESS BAR**************************************************** **************************************************************************************************************/ LiquidCrystal lcd(12, 11, 5, 4, 3, 2); LCDProgressBar lcdBar1(&lcd, 0, 8, 8); //inclui uma barra no lcd, primeira linha, coluna 8. tamanho 8 LCDProgressBar lcdBar2(&lcd, 1, 12, 4); //inclui outra barra no lcd, segunda linha, coluna 12. tamanho 4 void setup() { Serial.begin(9600); lcdBar1.createChars(); pinMode(44, OUTPUT); analogWrite(44, 255/6); //utilizado para aumentar o contraste lcd.begin(16, 2); } int i = 0; int perc; void loop() { lcd.setCursor(0, 0); int value = i % 100; perc = value/100.0 * 100; if (value < 010) {lcd.print("00");} else { if (value < 100) {lcd.print("0");} } lcd.print(value); lcd.print("/"); lcd.print(100); lcdBar1.setPerc(perc); //atualização da primeira barra de progresso lcd.setCursor(0, 1); value = (i++) % 200; perc = value/200.0 * 100; if (value <= 010) {lcd.print("00");} else { if (value < 100) {lcd.print("0");} } lcd.print(value); lcd.print("/"); lcd.print(200); lcdBar2.setPerc(perc); //atualização da segunda barra de progresso delay(100); }
Código 02 da segunda versão :
/* Fabiano A. Arndt - 2015 www.youtube.com/user/fabianoallex www.facebook.com/dicasarduino fabianoallex@gmail.com */ #include <LiquidCrystal.h> /************************************************************************************************************* *******************************CLASSE LCD PROGRESS BAR******************************************************** **************************************************************************************************************/ byte c1[8] = {B00000, B00000, B00000, B00000, B00000, B00000, B00000, B11111}; byte c2[8] = {B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111}; byte c3[8] = {B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111}; byte c4[8] = {B00000, B00000, B00000, B00000, B11111, B11111, B11111, B11111}; byte c5[8] = {B00000, B00000, B00000, B11111, B11111, B11111, B11111, B11111}; byte c6[8] = {B00000, B00000, B11111, B11111, B11111, B11111, B11111, B11111}; byte c7[8] = {B00000, B11111, B11111, B11111, B11111, B11111, B11111, B11111}; byte c8[8] = {B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111}; class LCDProgressBar { private: LiquidCrystal * _lcd; int _row; int _col; int _len; int _perc; /*0..100*/ public: void createChars() { _lcd->createChar(0, c1); _lcd->createChar(1, c2); _lcd->createChar(2, c3); _lcd->createChar(3, c4); _lcd->createChar(4, c5); _lcd->createChar(5, c6); _lcd->createChar(6, c7); _lcd->createChar(7, c8); } LCDProgressBar(LiquidCrystal * lcd, int row, int col, int len) { _lcd = lcd; _row = row; _col = col; _len = len; } void setPerc(int perc){ _perc = perc; if (perc > 100) { _perc = 100; } if (perc < 000) { _perc = 000; } _lcd->setCursor(_col, _row); for (int i=0; i<(_len);i++) { _lcd->print(" "); } _lcd->setCursor(_col, _row); int bars = (8+1) * _len * _perc / 100.0; int div = bars / 8.0; //divisao int resto = bars % 8; //resto Serial.println(div); for (int i=0; i<div; i++) { _lcd->write((byte)7); } //pinta todo o quadro if (resto > 0 ) { _lcd->write((byte)(resto-1)); } //pinta o quadro com a quantidade de barras proporcional } }; /************************************************************************************************************* *******************************FIM CLASSE LCD PROGRESS BAR**************************************************** **************************************************************************************************************/ LiquidCrystal lcd(12, 11, 5, 4, 3, 2); LCDProgressBar lcdBar1(&lcd, 1, 0, 1); //inclui uma barra no lcd, segunda linha, coluna 0. tamanho 1 LCDProgressBar lcdBar2(&lcd, 1, 2, 1); //inclui outra barra no lcd, segunda linha, coluna 2. tamanho 1 LCDProgressBar lcdBar3(&lcd, 1, 4, 1); //inclui outra barra no lcd, segunda linha, coluna 4. tamanho 1 LCDProgressBar lcdBar4(&lcd, 1, 6, 1); //inclui outra barra no lcd, segunda linha, coluna 6. tamanho 1 LCDProgressBar lcdBar5(&lcd, 1, 8, 1); //inclui outra barra no lcd, segunda linha, coluna 8. tamanho 1 LCDProgressBar lcdBar6(&lcd, 1, 10, 1); //inclui outra barra no lcd, segunda linha, coluna 10. tamanho 1 LCDProgressBar lcdBar7(&lcd, 1, 12, 1); //inclui outra barra no lcd, segunda linha, coluna 12. tamanho 1 LCDProgressBar lcdBar8(&lcd, 1, 14, 1); //inclui outra barra no lcd, segunda linha, coluna 14. tamanho 1 void setup() { Serial.begin(9600); lcdBar1.createChars(); pinMode(44, OUTPUT); analogWrite(44, 255/6); //utilizado para aumentar o contraste lcd.begin(16, 2); } unsigned int i = 0; int perc; void loop() { lcd.setCursor(0, 0); lcd.print("1 2 3 4 5 6 7 8"); lcd.setCursor(0, 1); int value = i % 100; perc = value/100.0 * 100; lcdBar1.setPerc(perc); //atualização da primeira barra de progresso value = i % 10; perc = value/10.0 * 100; lcdBar2.setPerc(perc); //atualização da segunda barra de progresso value = i % 50; perc = value/50.0 * 100; lcdBar3.setPerc(perc); //atualização da terceira barra de progresso value = i % 300; perc = value/300.0 * 100; lcdBar4.setPerc(perc); //atualização da quarta barra de progresso value = i % 240; perc = value/240.0 * 100; lcdBar5.setPerc(perc); //atualização da quinta barra de progresso value = i % 140; perc = value/140.0 * 100; lcdBar6.setPerc(perc); //atualização da sexta barra de progresso value = i % 30; perc = value/30.0 * 100; lcdBar7.setPerc(perc); //atualização da setima barra de progresso value = (i++) % 180; perc = value/180.0 * 100; lcdBar8.setPerc(perc); //atualização da oitava barra de progresso delay(100); }
Atualizado 25/05/2016
Em um artigo sobre Rotary Encoder fiz alguns exemplos utilizando as barras de progresso e fiz algumas modificações em uma das barras mostradas aqui.
Veja o artigo aqui: http://fabianoallex.blogspot.com.br/2016/05/arduino-rotary-encoder.html
Vídeo:
Atualizado 27/05/2016
Implementei outra versão das barras de progresso, ela segue o padrão utilizado para mostrar o volume de um som ou a intensidade de um sinal sem fio.
Há duas possibilidades de uso, com altura=1 ou altura=2, que indicará se a barra ocupará uma ou duas linhas do display.
Vídeo:
Código-fonte:
/* Fabiano A. Arndt - 2016 www.youtube.com/user/fabianoallex www.facebook.com/dicasarduino fabianoallex@gmail.com */ #include <LiquidCrystal.h> /************************************************************************************************************* ************************************CLASSE ROTARY ENCODER***************************************************** *************************************************************************************************************/ #define ROTARY_NO_BUTTON 255 struct RotaryEncoderLimits{ int min; int max; }; class RotaryEncoder { private: byte _pin_clk; byte _pin_dt; byte _pin_sw; volatile byte _num_results; volatile int _result; volatile int * _results; byte _index_result; RotaryEncoderLimits * _limits; boolean _a; boolean _b; public: RotaryEncoder(byte pin_clk, byte pin_dt, byte pin_sw = ROTARY_NO_BUTTON, byte num_results=1, RotaryEncoderLimits * limits=0){ //parametro do botao opcional _pin_clk = pin_clk; _pin_dt = pin_dt; _pin_sw = pin_sw; pinMode(_pin_clk, INPUT); pinMode(_pin_dt, INPUT); if (_pin_sw != ROTARY_NO_BUTTON){ pinMode(_pin_sw, INPUT); digitalWrite(_pin_sw, HIGH); } if (num_results == 0) { num_results = 1; } _num_results = num_results; _results = new int[_num_results]; for (int i; i<_num_results; i++){ _results[i] = (limits) ? limits[i].min : 0; } _index_result = 0; _limits = limits; _a = false; _b = false; } byte getIndex() { return _index_result; } void next() { _index_result++; if (_index_result >= _num_results) { _index_result = 0; } } void update_a() { _result = 0; delay (1); if( digitalRead(_pin_clk) != _a ) { _a = !_a; if ( _a && !_b ) { _result = -1; } } if (_results[_index_result]+_result >= _limits[_index_result].min && _results[_index_result]+_result <= _limits[_index_result].max ) { _results[_index_result] += _result; } } void update_b() { _result = 0; delay (1); if( digitalRead(_pin_dt) != _b ) { _b = !_b; if ( _b && !_a ) { _result = +1; } } if (_results[_index_result]+_result >= _limits[_index_result].min && _results[_index_result]+_result <= _limits[_index_result].max ) { _results[_index_result] += _result; } } int read(){ return _result; } //retorn -1, 0 ou 1. int getValue(int index=-1) { //retorna o valor da variável corrente ou a passada como parametro if (index < 0 ){ return _results[_index_result]; } return _results[index]; } void setValue(int value){ _results[_index_result] = value; } //caso a variável inicializa em determinado valor diferente de zero, utilizar esse método. int buttonRead(){ return (_pin_sw == ROTARY_NO_BUTTON) ? LOW : digitalRead(_pin_sw); } }; /************************************************************************************************************* ************************************FIM CLASSE ROTARY ENCODER************************************************* *************************************************************************************************************/ /************************************************************************************************************* *******************************CLASSE LCD PROGRESS BAR******************************************************** **************************************************************************************************************/ byte c0[8] = {B00000, B00000, B00000, B00000, B00000, B00000, B00000, B10000 }; byte c1[8] = {B00000, B00000, B00000, B00000, B00000, B00000, B11000, B11000 }; byte c2[8] = {B00000, B00000, B00000, B00000, B00011, B00011, B11011, B11011 }; byte c3[8] = {B00000, B00000, B11000, B11000, B11000, B11000, B11000, B11000 }; byte c4[8] = {B00011, B00011, B11011, B11011, B11011, B11011, B11011, B11011 }; byte c5[8] = {B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 }; byte c6[8] = {B11011, B11011, B11011, B11011, B11011, B11011, B11011, B11011 }; class LCDProgressBar { private: LiquidCrystal * _lcd; //ponteiro para um objeto lcd int _row; int _col; int _perc; /*0..100*/ int _heigh; public: void createChars() { _lcd->createChar(0, c0); _lcd->createChar(1, c1); _lcd->createChar(2, c2); _lcd->createChar(3, c3); _lcd->createChar(4, c4); _lcd->createChar(5, c5); _lcd->createChar(6, c6); } LCDProgressBar(LiquidCrystal * lcd, int row, int col, int heigh=1) { _lcd = lcd; _row = row; _col = col; _heigh = (heigh >= 2 && _row > 0) ? 2 : 1; //heigh assume apenas os valores 2 e 1. e só assume valor = 2 quando estiver posicionado a partir da segunda linha } void setPerc(int perc) { int division = (_heigh == 2) ? 33 / 2 : 33; _perc = perc; if (perc > 100) { _perc = 100; } if (perc < 000) { _perc = 000; } if (_heigh == 2){ _lcd->setCursor(_col+2, _row-1); _lcd->print(" "); _lcd->setCursor(_col+2, _row-1); } _lcd->setCursor(_col, _row); _lcd->print((_heigh == 2) ? " " : " "); _lcd->setCursor(_col, _row); if (_perc == 0) { _lcd->write((byte)0); } else { if (_perc > 0 && _perc <= division) { _lcd->write((byte)1); } else { _lcd->write((byte)2); if (_perc > division*2 && _perc < 100/_heigh) { _lcd->write((byte)3); } if (_perc >= 100/_heigh) { _lcd->write((byte)4); } } } if (_heigh == 2 && _perc > 50){ if (_perc > 50 && _perc <= (50+division)) { _lcd->write((byte)5); } else { _lcd->write((byte)6); if (_perc > (50+division*2) && _perc < 100) { _lcd->write((byte)5); } if (_perc == 100 ) { _lcd->write((byte)6); } } _lcd->setCursor(_col+2, _row-1); _lcd->print(" "); _lcd->setCursor(_col+2, _row-1); if (_perc > 50 && _perc <= (50+division)) { _lcd->write((byte)1); } else { _lcd->write((byte)2); if (_perc > (50+division*2) && _perc < 100 ) { _lcd->write((byte)3); } if (_perc >= 100) { _lcd->write((byte)4); } } } } }; /************************************************************************************************************* *******************************FIM CLASSE LCD PROGRESS BAR**************************************************** **************************************************************************************************************/ /************************************************************************************************************* *******************************DECLARACAO DOS OBJETOS********************************************************* **************************************************************************************************************/ LiquidCrystal lcd(12, 11, 10, 9, 8, 7); LCDProgressBar lcdBar1(&lcd, 0, 9, 1); //inclui uma barra no lcd, primeira linha, coluna 9. altura 1 LCDProgressBar lcdBar2(&lcd, 1, 11, 2); //inclui outra barra no lcd, segunda linha, coluna 11. altura 2 RotaryEncoderLimits lim[] = { {0,30}, {0,20} }; //limites máximos e mínimos que as variaveis podem atingir RotaryEncoder re(A0, A1, 4, 2, lim); //pino clk, pino dt, pino sw, variaveis, limites /************************************************************************************************************* *******************************FIM DECLARACAO DOS OBJETOS***************************************************** **************************************************************************************************************/ /************************************************************************************************************* *******************************TRATAMENTO DAS INTERRUPÇÕES**************************************************** **************************************************************************************************************/ //interrupções dos pinos A0 e A1 via Pin Change Interrupt ISR(PCINT1_vect) { volatile static byte lastVal_a0 = LOW; volatile static byte lastVal_a1 = LOW; byte val_a0 = digitalRead(A0); byte val_a1 = digitalRead(A1); if (lastVal_a0 != val_a0){ re.update_a(); lastVal_a0 = val_a0; } if (lastVal_a1 != val_a1){ re.update_b(); lastVal_a1 = val_a1; } } void setup_interrupts(){ //-----PCI - Pin Change Interrupt ---- pinMode(A0,INPUT); // set Pin as Input (default) digitalWrite(A0,HIGH); // enable pullup resistor pinMode(A1,INPUT); // set Pin as Input (default) digitalWrite(A1,HIGH); // enable pullup resistor cli(); PCICR |= 0b00000010; // habilita a porta C - Pin Change Interrupts PCMSK1 |= 0b00000011; // habilita interrupção da porta c nos pinos: PCINT8 (A0) e PCINT9(A1) sei(); } /************************************************************************************************************* *******************************FIM TRATAMENTO DAS INTERRUPÇÕES**************************************************** **************************************************************************************************************/ void indicador_rotary(){ char c = ((re.getIndex() == 0)) ? '>' : ' '; lcd.setCursor(7, 0); lcd.print(c); c = ((re.getIndex() == 1)) ? '>' : ' '; lcd.setCursor(7, 1); lcd.print(c); } void setup() { setup_interrupts(); lcdBar1.createChars(); lcd.begin(16, 2); indicador_rotary(); } void loop() { static int value1 = -1; static int value2 = -1; if (value1 != re.getValue(0)) { lcd.setCursor(0, 0); value1 = re.getValue(0); int perc = value1/30.0 * 100; if (value1 < 10) {lcd.print("00");} else { if (value1 < 100) {lcd.print("0");} } lcd.print(value1); lcd.print("/"); lcd.print(30); lcdBar1.setPerc(perc); //atualização da primeira barra de progresso } if (value2 != re.getValue(1)) { lcd.setCursor(0, 1); value2 = re.getValue(1); int perc = value2/20.0 * 100; if (value2 < 10) {lcd.print("00");} else { if (value2 < 100) {lcd.print("0");} } lcd.print(value2); lcd.print("/"); lcd.print(20); lcdBar2.setPerc(perc); //atualização da segunda barra de progresso } //controla o click do botao do enconder static byte b = HIGH; //pra ler apenas uma vez o botao ao pressionar if( re.buttonRead() == LOW && b != re.buttonRead() ) { re.next(); //passa para a próxima variável (index) indicador_rotary(); delay(200); //debounce meia boca } b = re.buttonRead(); delay(100); }
e nessa outra versão, uma barra que permite informar valores que variam de um número negativo até um número positivo:
vídeo
código-fonte:
/* Fabiano A. Arndt - 2016 www.youtube.com/user/fabianoallex www.facebook.com/dicasarduino fabianoallex@gmail.com */ #include <LiquidCrystal.h> /************************************************************************************************************* ************************************CLASSE ROTARY ENCODER***************************************************** *************************************************************************************************************/ #define ROTARY_NO_BUTTON 255 struct RotaryEncoderLimits{ int min; int max; }; class RotaryEncoder { private: byte _pin_clk; byte _pin_dt; byte _pin_sw; volatile byte _num_results; volatile int _result; volatile int * _results; byte _index_result; RotaryEncoderLimits * _limits; boolean _a; boolean _b; public: RotaryEncoder(byte pin_clk, byte pin_dt, byte pin_sw = ROTARY_NO_BUTTON, byte num_results=1, RotaryEncoderLimits * limits=0){ //parametro do botao opcional _pin_clk = pin_clk; _pin_dt = pin_dt; _pin_sw = pin_sw; pinMode(_pin_clk, INPUT); pinMode(_pin_dt, INPUT); if (_pin_sw != ROTARY_NO_BUTTON){ pinMode(_pin_sw, INPUT); digitalWrite(_pin_sw, HIGH); } if (num_results == 0) { num_results = 1; } _num_results = num_results; _results = new int[_num_results]; for (int i; i<_num_results; i++){ _results[i] = (limits) ? limits[i].min : 0; } _index_result = 0; _limits = limits; _a = false; _b = false; } byte getIndex() { return _index_result; } void next() { _index_result++; if (_index_result >= _num_results) { _index_result = 0; } } void update_a() { _result = 0; delay (1); if( digitalRead(_pin_clk) != _a ) { _a = !_a; if ( _a && !_b ) { _result = -1; } } if (_results[_index_result]+_result >= _limits[_index_result].min && _results[_index_result]+_result <= _limits[_index_result].max ) { _results[_index_result] += _result; } } void update_b() { _result = 0; delay (1); if( digitalRead(_pin_dt) != _b ) { _b = !_b; if ( _b && !_a ) { _result = +1; } } if (_results[_index_result]+_result >= _limits[_index_result].min && _results[_index_result]+_result <= _limits[_index_result].max ) { _results[_index_result] += _result; } } int read(){ return _result; } //retorn -1, 0 ou 1. int getValue(int index=-1) { //retorna o valor da variável corrente ou a passada como parametro if (index < 0 ){ return _results[_index_result]; } return _results[index]; } void setValue(int value, int index=-1){ _results[ (index==-1) ? _index_result : index] = value; } //caso a variável inicializa em determinado valor diferente de zero, utilizar esse método. int buttonRead(){ return (_pin_sw == ROTARY_NO_BUTTON) ? LOW : digitalRead(_pin_sw); } }; /************************************************************************************************************* ************************************FIM CLASSE ROTARY ENCODER************************************************* *************************************************************************************************************/ /************************************************************************************************************* *******************************CLASSE LCD PROGRESS BAR******************************************************** **************************************************************************************************************/ /* 0 1 2 3 4 ** ** ** ** ** ** ** ** ** ** * ** ** ** ** * ** ** ** ** * ** ** ** ** * ** ** ** ** * ** ** ** ** * ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ byte c0[8] = {B11011, B00000, B00000, B00000, B00000, B00000, B00000, B11011 }; byte c1[8] = {B11011, B00000, B00000, B00100, B00100, B00000, B00000, B11011 }; byte c2[8] = {B11011, B11000, B11000, B11000, B11000, B11000, B11000, B11011 }; byte c3[8] = {B11011, B00011, B00011, B00011, B00011, B00011, B00011, B11011 }; byte c4[8] = {B11011, B11011, B11011, B11011, B11011, B11011, B11011, B11011 }; class LCDProgressBar { private: LiquidCrystal * _lcd; //ponteiro para um objeto lcd int _row; int _col; int _perc; /*0..100*/ int _len; public: void createChars() { _lcd->createChar(0, c0); _lcd->createChar(1, c1); _lcd->createChar(2, c2); _lcd->createChar(3, c3); _lcd->createChar(4, c4); } LCDProgressBar(LiquidCrystal * lcd, int row, int col, int len) { _lcd = lcd; _row = row; _col = col; _len = len; } void setPerc(int perc) { _perc = perc; if (_perc > 100) { _perc = 100; } if (_perc < -100) { _perc = -100; } _lcd->setCursor(_col, _row); for (int i=0; i<(_len*2-1);i++) { _lcd->write((byte)0); } //preenche com caracteres vazio _lcd->setCursor(_col + (_len-1), _row); _lcd->write((byte)1); //preenche com caracter zero (nenhum valor) if (_perc > 0){ _lcd->setCursor(_col + (_len-1), _row); int bars = (2*(_len-1)+1) * _perc / 100; if (bars >= 1) { _lcd->write((byte)3); } int div = (bars-1) / 2; //divisao int resto = (bars-1) % 2; //resto for (int i=0; i<div; i++) { _lcd->write((byte)4); } //pinta todo o quadro if (resto > 0) { _lcd->write((byte)2); } } else if (_perc < 0) { _lcd->setCursor(_col + (_len-1), _row); int bars = (2*(_len-1)+1) * (-_perc) / 100; if (bars >= 1) { _lcd->write((byte)2); } int div = (bars-1) / 2; //divisao int resto = (bars-1) % 2; //resto int i = 0; for (i=0; i<div; i++) { _lcd->setCursor(_col + _len/2-i, _row); _lcd->write((byte)4); } if (resto > 0) { _lcd->setCursor(_col + _len/2-i, _row); _lcd->write((byte)3); } } } }; /************************************************************************************************************* *******************************FIM CLASSE LCD PROGRESS BAR**************************************************** **************************************************************************************************************/ /************************************************************************************************************* *******************************DECLARACAO DOS OBJETOS********************************************************* **************************************************************************************************************/ LiquidCrystal lcd(12, 11, 10, 9, 8, 7); LCDProgressBar lcdBar1(&lcd, 0, 9, 3); //inclui uma barra no lcd, primeira linha, coluna 9. tamanho 3 (3*2-1 --> 5) LCDProgressBar lcdBar2(&lcd, 1, 9, 4); //inclui outra barra no lcd, segunda linha, coluna 11. tamanho 4 (4*2-1 --> 7) RotaryEncoderLimits lim[] = { {-30,30}, {-20,20} }; //limites máximos e mínimos que as variaveis podem atingir RotaryEncoder re(A0, A1, 4, 2, lim); //pino clk, pino dt, pino sw, variaveis, limites /************************************************************************************************************* *******************************FIM DECLARACAO DOS OBJETOS***************************************************** **************************************************************************************************************/ /************************************************************************************************************* *******************************TRATAMENTO DAS INTERRUPÇÕES**************************************************** **************************************************************************************************************/ //interrupções dos pinos A0 e A1 via Pin Change Interrupt ISR(PCINT1_vect) { volatile static byte lastVal_a0 = LOW; volatile static byte lastVal_a1 = LOW; byte val_a0 = digitalRead(A0); byte val_a1 = digitalRead(A1); if (lastVal_a0 != val_a0){ re.update_a(); lastVal_a0 = val_a0; } if (lastVal_a1 != val_a1){ re.update_b(); lastVal_a1 = val_a1; } } void setup_interrupts(){ //-----PCI - Pin Change Interrupt ---- pinMode(A0,INPUT); // set Pin as Input (default) digitalWrite(A0,HIGH); // enable pullup resistor pinMode(A1,INPUT); // set Pin as Input (default) digitalWrite(A1,HIGH); // enable pullup resistor cli(); PCICR |= 0b00000010; // habilita a porta C - Pin Change Interrupts PCMSK1 |= 0b00000011; // habilita interrupção da porta c nos pinos: PCINT8 (A0) e PCINT9(A1) sei(); } /************************************************************************************************************* *******************************FIM TRATAMENTO DAS INTERRUPÇÕES**************************************************** **************************************************************************************************************/ void indicador_rotary(){ char c = ((re.getIndex() == 0)) ? '>' : ' '; lcd.setCursor(7, 0); lcd.print(c); c = ((re.getIndex() == 1)) ? '>' : ' '; lcd.setCursor(7, 1); lcd.print(c); } void setup() { setup_interrupts(); lcdBar1.createChars(); lcd.begin(16, 2); re.setValue(0, 0); re.setValue(0, 1); indicador_rotary(); } void loop() { static int value1 = -1; static int value2 = -1; if (value1 != re.getValue(0)) { lcd.setCursor(0, 0); value1 = re.getValue(0); int perc = value1/30.0 * 100; lcd.print(" "); lcd.setCursor(0, 0); lcd.print(value1); lcd.print("/"); lcd.print(30); lcdBar1.setPerc(perc); //atualização da primeira barra de progresso } if (value2 != re.getValue(1)) { lcd.setCursor(0, 1); value2 = re.getValue(1); int perc = value2/20.0 * 100; lcd.print(" "); lcd.setCursor(0, 1); lcd.print(value2); lcd.print("/"); lcd.print(20); lcdBar2.setPerc(perc); //atualização da segunda barra de progresso } //controla o click do botao do enconder static byte b = HIGH; //pra ler apenas uma vez o botao ao pressionar if( re.buttonRead() == LOW && b != re.buttonRead() ) { re.next(); //passa para a próxima variável (index) indicador_rotary(); delay(200); //debounce meia boca } b = re.buttonRead(); delay(100); }