PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : IF Else SCHLEIFEN



Andy79
07.05.2008, 16:08
Moin zusammen !

Hab da mal wieder ein Problemchen, bei dem ich seid Tagen verzweifel !
Ich will eigentlich nur ne If Else Schleife machen.
Ohne die Schleife funktioniert mein Programm.
Sobald ich die Schleife drin hab, bekomme ich im AVR Studio folgende Meldung :

c:\winavr\bin\..\lib\gcc\avr\4.1.1\..\..\..\..\avr \bin\ld.exe: region text is full (Aquacontrol.elf section .text)

Kann mir da jemand weiterhelfen ?

Danke schonmal für Eure Hilfen !

PicNick
07.05.2008, 16:22
Versuch's mal so, versuchsweise, das kommt mir übersichtlicher vor


new_line(1,4); // Schreibe in Zeile1, Spalte4
lcd_write("Temperatur"); // den Text "Temperatur" auf das LCD
new_line(2,10); // Schreibe in Zeile12 Spalte10
lcd_write("ßC"); // den Text "Grad Celcius" auf das LCD
new_line(2,3); // Schreibe in Zeile2, Spalte3
if (Temperatur<24)
{
lcd_write("zu niedrig!"); // den Inhalt "zu hoch !" auf das LCD
}
else
{
if (Temperatur>28)
{
lcd_write("zu hoch !"); // den Inhalt "zu hoch !" auf das LCD
}
else
{
lcd_write(Buffer); // den Inhalt des ADC Registers
}
}
for(i=1;i<25;i++) // Durchlaufe die Schleife 30 mal
{
_delay_ms(250);
}

Andy79
07.05.2008, 18:11
Danke für die superschnelle Antwort !
Also ich bekomme jetzt beim Kompilieren keine Fehlermeldung mehr.
Jedoch wenn ich brennen will kommt die für mich nicht gewohnte angehängte Meldung !

Im Display seh ich wenn ich auf ja gehe,nach dem brennen teilweise Hypogliphen, teilweise ists okay !?!?

SprinterSB
07.05.2008, 18:19
Es ist im Endeffekt die gleiche Fehlermeldung wie oben:

Das Programm ist zu fett für den µC und passt nicht komplett rein.

Andy79
07.05.2008, 18:39
Hmmm, komisch ! Besteht eigentlich nur aus ein paar zeilen Ausgabe auf Display, ner Uhr die über I2C ausgelesen wird und dieser messung hier.

Ist ein MEGA8

Pascal
07.05.2008, 18:47
Dein Problem werden neben den paar strings wohl die float-Rechnungen sein. Die brauchen schon böse viel Speicherplatz. Überleg dir mal, wie du das evtl. einfach gestalten könntest.
So ein ATMega8 ist schon ziemlich schnell voll.

PicNick
07.05.2008, 18:53
Na, stell dein Programm mal da rein. Ich denke doch, daß wir es ein bisschen kompakter kriegen.

Andy79
07.05.2008, 19:02
Also, hier mein Programm, was mal mein Technikerprojekt geben sollte !
Eigentlich kommt noch eine AD Wandlung für den PH Wert dazu, was aber glaub dann wirklich zuviel fürn Prozessor wird. Wenns ihm jetzt schon zuviel ist.
Die Funkionen macht man ja normal in C Files, wie wirs gelernt haben. *lol* funktioniert so aber auch. :-) Brauch das so mehr Platz ?

Möglich dass hier und da ein paar Unschönheiten drin sind --> Anfänger :-(

Aber es ist noch kein Meister vom Himmel gefallen !

PicNick
08.05.2008, 08:56
Ich versuch's portionen-weise, weil ich leider nicht durchgehend Zeit habe:

z.B Wochentag ausgabe, statt "switch"



static char daytab[] = "MoDiMiDoFrSaSo";

memcpy(Buffer, daytab[ (day-1) << 1 ], 2);
Buffer[2] = '.';
Buffer[3] = 0x00; // string-terminator
lcd_write(Buffer);

PicNick
08.05.2008, 10:02
So, nun die komplette Uhr-Ausgabe. Ich denk, da ist ein bisschen was zu holen


static char daytab[] = "MoDiMiDoFrSaSo";

//---------------------------------------------------------
//line2 123456789012
// hh:mm:ss
Buffer[0] = (std >> 4) | 0x30; // 5
Buffer[1] = (std & 0x0f) | 0x30; // 6
Buffer[2] = ':' // 7
Buffer[3] = (min >> 4) | 0x30; // 8
Buffer[4] = (min & 0x0f) | 0x30; // 9
Buffer[5] = ':' // 10
Buffer[6] = (sek >> 4) | 0x30; // 11
Buffer[7] = (sek & 0x0f) | 0x30; // 12
Buffer[8] = 0x00; // string-terminator
new_line(2,5); // legt die Zeile, und dann die Spalte fest
lcd_write(Buffer);
//---------------------------------------------------------
//line1 12345678901234
// dd. dd.mm.yy
memcpy(Buffer, (char*)&daytab[ (day-1) << 1 ], 2);
Buffer[2] = '.';
Buffer[3] = 0x00;
new_line(1,2); // legt die Zeile, und dann die Spalte fest
lcd_write(Buffer);

Buffer[0] = (date >> 4) | 0x30;
Buffer[1] = (date & 0x0f) | 0x30;
Buffer[2] = '.'
Buffer[3] = (month >> 4) | 0x30;
Buffer[4] = (month & 0x0f) | 0x30;
Buffer[5] = '.'
Buffer[6] = (year >> 4) | 0x30;
Buffer[7] = (year & 0x0f) | 0x30;
Buffer[8] = 0x00;
new_line(1,7); // legt die Zeile, und dann die Spalte fest
lcd_write(Buffer);

Schau aber sicherheitshalber, ob ich mich wo verschrieben habe.

SprinterSB
08.05.2008, 10:34
Ein Haup-Batzen dürfte die Verwendung von float sein.

Nimm zB folgendes Progrämmchen:


float a, b, c, d;

void foo ()
{
a = b*d - a/c;
}

int main()
{
while (1);
}


Und übersetz es wie gewohnt mit "avr-gcc -mmcu=atmega8 -Os -o float.elf float.c"

Dann schauen wir auf die Größe mit "avr-size float.elf"

text data bss dec hex filename
2730 8 16 2754 ac2 float.elf


Der ATmega8 ist also schon zu 1/3 voll. Wo die draufgehen sieht man mit "avr-nm -S --size-sort float.elf"

00800074 00000004 B a
00800068 00000004 B b
0080006c 00000004 B c
00800070 00000004 B d
00800060 00000008 D __thenan_sf
000000f8 0000000a T main
00000346 00000056 T __addsf3
0000039c 0000005e T __subsf3
0000005c 0000009c T foo
00000948 000000f4 T __unpack_f
00000626 00000156 T __divsf3
0000077c 000001cc T __pack_f
000003fa 0000022c T __mulsf3
00000102 00000244 t _fpadd_parts

In die zweiten Spalte stehen die Größen der Objekte (Bytes in hex). Das __*-Zeug kommt von der float-Software die dazugelinkt werden muss, weil AVR keine float/double Hardware-Unterstützung hat.

Wenn du die Größen deiner Funktionen so auflistet, erkennt man wo am meisten Platz verbraucht wird und wo eine Optimierung am meisten bringt.

Die Optimierungsstufe von avr-gcc sollte -Os sein. -O0 oder -O3 sind keinesfalls ratsam.

Ansonsten hilft, mehrfach verwendete Sachen in eigene Funktionen zu packen. Damit kann der Code wiederverwendet werden und muss nicht jedesmal mit leicht anderen Parametern erzeugt werden.



//-----------------------------------------------------------------------------------------------------------------
// Titel : LCD 4x16 zeigt die Uhrzeit an für Testschaltung MYAVR
//-----------------------------------------------------------------------------------------------------------------
// Prozessor : ATmega8
// Takt : 3686400 Hz
// Sprache : C
// Datum : 10.04.2008
// Version : 1.0
// Autor :
//-----------------------------------------------------------------------------------------------------------------
#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 3686400UL // Quarz mit 3.6864 Mhz
#endif
#include <util/delay.h> // definiert _delay_ms() Warteschleife
#include "i2cmaster.h"
#include <stdlib.h>
#include <string.h>
#define DS13 0xd0 // device address of Realtime Clock DS1307, see datasheet
char i;


/////////////////////////////////////////////////////////////////////////////
// Uhr
/////////////////////////////////////////////////////////////////////////////

// Schreibt 'num' gefolgt von 'c' an position line:pos (zeile:spalte)
void lcd_write_num (unsigned char line, unsigned char pos, unsigned char num, char c)
{
unsigned char digit;
static char buf[4];

buf[2] = c;
buf[3] = 0;
new_line (line, pos); // legt die Zeile, und dann die Spalte fest

digit = num >> 4;
buf[0] = digit + '0';

digit = num & 0xf;
buf[1] = digit + '0';
}

static const char * day_of_week[] =
{
"Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"
};

void Uhr2()
{
i2c_init(); // initialize I2C library
unsigned char sek, min, std, day, date, month, year; // Typ char gibt Sekunde,Minute,Stunde,Wochentag,Tag den,Monat,Jahr.
unsigned char i;

for (i=1; i<30; i=i+1)
{
_delay_ms(250);

//-----------------------------------------------------------------------------------------------------------------
// Daten Auslesen des Realtime Clock DS 1307
//-----------------------------------------------------------------------------------------------------------------
i2c_start_wait(DS13+I2C_WRITE); // setzt die Adresse vom DS13 und den schreiben mode
i2c_write(0x00); // schreibe Address = 0 liegt Wert Zeitdaten
i2c_rep_start(DS13+I2C_READ); // setzt die Adresse vom DS13 und den lese mode
sek = i2c_readAck(); // lese den Inhalt von Adresse 0 Sekunden
min = i2c_readAck(); // lese den Inhalt von Adresse 1 Minuten
std = i2c_readAck(); // lese den Inhalt von Adresse 2 Stunden
day = i2c_readAck(); // lese den Inhalt von Adresse 3 WochenTag
date = i2c_readAck(); // lese den Inhalt von Adresse 4 Tag den
month = i2c_readAck(); // lese den Inhalt von Adresse 5 Monate
year = i2c_readNak(); // lese den Inhalt von Adresse 6 Jahre
i2c_stop(); // Ende des einlesens
//-----------------------------------------------------------------------------------------------------------------
// LCD Hintergundbeleuchtung einschalten.
// Ausgabe der Stunden auf das LCD Display.
lcd_write_num (2, 5, std, ':');
//-----------------------------------------------------------------------------------------------------------------
// Ausgabe der Minuten auf das LCD Display.
lcd_write_num (2, 8, min, ':');
//-----------------------------------------------------------------------------------------------------------------
// Ausgabe der Sekunden auf das LCD Display.
lcd_write_num (2, 11, sek, 0);
//-----------------------------------------------------------------------------------------------------------------
// Ausgabe der Wochentage auf das LCD Display.
if (day >= 1 && day <= 7)
{
new_line(1,2); // legt die Zeile, und dann die Spalte fest
lcd_write (day_of_week[day-1]);
}
//-----------------------------------------------------------------------------------------------------------------
// Ausgabe der Tages auf das LCD Display.
lcd_write_num (1, 7, date, '.');
//-----------------------------------------------------------------------------------------------------------------
// Ausgabe die Monate auf das LCD Display.
lcd_write_num (1, 10, month, '.');
//-----------------------------------------------------------------------------------------------------------------
// Ausgabe der Jahre auf das LCD Display.
lcd_write_num (1, 13, year, 0);
}
}

//-----------------------------------------------------------------------------------------------------------------




deep-thought> avr-nm -S --size-sort uhr.o
00000001 00000001 C i
00000000 00000004 b buf.0
00000015 0000000e d day_of_week
0000033e 0000002e T lcd_write_num
0000036c 000000c0 T Uhr2
00000000 0000033e T Uhr


Das ist nicht nur übersichtlicher, sondern auch etwas kleiner (256 Bytes anstatt 830, und itoa ist noch net mitgerechnet).

Andy79
08.05.2008, 16:10
Tach !

Wow, da geht was, bin überrascht !
Also in der UHr bin ich grad noch am Suchen, muss noch en Bug drin sein.

Zu dem float....
...denke auch dass es hauptsächlich von dem kommt.
Könntest du mir es mal bitte in die temp.h so reinkopieren wie du meinst ?

Komm sooo net ganz klar :-)

Danke Danke Danke

Andy79
19.05.2008, 15:02
Hallo Freunde ! O:)
Also, wie ihr im Anhang erkennen könnt, hat mir jemand geholden das Programm zu schrumpfen ! Um einiges :-)
Es wird davon ausgegeangen, dass bei 0°C 2,5 Volt anstehen.
Was ich auch gemessen hab und auch richtig ist. Angezeigt wird mir nur leider 39 °C. Soweit sogut. Dann hab ich einen - Offset ins Programm geschrieben, dass mir die Temperatur richtig ausgegeben wird.
Wenn ich allerdings jetzt den Fühler in cirka 26 °C warmes Wasser eintauche werden mir nur 9°C angezeigt. ](*,)

Hmmm, könnte mir nochmal jemand über die Funktion drüberschauen.
Blick da selber net sooo ganz durch. Anfängersyndrom :-k

Wäre um jede Hilfe dankbar !!!

Gruss Andy

Neutro
19.05.2008, 15:15
Wenn es sich bei deinem Temperaturfühler um einen NTC/PTC handeln sollte ist das normal. Die Dinger haben keine lineare Kennlinie!
D.H wenn die Temperatur bei 0°C Kalbriert hast und du 20°C messen willst
wird der Wert durch die Nichtlinearität des Temperaturfühlers verfälscht, Die angezeigte Temperatur ist also falsch.
Für solche Zwecke braucht man Temperaturfühler die Linear sind und über
I2C Ausgelesen werden.

Andy79
19.05.2008, 15:21
Ich habe einen PT100 ! In dem Temperaturbereich wo ich messen will, also zwischen 22 und 29 Grad ist er "nahezu" linear. Mit meinem "alten" Quellcode hat es ja soweit funktioniert. Nur dass das Programm wegen dem float zu gross wurde. Da hatte ich es geschafft bei 0°C auch die 0°C angezeigt zu bekommen und bei 26 °C hatte ich eine minimale Abweichung von cirka 1/2 Grad !

SprinterSB
19.05.2008, 16:58
äh. kann es sein daß man zum Auspacken von dem rar-Zeug ne Lizenz erwerben muss?

Hannst das net verpacken als .zip, .7z, .gz oder .bz2 ?

Andy79
19.05.2008, 17:19
Eigentlich net, aber kein Problem. Hier als .zip

SprinterSB
19.05.2008, 17:37
ok, hab das 7-zip besorgt

Knackus ist


ADCSRA |= (1<<ADSC);
tmph = ADCH;
Temperatur1(tmph);
ADCSRA |= (1<<ADSC);
tmpl = ADCL;
Temperatur2(tmpl);


1) Du musst warten, bis der ADC fertig ist
2) Die Werte vom ADC sind doch positiv, wieso machst du in Tem1 mit dem Vorzeichen rum...?
3) Du hast 16-Bit-Werte --> also liest man auch 16 Bit vom ADC


ADCSRA |= (1<<ADSC);
while (...);
uint16_t tmp = ADC;
Temperatur (tmp);


Wie ist den die Abbildung von ADC --> Temperatur?

Andy79
19.05.2008, 17:47
Ich hab mal versucht, ob es klappt, also PLUS und MISUNS mit auszugeben ! GEht auch soweit. Okay, du sagst warten bis der ADC fertig ist. Meinst du dass deswegen das Wandlungsergebnis nicht stimmt ?

SprinterSB
19.05.2008, 18:31
...es sei denn, dein ACD hat ne Kristallkugel drinne und kann in die Zukunft schauen. Schau einfach mal ins Handbuch.


ADC Conversion Result

After the conversion is complete (ADIF is high), the conversion result can be found in the ADC Result Registers.