www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LCD_Formarierungsalgorithmus-sprintf


Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe jetzt einen Formatierungsalgorithmus geschrieben und sitze 
schon ne Stunde rum und kann den Fehler nicht finden. Das Resultat ist, 
dass ich auf beiden Zeilen des Displays was sehe und zwar ändern sich 
die Werte. Gemessen wird richtig denn manchmal stimmen die Werte, die 
angezeit werden, aber alles irgendwie verwischt.
--> Code(Der Code dient natürlich dem Zweck des Roboters und ich habe 
ihn auch dementsprechend entwickelt, also nicht wundern wegen der vielen 
Dekl und Def und includes..., hoffe mir kann trotzdem jemand helfen:
#include <stdio.h>
#include <stdint.h>
#include <avr/io.h>
#include <string.h>
#include <util/delay.h>
#include <string.h>
#include <avr/signal.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <inttypes.h>
#include <math.h>

//Definitionen--------------------------------------------------------
#define ON 200   //Motor ein für PWM
#define OFF 0  //Motor aus für PWM
#define UART_BAUD_RATE 9600  //UART Baudrate
#define BufferMAX 100  //Buffer für Stringumwandlungen und Typumwandlungen
#define Ta 0.01f //Parameter für PID Algorithmus
#define ADC_Korr(ReferenceVoltage,BitMode) ((ReferenceVoltage)/(pow(2,BitMode)))

//Deklarierte Funktionen----------------------------------------------
uint8_t GetADC_8bit(uint8_t Chanel);

//Sub-Routines--------------------------------------------------------
#include "UART_Init.h"
#include "lcd-routines.h"
#include "Unterprogramme.h"
//--------------------------------------------------------------------

static volatile int y, esum, ealt, Regeldifferenz;
#define Kp 0  //Reglerparameter Proportional
#define Ki 0  //Reglerparameter Integral
#define Kd 0  //Reglerparameter Differncial
//Main-Program--------------------------------------------------------
int main()
{
  //Deklarierte Variablen im RAM:
  unsigned int Sensor0, Sensor1, Sensor2, Sensor3, Sensor4, zaehlerLCD, zaehlerVal;
  char Buffer[BufferMAX] = { 0 };

  //Deklarierte Variablen im EEPROM:

  //LCD init:
  lcd_init();
  lcd_clear();

  //UART_init:
  uart_init(UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU));

  //ADC-Init:
  ADMUX |= (1<<REFS0); //Refernz Intern-AVCC mit Kondensator gegen GND
  ADMUX |= (1<<ADLAR); //8Bit Modus ein
  ADCSRA |= (1<<ADEN) | (1<<ADPS2); //ADC Enable, Prescaler = 16

  //Timer/Counter0 Konfiguration:
  TCCR0 &=~ ((1<<WGM00) | (1<<WGM01)); //Normal-Modus
  TCCR0 |= (1<<CS01); //Prescaler = 8
  TIMSK |= (1<<TOIE0); //Interrupt enable --> Overflow

  //Timer/Counter1 Konfiguration:
  TCCR1A |= (1<<WGM10); TCCR1B |= (1<<WGM12); //PWM Mode = 8bit Fast PWM
  TCCR1B |= (1<<CS10); // Prescaler = 1024, da Motortreiber!
  TCCR1A |= (1<<COM1A1) | (1<<COM1B1) ; //Nicht invertierend

  //Ein-/Ausgabe:
  DDRB = 0b00001111;  //Motoren
  PORTB = 0b00001010; //Rotation of Motors in same direct

  DDRD |= (1<<PD4) | (1<<PD5); //PWM Kanäle als Ausgang

  //Enable Interrupt:
  sei();

  //Read EEPROM:*****************************

  //*****************************************

  //Main-Loop:*********************************************************************
  while(1)
  {
    for(zaehlerLCD = 0, zaehlerVal = 0; zaehlerVal < 5; zaehlerLCD += 4, zaehlerVal++)
    {
      lcd_setcursor(zaehlerLCD, 0);
      sprintf(Buffer, "%.1f ", (double)GetADC_8bit(zaehlerVal));
      lcd_string(Buffer);
    }
    _delay_ms(50);
  }
  //back***************************************************************************
  return 0;
}

ISR(TIMER0_OVF_vect)
{
  static int e;
  e = Regeldifferenz;          //Regeldifferenz = Führungsgröße - Rückführgröße
  esum = esum + e;                //Integration I-Anteil
  y = Kp*e + Ki*Ta*esum + (Kd*((e -ealt)/Ta));  //PID-Regelalgorithmus
  ealt = e;                    //Differzenteil
}


Gruß Bro

Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aus der for Schleife kommt er noch raus und es geht dann von vorn los, 
aber irgendwie überschreibt er oder nimmt die falsche x Koordinate, 
wieso auch immer.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>aber irgendwie überschreibt er oder nimm die falsche x Koordinate,
>wieso auch immer.

Du redest wirres Zeug.

Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
holger schrieb:
> Du redest wirres Zeug.

wie meinst du das, weißt du wo der Fehler liegt?

Gruß Bro

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1/ Wenn du nicht alles in eine Zeile packst, machst du es dir als Leser 
einfacher und dem Compiler/µC nicht schwerer.
    zaehlerLCD = 0;
    for(zaehlerVal = 0; zaehlerVal < 5; zaehlerVal++)
    {
      lcd_setcursor(zaehlerLCD, 0);
      sprintf(Buffer, "%.1f ", (double)GetADC_8bit(zaehlerVal));
      lcd_string(Buffer);
      zaehlerLCD += 4; 
    }

2/ "Alles Verwischt" ist für mich klar, wenn alle ca. 50ms eine 
Komplettausgabe auf dem LCD gemacht wird.

3/ Bist du sicher mit dem Start des Spalten/Zeilenindex 0,0 beim LCD? 
Das ist ungewöhnlich. Öfter sieht man 0,1
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan B. schrieb:
> 2/ "Alles Verwischt" ist für mich klar, wenn alle ca. 50ms eine
> Komplettausgabe auf dem LCD gemacht wird.

Begründe das mal, das versteh ich nämlich nicht.

Stefan B. schrieb:
> 3/ Bist du sicher mit dem Start des Spalten/Zeilenindex 0,0 beim LCD?
> Das ist ungewöhnlich. Öfter sieht man 0,1

Ok, du hast es gefunden, und das war niht einmal der einzige Fehler.

Danke!

Gruß Bro

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Brocken Sei schrieb:

>> 2/ "Alles Verwischt" ist für mich klar, wenn alle ca. 50ms eine
>> Komplettausgabe auf dem LCD gemacht wird.
>
> Begründe das mal, das versteh ich nämlich nicht.

Kannst du irgendetwas lesen, wenn sich eine angezeigte Zahl in der 
Sekunde 20 mal ändert? (*)

Wenn du 5 mal in der Sekunde eine Zahl austauscht, musst du schon froh 
sein, wenn du die Zahlen noch einzeln identifizieren kannst. Und selbst 
dann ist es von Vorteil wenn man dafür sorgt, dass die Einerstelle immer 
an der gleichen Stelle auftaucht, die Zehnerstelle immer an der gleichen 
Stelle auftaucht etc.

(*) stimmt ja eigentlich gar nicht.
Du klatscht ja die 5 Zahlen mit Full Speed um jeweils 4 Zeichen versetzt 
(!) aufs LCD und erst dann wird eine winzige Pause eingelegt.

Und ja: Da du das LCD nie löscht, überschreibst du nur.

Wenn am LCD

    +---+---+---+---+---+---+---+---+
    | 1 | 0 | 0 | 0 |   |   |   |   |
    +---+---+---+---+---+---+---+---+

also 1000 steht und du schreibst im nächsten Schleifendurchlauf eine 999 
beginnend mit dem linken Rand drüber, dann steht da

    +---+---+---+---+---+---+---+---+
    | 9 | 9 | 9 | 0 |   |   |   |   |
    +---+---+---+---+---+---+---+---+

also 9990, weil ja niemand die letzte 0 von den 1000 mit einem 
Leerzeichen überschrieben hat.

Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Kannst du irgendetwas lesen, wenn sich eine angezeigte Zahl in der
> Sekunde 20 mal ändert?

Hmm, ich will aber nicht wissen wie sich die Zahl verändert sondern den 
aktuellen Zustand und ja das sehe ich dann.

Karl heinz Buchegger schrieb:
> Und selbst
> dann ist es von Vorteil wenn man dafür sorgt, dass die Einerstelle immer
> an der gleichen Stelle auftaucht, die Zehnerstelle immer an der gleichen
> Stelle auftaucht etc.

habe ich jeh was anderes behauptet Karl?

Gruß Bro

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Brocken Sei schrieb:

>> Und selbst
>> dann ist es von Vorteil wenn man dafür sorgt, dass die Einerstelle immer
>> an der gleichen Stelle auftaucht, die Zehnerstelle immer an der gleichen
>> Stelle auftaucht etc.
>
> habe ich jeh was anderes behauptet Karl?

Es spielt keine Rolle ob du das behauptet hast oder nicht. Programmiert 
hast du es jedenfalls nicht.

Wenn am LCD

    +---+---+---+---+---+---+---+---+
    | 1 | 0 | 0 | 0 |   |   |   |   |
    +---+---+---+---+---+---+---+---+

also 1000 steht und du schreibst im nächsten Schleifendurchlauf eine 999 
beginnend mit dem linken Rand drüber, dann steht da

    +---+---+---+---+---+---+---+---+
    | 9 | 9 | 9 | 0 |   |   |   |   |
    +---+---+---+---+---+---+---+---+

also 9990, weil ja niemand die letzte 0 von den 1000 mit einem 
Leerzeichen überschrieben hat.

Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> (*) stimmt ja eigentlich gar nicht.
> Du klatscht ja die 5 Zahlen mit Full Speed um jeweils 4 Zeichen versetzt
> (!) aufs LCD und erst dann wird eine winzige Pause eingelegt.

Richtig.

Gruß Bro

Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Und ja: Da du das LCD nie löscht, überschreibst du nur.

richtig, deshalb habe ich auch auf 1.1 formatiert. Ich komm sowieso nie 
über die 5V.

Gruß Bro

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Probier mal diese Variante. Die sorgt wenigstens dafür, dass die Zahlen 
immer mit einer konstanten Feldbreite im Buffer abgebildet werden. 
Dann sind wenigstens die Dezimalpunkte immer an derselben Stelle.
 while(1)
  {
    zaehlerLCD = 0;
    for(zaehlerVal = 0; zaehlerVal < 5; zaehlerVal++)
    {
      lcd_setcursor( zaehlerLCD, 0 );
      sprintf(Buffer, "%6.11f ", (double)GetADC_8bit(zaehlerVal));
      lcd_string(Buffer);
      zaehlerLCD += 6; 
    }

    _delay_ms(50);
  }

Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Es spielt keine Rolle ob du das behauptet hast oder nicht. Programmiert
> hast du es jedenfalls nicht.

Was du da redest..., wie kommt du immer auf so was? Dieses Programm habe 
ich mir überlegt mit !allem! drum und dran! Und ich finde ich habe mich 
sehr in der Programmiersprache C befreundet, denn ich versteh alles von 
meinem Programm, jede Zeile, frag mich doch wenn du mir nicht glaubst.

Ich hatte ja auch erwähnt dass ich nicht nur einen Fehler habe.
Falls es dich interessiert, so schauts dann aus:
#include <stdio.h>
#include <stdint.h>
#include <avr/io.h>
#include <string.h>
#include <util/delay.h>
#include <string.h>
#include <avr/signal.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <inttypes.h>
#include <math.h>

//Definitionen--------------------------------------------------------
#define ON 200   //Motor ein für PWM
#define OFF 0  //Motor aus für PWM
#define UART_BAUD_RATE 9600  //UART Baudrate
#define BufferMAX 100  //Buffer für Stringumwandlungen und Typumwandlungen
#define Ta 0.01f //Parameter für PID Algorithmus
#define ADC_Korr(ReferenceVoltage,BitMode) ((ReferenceVoltage)/(pow(2,BitMode)))

//Deklarierte Funktionen----------------------------------------------
uint8_t GetADC_8bit(uint8_t Chanel);

//Sub-Routines--------------------------------------------------------
#include "UART_Init.h"
#include "lcd-routines.h"
#include "Unterprogramme.h"
//--------------------------------------------------------------------

static volatile int y, esum, ealt, Regeldifferenz;
#define Kp 0  //Reglerparameter Proportional
#define Ki 0  //Reglerparameter Integral
#define Kd 0  //Reglerparameter Differncial
//Main-Program--------------------------------------------------------
int main()
{
  //Deklarierte Variablen im RAM:
  unsigned int Sensor0, Sensor1, Sensor2, Sensor3, Sensor4, zaehlerLCD, zaehlerVal;
  char Buffer[BufferMAX] = { 0 };

  //Deklarierte Variablen im EEPROM:

  //LCD init:
  lcd_init();
  lcd_clear();

  //UART_init:
  uart_init(UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU));

  //ADC-Init:
  ADMUX |= (1<<REFS0); //Refernz Intern-AVCC mit Kondensator gegen GND
  ADMUX |= (1<<ADLAR); //8Bit Modus ein
  ADCSRA |= (1<<ADEN) | (1<<ADPS2); //ADC Enable, Prescaler = 16

  //Timer/Counter0 Konfiguration:
  TCCR0 &=~ ((1<<WGM00) | (1<<WGM01)); //Normal-Modus
  TCCR0 |= (1<<CS01); //Prescaler = 8
  TIMSK |= (1<<TOIE0); //Interrupt enable --> Overflow

  //Timer/Counter1 Konfiguration:
  TCCR1A |= (1<<WGM10); TCCR1B |= (1<<WGM12); //PWM Mode = 8bit Fast PWM
  TCCR1B |= (1<<CS10); // Prescaler = 1024, da Motortreiber!
  TCCR1A |= (1<<COM1A1) | (1<<COM1B1) ; //Nicht invertierend

  //Ein-/Ausgabe:
  DDRB = 0b00001111;  //Motoren
  PORTB = 0b00001010; //Rotation of Motors in same direct

  DDRD |= (1<<PD4) | (1<<PD5); //PWM Kanäle als Ausgang

  //Enable Interrupt:
  sei();

  //Read EEPROM:*****************************

  //*****************************************

  //Main-Loop:*********************************************************************
  while(1)
  {
    for(zaehlerLCD = 0, zaehlerVal = 0; zaehlerVal < 5; zaehlerLCD += 4, zaehlerVal++)
    {
      lcd_setcursor(zaehlerLCD, 1);
      sprintf(Buffer, "%1.1f", (double)GetADC_8bit(zaehlerVal)*ADC_Korr(5,8));
      lcd_string(Buffer);
    }
    _delay_ms(50);
  }
  //back***************************************************************************
  return 0;
}

ISR(TIMER0_OVF_vect)
{
  static int e;
  e = Regeldifferenz;          //Regeldifferenz = Führungsgröße - Rückführgröße
  esum = esum + e;                //Integration I-Anteil
  y = Kp*e + Ki*Ta*esum + (Kd*((e -ealt)/Ta));  //PID-Regelalgorithmus
  ealt = e;                    //Differzenteil
}


Gruß Bro

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Brocken Sei schrieb:
> Karl heinz Buchegger schrieb:
>> Und ja: Da du das LCD nie löscht, überschreibst du nur.
>
> richtig, deshalb habe ich auch auf 1.1 formatiert.

Wo hast du das?

Ausserdem ist 1.1 Blödsinn.

Die Zahl vor dem Punkt gibt die Gesamtzahl an Zeichen an, inklusive 
Vorzeichen und Dezimalpunkt. Die Zahl nach dem Punkt gibt an wieviele 
Stellen davon Nachkommastellen sein sollen.

1.1 ist daher Blödsinn. Du kannst nicht eine Kommazahl mit einem 
Deezimalpunkt und einer Nachkommastelle in einerm Zeichenfeld mit der 
Gesamtbreite von 1 Zeichen unterbringen.

Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Probier mal diese Variante. Die sorgt wenigstens dafür, dass die Zahlen
> immer mit einer konstanten Feldbreite im Buffer abgebildet werden.
> Dann sind wenigstens die Dezimalpunkte immer an derselben Stelle.
>  while(1)
>   {
>     zaehlerLCD = 0;
>     for(zaehlerVal = 0; zaehlerVal < 5; zaehlerVal++)
>     {
>       lcd_setcursor( zaehlerLCD, 0 );
>       sprintf(Buffer, "%6.11f ", (double)GetADC_8bit(zaehlerVal));
>       lcd_string(Buffer);
>       zaehlerLCD += 6;
>     }
>
>     _delay_ms(50);
>   }


siehe:

Autor: Brocken Sei (Gast)
Datum: 22.08.2010 23:59

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Brocken Sei schrieb:

> siehe:
>
> Autor: Brocken Sei (Gast)
> Datum: 22.08.2010 23:59

In jedem Code davor war das noch nicht so.
Und meine Aufforderung nach Formatierbreiten war noch ehe du deinen Code 
gepostet hast. Ansonsten hättest du dich in deiner Antwort, in der zum 
ersten mal Formatierbreiten vorhanden sind, nicht darauf beziehen 
können.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Brocken Sei schrieb:

> Was du da redest..., wie kommt du immer auf so was?

Weil ich mir den Code ansehe, den du postest :-)

> Dieses Programm habe
> ich mir überlegt mit !allem! drum und dran! Und ich finde ich habe mich
> sehr in der Programmiersprache C befreundet

Ja, wird schon.

Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> In jedem Code davor war das noch nicht so.
> Und meine Aufforderung nach Formatierbreiten war noch ehe du deinen Code
> gepostet hast. Ansonsten hättest du dich in deiner Antwort, in der zum
> ersten mal Formatierbreiten vorhanden sind, nicht darauf beziehen
> können.

Nun ja, ich hatte gedacht, dass das Thema erledigt war da ich es doch 
schon schaffte. Ich glaub jetzt unterstellst du mir wieder dass ich das 
nur hinbekommen habe weil du mir das so erklärst hast oder darauf 
hingewiesen hast. Ich muss aber leider sagen, dass ich das schon fertig 
hatte als ich geschrieben hatte dass ich fertig war. Und nach der ersten 
Antwort wusste ich schon dass die Leute nicht heiß darauf wären meinen 
Code zu analysieren.
Sry wegen der Verwirrung, aber alle Ideen hatte ich, und du hast 
versucht mir zu helfen, und dafür danke ich dir, aber nur in Grenzen, 
denn du kannst es scheinbar nicht widerstehen mich fertig zu machen, 
aber keine Angst, ich lass mich nicht fertig machen

Gruß Bro

Autor: Brocken Sei (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Ja, wird schon.

Jo, Thx

Gute Nacht
Bro

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Brocken Sei schrieb:

> Nun ja, ich hatte gedacht, dass das Thema erledigt war da ich es doch
> schon schaffte.

Nein. Überhaupt nicht.
Aber des öfteren überschneiden sich auch schon mal unsere Schreibzeiten. 
Da ist es dann immer gut, ehe man eine geharnischte Antwort schreibt 
auch mal auf die Postingzeit zu achten. Wenn die ein paar Minuten 
auseinanderliegen anzunehmen, dass man mehr oder weniger gleichzeitig 
geschrieben hat.

> hingewiesen hast. Ich muss aber leider sagen, dass ich das schon fertig
> hatte als ich geschrieben hatte dass ich fertig war.

Das konnte ich so nicht aus deiner Antwort rauslesen.

> Sry wegen der Verwirrung, aber alle Ideen hatte ich, und du hast
> versucht mir zu helfen, und dafür danke ich dir, aber nur in Grenzen,
> denn du kannst es scheinbar nicht widerstehen mich fertig zu machen,
> aber keine Angst, ich lass mich nicht fertig machen

:-)
Jetzt weißt du wenigstens, wie das mit der Formatierung und der 
Feldbreite funktioniert und du wirst es nie mehr vergessen. Eines sollte 
man noch erwähnen: Wenn die Feldbreite nicht ausreicht, wie bei dir, 
dann vergrößert sie printf auch eigenmächtig. Daher hat 1.1 zwar keinen 
Fehler produziert, aber es hat auch nicht das getan was du wolltest.
:-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.