Hallo!
Ich habe gerade ein Programm zur Auswertung eines TSIC-Temperatursensors
zur Steuerung von einigen Ausgängen geschrieben. Dazu benutze ich den
C-Code von Beitrag "wie Daten an MSP430F1611 seriell einlesen?" . Allerdings
erzeugt der avr-gcc compiler daraus eine ziemlich große Datei... Wenn
ich alles andere weglasse und nur die Funktion zum Auslesen und die
Umwandlung in einen String im Programm (Anhang) drin lasse ist die
erzeugte binary immer noch 4406 bytes groß.
Kann mir einer sagen wie ich das Programm kleiner bekomme?
geändert... Sollte eigentlich rein Mathematisch funktionieren, odeer hab
ich da was übersehen?
jetzt muss ich mich nur noch um das richtige setzen des Kommas
kümmern...
rogger schrieb:
> auch mit "-lm" komme ich auf 4406 bytes...
-lm ist ja auch eigentlich kein Compilerschalter, sondern ein
Linkerschalter. ;-)
Also wahrscheinlich einfach in die falsche "Schalterliste" eingetragen.
Ich bin im AVR-Studio scheinbar noch nicht so fit... Hab jetzt "-lm" als
Linkerschalter eingetragen und komm immernoch auf 4kb...
Ich werds morgen nochmal unter gewohnter Umgebung (linux + avr-gcc)
probieren da kann ich wenigstens die Linkeroptionen selbst verändern^^
Ich glaube ich werde trotzdem die festkommarithmetische Lösung benutzen
die ist ja trotzdem nur halb so groß. Damit komme ich nur auf 720 bytes.
rogger...
>wenn du die Compileroption -Os meinst, dann muss ich sagen die ist aktiviert...
Ja, die meinte ich.
Beim AVR-Studio (wieso hast du das nicht im ersten post erwähnt?) setzt
man das "-lm", indem man in den project-options, linkeroptions (oder
hieß das libraries? -- hab kein Avr-studio hier) die 'libm.a' auswählt.
hth, Jörg
>> geändert... Sollte eigentlich rein Mathematisch funktionieren, odeer hab> ich da was übersehen?
Warum stellst du nicht einfach so um
1
Temp_celsius=(temperatur*200/2047)-50;
(Hintergedanke:
Du willst die Division so spät wie möglich machen. Bei der Division
gehen dir die Nachkommastellen flöten, daher willst du es solange wie
möglich hinauszuögern. Bei den anderen Operationen kann dir nichts
verloren gehen, dafür droht allerdings die Gefahr eines Overflow. Das
muss man mit den tatsächlichen Werten abklären, ob die Multiplikation
mit 200 einen Overflow generieren kann.
Das ist eine teure Operation
temp_value1 |= 1 << (8-i); // get the bit
Um mit einer variablen Bitanzahl zu schieben, muss ein AVR ganz schönen
Aufwand treiben. Besser ist es eine 'Maske' zu haben und die Maske nach
jeder Operation eine Stelle weiterzuschieben.
In deinem Fall ist es allerdings noch einfacher, einfach das Ergebnis um
1 Stelle weiterzuschieben und immer nur das Bit 0 bei Bedarf zu setzen
1
for(i=0;i<9;i++){
2
while(TSIC_SIGNAL_HIGH);// wait for falling edge
3
_delay_us(60);
4
if(TSIC_SIGNAL_HIGH)
5
temp_value1|=1;
6
temp_value1<<=1;
7
while(TSIC_SIGNAL_LOW);// wait until line comes high again
8
}
Und warum hast du den Code um Bits einzulesen doppelt im Code anstelle
einer Funktion die 2 mal aufgerufen wird?
Selbiges nochmal in grün für das Checken der Parity.
Wobei du dem AVR viel Arbeit (und damit auch einiges an Code) abnehmen
kannst, wenn du von vorneherein das Parity Bit extra betrachtest und nur
8 Bit + Parity Bit empfängst. Dann brauchst du dafür keine 16 Bit
Variablen und der AVR muss nicht nutzlose Bits durch die Gegend
schieben.
Ich hätte ja nicht gedacht dass man noch so viel aus dem Programm
rausholen kann!
Ich werde mich dann nacher wenn ich Zeit habe mal hinsetzen und das
ganze Etwas umbauen...
Meine Lösung werde ich dann wieder hier Posten.
Vielen Dank soweit!
roggerb
so ich bin endlich mal wieder dazu gekommen etwas weiter zumachen und
habe einmal versucht eure Vorschläge einzubauen. Das Ergebnis findet ihr
im Anhang.
Im Moment komme ich auf 752 Bytes.
Ich konnte meine Änderungen bisher noch nicht auf dem Atmega testen,
deswegen weiß ich auch noch nicht ob mein Programm fehlerhaft ist.
rogger
Das Programm hat noch ein paar Macken:
- Zuviele bits werden gelesen
- Daten werden einmal zuviel nach links geschoben
- parity prüft zu wenig bits
- zu großer datentyp als zählvariable
- itoa aus der bibliothek scheint kleiner
- temperatur zu klein (z.B. 930*200=186000)
- konstanten ggf. mit "L" kennzeichnen
- ein else kann eingespart werden
Ansonsten danke für den Code!
Dieser Beitrag ist zwar schon kalter Kaffee, aber ich kann es mir mein
Unverständnis über solche Leute nicht verkneifen.
@ Dude schrieb:
...
> Ansonsten danke für den Code!
Das sind sie, das Forum nutzen und nur nehmen. Mir würde dieser Code
bestimmt auch weiterhelfen. Ist zwar in C, aber ein Debuggerlauf zeigt
mir ja auch Assembler.
mfg Roger
Hallo,
ich versuche mich gerade auch mit dem TSIC-206. Die ausgewerteten
Temperaturen gebe ich momentan per UART aus. Jedoch kommen keine
vernünftigen Werte zustande. Gibt es eine funktionierdende Version von
testtemp.c?
Gruß
Karl Heinz Buchegger schrieb:> Temp_celsius = (temperatur * 200 / 2047) - 50;
eventuell noch in
Temp_celsius = (temperatur * 200 / 2048) - 50;
ändern, damit hat es der µC noch ein wenig einfacher.
So ich poste jetzt hier eine Version, die die vorgeschlagenen Änderungen
von Dude beinhaltet.
Das Beispiel ist ein Eclipse Projekt mit LCD.
Die gleichen Dateien aus dem Projekt sind nochmal extra angehängt.
Diese Version kommt ohne Interrupt oder Timer aus
PS: Ich sehe den Derben Umgangston hier im Forum immer mit einem Lächeln
im Gesicht an, weil es erschreckend ist, wie kurz bei einigen hier die
Soziale Kompetenz kommt.
Das Verhalten von "Dude" passt ganz dazu. Und jetzt macht mich und
"mein" Code fertig, ich warte schon darauf... ;) ;) ;)
Ahoi!
Ich habe heute gerade an einer ZACwire-Implementierung per Interrupt
gearbeitet. Danach bin ich auf diesen (alten) Thread gestoßen.
Vielleicht hilft mein Code ja jemanden, der's per INT bauen will.
Der TSic wird hier kontinuierlich ausgelesen, auf eine Steuerrung der
Spannungsversorgung des TSic habe ich deshalb verzichtet. Das ist meiner
Meinung nach auch nur beim Polling sinnvoll.
Lt. Datenblatt verheizt der TSIC 80µA bei 5V.
Als Eingang benutzt der Code Pin D4 mit der PCINT20-Funktion.
Zugegebenermaßen ist es ein schneller Hack aber es sollte nicht
schwierig zu sein, den Code an eigene Bedürfnisse anzupassen.
So können natürlich auch andere Pin-Change-Interrupteingänge oder
INT0/INT1 benutzt werden, wobei die Polarität fallend sein muss. Bei
Benutztung von PCINT wird die steigende Flanke in der ISR rausgefiltert.
Als einzige Verbesserungen zum Code von Anton sind lediglich das Timeout
bei der Flankenerkennung und die im Datenblatt empfohlene Messung der
Breite des Startbits zu nennen. Ersteres bewirkt, dass das Programm
nicht hängenbleibt, wenn der TSic ausfällt/abgezogen wird, Zweiteres
sollte für ein genaueres Timing sorgen und das Auslesen robuster machen.
Durch die Strobemessung und das Timing beim Einlesen der einzelnen Bits
ist die Laufzeit der ISR etwas größer als die Übertragungsdauer eines
Datenwortes. Geschätzt sind es 2,7mS: (1 Startbit + 18 Datenbits inkl.
Parity + 1/2 Stopbit) * 125µS. Der TSic sendet 10 Messungen/Sekunde,
also verbraucht die ISR ca. 27,5mS/S.
Grundsätzlich ist das Interruptverfahren also nicht unbedingt 'besser'.
Je nach Andwendungsfall kann es aber bequemer sein. Auf jeden Fall
verbraucht es insgesamt mehr Rechenzeit und Strom als das Polling mit
Spannungssteuerung des TSic. Wobei beim Polling zu beachten ist, dass
der TSic nach dem Einschalten zwischen 65mS und 85mS braucht, um das
Messergebnis zu liefern und empfohlen wird, V+ des TSic mit einem
Tiefpassfilter an den µC zu koppeln -> mehr Bauteile.
/Carsten
Die Version die ich gepostet habe hat noch ein Problem.
Es wird eine temperatur ca 2°C zu hoch angezeigt. Das Problem liegt
irgendwo in der Parrity-Verarbeitung.
1
uint8_treadParity(){
2
while(TSIC_SIGNAL_HIGH)
3
;// wait for falling edge
4
_delay_us(63);
5
if(TSIC_SIGNAL_HIGH)
6
return1;
7
return0;
8
}
müsste heißen:
1
uint8_treadParity(){
2
while(TSIC_SIGNAL_HIGH)
3
;// wait for falling edge
4
_delay_us(63);
5
if(TSIC_SIGNAL_HIGH){
6
while(TSIC_SIGNAL_LOW)
7
;// wait until line comes high again
8
return1;
9
}
10
while(TSIC_SIGNAL_LOW)
11
;// wait until line comes high again
12
return0;
13
}
Leider ist noch mehr faul, da dann nur noch gerade Zahlenwerte am LSB
rauskommen.
Vielleicht liegt es auch irgendwie an der Pointer Verarbeitung, weil
meiner Meinung nach macht das Programm genau das was die Version von
Carsten macht.
@Carsten: mein Compiler meint das die parity_even_bit-Fkt. nichts macht.
Schade die Version von Rogger finde ich sehr elegant und schön
geschrieben..
Aber nach mehreren Tagen des Versuchens gebe ich an dieser Stelle auf :(
So jetzt hier eine Version die wirklich geht, auch ohne Fehler soweit
ich das jetzt beurteilen kann.
PS: es ist eine Mischung aus der Version von rogger und Carsten, jedoch
komplett neu aufgebaut.
Hier mal meine Version, beide Bytes werden eingelesen und gleich die
Parität geprüft. Das läuft so seit Monaten erfolgreich.
Geschrieben für PIC 18F2620 mit C18.
Vielleicht lässt sich aus dem Code noch die eine oder andere Anregung
entnehmen.
Holger