www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik String an LCD ausgeben


Autor: Marcel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte gerne eine Variable an ein Display (EA W204-BNLED via Channaa 
I2C- LCD Adapter) ausgeben. Dazu muss ich aber erst einen String an das 
LCD senden können.

Ich habe nun einfach den Code des String-Unterprogrammes aus dem 
Tutorial übernommen und angepasst.
Hier der betroffene Ausschnitt aus dem ganzen Programm (siehe Anhang):
void i2c_writes(char *data)
{
  i2c_start_wait(LCD+I2C_WRITE);         // I2C Adresse und "Schreib Modus" setzen
  i2c_write(0x76);                       // Schreib Adresse 0x76 (String)
    while(*data) 
  {
      i2c_write('*data');
      data++;
    }
  i2c_stop();                            // I2C Stop
}

Nun erhalte ich beim Kompilieren die Warnung "warning character constant 
too long for its type"

Das Display zeigt dann bloss Spannung A an wobei das A blinkt. TEST 
erscheint nicht.

Was läuft hier schief?

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

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:

>       i2c_write('*data');

Ohne '
Du willst ja das Zeichen senden, welches an der Position data
gespeichert ist

        i2c_wwrite( *data );

> Nun erhalte ich beim Kompilieren die Warnung "warning character constant
> too long for its type"

Logisch. ' steht in C für dies_ist_ein_Character, so wie
beispielsweise 'A', 'B' oder auch '9'
'*data' ist aber kein einzelnes Zeichen.

Aber das willst du ja auch gar nicht, du willst das Zeichen
senden, welches an der Speicheradresse die in data steht.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:

>   while(*data)
>   {
>       i2c_write('*data');
                  ^     ^

Lass das weg. Das käme nur hin, wenn ein Buchstabenkonstante oder eine 
Zifferkonstante direkt als Funktionsargument übergeben würde.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe ich geändert der Fehler ist weg aber TEST erscheint weiterhin 
nicht.

Marcel

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lass mal display() weg. Möglicherweise überschreibt/löscht das dir das 
TEST.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So jetzt klappts, hat aber noch nen kleinen Fehler. Poste nach dem 
Mittag den neuen Code und das Problem.

Mahlzeit :)

Autor: Marcel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Also hier die neueste Version, habe noch einen Uart Test eingebaut 
welcher auch funktioniert. Die Ausgabe des Strings funktioniert nun 
jedoch erhalte ich wieder 2 Warnungen:

../ipa_2902_v01.c:37: warning: passing argument 1 of 'i2c_write' makes 
integer from pointer without a cast
../ipa_2902_v01.c: In function 'i2c_writes':
../ipa_2902_v01.c:45: warning: passing argument 1 of 'i2c_writec' makes 
pointer from integer without a cast

Betroffen sind die Unterprogramme:
void i2c_writec(char *data)
{
  i2c_start_wait(LCD+I2C_WRITE);         // I2C Adresse und "Schreib Modus" setzen
  i2c_write(0x76);            // Schreib Adresse 0x76 (String)
  i2c_write(data);
  i2c_stop();
}

void i2c_writes(char *data)
{
    while(*data) 
  {
      i2c_writec(*data);
      data++;
    }
}

Die ausgabe des Strings funktioniert zwar, jedoch erscheint jeweils das 
2te Zeichen des Strings nicht, in diesem Fall ACDEFE....

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

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:

>
> void i2c_writec(char *data)

Hier willst du keinen Pointer haben.
In data steht bereits der auszugebende Character.

void i2c_writec(char data)

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich "void i2c_writec(char data)" schreibe kriege ich einen Fehler, 
wenn ich einfach nur den Pointer weglass kriege ich nur noch eine 
Warnung aber `bcde... anstelle ABCDE.

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

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:
> Wenn ich "void i2c_writec(char data)" schreibe kriege ich einen Fehler,

Welchen?
Wo?

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
../ipa_2902_v01.c:50: error: expected expression before 'char'

in der Zeile die ich geändert habe also "void i2c_writec(char data)"

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

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:
> ../ipa_2902_v01.c:50: error: expected expression before 'char'
>
> in der Zeile die ich geändert habe also "void i2c_writec(char data)"

Das ergibt so noch keinen Sinn.
Zeig mal mehr von der Umgebung an dieser Stelle.
Oder einfach den kompletten Code.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier die aktuellste Version, Display() habe ich erstmal auskommentiert, 
nun ist neben Uart noch ein ADC hinzugekommen.

Die Umgebung:
void i2c_writec(char *data)
{
  i2c_start_wait(LCD+I2C_WRITE);             // I2C Adresse und "Schreib Modus" setzen
  i2c_write(0x76);                // Schreib Adresse 0x76 (String)
  i2c_write(data);                
  i2c_stop();
}

void i2c_writes(char *data)
{
    while(*data) 
  {
      i2c_writec(data);
      data++;
    }
}

void display_init(void)
{
  i2c_start_wait(LCD+I2C_WRITE);             // I2C Adresse und "Schreib Modus" setzen
  i2c_write(0x6C);                // Display Konfiguration
  i2c_write(0x0C);                // Display ein, Cursor aus
  i2c_stop();                    // I2C Stop
  
  i2c_start_wait(LCD+I2C_WRITE);             // I2C Adresse und "Schreib Modus" setzen
  i2c_write(0x61);                // Display komplett löschen
  i2c_stop();                    // I2C Stop

  i2c_writes("ABCDEFG");              // String an LCD  
}

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void i2c_writec(char data)
{
  i2c_start_wait(LCD+I2C_WRITE);  // I2C Adresse und "Schreib Modus" 
setzen
  i2c_write(0x76);                // Schreib Adresse 0x76 (String)
  i2c_write(data);
  i2c_stop();
}

void i2c_writes(char *data)
{
  while(*data)
  {
    i2c_writec(*data);
    data++;
  }
}

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ichs so schreibe wie Stefan erhalte ich keine Fehler und auch keine 
Warnung. Der Text ist auch grossgeschrieben wie gewünscht jedoch fehlt 
wie immer das zweite Zeichen des Strings also ACDEF statt ABCDEF. Sehr 
merkwürdig.

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

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:
> Wenn ichs so schreibe wie Stefan erhalte ich keine Fehler und auch keine
> Warnung.

Liegt, daran, dass zumindest die String-Behandlung damit korrekt
ist.

> Der Text ist auch grossgeschrieben wie gewünscht jedoch fehlt
> wie immer das zweite Zeichen des Strings also ACDEF statt ABCDEF. Sehr
> merkwürdig.

Könnte das irgend ein I2C-Problem sein?

Was ist mit dem Code 0x76, der in deinem Code immer wieder
auftaucht. Könnte der damit etwas zu tun haben?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein anderer Code im Programm schreibt vielleicht auf die Stelle 
'ABCDEF' ein ' A' und dann sieht es aus wie ' ACDEF'.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erst kurz zu Stefans Beitrag:
Habe ich derzeit auskommentiert, schreibt aber auch erst an 10ter Stelle 
das blinkende A wie ich es auch möchte.

Jetzt zu Karl Heinz:
Das LCD Display ist über den Adapter des Ingenieurbüros Channaa 
angeschlossen. Ich muss möglichst viele Port Pins freihalten daher habe 
ich mich überhaupt für I2C entschieden.

Mit dem Code 0x76 gebe ich nun den Befehl WriteString siehe Datenblatt 
Seite 17: http://www.channaa.com/files/I2C_LCD_Adapter_V10_Rev5.PDF

In der Ursprungsversion sah das ganze so aus:
  i2c_start_wait(LCD+I2C_WRITE);         // I2C Adresse und "Schreib Modus" setzen
  i2c_write(0x76);            // Schreib Adresse 0x76 (String)
  i2c_write('A');             // A
  i2c_write('B');             // B
  i2c_write('C');             // C
  i2c_write('D');             // D
  i2c_stop();                 // I2C Stop

So funktioniert es, auch jetzt noch.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was sagt dein Debugger?



Mann könnte es aber auch so machen:
void i2c_writec(char *data)
{
  i2c_start_wait(LCD+I2C_WRITE);
  i2c_write(0x76);              
  i2c_write(*data);                
  i2c_stop();
}

void i2c_writes(char *data)
{
    while(*data) 
  {
      i2c_writec(data);
      data++;
    }
}

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

Bewertung
0 lesenswert
nicht lesenswert
Gast wrote:

> Mann könnte es aber auch so machen:

Könnte man, ist aber nicht so praktikabel.
int main()
{
  ...
  i2c_writec( 'a' );
}

geht dann erst mal in die Hose.
int main()
{
  ...
  i2c_writec( &'a' );
}

geht auch nicht

und
int main()
{
  char MyA = 'a';
  ...
  i2c_writec( &MyA );
}

ist ja wohl der Albtraum schlechthin :-)

So wie es ist, also einem char Argument bei i2c_writec
ist das schon in Ordnung.

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

Bewertung
0 lesenswert
nicht lesenswert
@Marcel

Was passiert, wenn du nicht die WriteString sondern die
CharToLCD Funktion benutzt
void i2c_writec(char data)
{
  i2c_start_wait(LCD+I2C_WRITE);
  i2c_write(0x64);              
  i2c_write(data);                
  i2c_stop();
}

void i2c_writes(char *data)
{
  while(*data) 
  {
      i2c_writec(*data);
      data++;
  }
}

Im übrigen würde ich da sowieso 2 getrennte Funktionen dafür
einsetzen, wenn dir der I2C Adapter das schon so anbietet
void i2c_writec(char data)
{
  i2c_start_wait(LCD+I2C_WRITE);
  i2c_write(0x64);              
  i2c_write(data);                
  i2c_stop();
}

void i2c_writes(char *data)
{
  i2c_start_wait(LCD+I2C_WRITE);
  i2c_write(0x76);              

  while(*data) 
  {
      i2c_write(*data);
      data++;
  }

  i2c_stop();
}

Probier mal beide Varianten aus.

(Ich finde es nicht sehr schlau, wenn du in ein Testprogramm
für die LCD gleich UART und ADC mit einbaust. Je mehr Subsysteme
aktiv sind, desto mehr Fehler kann man sich einhandeln. Test-
programme sollten eigentlich immer so einfach wie nur irgendwie
möglich sein)

Autor: Marcel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

so habe heute morgen mal beide Varianten ausprobiert, die erste 
Funktionierte nicht, "frass" erneut das 2te Zeichen.

Die zweite musste ich noch etwas anpassen und nun läuft es:
void i2c_writec(char *data)
{
  i2c_start_wait(LCD+I2C_WRITE);             // I2C Adresse und "Schreib Modus" setzen
  i2c_write(0x64);                // Schreib Adresse 0x76 (String)
  i2c_write(*data);                
  i2c_stop();
}

void i2c_writes(char *data)
{
  i2c_start_wait(LCD+I2C_WRITE);
  i2c_write(0x76);

    while(*data) 
  {
      i2c_write(*data);
      data++;
    }
  i2c_stop();
}

Besten Dank für die Hilfe :)

Marcel

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

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:
> Hallo,
>
> so habe heute morgen mal beide Varianten ausprobiert, die erste
> Funktionierte nicht, "frass" erneut das 2te Zeichen.
>
> Die zweite musste ich noch etwas anpassen und nun läuft es:
>
> void i2c_writec(char *data)


Wie oft denn noch:
Das hier ist Unsinn.
Diese Funktion soll einen einzigen Character aufs Display
ausgeben. Dazu ist ein Pointer kontraproduktiv, weil du
die Funktion dann nicht vernünftig (beim Aufruf) benutzen kannst.

[C]
void i2c_writec(char data)
{
  i2c_start_wait(LCD+I2C_WRITE);             // I2C Adresse und "Schreib Modus" setzen
  i2c_write(0x64);                // Schreib Adresse 0x76 (String)
  i2c_write(data);                
  i2c_stop();
}

Das hier kannst du zb so verwenden
int main()
{
  ...
  i2c_writec( 'A' );
  ...
}

Deine Version muss so benutzt werden und kann auch nicht
anders benutzt werden:
int main()
{
  char a_char = 'a';

  ...
  i2c_writec( &a_char );
  ...
}

Autor: Marcel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

hattest recht habe ich noch angepasst.

Nun versuche ich den ADC Wert auf dem Display anzuzeigen. Die Ausgabe 
einer Variable hat auf Anhieb geklappt, doch der AD Wandler mach noch 
macken.

Die ADC Subroutine habe ich aus dem Tutorial übernommen und für meine 
Zwecke angepasst (8MHz, AVREF als Referenz). Nun gibt er mir auf dem 
Display aber immer 1023 also quasi 5V aus. Egal ob ich auf den Kanal0 
via Poti zwischen 0-5V habe.

Sieht jemand den Fehler? Dürfe in der Sensor Subroutine liegen:
// Analog-Digital Wandler einlesen
uint16_t Sensor(uint8_t mux)
{
    uint8_t i;                    // Varaible i
   uint16_t result;                // Variable result
 
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);   // ADC aktivieren und Frequenzvorteiler auf 64 

   ADMUX = mux;                              // Kanal waehlen
  ADCSRA |= (1<<ADSC);                      // "Aufwärm" Wandlung
   while ( ADCSRA & (1<<ADSC) ){}            // auf Abschluss der Wandlung warten
   result = ADCW;                    // ADCW muss einmal gelesen werden,
                                    // sonst wird Ergebnis der nächsten Wandlung
                                    // nicht übernommen.
   
   /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
   result = 0; 
   for( i=0; i<4; i++ )
   {
     ADCSRA |= (1<<ADSC);                  // eine Wandlung "single conversion"
      while ( ADCSRA & (1<<ADSC) ) {}        // auf Abschluss der Konvertierung warten
      result += ADCW;                  // Wandlungsergebnisse aufaddieren
   }
 
   ADCSRA &= ~(1<<ADEN);                    // ADC deaktivieren

   result /= 4;                             // Summe durch vier teilen = arithm. Mittelwert
   return result;
}

Marcel

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

Bewertung
0 lesenswert
nicht lesenswert
Wie ist AVRef beschaltet?

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit 5V über L/C Netzwerk wie es das Datenblatt vorschlägt.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ne sorry AVCC ist so beschaltet, AVRev ist über einen 1uF auf GND.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Argh, danke geht natülich nicht wenn ich 0V als Referenz nehme -.-

ADMUX |= (1<<REFS0);

Und es klappte.

Autor: Marcel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich bins nochmal. Nun möchte ich ja die Spannung die ich einlese auch 
noch auf dem Display ausgeben. Mit dem jetztigen Code geht das schonmal 
jedoch nur ganzzahlig. Das heisst mit dem Code so wie er angehängt ist 
wird mir 0-5 angezeigt, kommentiere ich die Umrechnung aus wird mir 
0-1023 angezeigt.

Gehe ich richtig in der Annahme das ich für Nachkommastellen mit 
Festkommaarithmetik arbeiten muss wie es im Tutorial steht? Leider wird 
im Tutorial nur Assembler Code verwendet und ich kann die als Bild 
eingefügten Formeln im Tutorial nicht lesen da sie flasch dargestellt 
werden.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

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

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:

> Gehe ich richtig in der Annahme das ich für Nachkommastellen mit
> Festkommaarithmetik arbeiten muss wie es im Tutorial steht? Leider wird
> im Tutorial nur Assembler Code verwendet und ich kann die als Bild
> eingefügten Formeln im Tutorial nicht lesen da sie flasch dargestellt
> werden.

Das Prinzip ist sehr einfach:
Wenn du anstelle von 5 mit 50 multiplizierst, dann erhältst du
nicht Zahlen von 0 bis 5 sondern von 0 bis 50. Im Prinzip
hast du dann schon eine Kommastelle, du musst nur bei der
Ausgabe dafür sorgen, daß zwischen erster und zweiter
Ausgabestelle ein Komma eingefügt wird. So wird dann aus 49
auf der Anzeige ein 4,9 und aus 12 wird 1,2. Vorsicht bei
Werten kleiner 10, musst du noch eine künstliche 0 davorstellen.
Denn aus 8 muss ja 0,8 werden.

Eine sehr simple, wenn auch rechenintensive Methode ist
zb. folgendes
    ....
    adcval *= 50;       // eine Nachkommastelle, daher 50
    adcval /= 1023;

    sprintf( buffer, "%d,%01d", adcval / 10, adcval % 10 );


PS: an deinen Kommentaren musst du noch arbeiten. Ein Kommentar ala

    adcval *= 5;       // mit 5 multiplizieren

ist ein sinnloser Kommentar. Da ist es besser du lässt ihn weg.
Das verwirrt dann wenigstens keinen, wenn du im Code die 5 mal
gegen etwas anderes austauschst und im Kommentar den Update vergisst.
Kommentare sollen nicht das erzählen, was ohnehin im Code bereits
steht. Jeder halbwegs C-mächtige Anfänger kann aus

   adcval *= 5;

in weniger als 2 Zehntelsekunden ablesen, dass hier adcval mit
5 multiplizert wird. Das brauchst du nicht kommentieren. Viel
interesanter ist warum adcval ausgerechnet mit 5 multipliziert
wird! Aber das steht, leider, leider, nicht im Kommentar.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe es mit deinem Vorschlag versucht klappt ganz gut ich erhalte aber 2 
Warnungen:

../ipa_2902_v01.c:118: warning: implicit declaration of function 
'sprintf'
../ipa_2902_v01.c:118: warning: incompatible implicit declaration of 
built-in function 'sprintf'

Wie kriege ich die noch weg?

Ausserdem möchte ich gerne noch eine zweite Nachkommastelle, dies habe 
ich versucht es klappt aber nicht:
adcval *= 500;                // adcval mit 500 multiplizieren
adcval /= 1023;                // adcval durch 1023 dividieren
sprintf(adc,"%d,%01d%001d",adcval/10,adcval%10,adcval%1); // Festkommaarithmetik

Bezüglich Komentar gebe ich dir Recht, dies werde ich in einer 
endgültigen Version noch anpassen.

Marcel

Autor: Marcel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier noch die aktuelle Version

Autor: FBI (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

da fehlt noch ein Headerfile:
#include <stdio.h>
Dann sollten auch die Warnungen weg sein.

CU

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast Recht FBI, Danke.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kennt jemand einen Link bezüglich der sprintf Syntax? Schaffe die 2te 
Nachkommastelle nicht :(

Autor: FBI (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wärs denn mit der avr-libc Doku?
http://www.nongnu.org/avr-libc

Die sollte sich aber eigentlich auch auf Deinem Rechner befinden!

Autor: Marcel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So nun läuft es, jedoch sind noch zwei Fehler zu beheben:

1. Bei 9mV ist die Anzeige noch 0.9V, erst wenn 10 mV erreicht sind wird 
die Stelle geschoben und die Anzeige wechselt auf 0.10V.
Wie kann ich nun noch die zusätzliche 0 erzeugen um 0.09V bei 9mV 
anzuzeigen.
uint32_t adcval;               // Variable adcval
char adc[20];                  // Variable adc
adcval = Sensor(0);            // adcval entspricht Kanal 0
adcval *= 500;                 // adcval mit 500 multiplizieren
adcval /= 1023;                // adcval durch 1023 dividieren
sprintf(adc,"%ld,%0ld",adcval/100,adcval%100); // Festkommaarithmetik

2. Die Angezeigte Spannung stimmt nicht mit der realen Spannung überein 
bei 4.3V werden bereits 5V angezeigt also 0.7V Offset je niedriger die 
Spannung desto kleiner der Offset. Die Rechnung (ADC*500)/1023 stimmt 
doch?

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich:
adcval *= 500;                 // adcval mit 500 multiplizieren
adcval /= 1023;                // adcval durch 1023 dividieren
in
adcval *= 432;                 // adcval mit 500 multiplizieren
adcval /= 1023;                // adcval durch 1023 dividieren

ändere so stimmen die Messwerte zwar duchs Band weg jedoch ist dann der 
Maximale Messwert natürlich bei 4.32V.

Gibt es noch einen Anderen Weg das anzugleichen?

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

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:
> So nun läuft es, jedoch sind noch zwei Fehler zu beheben:
>
> 1. Bei 9mV ist die Anzeige noch 0.9V, erst wenn 10 mV erreicht sind wird
> die Stelle geschoben und die Anzeige wechselt auf 0.10V.
> Wie kann ich nun noch die zusätzliche 0 erzeugen um 0.09V bei 9mV
> anzuzeigen.

Du hast die Doku zu sprintf (und Konsorten) immer noch nicht
gelesen. Sonst wüsstest du, dass du das mit dem Format String
hinbügeln kannst.

  sprintf( adc, "%ld,%02ld", ....
                      ^^
                      ||
                      |+--  Diese 2 bedeutet, dass die Ausgabe in
                      |     einem Feld der Breite 2 Zeichen gemacht
                      |     werden soll. 10 würde als als "10"
                      |     ausgegeben, wohingegen 9 als " 9" ausgegeben
                      |     wird
                      |
                      +---  Diese 0 bedeutet, dass führende Leerzeichen
                            in der Ausgabe, wie sie zb. bei " 9"
                            auftreten würden, durch 0 ersetzt werden.
                            eine Ausgabe von 9 würde also als "09"
                            ausgegeben.

Summa, summarum wird also dein 'Nachkommaanteil' in einem Feld
der Breite 2 ausgegeben, wobei führende Leerzeichen als '0'
ausgegeben werden.

wenn dein Wert also 209 ist, dann liefert 209/100 -> 2
und 209%100 -> 9

Zuerst werden die 2 ausgegeben, dann das ',' und dann die 9, wobei
die 9 als "09" ausgegeben werden. In Summe steht also dort "2,09"

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

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:

> 2. Die Angezeigte Spannung stimmt nicht mit der realen Spannung überein
> bei 4.3V werden bereits 5V angezeigt also 0.7V Offset je niedriger die
> Spannung desto kleiner der Offset. Die Rechnung (ADC*500)/1023 stimmt
> doch?

Miss mal deine Referenzspannung am Pin ARef nach.

Autor: Shin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe jetzt noch eine dritte Nachkommastelle hinzugefügt und zusätzlich 
die Breite festgelegt.
adcval *= 4320;                 // adcval mit 4320 multiplizieren
adcval /= 1023;                // adcval durch 1023 dividieren
sprintf(adc,"%ld,%3ld",adcval/1000,adcval%1000); // Festkommaarithmetik

Jetzt erhalte ich als Anzeige z.B 1.  2V oder 1. 23V. Das ist schonmal 
besser da alle Stellen fixiert sind jedoch wäre es schön wenn man nun 
noch die Leerschläge duch Nullen ersetzen kann.

Das zweite Problem mit den 4.32V konnte ich bisher auch noch nicht 
lösen.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah, die eine Null hat noch gefehlt, danke.

An ARef habe ich derzeit 0V da ich noch mit AVCC als Referenz arbeite. 
Diese Spannung hat etwas Brumm aber nicht so stark das es einen solchen 
Offset gibt. Am Montag erhalte ich noch eine Referenzspannung welche ich 
dann an ARev anschliesse.

Mein Kollege das Problem liege ev. beim Datenbereich, also das die Zahl 
zu gross wird. Was meinst du?

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

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:
> Ah, die eine Null hat noch gefehlt, danke.
>
> An ARef habe ich derzeit 0V da ich noch mit AVCC als Referenz arbeite.

Das macht nichts.
Wenn du AVcc als Referenz gewählt hast, wird diese Spannung an ARef
ausgegeben. Als Minimalbeschaltung sollte dann ein Kondensator
von ARef nach Masse geschaltet werden. So um die 100nF

> Mein Kollege das Problem liege ev. beim Datenbereich, also das die Zahl
> zu gross wird. Was meinst du?

Hab ich nicht kontrolliert. Aber rechne doch einfach mal nach.
Nimm einen Taschenrechner und vollzieh die Berechnung nach. Wenn
irgendwann auf deinem Taschenrechner eine Zahl größer als 32767
auftaucht, dann hast du ein Problem.

Sehe gerade beim Zurückscrollen:
Dein adcval ist ein uint32_t. Daher: Vergiss das mit den 32767.
Die Grenze liegt wesentlich höher und ist so sicher nicht zu
erreichen.
Ich bleibe dabei: Halte mal ein Voltmeter an den Pin ARef.
(Oszi wäre besser)

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, ja Kondensator ist drin. Nachgerechnet haben wir vorhin auch, 
kein Problem.

Hast Recht, sowohl an ARev wie auch an AVCC messe ich mit Scope bloss 
4.4-4.5V, merkwürdig. Als Speisung habe ich einen AC/DC Wandler von 
Traco mit 5V/3A also daran dürfte es nicht liegen.

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.