AVR TSIC Auswertung => riesen Programm

Gast #1518003
Lesenswert?

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?
Angehängte Dateien:
Gast #1518185
Lesenswert?

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...
#1518917
Lesenswert?

rogger schrieb:

> ich habs jetzt mal in
1
 Temp_celsius = ((temperatur*100 / 2047 * 200)
2
> - 5000)/10;
>
> 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.
#1518920
Lesenswert?

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.
Gast #1528903
Lesenswert?

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
Angehängte Dateien:
Gast #1889277
Lesenswert?

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!
Gast #2248943
Lesenswert?

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
#3104187
Lesenswert?

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...  ;) ;) ;)
Angehängte Dateien:
Gast #3113051
Lesenswert?

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
Angehängte Dateien:
#3157647
Lesenswert?

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_t readParity() {
2
  while (TSIC_SIGNAL_HIGH)
3
    ;             // wait for falling edge
4
  _delay_us(63);
5
  if (TSIC_SIGNAL_HIGH)
6
    return 1;
7
  return 0;
8
}

müsste heißen:
1
uint8_t readParity() {
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
      return 1;
9
  }
10
   while (TSIC_SIGNAL_LOW)
11
      ;           // wait until line comes high again
12
  return 0;
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 :(

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren