Forum: Mikrocontroller und Digitale Elektronik LCD_Formarierungsalgorithmus-sprintf


von Brocken Sei (Gast)


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:
1
#include <stdio.h>
2
#include <stdint.h>
3
#include <avr/io.h>
4
#include <string.h>
5
#include <util/delay.h>
6
#include <string.h>
7
#include <avr/signal.h>
8
#include <avr/pgmspace.h>
9
#include <avr/interrupt.h>
10
#include <avr/eeprom.h>
11
#include <inttypes.h>
12
#include <math.h>
13
14
//Definitionen--------------------------------------------------------
15
#define ON 200   //Motor ein für PWM
16
#define OFF 0  //Motor aus für PWM
17
#define UART_BAUD_RATE 9600  //UART Baudrate
18
#define BufferMAX 100  //Buffer für Stringumwandlungen und Typumwandlungen
19
#define Ta 0.01f //Parameter für PID Algorithmus
20
#define ADC_Korr(ReferenceVoltage,BitMode) ((ReferenceVoltage)/(pow(2,BitMode)))
21
22
//Deklarierte Funktionen----------------------------------------------
23
uint8_t GetADC_8bit(uint8_t Chanel);
24
25
//Sub-Routines--------------------------------------------------------
26
#include "UART_Init.h"
27
#include "lcd-routines.h"
28
#include "Unterprogramme.h"
29
//--------------------------------------------------------------------
30
31
static volatile int y, esum, ealt, Regeldifferenz;
32
#define Kp 0  //Reglerparameter Proportional
33
#define Ki 0  //Reglerparameter Integral
34
#define Kd 0  //Reglerparameter Differncial
35
//Main-Program--------------------------------------------------------
36
int main()
37
{
38
  //Deklarierte Variablen im RAM:
39
  unsigned int Sensor0, Sensor1, Sensor2, Sensor3, Sensor4, zaehlerLCD, zaehlerVal;
40
  char Buffer[BufferMAX] = { 0 };
41
42
  //Deklarierte Variablen im EEPROM:
43
44
  //LCD init:
45
  lcd_init();
46
  lcd_clear();
47
48
  //UART_init:
49
  uart_init(UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU));
50
51
  //ADC-Init:
52
  ADMUX |= (1<<REFS0); //Refernz Intern-AVCC mit Kondensator gegen GND
53
  ADMUX |= (1<<ADLAR); //8Bit Modus ein
54
  ADCSRA |= (1<<ADEN) | (1<<ADPS2); //ADC Enable, Prescaler = 16
55
56
  //Timer/Counter0 Konfiguration:
57
  TCCR0 &=~ ((1<<WGM00) | (1<<WGM01)); //Normal-Modus
58
  TCCR0 |= (1<<CS01); //Prescaler = 8
59
  TIMSK |= (1<<TOIE0); //Interrupt enable --> Overflow
60
61
  //Timer/Counter1 Konfiguration:
62
  TCCR1A |= (1<<WGM10); TCCR1B |= (1<<WGM12); //PWM Mode = 8bit Fast PWM
63
  TCCR1B |= (1<<CS10); // Prescaler = 1024, da Motortreiber!
64
  TCCR1A |= (1<<COM1A1) | (1<<COM1B1) ; //Nicht invertierend
65
66
  //Ein-/Ausgabe:
67
  DDRB = 0b00001111;  //Motoren
68
  PORTB = 0b00001010; //Rotation of Motors in same direct
69
70
  DDRD |= (1<<PD4) | (1<<PD5); //PWM Kanäle als Ausgang
71
72
  //Enable Interrupt:
73
  sei();
74
75
  //Read EEPROM:*****************************
76
77
  //*****************************************
78
79
  //Main-Loop:*********************************************************************
80
  while(1)
81
  {
82
    for(zaehlerLCD = 0, zaehlerVal = 0; zaehlerVal < 5; zaehlerLCD += 4, zaehlerVal++)
83
    {
84
      lcd_setcursor(zaehlerLCD, 0);
85
      sprintf(Buffer, "%.1f ", (double)GetADC_8bit(zaehlerVal));
86
      lcd_string(Buffer);
87
    }
88
    _delay_ms(50);
89
  }
90
  //back***************************************************************************
91
  return 0;
92
}
93
94
ISR(TIMER0_OVF_vect)
95
{
96
  static int e;
97
  e = Regeldifferenz;          //Regeldifferenz = Führungsgröße - Rückführgröße
98
  esum = esum + e;                //Integration I-Anteil
99
  y = Kp*e + Ki*Ta*esum + (Kd*((e -ealt)/Ta));  //PID-Regelalgorithmus
100
  ealt = e;                    //Differzenteil
101
}

Gruß Bro

von Brocken Sei (Gast)


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.

von holger (Gast)


Lesenswert?

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

Du redest wirres Zeug.

von Brocken Sei (Gast)


Lesenswert?

holger schrieb:
> Du redest wirres Zeug.

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

Gruß Bro

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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

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-Tutorial/LCD-Ansteuerung

von Brocken Sei (Gast)


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

von Karl H. (kbuchegg)


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.

von Brocken Sei (Gast)


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

von Karl H. (kbuchegg)


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.

von Brocken Sei (Gast)


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

von Brocken Sei (Gast)


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

von Karl H. (kbuchegg)


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.
1
 while(1)
2
  {
3
    zaehlerLCD = 0;
4
    for(zaehlerVal = 0; zaehlerVal < 5; zaehlerVal++)
5
    {
6
      lcd_setcursor( zaehlerLCD, 0 );
7
      sprintf(Buffer, "%6.11f ", (double)GetADC_8bit(zaehlerVal));
8
      lcd_string(Buffer);
9
      zaehlerLCD += 6; 
10
    }
11
12
    _delay_ms(50);
13
  }

von Brocken Sei (Gast)


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:
1
#include <stdio.h>
2
#include <stdint.h>
3
#include <avr/io.h>
4
#include <string.h>
5
#include <util/delay.h>
6
#include <string.h>
7
#include <avr/signal.h>
8
#include <avr/pgmspace.h>
9
#include <avr/interrupt.h>
10
#include <avr/eeprom.h>
11
#include <inttypes.h>
12
#include <math.h>
13
14
//Definitionen--------------------------------------------------------
15
#define ON 200   //Motor ein für PWM
16
#define OFF 0  //Motor aus für PWM
17
#define UART_BAUD_RATE 9600  //UART Baudrate
18
#define BufferMAX 100  //Buffer für Stringumwandlungen und Typumwandlungen
19
#define Ta 0.01f //Parameter für PID Algorithmus
20
#define ADC_Korr(ReferenceVoltage,BitMode) ((ReferenceVoltage)/(pow(2,BitMode)))
21
22
//Deklarierte Funktionen----------------------------------------------
23
uint8_t GetADC_8bit(uint8_t Chanel);
24
25
//Sub-Routines--------------------------------------------------------
26
#include "UART_Init.h"
27
#include "lcd-routines.h"
28
#include "Unterprogramme.h"
29
//--------------------------------------------------------------------
30
31
static volatile int y, esum, ealt, Regeldifferenz;
32
#define Kp 0  //Reglerparameter Proportional
33
#define Ki 0  //Reglerparameter Integral
34
#define Kd 0  //Reglerparameter Differncial
35
//Main-Program--------------------------------------------------------
36
int main()
37
{
38
  //Deklarierte Variablen im RAM:
39
  unsigned int Sensor0, Sensor1, Sensor2, Sensor3, Sensor4, zaehlerLCD, zaehlerVal;
40
  char Buffer[BufferMAX] = { 0 };
41
42
  //Deklarierte Variablen im EEPROM:
43
44
  //LCD init:
45
  lcd_init();
46
  lcd_clear();
47
48
  //UART_init:
49
  uart_init(UART_BAUD_SELECT(UART_BAUD_RATE, F_CPU));
50
51
  //ADC-Init:
52
  ADMUX |= (1<<REFS0); //Refernz Intern-AVCC mit Kondensator gegen GND
53
  ADMUX |= (1<<ADLAR); //8Bit Modus ein
54
  ADCSRA |= (1<<ADEN) | (1<<ADPS2); //ADC Enable, Prescaler = 16
55
56
  //Timer/Counter0 Konfiguration:
57
  TCCR0 &=~ ((1<<WGM00) | (1<<WGM01)); //Normal-Modus
58
  TCCR0 |= (1<<CS01); //Prescaler = 8
59
  TIMSK |= (1<<TOIE0); //Interrupt enable --> Overflow
60
61
  //Timer/Counter1 Konfiguration:
62
  TCCR1A |= (1<<WGM10); TCCR1B |= (1<<WGM12); //PWM Mode = 8bit Fast PWM
63
  TCCR1B |= (1<<CS10); // Prescaler = 1024, da Motortreiber!
64
  TCCR1A |= (1<<COM1A1) | (1<<COM1B1) ; //Nicht invertierend
65
66
  //Ein-/Ausgabe:
67
  DDRB = 0b00001111;  //Motoren
68
  PORTB = 0b00001010; //Rotation of Motors in same direct
69
70
  DDRD |= (1<<PD4) | (1<<PD5); //PWM Kanäle als Ausgang
71
72
  //Enable Interrupt:
73
  sei();
74
75
  //Read EEPROM:*****************************
76
77
  //*****************************************
78
79
  //Main-Loop:*********************************************************************
80
  while(1)
81
  {
82
    for(zaehlerLCD = 0, zaehlerVal = 0; zaehlerVal < 5; zaehlerLCD += 4, zaehlerVal++)
83
    {
84
      lcd_setcursor(zaehlerLCD, 1);
85
      sprintf(Buffer, "%1.1f", (double)GetADC_8bit(zaehlerVal)*ADC_Korr(5,8));
86
      lcd_string(Buffer);
87
    }
88
    _delay_ms(50);
89
  }
90
  //back***************************************************************************
91
  return 0;
92
}
93
94
ISR(TIMER0_OVF_vect)
95
{
96
  static int e;
97
  e = Regeldifferenz;          //Regeldifferenz = Führungsgröße - Rückführgröße
98
  esum = esum + e;                //Integration I-Anteil
99
  y = Kp*e + Ki*Ta*esum + (Kd*((e -ealt)/Ta));  //PID-Regelalgorithmus
100
  ealt = e;                    //Differzenteil
101
}

Gruß Bro

von Karl H. (kbuchegg)


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.

von Brocken Sei (Gast)


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

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


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.

von Brocken Sei (Gast)


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

von Brocken Sei (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Ja, wird schon.

Jo, Thx

Gute Nacht
Bro

von Karl H. (kbuchegg)


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.
:-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.