Go Down

Topic: Progress Bar Problem (Read 3446 times) previous topic - next topic

TSW68

Hier im Thema alles gelesen
Die map Funktion ja aber wie ? Englisch ist mangelhaft .
Bitte die Lösung.

combie

Säge kein Sägemehl.

agmue

agmue, mein kleiner Angeber… ;)
Mir ging es nur um die Prozentrechnung, das ist ja nun wirklich keine Sache ::)

Ja, sieht ganz hübsch aus, darum der komplette Sketch, wie ich getestet habe:

Code: [Select]
#include <Wire.h>
#include <hd44780.h> // include hd44780 library header file
#include <hd44780ioClass/hd44780_I2Cexp.h> // i/o expander/backpack class
hd44780_I2Cexp lcd; // auto detect backpack and pin mappings

const byte LCD_NB_ROWS = 4 ;
const byte LCD_NB_COLUMNS = 20 ;

byte START_DIV_0_OF_1 [ 8 ] = {
  B01111 ,
  B11000 ,
  B10000 ,
  B10000 ,
  B10000 ,
  B10000 ,
  B11000 ,
  B01111
};  // Char start 0/1

byte START_DIV_1_OF_1 [ 8 ] = {
  B01111 ,
  B11000 ,
  B10011 ,
  B10111 ,
  B10111 ,
  B10011 ,
  B11000 ,
  B01111
};  // Tank beginning 1/1

byte DIV_0_OF_2 [ 8 ] = {
  B11111 ,
  B00000 ,
  B00000 ,
  B00000 ,
  B00000 ,
  B00000 ,
  B00000 ,
  B11111
};  // Medium tank 0/2

byte DIV_1_OF_2 [ 8 ] = {
  B11111 ,
  B00000 ,
  B11000 ,
  B11000 ,
  B11000 ,
  B11000 ,
  B00000 ,
  B11111
};  // Medium tank 1/2

byte DIV_2_OF_2 [ 8 ] = {
  B11111 ,
  B00000 ,
  B11011 ,
  B11011 ,
  B11011 ,
  B11011 ,
  B00000 ,
  B11111
};  // Medium tank 2/2

byte END_DIV_0_OF_1 [ 8 ] = {
  B11110 ,
  B00011 ,
  B00001 ,
  B00001 ,
  B00001 ,
  B00001 ,
  B00011 ,
  B11110
};  // late tank 0/1

byte END_DIV_1_OF_1 [ 8 ] = {
  B11110 ,
  B00011 ,
  B11001 ,
  B11101 ,
  B11101 ,
  B11001 ,
  B00011 ,
  B11110
};  // Char end 1/1

void setup_progressbar() {
  lcd.createChar(0, START_DIV_0_OF_1);
  lcd.createChar(1, START_DIV_1_OF_1);
  lcd.createChar(2, DIV_0_OF_2);
  lcd.createChar(3, DIV_1_OF_2);
  lcd.createChar(4, DIV_2_OF_2);
  lcd.createChar(5, END_DIV_0_OF_1);
  lcd.createChar(6, END_DIV_1_OF_1);
}

void draw_progressbar(byte lcdwert) {
  lcd.setCursor(0, 0);
  lcd.print(lcdwert);
  lcd.print(F(" %  "));
  lcd.setCursor(0, 1);

  byte nb_columns = map(lcdwert, 0, 100, 0, LCD_NB_COLUMNS * 2 - 2);
  // Chaque caractére affiche 2 barres verticales, mais le premier et dernier caractére n'en affiche qu'une.
  for (byte i = 0; i < LCD_NB_COLUMNS; ++i) {

    if (i == 0) { // Premiére case
      if (nb_columns > 0) {
        lcd.write(1); // Char début 1 / 1
        nb_columns -= 1;
      } else {
        lcd.write((byte) 0); // Char début 0 / 1
      }
    } else if (i == LCD_NB_COLUMNS - 1) { // Derniére case
      if (nb_columns > 0) {
        lcd.write(6); // Char fin 1 / 1
      } else {
        lcd.write(5); // Char fin 0 / 1
      }
    } else { // Autres cases
      if (nb_columns >= 2) {
        lcd.write(4); // Char div 2 / 2
        nb_columns -= 2;
      } else if (nb_columns == 1) {
        lcd.write(3); // Char div 1 / 2
        nb_columns -= 1;
      } else {
        lcd.write(2); // Char div 0 / 2
      }
    }
  }
}

void setup() {
  lcd.begin(LCD_NB_COLUMNS, LCD_NB_ROWS);
  setup_progressbar();
  lcd.clear();
}

void loop() {
  for (uint16_t zahl = 0; zahl <= 5000; zahl += 10)
  {
    byte lcdwert = zahl / 50;
    draw_progressbar(lcdwert);
    lcd.setCursor(0, 2);
    lcd.print("Wert: ");
    lcd.print(zahl);
    lcd.print("   ");
    delay(100);
  }
}
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

dony

#18
Jan 30, 2018, 04:57 pm Last Edit: Jan 30, 2018, 05:01 pm by dony
Hallo,

Also eigentlich muss man nur in der for schleife anpassen 5000 und 50, bei 800 sind es 8. Verstehst Du warum?
Natürlich sollte man das so programmieren, damit man nur den lcdwert definieren muss.

lg dony
edit: @agmue, bei Dir funktioniert der Code? <- Das ist ein anderes Display (hd44780)
Grüße, Donny

agmue

edit: @agmue, bei Dir funktioniert der Code? <- Das ist ein anderes Display (hd44780)
Nein, nur eine Bibliothek, die beispielsweise die I2C-Adresse selbst ausknobelt.

Selbes Display, andere Bibliothek:

Code: [Select]
#include <LCD.h>                //NewliquidCrystal
#include <LiquidCrystal_I2C.h>  //NewliquidCrystal
#include <Wire.h>

#define I2C_ADDR     0x27                         // 20x4 Display
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7

LiquidCrystal_I2C  lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin, BACKLIGHT_PIN, POSITIVE);

const byte LCD_NB_ROWS = 4 ;
const byte LCD_NB_COLUMNS = 20 ;

byte START_DIV_0_OF_1 [ 8 ] = {
  B01111 ,
  B11000 ,
  B10000 ,
  B10000 ,
  B10000 ,
  B10000 ,
  B11000 ,
  B01111
};  // Char start 0/1

byte START_DIV_1_OF_1 [ 8 ] = {
  B01111 ,
  B11000 ,
  B10011 ,
  B10111 ,
  B10111 ,
  B10011 ,
  B11000 ,
  B01111
};  // Tank beginning 1/1

byte DIV_0_OF_2 [ 8 ] = {
  B11111 ,
  B00000 ,
  B00000 ,
  B00000 ,
  B00000 ,
  B00000 ,
  B00000 ,
  B11111
};  // Medium tank 0/2

byte DIV_1_OF_2 [ 8 ] = {
  B11111 ,
  B00000 ,
  B11000 ,
  B11000 ,
  B11000 ,
  B11000 ,
  B00000 ,
  B11111
};  // Medium tank 1/2

byte DIV_2_OF_2 [ 8 ] = {
  B11111 ,
  B00000 ,
  B11011 ,
  B11011 ,
  B11011 ,
  B11011 ,
  B00000 ,
  B11111
};  // Medium tank 2/2

byte END_DIV_0_OF_1 [ 8 ] = {
  B11110 ,
  B00011 ,
  B00001 ,
  B00001 ,
  B00001 ,
  B00001 ,
  B00011 ,
  B11110
};  // late tank 0/1

byte END_DIV_1_OF_1 [ 8 ] = {
  B11110 ,
  B00011 ,
  B11001 ,
  B11101 ,
  B11101 ,
  B11001 ,
  B00011 ,
  B11110
};  // Char end 1/1

void setup_progressbar() {
  lcd.createChar(0, START_DIV_0_OF_1);
  lcd.createChar(1, START_DIV_1_OF_1);
  lcd.createChar(2, DIV_0_OF_2);
  lcd.createChar(3, DIV_1_OF_2);
  lcd.createChar(4, DIV_2_OF_2);
  lcd.createChar(5, END_DIV_0_OF_1);
  lcd.createChar(6, END_DIV_1_OF_1);
}

void draw_progressbar(byte lcdwert) {
  lcd.setCursor(0, 0);
  lcd.print(lcdwert);
  lcd.print(F(" %  "));
  lcd.setCursor(0, 1);

  byte nb_columns = map(lcdwert, 0, 100, 0, LCD_NB_COLUMNS * 2 - 2);
  // Chaque caractére affiche 2 barres verticales, mais le premier et dernier caractére n'en affiche qu'une.
  for (byte i = 0; i < LCD_NB_COLUMNS; ++i) {

    if (i == 0) { // Premiére case
      if (nb_columns > 0) {
        lcd.write(1); // Char début 1 / 1
        nb_columns -= 1;
      } else {
        lcd.write((byte) 0); // Char début 0 / 1
      }
    } else if (i == LCD_NB_COLUMNS - 1) { // Derniére case
      if (nb_columns > 0) {
        lcd.write(6); // Char fin 1 / 1
      } else {
        lcd.write(5); // Char fin 0 / 1
      }
    } else { // Autres cases
      if (nb_columns >= 2) {
        lcd.write(4); // Char div 2 / 2
        nb_columns -= 2;
      } else if (nb_columns == 1) {
        lcd.write(3); // Char div 1 / 2
        nb_columns -= 1;
      } else {
        lcd.write(2); // Char div 0 / 2
      }
    }
  }
}

void setup() {
  lcd.begin(LCD_NB_COLUMNS, LCD_NB_ROWS);
  setup_progressbar();
  lcd.clear();
}

void loop() {
  for (uint16_t zahl = 0; zahl <= 5000; zahl += 10)
  {
    byte lcdwert = zahl / 50;
    draw_progressbar(lcdwert);
    lcd.setCursor(0, 2);
    lcd.print("Wert: ");
    lcd.print(zahl);
    lcd.print("   ");
    delay(100);
  }
}
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

dony

#20
Jan 30, 2018, 05:20 pm Last Edit: Jan 30, 2018, 08:25 pm by dony
Also Dein Code funktioniert so bei mir nicht! Ich hab hier meinen gepostet:

Code: [Select]

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

  const int LCD_NB_ROWS = 4 ;
  const int LCD_NB_COLUMNS = 20 ;
 
  LiquidCrystal_I2C lcd(0x27, 20,4);

  byte START_DIV_0_OF_1 [ 8 ] = {
  B01111 ,
  B11000 ,
  B10000 ,
  B10000 ,
  B10000 ,
  B10000 ,
  B11000 ,
  B01111
  };  // Char start 0/1

  byte START_DIV_1_OF_1 [ 8 ] = {
  B01111 ,
  B11000 ,
  B10011 ,
  B10111 ,
  B10111 ,
  B10011 ,
  B11000 ,
  B01111
  };  // Tank beginning 1/1

  byte DIV_0_OF_2 [ 8 ] = {
  B11111 ,
  B00000 ,
  B00000 ,
  B00000 ,
  B00000 ,
  B00000 ,
  B00000 ,
  B11111
  };  // Medium tank 0/2

  byte DIV_1_OF_2 [ 8 ] = {
  B11111 ,
  B00000 ,
  B11000 ,
  B11000 ,
  B11000 ,
  B11000 ,
  B00000 ,
  B11111
  };  // Medium tank 1/2

  byte DIV_2_OF_2 [ 8 ] = {
  B11111 ,
  B00000 ,
  B11011 ,
  B11011 ,
  B11011 ,
  B11011 ,
  B00000 ,
  B11111
  };  // Medium tank 2/2

  byte END_DIV_0_OF_1 [ 8 ] = {
  B11110 ,
  B00011 ,
  B00001 ,
  B00001 ,
  B00001 ,
  B00001 ,
  B00011 ,
  B11110
  };  // late tank 0/1

  byte END_DIV_1_OF_1 [ 8 ] = {
  B11110 ,
  B00011 ,
  B11001 ,
  B11101 ,
  B11101 ,
  B11001 ,
  B00011 ,
  B11110
  };  // Char end 1/1

 void setup_progressbar() {


  lcd.createChar(0, START_DIV_0_OF_1);
  lcd.createChar(1, START_DIV_1_OF_1);
  lcd.createChar(2, DIV_0_OF_2);
  lcd.createChar(3, DIV_1_OF_2);
  lcd.createChar(4, DIV_2_OF_2);
  lcd.createChar(5, END_DIV_0_OF_1);
  lcd.createChar(6, END_DIV_1_OF_1);
}

void draw_progressbar(byte lcdwert) {


  lcd.setCursor(0, 0);
  lcd.print(lcdwert);
  lcd.print(" %  ");

  lcd.setCursor(0, 1);


 // byte nb_columns = map(lcdwert, 0, 100, 0, LCD_NB_COLUMNS * 2 - 2);
   byte nb_columns = map(lcdwert, 0, 100, 0, LCD_NB_COLUMNS * 2 - 2);
  // Chaque caractére affiche 2 barres verticales, mais le premier et dernier caractére n'en affiche qu'une.


  for (byte i = 0; i < LCD_NB_COLUMNS; ++i) {

    if (i == 0) { // Premiére case
 

      if (nb_columns > 0) {
        lcd.write(1); // Char début 1 / 1
        nb_columns -= 1;
 
      } else {
        lcd.write((byte) 0); // Char début 0 / 1
      }
 
    } else if (i == LCD_NB_COLUMNS -1) { // Derniére case
 

      if (nb_columns > 0) {
        lcd.write(6); // Char fin 1 / 1
 
      } else {
        lcd.write(5); // Char fin 0 / 1
      }
 
    } else { // Autres cases
 

      if (nb_columns >= 2) {
        lcd.write(4); // Char div 2 / 2
        nb_columns -= 2;
 
      } else if (nb_columns == 1) {
        lcd.write(3); // Char div 1 / 2
        nb_columns -= 1;
 
      } else {
        lcd.write(2); // Char div 0 / 2
      }
    }
  }
}

void setup(){

  lcd.begin(20, 4);
  lcd.init();
  lcd.backlight();

  setup_progressbar();
  lcd.clear();
}
void loop(){

for (uint16_t zahl = 0; zahl <= 800; zahl += 10)
  {
    byte lcdwert = zahl / 8;
    draw_progressbar(lcdwert);
    lcd.setCursor(0, 2);
    lcd.print("Wert: ");
    lcd.print(zahl);
    lcd.print("   ");
    delay(100);
  }
  delay(2000);
}

Der Grobe unterschied:
Code: [Select]

  LiquidCrystal_I2C lcd(0x27, 20,4);  // I2C Adresse, Felder, Zeilen
  /*  im Setup */
  //lcd.begin(20, 4); // <- Das brauche ich nicht unbediengt
  lcd.init();  // <- ohne dem geht gar nichts!
  lcd.backlight();


lg dony
edit: Ich verwende ein 20x4 Display, mit einem IC: PCF8574T von YUR BOT ist das 'breakout' hinten am Display.
Grüße, Donny

agmue

#21
Jan 30, 2018, 06:47 pm Last Edit: Jan 30, 2018, 06:48 pm by agmue
edit: Ich verwende ein 20x4 Display, mit einem IC: PCF8574T von YUR BOT ist das 'breakout' hinten am Display.
Nicht die Displays unterscheiden sich, sondern die von uns verwendeten Programmbibliotheken. Mit dem Namen LiquidCrystal_I2C gibt es leider viele unterschiedliche. Meine ist diese:

http://www.instructables.com/id/How-to-connect-a-serial-LCD-to-an-Arduino-UNO/step2/The-Sketch/ Beschreibung
https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home Beschreibung
https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads Download

Ich habe sie gewählt, weil die verwendeten Pins transparent festgelegt werden können.

Dann bin ich aber durch dieses Forum auf die Bibliothek hd44780 gestoßen, die das alles automatisch ermittelt und auch mit zwei Displays zurechtkommt. Da ich faul bin, verwende ich für Testsketche nun diese.
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

dony

#22
Jan 30, 2018, 08:19 pm Last Edit: Jan 30, 2018, 08:29 pm by dony
Nicht die Displays unterscheiden sich, sondern die von uns verwendeten Programmbibliotheken. Mit dem Namen LiquidCrystal_I2C gibt es leider viele unterschiedliche...
Ja das ist mir schon klar, mich hat das mit den selben Namen irritiert. Ich wusste nicht, das es viele mit den selben Namen gibt.

Alles Klar! Danke für die Links :)
lg dony
*edit*
Grüße, Donny

TSW68

Mit der map Funktion habe ich jetzt verstanden.
Bin noch am rätseln das es so ist wie ich es brauche.
Möchte ja mit der Progress Bar einen Wert einstellen
deshalb brauche ich eigentlich einen anfangswert und einen entwert.
50 - 800 in 10er schritten +-
Jetzt habe ich z.B eine Zahl 400 also die Hälfte von 400
Also Progress Bar zeigt bis zur Mitte an.

50 |========                | 800

Zahl = 800

50 |===============| 800

Die Zahl zwischen 50 und 800 endert dich also immer plus minus 10


Liebe Grüße tsw68



Klaus_ww

Ähh, wenn der Anfangswert 50 ist und der Endwert 800, dann ist die Hälfte des Anzeigebereichs (800-50)/2 = 375.

Ich habe noch nicht verstanden, wo genau Dein Problem jetzt ist.
Freizeit-Programmierer mit moderatem Ehrgeiz besseren Code zu schreiben.

dony

Hallo,

Schau Dir mal genau an was ich zum vorherigen Sketch von mir geändert habe.
Code: [Select]

for (uint16_t zahl = 0; zahl <= 800; zahl += 10) { // Ich hab den lcdwert von 5000 auf 800 reduziert.
    byte lcdwert = zahl / 8; // <-- Ich hab die Zahl von 50 auf 8 geändert.

Rückgerrechnet: 5000 / 50 = 100 ergibt 800 / 100 = 8. Im Code schaut das dann so aus:
Code: [Select]

int maxWert = 1000; // Da wird nur der höchste Wert definiert.
int Wert2 /= 100; // der maxWert wird durch 100 geteilt und in einer eigenen Variable gespeichert

for (uint16_t zahl = 0; zahl <= maxWert; zahl += 10)
  {
    byte lcdwert = zahl / Wert2;

Ich habe das nicht mit float probiert.

Also die map() funktion gibt einen... :smiley-confuse: Stell Dir vor Du erwartest eine Eingabe von 0-1024, sagen wir 512 und möchtest die Zahl in einen Bereich von 0-255 bringen. Was nun... Ok, 512 ist die 50% also muss die neue Zahl 255-(255/2) = 127,5 = 128.
Um diese Zahl (128) einfach zu rechnen, gibt es die map() Funktion.
Code: [Select]

int ausgangsZahl = 694
int ergebniss = map(ausgangsZahl, 0, 1024, 0 , 255);


lg dony
Grüße, Donny

TSW68

Quote
Ähh, wenn der Anfangswert 50 ist und der Endwert 800, dann ist die Hälfte des Anzeigebereichs (800-50)/2 = 375.
400 nur ein Beispiel . Zahl zwischen 50 und 800 soll angezeigt werden

Sagen wir es mal so:
Die Frequenzen beim Radio 50-800 dein Lieblingssender liegt bei 400
Jetzt möchtest du einen anderen Sender einstellen
Taste plus minus ,nächste Sender bei 50 Oder 800 .

Lieblingssender = Voreinstellung 400 die ich später durch eine Variable ersetze.
Taster minus ,Balken wandert nach links Max. 50
Taster rechts ,Balken  wandert nach rechts Max. 800


dony

#27
Jan 30, 2018, 09:50 pm Last Edit: Jan 30, 2018, 10:06 pm by dony
Wie kommt ihr auf 800 und 50, die 50 waren soweit ich weiß auf die 5000 bezogen. Ändere mal die Zahl 50  durch die Zahl 8 (unterhalb des for() Befehl), 800 bleibt. ;)

lg dony
edit: Aso, jetzt versteh ich Dein Problem, Du willst das die Anzeige nicht bei 0 beginnt sondern bei 50 oder was auch immer. Leider hab ich auf schnell auch keine Lösung. So fängt er bei 50 an zu zählen aber da sollten die Prozent raus und oben links der Anfangswert und rechts der Endwert, ich hab das mal unten dazuge.print.
Code: [Select]

for (uint16_t zahl = 50; zahl <= 800; zahl += 10)
  {
    byte lcdwert = zahl / 8;
    draw_progressbar(lcdwert);
    lcd.setCursor(0, 2);
    lcd.print(50);
    lcd.setCursor(16, 2);
    lcd.print("800");
    lcd.setCursor(0, 3);
    lcd.print("Wert: ");
    lcd.print(zahl);
    delay(300);
  }
Grüße, Donny

dony

#28
Jan 30, 2018, 10:12 pm Last Edit: Jan 30, 2018, 10:39 pm by dony
Hallo nochmal,

Noch ein loop Beispiel:
Code: [Select]
void loop(){
    int zahl = 400;
    draw_progressbar(zahl/8);
    lcd.setCursor(0, 2);
    lcd.print(50);
    lcd.setCursor(17, 2);
    lcd.print(800);
    lcd.setCursor(0, 3);
    lcd.print("Wert: ");
    lcd.print(zahl);
    delay(300);


}

Da musst Du natürlich jetzt noch dazuprogrammieren wann die zahl geändert werden soll.
edit: Auf jeden Fall hast mehrere Variablen, die berrechnet oder definiert werden müssen.
Code: [Select]

int minWert = 50;
int maxWert = 800;
int aktuellerWert = 400;
int neuerWert;

/* loop */
if(aktuellerWert != neuerWert) {  // Wenn ein neuer Wert kommt, Progress Bar ändern
  aktuellerWert = neuerWert;  // Habe ich nachträglich eingefügt!!!

  lcd.clear();
  draw_progressbar(aktuellerWert/(maxWert/100));
  lcd.setCursor(0, 2);  // Ob und was da steht ist Geschmackssache
  lcd.print(minWert );
  lcd.setCursor(15, 2);
  lcd.print(maxWert);
  lcd.setCursor(0, 3);
  lcd.print("Wert: ");
  lcd.print(aktuellerWert);
}

Ich hoffe das ich Dir damit geholfen habe, dafür verwende ich Deinen Code ;)

lg dony
Grüße, Donny

TSW68

#29
Jan 30, 2018, 10:26 pm Last Edit: Jan 30, 2018, 10:45 pm by TSW68
Ja genau so! dony Du hast es endlich.en.
nur kein balken zu seh

Edit:
Alles OK

Go Up