PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Temperatur verarbeiten über Analog



Woftschik
12.05.2009, 09:22
Hallo Leute!!!

Stehe voll auf dem Schlauch, weiß nicht mehr weiter!
Habe in Googel nichts gefunden, was mir so richtig weiter geholfen hat.

Folgendes Problem:
Ich habe folgenden Code unter diesem Link
https://www.roboternetz.de/wissen/index.php/ADC_(Avr)
gefunden. (C/C++)

In bemerkungen steht "In result steht das Ergebnis."
Wie bearbeite ich diesen result?
Was ist das für ein Dateiformat?
Wie kann ich es nach der Bearbeitung im Display anzeigen?

Woftschik
12.05.2009, 15:13
Kann denn jemand mir keiner helfen?

Vielleicht kann mir jemand zeigen wie ich ein anderen C Code für Analog schreibe.

BurningBen
12.05.2009, 15:23
result enthält einen integer.
Vermutlich von 0 (für 0V) bis 1024 (für 2,56V) an ADC0

Den kannst du jetzt vergleichen, dividieren, multiplizieren, was dazu addieren etc. pp.

Woftschik
12.05.2009, 15:31
Hi BurningBen!

Ich danke dir für die schnelle Antwort.
Du meinst das der result einfach eine normale Variable ist :-k

Wieso heißt es den "" uint16_t result = 0; ""?
Was soll den das uint16_t bedeuten ???

BurningBen
12.05.2009, 15:50
Da wird die Variable result definiert. Und zwar als unsigned int (ohne vorzeichen) allerdings nur 16 bit lang, statt normalerweise 32bit

Woftschik
12.05.2009, 15:59
achso verstehe?
Muss leider jetzt weg. Werde heute abend erst wieder dran sein. Melde nich auch dann wieder.
Danke vorab.!

Woftschik
12.05.2009, 21:23
Ok es funktioniert soweit ABER....

ich habe z.B. auf dem Display dann "" 4bc5 "" stehen.
Ist das HEX???? :-k

BurningBen
12.05.2009, 21:32
hexadezimal glaube ich eigentlich nicht, das wären 19397 in Dezimal

Hast du den Integer vorher in nen String umgewandelt fürs Display?

Woftschik
12.05.2009, 21:37
Äh Nein habe ich nicht..
sollte man das?
Wie denn?

Woftschik
13.05.2009, 07:06
Ich habe mir das nochmal genauer angeschaut:
Ich denke das ich es doch habe, weil ich folgendes geschrieben habe...

itoa (result, buffer, 16);
lcd_puts(buffer);


es ist so:

result ist ein INT
buffer ist ein char

wenn ich result direkt ausgebe dann zeigt mir das Display verschiedene Zeichen an.

Ich denkemal ich muss das doch irgendwie wandeln, oder nicht?

Hubert.G
13.05.2009, 12:40
Dein Wurm liegt wohl hier

itoa (result, buffer, 16);
lcd_puts(buffer);

Es sollte wohl heißen:
itoa (result, buffer, 10);
lcd_puts(buffer);
Denn die Ausgabe soll doch im 10er System sein und nicht im 16er.

Woftschik
14.05.2009, 20:02
HI

@Hubert.G

Oh ja habe das geändert, seit dem habe ich auch nur zahlen raus.
Ist das den richtig das ich Zahlen bis zu 10000 habe.
Wenn ich den poti bis zu Anschlag gedreht habe, habe ich auch wieder die zahl 1023 und an dem anderen Anschlag so um die 1300.
Ach habe vergessen es mitzuteilen das ich erstmal ein Poti statt Temp-sensor angeklemmt habe.

Hubert.G
14.05.2009, 21:35
Du hast die Referenzspannung 2,56V eingestellt, gehst aber bis 5V.
Die Zeile muss so lauten:

//AVCC als Referenzspannung verwenden
ADMUX |= (1<<REFS0);

Aber warum du die Ausgabe bis 1300 bekommst ist mir nicht klar. Bist du sicher das du dich nicht verschrieben hast. Es dürfte max. 1023 sein.

Woftschik
14.05.2009, 23:30
Hallo!

@Hubert.G

Du hast recht mit der 1300 ich hatte ja nur geschätzt die richtige zahl lautet
1243.
Ich denke mir das diese Zahl daher zustande kommd, da letzte Zahle (3) nicht automatisch gelöscht werden wenn es z.B. unter Tausend kommt.
Bei der (4) ist es genau so.


Jetzt will ich die Funktion schreiben für den Sensor.
Aus dem Datenblatt habe ich mir Daten rausgeschrieben und daraus in Ecxel eine Funktion erstellt (siehe Anhang).
Muss jetzt irgendwie das ganze kombenieren, 1023 Anteile der 5V Spannung mit der Gleichung (oh ja muss irgendwie die Gleichung erstellen).

Woftschik
14.05.2009, 23:35
ups, hier die Funktion!

Hubert.G
15.05.2009, 10:59
Bei deinem "nicht automatisch gelöscht werden" kann ich dir nicht ganz folgen.
Result wird hier gelöscht:
uint16_t readADC(uint8_t channel) {
uint8_t i;
uint16_t result = 0;

Die ADC-Register werden nach dem Abfragen automatisch gelöscht.

Poste doch mal den gesamten Code wie du ihn geschrieben hast.[/quote]

Woftschik
15.05.2009, 17:02
Hi!

@Hubert.G

Ich meinte mit dem löschen z.B. wird auf dem Display
die Zahl 1023 angezeit. Dreht man an dem Poti
bekommt man z.B. die Zahl 745.
Also ist man unter der Tausender
quasi sollte die 1 gelöscht werden
da nur dreistellig. Beispiel:
1023
745 die tausender stelle bleibt leer
Aber auf Display wird angezeigt 1745

hoffentlich ist das jetzt besser erklärt

Ich habe das löschen dann mit dem Befehl


lcd_gotoxy(16,0);
lcd_putc(254);

hin bekommen




int main(void)
{



uint16_t readADC(uint8_t channel)
{
uint8_t i;
uint16_t result = 0;


// Den ADC aktivieren und Teilungsfaktor auf 64 stellen
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);

// Kanal des Multiplexers waehlen
ADMUX = channel;
// Interne Referenzspannung verwenden (also 2,56 V)
// ADMUX |= (1<<REFS1) | (1<<REFS0);

//AVCC als Referenzspannung verwenden
ADMUX |= (1<<REFS0);

// Den ADC initialisieren und einen sog. Dummyreadout machen
ADCSRA |= (1<<ADSC);
while(ADCSRA & (1<<ADSC));

// Jetzt 3x die analoge Spannung and Kanal channel auslesen
// und dann Durchschnittswert ausrechnen.
for(i=0; i<4; i++) {
// Eine Wandlung
ADCSRA |= (1<<ADSC);
// Auf Ergebnis warten...
while(ADCSRA & (1<<ADSC));

result += ADCW;
}

// ADC wieder deaktivieren
ADCSRA &= ~(1<<ADEN);

result /= 4;


return result;
}


if (result < 1000)
{
lcd_gotoxy(16,0);
cd_putc(254);

lcd_gotoxy(13,0);
itoa (result, buffer, 10);
lcd_puts(buffer);
}
if (result < 100)
{
lcd_gotoxy(15,0);
lcd_putc(254);

lcd_gotoxy(13,0);
itoa (result, buffer, 10);
lcd_puts(buffer);
}
if (result > 1000)
{

lcd_gotoxy(13,0);
itoa (result, buffer, 10);
lcd_puts(buffer);
}



Weißt du wie man eine Hyperbel berechnet? Ich habe eine Funktion aber mir fehlt die Gleichung.

Hubert.G
15.05.2009, 20:31
Eine andere Lösung ist die Zeichenanzahl abzufragen mit "len" und dann die entsprechenden Leerzeichen einzufügen.
Nein Hyperbel berechnen kann ich nicht.

Woftschik
15.05.2009, 21:12
Hi!

Hört sich interessant an mit dem "len"
Was mach ich da genau?

Hubert.G
15.05.2009, 21:34
Es heisst strlen, max. Zeichenzahl hier 5, Leerzeichen im


char fuellzeichen[5][6]PROGMEM ={"0"," "," "," "," "};/* Texte für die LCD-Ausgabe im Flash*/

if (strlen(VWert1) ==4){
lcd_puts_p(fuellzeichen[1]);
}
else if(strlen(VWert1) ==3){
lcd_puts_p(fuellzeichen[2]);
}
else if(strlen(VWert1) ==2){
lcd_puts_p(fuellzeichen[3]);
}
else if(strlen(VWert1) ==1){
lcd_puts_p(fuellzeichen[4]);
}
VWert1 ist hier die auszugebende Variable.
Spart zwar keinen Platz im Flash, dafür aber im RAM.

Woftschik
15.05.2009, 21:52
Hi

Ich habe die Variablen x und y als int. Diese habe ich statt VWert1 eingesetzt, wie du beschrieben hast.
Leider funzt es nicht folgende fehlermeldungen bekomme ich (siehe bild)

Hubert.G
16.05.2009, 09:50
Du brauchst da noch zwei Include:
#include <string.h>
#include <avr/pgmspace.h>
Wenn es trotzdem nicht klappt, dann müsstest du mal den gesamten Codeteil posten.

vohopri
16.05.2009, 11:24
Hallo wof,

wieso subtrahierst du nicht 1000 dann, wenn die Tausenderstelle stört.
Die Modulofunktion kann das auch, wenn sie zur Verfügung steht.

grüsse,
Hannes

Woftschik
17.05.2009, 21:31
HI

@Hubert.G
irgendwie will es nicht klappen!
hier ein teil des Programmes zumindest die nötigen sachen.





#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h> //String im Flash belassen
#include "lcd.h"
#include <util/delay.h>
#include <string.h>

#include <inttypes.h>



/*
** constant definitions
*/
static const PROGMEM unsigned char copyRightChar[] =
{
0x07, 0x08, 0x13, 0x14, 0x14, 0x13, 0x08, 0x07,
0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00
};



// die Funktion "Verzögerung" ins Programm einbringen

void delay_ms(uint16_t ms)
{

for(uint16_t t=0; t<=ms; t++)
_delay_ms(1);
}








int main(void)
{



uint16_t readADC(uint8_t channel)
{
uint8_t i;
uint16_t result = 0;


// Den ADC aktivieren und Teilungsfaktor auf 64 stellen
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);

// Kanal des Multiplexers waehlen
ADMUX = channel;
// Interne Referenzspannung verwenden (also 2,56 V)
// ADMUX |= (1<<REFS1) | (1<<REFS0);

//AVCC als Referenzspannung verwenden
ADMUX |= (1<<REFS0);

// Den ADC initialisieren und einen sog. Dummyreadout machen
ADCSRA |= (1<<ADSC);
while(ADCSRA & (1<<ADSC));

// Jetzt 3x die analoge Spannung and Kanal channel auslesen
// und dann Durchschnittswert ausrechnen.
for(i=0; i<4; i++) {
// Eine Wandlung
ADCSRA |= (1<<ADSC);
// Auf Ergebnis warten...
while(ADCSRA & (1<<ADSC));

result += ADCW;
}

// ADC wieder deaktivieren
ADCSRA &= ~(1<<ADEN);

result /= 4;


return result;
}











char fuellzeichen[5][6]PROGMEM ={"0"," "," "," "," "};/* Texte für die LCD-Ausgabe im Flash*/

if (strlen(x) ==4){
lcd_puts_p(fuellzeichen[1]);
}
else if(strlen(y) ==3){
lcd_puts_p(fuellzeichen[2]);
}














//Variablen deklarieren

char Out[80];
char buffer[20];
int setup_zeit = 180;
int setup_temp = 50;
int bild_aufruf = 0;
int ist_zeit = 0;
int ist_temp = 0;
int summer = 0;
int automatik_betrieb = 0;
int y = 0;
int x = 0;
int z = 0;


@vohopri
wenn ich ständig -1000 rechnen würde dann bekomme ich ja nie die tausender stelle.
Die stelle soll vorhanden sein wenn die Zah über tausend ist und wenn es unter tausend fällt wird sie halt nicht automatisch gelöscht.

Hubert.G
18.05.2009, 09:02
Ich kann da keinen Fehler entdecken. Was funktioniert nicht ?

vohopri
18.05.2009, 09:07
Hallo wof,

das hast du völlig richtig erkannt. Darum habe ich auch nicht von "ständig subtrahieren" geschrieben, sondern "wenn die Tausenderstelle stört".

Dass du selbständig das "wenn" in ein "if" umsetzen kannst, hätte ich eigentlich schon erwartet.

grüsse,
Hannes

Woftschik
18.05.2009, 19:38
HI!!

@Hubert.G
Ich weiß nicht was da nicht genau funktioniert. Wenn ich diese Zeilen ausklammere dann funktioniert das. Fehlermeldungen vom Compiler siehe Bild.



char fuellzeichen[5][6]PROGMEM ={"0"," "," "," "," "};/* Texte für die LCD-Ausgabe im Flash*/

if (strlen(x) ==4){
lcd_puts_p(fuellzeichen[1]);
}
else if(strlen(y) ==3){
lcd_puts_p(fuellzeichen[2]);
}




vielleicht stimmt da was mit der Schreibweiße nicht?


@vohopri
Danke! Hatte das auch vorher so gehabt mit dem "if" ,nur ist es nicht unbedingt die eleganteste Lösung.
Wenn dieser Code oben von Hubert.G funktionieren wird, das nenne ich dann eine elegante Lösung.

Hubert.G
18.05.2009, 19:56
Jetzt die Warnings mal beiseite gelassen, wo deklarierst du denn x und y.

Woftschik
18.05.2009, 20:09
Jetzt habe ich verstanden.
Die Variablen Deklaration war nach diesen Zeilen die du mir gegeben hast.
Jetzt habe ich sie auscgeschnitten und oben eingefügt, kein Compiler fehler mehr. Aber irgendwie werden mir die"unnötigen" Zahlen der Variablen X und Y nicht gelöscht.
Muss ich da noch was einfügen?

Woftschik
18.05.2009, 20:19
Ich hab es jetzt.
Leider schreibt er mir statt die Füllzeichen andere möglichen zeichen rein
Was heißt eigentlich PROGMEM ={"0"," "," "," "," "}; ?????

Hubert.G
18.05.2009, 21:07
Damit holt sich das Programm zur Laufzeit die Daten aus dem Flash. Diese Zeile gehört auch ganz nach oben zu den #define usw.
Du musst auch die Warning beachten.

Woftschik
18.05.2009, 21:43
AAHH OK!

Laut Warning wird progmem ignorierd.
Ich habe es eben versucht bei den define einzusetzen, doch sobald ich diese Zeilen auserhalb meiner void main lege, dann gibt es Fehler.
Muss ich da auf was achten?

Hubert.G
19.05.2009, 09:42
Kannst du mir das gesamte Programm mal schicken, dann kann ich es mir im AVR-Studio selbst ansehen. Ich brauche da aber alle *.c und *.h files.
Ich denke mal du hast da einige Fehler drinnen.

Woftschik
19.05.2009, 11:08
HI Hubert.G

Ich schicke dir das Programm heuteabend per E-Mail.
Deine E-Mail habe ich auf deiner Homepage gefunden.

Woftschik
20.05.2009, 10:26
HI Hubert

hast du meine e-mail bekommen??

Hubert.G
20.05.2009, 12:00
Hallo
Hab es dir gestern Abend noch zurückgeschickt.

Woftschik
20.05.2009, 13:40
Leider ist bei mir nichts angekommen!
Könntest du es bitte nochmal zuschicken?

Woftschik
21.05.2009, 21:26
Hi Hubert

Ich danke dir das du mal drüber geschaut hast!
Das mit dem "sprintf" habe ich im Netz gefunden bezüglich
Ausgabe von Zahlen mit Komma.
Mit dieser Funktion konnte ich sogar bestimmen wieviele stellen nach dem Komma angezeigt werden sollen.

Mit dem strlen habe ich so gemacht





lcd_gotoxy(13,0);
itoa (y, buffer, 10);
lcd_puts( buffer);

if (strlen(setup_zeit) ==4){
lcd_puts_p(fuellzeichen[1]);
}
else if(strlen(buffer) ==3){
lcd_puts_p(fuellzeichen[2]);
}


schau mal bitte drüber ob ich dich richtig verstanden habe!

Hubert.G
22.05.2009, 08:57
Mit sprintf arbeite ich nicht, da kann ich nichts dazu sagen. Gibt der Compiler bei dir da keine Fehler oder Warning aus?.
Du musst mit strlen den Wert bearbeiten den du mit lcd_puts ausgibst.

Woftschik
22.05.2009, 10:43
Hi

bezüglich der sprinft Funktion, da gibt mein Compiler ein Warning raus.
Wie gibst du denn Komma zahlen auf einem Display aus?

Ok mit strlen funktioniert das jetzt! Danke!

Hubert.G
22.05.2009, 11:18
Ich berechne die Stellen immer, vielleicht gibt es einen schöneren Weg.
lcd_gotoxy(15,1);
Wandelwert=max/100; /* Maximalwert Vorkommastellen berechnen*/
ltoa(Wandelwert,Wert1,10); /* Maximalwert in ASCII-Wert umwandeln*/
lcd_puts_p(ausg[1]); /* ausgabe "max"*/
lcd_puts(Wert1); /* Wert von max auf Display ausgeben */
lcd_puts_p(fuellzeichen[1]); /*Komma ausgeben*/
Wandelwert=max%100; /* Maximalwert Nachkommastellen berechnen*/
if (strlen(Wert1)==2){ /*Wenn anzeige zweistellig, dann Kommastelle nur einstellig*/
Wandelwert=Wandelwert/10; /* Wert auf 1 Stelle begrenzen */
if(Wandelwert == 0){ /* Wenn die ausgabe =0 */
lcd_puts_p(fuellzeichen[0]); /* eine 0 ausgeben */
}
else{
ltoa(Wandelwert,Wert1,10); /*Wert auf ASCII wandeln */
lcd_puts(Wert1);
}
}
else{
ltoa(Wandelwert,Wert1,10); /* Maximalwert in ASCII-Wert umwandeln*/
if (strlen(Wert1)==1){ /* wenn Nachkommastelle nur im hundertstelbereich */
lcd_puts_p(fuellzeichen[0]); /* dann eine Null vorher einfügen */

}
lcd_puts(Wert1); /* auf Display ausgeben */
}
Ich weiss nicht ob du damit was anfangen kannst. Das mit dem sprintf habe ich vor langer Zeit mal probiert, hat mir allerdings den Code ziemlich aufgeblasen. Diese gezeigte Version ist wesentlich kleiner.

Woftschik
22.05.2009, 12:17
Verstehe!

Du gibst einmal die ganzezahlen aus und anschließend nach dem Komma Zahlen, dazwischen gibst du noch das komma aus.
Quasi gibst du Zahl1 Komma Zahl2 aus.

Woftschik
24.05.2009, 21:23
Hi Hubert!

Ich hätte da nur noch eine Frage!

Was bedeutet diese Zeile die du mir reingeschrieben hast?


#define F_CPU 4000000L


Ansonstens möchte ich mich für deine Hilfe SEHR bedanken.

Hubert.G
25.05.2009, 09:29
Diese Zeile gibt die Taktfrequenz an. Sonst stimmt dein delay nicht. Es gehört natürlich die tatsächliche Frequenz eingetragen.

Woftschik
25.05.2009, 11:08
Alles klar!
Danke nochmal!