Hallo zusammen,
ich versuche mich gerade am Auslesen eines TSIC Sensors mittels ZACWIRE.
Ehrlichgesagt tue ich mich gerade etwas schwer, vielmehr habe ich einen
ziemlichen Knoten im Kopf. Zu meinem Verständnisproblem:
Im Manual steht:
When the falling edge of the start bit occurs, it causes the mC to
branch to its ISR. The
ISR enters a counting loop incrementing a memory location (Tstrobe)
until it sees a rise on the ZACwireTM
signal. When Tstrobe has been acquired, the ISR can simply wait for the
next 9 falling edges (8 for data, 1 for
parity). After each falling edge, it waits for Tstrobe to expire and
then samples the next bit.
So weit so gut. Ich soll also die Strobe Time messen, da diese
auschlaggebend für die Messung der nachfolgenden Bits ist und sich mit
der Temperatur ändert.
Die Frage, die sich mir stellt: Woher weiss ich denn, WELCHE fallende
Flanke ich da gerade habe? Es kommt ja mit jedem Bit eine fallende
Flanke, wie kann ich also wissen, wo ich mich gerade befinde, um die
Zeit zu messen?
Gruß
Matthias
Welche fallende Flanke?
Der TSIC306 sendet (etwa) alle 100 ms für 2,6 ms.
Zu Anfang kann man da auch mal falsch liegen. Na und?
Danach ist 97 ms Ruhe und dann kommt die nächste
komplette Übertragung.
Lass das alles einen IRQ machen...
Bernie schrieb:> Welche fallende Flanke?Matthias P. schrieb:> When the falling edge of the start bit occurs...
Ok, so weit so gut, also muss ich im Prinzip nur solange warten bis die
ersten 97ms der Interrupt Pin auf HIGH war?
Willst du es per Interrupt machen, oder etwa im Hauptprogramm
drauf warten?
Geht es um einen TSIC306? Es gibt auch andere ZACWIRE-Sensoren,
denen man sogar mitteilen kann, wie oft sie Daten liefern sollen.
Ich habe es mal mit PINCHANGE-Interrupt am tiny24 gemacht,
dazu brauchte ich noch einen freilaufenden Counter, dessen
Zählerstand jeweils eingelesen wurde, um die Daten-Erfassung im
PINCHANGE-Interrupt mit Hilfe einiger reservierter Register
zu bewerkstelligen. In einem Register wird dem Hauptprogramm
mitgeteilt, wenn ein gültiger Wert fertig vorliegt.
Matthias P. schrieb:> Ok, so weit so gut, also muss ich im Prinzip nur solange warten bis die> ersten 97ms der Interrupt Pin auf HIGH war?
Der TSIC macht zwischen den Übertragungen eine Pause. Man sucht eine
Pause und reagiert auf die nächste fallende Flanke. Da beginnt das
Startbit.
Im Datenblatt gibt es auch einen anderen Hinweis: Die Synchronisation
kann durch Schalten der Versorgungsspannung erfolgen.
Bernie schrieb:> Willst du es per Interrupt machen, oder etwa im Hauptprogramm> drauf warten?
Per INT1 auf der fallenden Flanke
Bernie schrieb:> Geht es um einen TSIC306?
Ja.
MSP schrieb:> Der TSIC macht zwischen den Übertragungen eine Pause. Man sucht eine> Pause und reagiert auf die nächste fallende Flanke. Da beginnt das> Startbit.>> Im Datenblatt gibt es auch einen anderen Hinweis: Die Synchronisation> kann durch Schalten der Versorgungsspannung erfolgen.
Ok, da war ich ja schon auf dem richtigen Weg. ich werde dann beides mal
probieren. Letzteres ist ja schon insofern schick, als das man den
Stromverbrauch senken kann.
Danke für eure Antworten.
Suche auf jeden fall mal nach der App-Note für ZAC-Wire!
Egal ob du den µC durch Warten blockierst, oder eine
pfiffige Interrupt-Routine baust: Es werden nicht einfach
alle Datenbits rausgeschoben, die Bits sind auf 2 Gruppen
(mit kleiner Pause und neuem Startbit) verteilt.
Allerdings ist das beigefügte PIC-Beispiel nur tauglich,
wenn der µC sonst nichts zu tun hat. WARTEN mit NOP....
Die Synchronisation durch Schalten der Versorgungsspannung
ist "nett gemeint" - man darf dann 65...85 ms WARTEN (!),
bis die Datenübertragung (< 3 ms) beginnt.
Die Stromersparnis kommt erst zum Tragen, wenn man frühestens
nach einigen Sekunden die Temperatur erneut abruft und wenn
es wirklich auf 50 µA ankommt .
Bernie schrieb:> Die Synchronisation durch Schalten der Versorgungsspannung> ist "nett gemeint" - man darf dann 65...85 ms WARTEN (!),> bis die Datenübertragung (< 3 ms) beginnt.
Mensch Berniechen, sei doch nicht so einfältig. Auch wenn der Sensor
frei läuft, hast du die knapp 100ms Pause. Nach Reset muss sich der µC
mit dem Sensor synchronisieren und wieder können es bis knapp 100ms
werden. Der TSIC ist in einem Kunststoffgehäuse untergebracht. Das ist
relativ träge. Was meinst du, wäre eine sinnvolle Messfrequenz?
@MSP:
Was hat es mit Einfalt zu tun, wenn ich die Bearbeitung per
Interrupt empfehle, um das WARTEN zu VERMEIDEN?
Die Enrgieeinsparung bei seltenerer "Ablesung" habe ich doch
nicht in Frage gestellt.
Wer einen µC einsetzt, will den aber fast immer noch andere
Sachen erledigen lassen, als "WARTE AUF SENSORSIGNAL"...
65...85 ms kann man kaum als echten Zeitgewinn gegenüber 100 ms
verkaufen!
Oder hast du noch nicht verstanden, dass Interrupts bei Nicht-
Auslösung alle Zeit dem Hauptprogramm, oder anderen Interrupts
überlassen? ;-)
Bernie schrieb:> @MSP:> Wer einen µC einsetzt, will den aber fast immer noch andere> Sachen erledigen lassen, als "WARTE AUF SENSORSIGNAL"...
Mensch Bernie, jetzt verkaufts du dich noch d...er als oben.
Wo bitte schön habe ich geschrieben, dass keine Interrupts verwendet
werden sollen???
Der Tipp mit der geschalteten Versorgung erleichtert die
Synchronisation!!!
> 65...85 ms kann man kaum als echten Zeitgewinn gegenüber 100 ms> verkaufen!
In meinem Post schrieb ich, dass der TSIC träge ist. Die Auswertung
mit 100ms Messzyklen ist völlig übertrieben. Es ist also völlig egal, ob
20ms, 40ms, ..., 100ms. Ich würde den TSIC nur minimal alle 10s
abfragen. Vorher ist eine Temperaturänderung doch gar nicht im Inneren
des Sensors angekommen.
Was braucht's eine Synchchronisation, wenn die Interrupt-
Routine von ganz allein meldet: Neuer Wert vorhanden!
@ MSP: Schlaf weiter!
Die geschaltetete Versorgungsspannung spart bei Batterieprojekten
Strom und kostet ansonsten einen µC-Pin.
Außerdem:
Das Gegrantel bringt nix: Der TO hat schon lang nicht mehr
vorbeigeschaut. Gute Nacht!
Bernie schrieb:> Was braucht's eine Synchchronisation, wenn die Interrupt-> Routine von ganz allein meldet: Neuer Wert vorhanden!
Du bist ja der wahre Trollmaster. Und wer bitte schön schreibt die ISR?
Fällt die vom Himmel?
Ein embedded System hat nicht nur den Zustand "run". Es gibt auch
weitere. Irgendwann musst du schon die beiden ICs synchronisieren.
Dann schlaf mal gut und lass die großen Jungs das machen.
Bernie schrieb:> Zeig doch mal deine ISR,> ich hab schon eine!
Ahhhh, der Obertroll hat also ein Geheimnis. Du kennst den Sinn eines
Forums?
Der gute Matthias braucht Unterstützung bei der Auswertung eines TSIC.
Was helfen ihm wohl deine Belobigungen über deinen unveröffentlichen
Code?
Erklär einmal, wie du synchronisierst. Und zwar bei allen
Systemzuständen. Dann hätten wir etwas zur fachlichen Diskussion.
Warum sollte ich dir was verraten, wenn du mich als
Obertroll beschimpfst?
Jemand, der fähig ist, daraus zu lernen, mag doch nach deinen
Meckereien nicht mehr weiterlesen.
Trotzdem kleiner Tipp:
- 5..6 der Register 0..15 reservieren und initialisieren.
- INT1: Any logical change on INT1 generates an interrupt request.
- CTR0: freilaufend im Takt von 1 MHz
Flanke an INT1 -> IRQ
Negative Flanke: IRQ testet Overflow-Flag von CTR0 und resettet
ihn und das Overflow-Flag.
Lag ein Overflow vor: Start einer neuen Übertragung!
(Die Abstände innerhalb der Übertragung sind unter 256 µs.)
Bernie schrieb:> Warum sollte ich dir was verraten,
Mir musst du nichts verraten, aber du beteiligst dich an einer Frage von
Matthias.
> Flanke an INT1 -> IRQ> Negative Flanke: IRQ testet Overflow-Flag von CTR0 und resettet> ihn und das Overflow-Flag.> Lag ein Overflow vor: Start einer neuen Übertragung!> (Die Abstände innerhalb der Übertragung sind unter 256 µs.)
Na also, geht doch. Warum nicht gleich so?
Hatte gar nicht bemerkt, daß hier noch Diskussion stattgefunden hatte.
;)
Ich habe mich die letzten Tage mit dem TSIC beschäftigt, bin aber nicht
wirklich weitergekommen. Irgendwie stelle ich mich zu dumm an.
Erstmal interessiert mich ja die TStrobe Zeit. Ich hatte mir folgendes
überlegt:
Davon ausgehend das der TSIC am INT1 Pin hängt:
INT1 auf fallende Flanke
TSIC einschalten per µC
Bei fallender Flanke TIMER1 normal starten
INT1 auf steigende Flanke
bei steigender Flanke auf INT1 denselben wieder auf fallende Flanke
setzen
Bei der nächsten fallenden Flanke ist das Startbit komplett, also TCNT1
merken und Timer 1 im CTC Modus starten mit dem Wert aus TCNT1 in OCR1A.
Soweit müsste dann ja zumindest die TStrobe Zeit zu messen sein, ich
wollte dan zum Test den PINC4 in der ISR (TIMER1_COMPA_vect) toggeln.
Leider kommt da völliger Mist raus und der Pin toggelt mit etwa 200kHz
statt der etwa erwarteten 8kHz.
Konkret:
irgendwo in main.c
1
// enable INT0 and INT1
2
GICR=1<<INT0|1<<INT1;
3
4
// VUSB defaults for INT0 and trigger on falling edge for INT1
TCCR1B=(1<<WGM12)|(0<<CS12)|(0<<CS11)|(1<<CS10);// ctc, no prescaler
18
OCR1A=cmp;// set value to output compare register
19
//Enable the Output Compare A interrupt
20
TIMSK|=(1<<OCIE1A);
21
}
22
23
voidint1_falling_edge(void){
24
MCUCR&=~(1<<ISC10);
25
GIFR|=(1<<INTF1);// clear external interrupt flag
26
}
27
28
voidint1_rising_edge(void){
29
MCUCR|=(1<<ISC10);
30
GIFR|=(1<<INTF1);// clear external interrupt flag
31
}
und dann die ISRs:
1
ISR(TIMER1_COMPA_vect){
2
PORTC^=(1<<PC4);
3
}
4
5
ISR(INT1_vect){
6
7
if(state==ZAC_READING_START_BIT_LOW){
8
timer1_start_normal();
9
int1_rising_edge();
10
state=ZAC_READING_START_BIT_HIGH;
11
}
12
if(state==ZAC_READING_START_BIT_HIGH){
13
int1_falling_edge();
14
state=ZAC_ACQUIRING_TSTROBE;
15
}
16
if(state==ZAC_ACQUIRING_TSTROBE){
17
timer1_stop();
18
timer_value=TCNT1;
19
TCNT1=0;
20
timer1_start_ctc(timer_value);
21
state=ZAC_READING_HIGH_BYTE;
22
}
23
if(state==ZAC_READING_HIGH_BYTE){
24
// hier dann anfangen zu samplen
25
}
26
27
}
Aber es funktioniert nicht. Egal ob ich das 125µs Delay am Anfang
weglasse oder nicht. Ich hab den INT1 auch mal auf "Any logical change"
gestellt, aber ohne Erfolg,
Ist das hier grober Bockmist, oder habe ich einfach nur eine Kleinigkeit
übersehen?
So, rein theoretisch sollte es jetzt tun, leider kommt nur Unfug bei der
Messung raus. Ich probiere jetzt schon einige Stunden hin und her.
Zumindest bin ich ziemlich sicher, nach Messung mit dem Oszi am Debug
Pin, daß die TSIC Messung etwa alle 100ms stattfindet. So weit so gut.
Ich vemute inzwischen, daß das Polling und der INT0 für den USB Bus die
Messung durcheinanderbringen, sicher bin ich aber nicht. Ich kenne mich
dafür auch zuwenig aus.
Ich benutze im Wesentlichen die Schaltung im Anhang. Der TSIC hängt am
INT0 Pin des Mega8 und wird über PINC5 eingeschaltet. Zum Auslesen über
USB verwende ich das C-Programm des HID-data Beispiels aus der VUSB Lib.
Zumindest das funktioniert ohne Probleme.
Etwas Quelltext:
main.c
DBG1(0x01,0,0);/* debug output: main loop starts */
337
338
for(;;){/* main event loop */
339
DBG1(0x02,0,0);/* debug output: main loop iterates */
340
wdt_reset();
341
usbPoll();
342
}
343
344
return0;
345
}
zakwire.h
1
#ifndef ZACKWIRE_H_
2
#define ZACWIRE_H_
3
4
#define ZACPORT PORTC
5
#define ZACPIN PINC5
6
#define ZACINT INT0
7
8
voidzac_on(void);
9
voidzac_off(void);
10
11
typedefenumstate{
12
ZAC_READING_START_BIT_LOW,
13
ZAC_READING_START_BIT_HIGH,
14
ZAC_ACQUIRING_TSTROBE,
15
ZAC_STROBE_ACQUIRED,
16
ZAC_READING_PARITY,
17
ZAC_WAITING_STOPBIT,
18
ZAC_READING_LOW_BYTE,
19
ZAC_READING_STOP_BIT,
20
ZAC_READING_HIGH_BYTE,
21
ZAC_WAITING_NEXT
22
}zacstate;
23
24
externzacstatestate;
25
26
#endif /* ZACWIRE_H_ */
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<avr/interrupt.h>
4
#include<stdint.h>
5
#include<stdio.h>
6
7
#include"zacwire.h"
8
9
voidzac_on(){
10
ZACPORT|=1<<ZACPIN;
11
}
12
13
voidzac_off(){
14
ZACPORT&=1&ZACPIN;
15
}
Mein Problem ist wie gesagt, daß bei der Messung ziemlich seltsame Werte
herauskommen, die nicht dem Paket auf dem jeweiligen Oszillogramm
entsprechen.
Kann hier beizeiten mal jemand drüberschauen und mir einen Tip geben, wo
ich noch nach dem Fehler suchen könnte?
Bin für jede Hilfe dankbar.
Gruß
Matthias
Also, ich habe den ganzen USB Krams mal rausgeworfen, mir scheint, daß
die Synchronisation nicht klappt. Die Methode "Einschalten, dann Messen"
taugt offenbar nichts.
Bernie schrieb:> Trotzdem kleiner Tipp:> - 5..6 der Register 0..15 reservieren und initialisieren.> - INT1: Any logical change on INT1 generates an interrupt request.> - CTR0: freilaufend im Takt von 1 MHz>> Flanke an INT1 -> IRQ> Negative Flanke: IRQ testet Overflow-Flag von CTR0 und resettet> ihn und das Overflow-Flag.> Lag ein Overflow vor: Start einer neuen Übertragung!> (Die Abstände innerhalb der Übertragung sind unter 256 µs.)
Kannst Du mir das mal etwas genauer erklären?
Woher weiss ich in der ISR dann, um welche Flanke es sich handelt und
wie reserviere ich Register in C?
Nanu? Warum fragst du nicht "MSP (Gast)"? Der tut doch hier
so oberschlau!
Scherz beiseite, ich schrieb natürlich, dass es eine "schlaue"
Interruptroutine sein muss. Das soll nicht heißen, dass sie
schwer verständlich ist, sondern dass sie einiges - Schritt für
Schritt - bei jedem Pegelwechsel des TSIC bearbeitet.
Unser Verständnisproblem wäre jetzt, dass ich es in ASM
verwirklicht habe - und du es in C machen willst. Da kann ich
dir leider nicht sooo exakt helfen, besonders weil sich das
Tutorial um die Prozessor-Register R0...R31 elegant rumdrückt.
Fangen wir mal mit der Synchronisierung an:
-------------------------------------------
- Mach den mega8 ERST MAL frei von USB- oder sonstigen
nicht überschaubaren Aufgaben.
- Reserviere einige GLOBALE Variablen nur für diese
TSIC-Bearbeitung.
Erst mal eine für COUNT-OLD.
- Sorge dafür, dass einer der zwei 8-Bit-Timer/Counter des
mega8 mit etwa 1 MHz frei läuft.
- Schließe den TSIC an INT1 an und stelle den INT1 so ein,
dass er auf positive UND negative Flanken reagiert.
- Wird der INT1 ausgelöst, frage sofort PinD-Bit3 ab.
(Ist PinD-Bit3 = 0 liegt eine negative Flanke vor.)
- Lese den Zählerstand des Timer/Counters aus.
- Schau nach, ob Timer-Overflow dieses Zählers gesetzt wurde.
- Diesen Timer-Overflow sofort resetten.
- Ist bei negativer Flanke der neue Zählerstand abzüglich
COUNT-OLD größer als 200 (µs)? (Bei Timer-Overflow kannst du
diese Differenz um mindestens 256 (µs) erhöhen.)
Dann bist du am Startpunkt einer neuen Übertragung des TSIC!!!
Schalte JETZT an irgendeinem Portpin eine LED an!
Sonst (!) setze diesen Portpin jedes mal auf LED = aus.
- Vor dem Ende der INT1-Routine den neu gelesenen Zählerstand
in COUNT-OLD speichern.
Nun schau mal, ob die LED immer aufblitzt, wenn am Oszilloskop
gerade eine neue Übertragung abläuft.
Wenn du interessiert bist, melde dich wieder - ES IST MACHBAR!
Der Rest ist eher einfacher.
Bernie schrieb:> Warum fragst du nicht "MSP (Gast)"?
Du hast mich gerufen Bernie, hier bin ich. Das Thema ist
Synchronisation? (Hast du das wieder unterm Teppich hergeholt?)
1. per Portpin den TSIC einschalten und Eieruhr mit ca 20ms (Wert ist
unkritisch, s. Datenblatt) aufziehen: z. B. mit Timer Interrupt.
2. Bei abgelaufener Eieruhr (Timer Interrupt) den Portpin mit TSIC Daten
auf fallende Flanke Interrupt einstellen
3. Bei fallender Flanke beginnt das Starbit
das war 's :-P
Bernie schrieb:> Ist bei negativer Flanke der neue Zählerstand abzüglich> COUNT-OLD größer als 200 (µs)?
Woher kommt der Zeitwert. Die Bitrate vom TSIC unterliegt sehr starken
Schwankungen. Feste Werte sind mit Vorsicht zu genießen.
Bernie schrieb:> - Mach den mega8 ERST MAL frei von USB- oder sonstigen> nicht überschaubaren Aufgaben.
Ja, das habe ich jetzt mal gemacht, sonst seh' ich auch den Wald vor
lauter Bäumen nicht mehr.
Bernie schrieb:> - Wird der INT1 ausgelöst, frage sofort PinD-Bit3 ab.> (Ist PinD-Bit3 = 0 liegt eine negative Flanke vor.)
Ok, da hätte ich Depp ja auch mal dran denken können.
Bernie schrieb:> Wenn du interessiert bist, melde dich wieder - ES IST MACHBAR!> Der Rest ist eher einfacher.
Bin ich. Und ich bin natürlich davon ausgegangen das es machbar ist.
Offenbar mache ich noch einiges falsch, sonst würde ja etwas Sinnvolles
herauskommen.
Dank euch beiden, ich werde mich heute Abend dann wieder damit
beschäftigen und mich melden.
Oh, "MSP (Gast)" ist wieder dabei! Und schreibt falsch ab:
Von 20 ms steht nichts in der App-Note, sondern 65...85 ms.
Welchen Timer mit welcher Zählfrequenz benutzt du denn für die
Decodierung des "TSIC-Telegramms"?
Die Hardware für die "reine" Interrupt-Lösung (INT1 und einen
Timer/Counter) muss man auch bei der langweiligen WARTE-Lösung
für die Code-Erkennung belegen...
Wenn man die Temperatur seltener auslesen will, kann man die
"reine" Interrupt-Lösung natürlich auch Sekunden- oder Minuten-lang
ruhen lassen.
Oh, "MSP (Gast)" verbreitet Furcht vor großen Toleranzen -
machen wir es eben mit REICHLICHST Toleranz!
Nominelle Ausgaberate 10 Hz, Bitdauer 125 µs.
Kennt jemand Exemplare, die langsamer, als 50%, oder schneller,
als 200% sind?
Also Annahme: Bitdauer 62...250 µs (Ausgaberate 5...20 Hz).
Nehmen wir bei 8 MHz µC-Clock den Timer1 mit Prescaler 1/32.
Wenn wir seinen Zählerstand UND sein Overflow-Flag bei jeder
negativen INT1-Flanke auslesen und danach auf Null setzen, können wir
Zeiten von 0...1 ms mit 4 µs Auflösung erfassen.
Zeiten länger als 1 ms zeigen sich durch das Overflow-Flag.
Mehr Sicherheit für die Erkennung der Pause vorm Startbit, ohne
Langeweile beim µC, geht garnicht!
Erkennung von Logisch 1 und 0:
Bei positiver Flanke lesen wir nur den Zählerstand aus.
Das Startbit hat 50% duty cycle bei 62...250 µs Bitdauer: 31...125 µs.
=> Timer1-Stand nach der positive Flanke = 7...32. (Referenzwert!)
Somit lassen sich locker die duty cycle von 25% und 75% unterscheiden.
Logisch 0 / 1 bei Zählerstand < Referenzwert / > Referenzwert.
Auch bei Timer0 mit Prescaler 1/64 (Auflösung nur 8 µs) gäbe es keine
Probleme! Logisch 0 / 1 bei Zählerstand < 3 / > 3 ... < 16 / > 16.
@ Matthias P.:
Bei Interesse gibts dann auch Hinweise zur Auwertung.
Bernie schrieb:> Und schreibt falsch ab:> Von 20 ms steht nichts in der App-Note, sondern 65...85 ms.
Und Bernie stellt sich wieder d... an. Denn ich schrieb
MSP schrieb:> ca 20ms (Wert ist unkritisch
und warum? Es handelt sich um die Zeit, die ich dem TSIC gönne, damit er
sich nach Power On stabilisiert. Die Werte im Datenblatt werden nicht
immer eingehalten. Probier das ruhig einmal aus.
Bernie schrieb:> Welchen Timer mit welcher Zählfrequenz benutzt du denn für die> Decodierung des "TSIC-Telegramms"?>> Die Hardware für die "reine" Interrupt-Lösung (INT1 und einen> Timer/Counter) muss man auch bei der langweiligen WARTE-Lösung> für die Code-Erkennung belegen...>> Wenn man die Temperatur seltener auslesen will, kann man die> "reine" Interrupt-Lösung natürlich auch Sekunden- oder Minuten-lang> ruhen lassen.
???
Keine Ahnung wo ich dir hier helfen kann. Es ging doch um
Synchronisation.
und ich schrieb
MSP schrieb:> Bei abgelaufener Eieruhr (Timer Interrupt)Bernie schrieb:> Furcht vor großen Toleranzen -> machen wir es eben mit REICHLICHST Toleranz!
Zacwire ist ein Protokoll mit Übertragung der Baudrate. Feste Werte für
Zeiten sind nicht sinning und auch nicht erforderlich.
Bernie schrieb:> Also Annahme: Bitdauer 62...250 µs
Wie lang sind die Stop Bits zwischen den Daten? Aber nicht nach
Datenblatt sondern selbst gemessen.
Man merkt, dass dir meine Synchronosation gefällt. Sie hat ja Vorteile:
- unabhängig von der Baudrate
- schlank und kurz
- funktioniert in jedem Fall, denn es gibt nur einen Fall. Mit der
ersten fallenden Flanke beginnt das Startbit
@ MSP (Gast)
Hast du wieder keine Antwort, außer "Warteschleife"?
Das ist DEINE BESTE Lösung: Schlanke kurze WARTESCHLEIFEN.
Wer AHNUNG hat, kann andere Vorgehensweisen VERSTEHEN.
Kannst du das nicht?
Es ist wohl nicht mal DEINE Lösung, da du keine Auskunft
geben kannst, welche µC-Resourcen du dafür und für die
Dekodierung benutzt hast.
Bernie schrieb:> Wer AHNUNG hat, kann andere Vorgehensweisen VERSTEHEN.
Na Bernie, dann bemühe dich doch endlich. Denn das
Bernie schrieb:> Hast du wieder keine Antwort, außer "Warteschleife"?>> Das ist DEINE BESTE Lösung: Schlanke kurze WARTESCHLEIFEN.
zeigt, dass du den Text nicht gelesen oder nicht verstanden hast.
Bernie schrieb:> welche µC-Resourcen du dafür und für die> Dekodierung benutzt
Für Synchronisation und Datenempfang werden
Ausgang für ON/OFF TSIC
Eingang für Daten (interruptfähig)
Timer
benötigt.
Der TSIC ist Master der Übertragung. Es braucht eine Synchronisation mit
dem Slave. Und das muss in allen Fällen funktionieren. Den Master
kontrolliere ich über die Spannungsversorgung. Und die erste fallende
Flanke ist garantiert das Startbit. Für die Synchronisation wird keine
Rechenleistung benötigt.
Ich hoffe, jetzt hast du es verstanden.
Und da dir die Verschwendung von Rechenleistung wichtig ist:
Bei deiner Variante führt jede Flanke zu einer Berechnung und das können
über 30 Flanken sein.
Für die Synchronisation benötigt deine Variante nur die fallenden
Flanken. Das lässt sich später auf beide Flanken umkonfigurieren.
Die absoluten Zeiten wurden schon angesprochen.
@ MSP (Gast)
Hast du den ganzen Abend gewartet, dass dich jemand lobt?
Gibt leider nichts loben:
Ein µC in Warteschleife braucht keine Rechenleistung?
- Falsch:
In Warteschleifen steht die Rechenleistung nicht zur
Verfügung, die vielleicht anderswo gebraucht wird.
30 Flanken?
- Falsch:
Es sind genau 40 Flanken (20 neg, 20 pos.) pro Messwert.
Bis zur Startflanke braucht meine Variante nur ein paar
µC-Takte für die Initialisierung. Deine steht mindestens
160.000 (eher 680.000) µC-Takte dumm rum.
Falls du überhaupt schon mal daran gedacht hast, die
Datenbits zu dekodieren, musst du die auch bearbeiten.
Wenn meine Interruptlösung in der Pause auf das
Startbit wartet, wird der µC überhaupt nicht belastet.
Es kommt doch nichts - da kann man auch gleich beide
Flanken des INT1 aktivieren.
Du willst dekodieren, ohne auf die positiven
Flanken zu reagieren?
- Falsch:
Die Zeit von negativer zu positiver Flanke wird benötigt,
um beim Startbit die "Baudrate" zu bestimmen. Danach, um
den Bitwert (0/1) zu bestimmen.
Für mich erscheinst du einfach ignorant.
Das Wort kannst du bei WIKI nachlesen. Bei dir ist es aber
keine Absicht! - Dazu würde ja ein Mindestmaß an Wissen
gehören...
Nun Bernie, was ist mit dir los?
Weist du nicht, wie Interrupts in einer CPU verarbeitet werden? Oder
bist du ignorant und enttäuscht, weil deine mühsamm und mit viel Einsatz
gestrickte SW noch Verbesserungspotenial besitzt?
Aber ich will dir gerne helfen.
Bernie schrieb:> Ein µC in Warteschleife braucht keine Rechenleistung?
Wie kommst du immer wieder auf Warteschleife? Bei meiner Variante gibt
es keine Warteschleifen. Es wird ein Portpin gesetzt und der Interrupt
für eine negative Flanke aktiviert. Das war es. Jetzt kann der µC machen
was er will.
Bernie schrieb:> 30 Flanken?MSP schrieb:> das können> über 30 Flanken sein
Wenn du beim µC die Interrupts aktiviertst, weisst du nicht, was der
TSIC gerade macht. Im ungüstigen Fall passiert das genau im ersten
Startbit. Dann springst du bei jeder der über 30 Flanken in deine ISR
und rechnest.
Ob das kritisch ist, musst du selbst entscheiden. Dir war aber die
Verschwendung von Rechenleistung wichtig, oder?
Bernie schrieb:> Wenn meine Interruptlösung in der Pause auf das> Startbit wartet, wird der µC überhaupt nicht belastet.> Es kommt doch nichts - da kann man auch gleich beide> Flanken des INT1 aktivieren.
Doch, du benötigst Rechenleistung, siehe oben.
Bernie schrieb:> Du willst dekodieren, ohne auf die positiven> Flanken zu reagieren?MSP schrieb:> Für die Synchronisation benötigt deine Variante nur die fallenden> Flanken. Das lässt sich später auf beide Flanken umkonfigurieren.
Für die Synchronisation braucht man keine positiven Flanken. Wenn man
sie für die Datenbits braucht, konfiguriert man nach der Synchronisation
die Flanken um.
@ MSP (Gast)
Von klugen Menschen lass ich mich ungern "d... " nennen.
Von Menschen, wie dir, die nicht verstehen, worum es geht,
schon garnicht.
Bei meiner Lösung kostet der sichere (!) Empfang bei 8 MHz
mit Einschalten des TSIC 200 µs,
sonst (worst case) 400 µs.
Viel Spaß in deiner Warteschleife!
Biete was besseres, oder hasta la vista, Baby!
Bernie schrieb:> Viel Spaß in deiner Warteschleife!> Biete was besseres, oder hasta la vista, Baby!
Ok, es ist also dein angekratzter Stolz.
Deine Oberflächlichkeit bei Erkennung der Systemzustände lässt auf einen
Hobby Bastler schließen. Im industriellen Umfeld muss eben mehr beachtet
werden.
Bernie schrieb:> mit Einschalten des TSIC
Aber schön, dass du doch andere Ideen annimmst. Auch wenn es einen
weiteren Portpin kostet, hat es noch weitere Vorteile.
@ MSP (Gast) Mein Stolz? Deine Professionalität?
- Warum lauerst du denn hier tagelang auf ein bisschen
Anerkennung?
- Warum bist du so "d... " und kannst nicht über deine
einmal (abgekupferte?) Lösung hinausblicken?
Bei mir ist es eher die Freude, mit der Verbreitung von
Wissen über resourcensparende, sonst mindestens
gleichwertige Denkansätze, anderen bei der Problemlösung
zu helfen. - Darum antworte ich dir überhaupt noch.
Hab ich das Einschalten des TSIC abgelehnt?
- Nein, deine alberne Warteschleife dabei!
- Und dass man einen Portpin gegen << 0,1 mA Strom-
erparnis abwägen muss. Das sollten "Profis im
industriellen Umfeld" schon mal können!
Wer für triviale Probleme gleich zum nächstgrößeren µC
greift, hat noch nie Kostendruck gespürt. Das kostet
nicht nur die paar Cent des größeren Chips...
Weitere Vorteile?
Deine (zeitliche) µC-Belastung?
- Da kommt mal wieder nix. (Woher denn auch...)
Bernie schrieb:> Hab ich das Einschalten des TSIC abgelehnt?> - Nein, deine alberne Warteschleife dabei!
Und wenn du es 100mal wiederholst, wird es nicht realer. Tja, wenn 's
fachlich fehlt, dann ...
Bernie schrieb:> Bei mir ist es eher die Freude, mit der Verbreitung von> Wissen
Bernie, Bernie, dann fang doch bitte an. Von dir kommt nichts als
Selbstbelobing. Welche wissenwerte Dinge hast du denn verbreitet?
Den TSIC zu koppeln ist nicht gerade der höchste Schwierigkeitsgrad. Das
haben schon Hunderte gemacht. Und zu 99% nach einer der beiden
Möglichkeiten:
a) Zeit des Low-Pegel messen und mit der halben Bitzeit vergleichen
b) in der Mitte des Bits den Pegel abfragen (wie beim UART)
Bernielein hat Variante a) gewählt und glaubt damit das Ei des Columbus
gefunden zu haben. lol
Aber wie ich schon schrieb, ist das nur ein Teil der Systemzustände. Da
gibt es noch etwas darum herum.
He, hier gibts ja grade einen aktiven Thread fürn TSIC-Tempratursensor.
Ist der schwer einzuprogrammieren? Oder streitet ihr aus Spaß?
Bin an einer Steuerung mit AVR4313 und soll noch einen TSIC ranhängen,
weil man für einiges Temperaturkompensieren muss. 3 Ports sind noch
frei, USART aber nicht. Geht das und ohne Interrupt? Die Tempratur kommt
doch 10 mal die Sekunde.
danke J. Knetling
Schwer ist das nicht. Beim 4313 kann ja fast jeder Port-Pin
einen Interrupt auslösen - das brauchst du für die Erfassung
des Telegramms. Hast du noch einen Timer frei, oder einen
der durchgängig zählt?
Streiten? Man kann es auf verschiedene Weisen machen.
Manche Leute meinen, es gibt nur EINEN Weg. Aber wenn du
schon Steuerung kannst, wirst du schon sehen, was bei dir
am besten passt.
Machst du es in ASM oder C?
Ich verstehe den ganzen Thread nicht. ihr macht hier einen Popanz um
eines der einfachsten protokolle, die es überhaupt gibt:
Jedes Bit beginnt mit einer fallenden Flanke, das Startbit hat einen DC
von 50%, ist also leicht von den anderen Bits zu unterscheiden.
Hier gibt es fertige Codes für AVR und PIChttp://www.mikrocontroller.net/articles/Temperatursensor#TSic, einem
Beispiel für den PIC habe ich die folgende Erklärung entnommen:
1
; Duty-Cycle:
2
; Startbit 50%
3
; Daten-/Parity-Bit logic 0: 25%
4
; logic 1: 75%
5
; typ. Länge eines Bits: 125 usec
6
;
7
; Messprinzip:
8
; Die Bitlänge ist temperaturabhängig, deshalb bestimmt man die Bitlänge bei jedem Byte durch Messung des Startbits
9
; dieses hat einen Duty-Cycle von 50%. Wenn das halbe Startbit rum ist (LO), wird die Zeit t_strobe gemessen.
10
; Diese Zeit wartet man vom Start eines jeden Daten-Bytes, und nimmt dann den Zustand des Daten-Pins auf. Ist er
11
; LO, dann ist das Daten-Bit 0 (25% Duty-Cycle), ist er HI, dann ist das Daten-Bit 1 (75% Duty-Cycle)
Knetling schrieb:> Ist der schwer einzuprogrammieren?
Nein, keine große Nummer.
Knetling schrieb:> weil man für einiges Temperaturkompensieren muss
Was für Reaktionszeiten bei Temperaturänderung benötigst du? Der TSIC in
seinem Kunststoffgehäuse muss ja der Änderung folgen können. Evtl. kann
das durch Kopplung mit einer Wärmeleitfläche (Kühlkörper) verbessert
werden.
Knetling schrieb:> Die Tempratur kommt> doch 10 mal die Sekunde.
Aber so schnell wird sie sich im TSIC (also am Messpunkt) nicht
ändern. Also brauchst du nicht jeden Datenrahmen empfangen und bei
knappen Resourcen solltest du das auch nicht.
Bernie schrieb:> Schwer ist das nicht.
Da hatte ich bei dir einen anderen Eindruck. Ich dachte du hättest eine
Doktorarbeit über den TSIC geschrieben.
bingo schrieb:> eines der einfachsten protokolle, die es überhaupt gibtbingo schrieb:> Absolut easy, oder ...
full agree
Voll super, wird schon klar!
Geht das gut mit Versorgung ausm Portpin?
Also den TSIC alle Sekunden von einem Port eingeschalten, und einen
PCINT für die Daten aktivieren.
Timer0 muss dann für die Zeitgeschichten ran.
PCINT kommt bei jeder Flanke, da kommt mal keine bis zum Start-Bit. Dann
kommt die 50% Zeit, mess ich mit Timer0. Damit die andern Bits nach
fallende Flanke vergleichen.
Worauf muss ich 20ms warten?
Und wieso ist die Bitlänge tempraturabhängig? Dachte die Temperatur ist
in den 2 Datenbytes.
( Steht so im Datenblatt. )
Knetling schrieb:> Geht das gut mit Versorgung ausm Portpin?
Ja, aber Spannung anhand der Datenblätter kontrollieren.
Knetling schrieb:> Flanke, da kommt mal keine bis zum Start-Bit
Ja, aufm Labortisch. Besser ist es dem TSIC ein wenig Zeit zum
Stabilisieren zu geben. Die Zeit ist unkritisch, Bsp. 2ms ... 20ms.
Knetling schrieb:> Worauf muss ich 20ms warten?
Gar nicht, der Floh kommt von "Ich kann nicht lesen Bernie".
Knetling schrieb:> Und wieso ist die Bitlänge tempraturabhängig?
Intern im TSIC gibt es eine Takterzeugung. Die ist nicht
temperaturstabil. Das ist aber völlig egal, da die Bitzeit vom Startbit
abgeleitet wird.
Knetling schrieb:> Damit die andern Bits nach> fallende Flanke vergleichen.
oder ab dem halben Startbit bei den nächsten vollen Bitlängen auf den
Pegel gucken.
Für Bernie: Das dürften ein paar Maschinenbefehle weniger sein. Aber
eigentlich egal, wenn man die Zeit damit vergeudet, alle 100ms Daten zu
lesen. Klick?
Ich habe mal meinen LA angeworfen und das Protokoll aufgezeichnet.
Daraus kann man sehr schön sehen, dass es sehr wohl Sinn macht, die
Versorgung des TSIC über einen zusätzlichen Port ein und aus zu
schalten.
In Image1 wird der TSIC eingeschaltet (Vdd geht HI und wenige ns danach
auch Data), etwa 35 ms später kommen die 2 fast zusammenhängenden Blöcke
mit den Daten. Diese sind in Image 2 dargestellt: je ein Startbit (S), 8
Datenbits (0/1) und ein Paritybit (P). Wenn man per Timer die LO-Phase
des Starbits ausmisst (hier sind es etwa 62µs) und dann nach jeder
fallenden Flanke genau diese Zeit abwartet, braucht man nur den Zustand
von Data (0/1) aufzunehmen und hat das Datenbit.
In Image 3 ist der Verlauf aufgezeichnet, den man im frei laufenden
Modus hat: etwa alle 100 ms zwei fast zusammenhängende Datenblöcke.
Der Modus mit ein/aus geht also wesentlich schneller (nach 35 ms hat man
die Daten) als der frei laufende Modus (im Mittel dauert es 50 ms, bis
der Datenblock da ist). Da man im ein/aus-Modus sicher sein kann, dass
als erstes ein Startbit kommt, kann man die Daten einfach per Polling
aufnehmen, das sind nur wenige Befehle in ASM oder C. Im frei laufenden
Modus muss man erst mal auf eine Pause von einer gewissen Länge warten
(z.B. 60-80 ms) und dann pollen oder man nimmt per Interrupt auf und
muss entscheiden, ob ein Start- oder ein Daten-Bit vorliegt.
Zudem fällt die Erwärmung des Dies im TSIC weg, die angesichts des
geringen Stromverbrauch nur gering, aber messbar ist.
bingo schrieb:> etwa 35 ms später kommen
Aha, und was steht im Datenblatt? Ich kann die größeren Abweichungen
bestätigen.
bingo schrieb:> dann nach jeder> fallenden Flanke genau diese Zeit abwartet, braucht man nur den Zustand> von Data (0/1) aufzunehmen und hat das Datenbit.
oder du nimmst einen Timerinterrupt mit der doppelten Zeit (also von
einem ganzen Bit) den du nach dem halben Startbit (steigende Flanke)
scharf schaltest. Dann reicht der Zustand beim Timer-Ereignis.
bingo schrieb:> Der Modus mit ein/aus geht also wesentlich schneller> als der frei laufende Modus
das stimmt so nicht. Das hängt davon ab, wann die Auswertung startet.
Das kurz vor dem Satartbit sein, dann geht es schneller, oder während
oder kurz nach der Datenübertraguzng, dann dauert es länger.
bingo schrieb:> dass als erstes ein Startbit kommt, kann man die Daten einfach per Polling> aufnehmen
buhhh!
bingo schrieb:> Zudem fällt die Erwärmung des Dies im TSIC weg, die angesichts des> geringen Stromverbrauch nur gering, aber messbar ist.
da wäre ich an Daten interessiert.
BINGO! bingo! ;-)
Mit deinen Bildern schnall ich auch wie das 2. Byte kommt. In der
Zackwire-PDF sieht man das nichtso richtig.
0000001011010111 = 727
727 * 1000 / 1024 = 709
709 - 500 = 209
Braucht man keine Fließkommas, super. Hast du 20,9°C in der Bude? ;-)
Denk mal, ich geh so vor:
Ich werf alle Sekunde den TSIC an, und lass ab kurz danach den PCINT mit
dem Timer von fallende bis steigende Flanke die Bits bestimmen. Erster
Wert ist Refferenz, die andern vergleich ich auf länger-kürzer. Lässt
sich bestimmt leichter programmiern, als die Portabfrage nach
Refferenzzeit.
Wenn ich die Bilder seh, geht es 20 mal runter und 20 mal rauf. Sind 20
Bits. Kann ich ja nach 20 Bits im PCINT den TSIC wieder ausschalten.
Nächste Sekunde hol ich mir die Bits und lass das Ganze wieder losgehen.
Wirklich easy!
So schnell soll die Tempraturmessung ja nicht sein, wenn MSP da recht
hat. Kann mans bestimmt sein lassen, das zweite Startbit als Reffernz zu
nemen. Schmeiß ich hinterher raus.
Noch paar Fragen.
Komisch daß in der Zackwire-PDF 65-85ms nach einschalten steht. Auf den
Bildern sinds ja nur schlappe 40 ms. Na Egal, ist viel kleiner als meine
Sekunde und der PCINT hat solange nichts zu tun.
Sind die 125µs so ungenau? 8MHZ /64 = 125kHz = 8µs beim Timer0 müssten
doch reichen.
Muss ich 40 mal im PCINT kurz kucken welche Flanke war und Timer0
auslesen und vergleichen oder reseten. Was für 30 Berechnungen im PCINT
machen MSP Angst?
Das berechnen mach ich im Hauptprogramm, hat noch Reserve dafür.
Schönen Dank schon mal,
meld mich morgen wies klappt.
Sonnabens ist ja Zeit zum probiern.
Oha, die 39 ms Reaktionszeit bei "bingo (Gast)" sind überraschend, das
Bild sieht aber überzeugend aus. Habe dem Datenblatt mit 65...85 ms
vertraut.
Die Bilder sind wirklich gut fürs Verständnis! - Danke, "bingo (Gast)"!
Wie "Knetling" schreibt, liest man das ZacWire.PDF und ist danach noch
etwas unsicher...
Die Reaktionszeit hat bei mir aber keinen Einfluss, da der Interrupt vom
TSIC solange nicht stört. Nur doof, wenn eine Warteschleife zu lange
wartet...
Was macht ihr da für umständliche Sachen mit Polling, oder
Timerinterrupt nach jeder Flanke starten und nach irgendwelchen Zeiten
scharfschalten?
Ich gehe da etwas praktischer ran:
Der Interrupt fürs TSIC-Signal und der freilaufende Timer sind sowieso
im Geschäft, also:
TSIC-negative Flanke: Timer-Reset,
TSIC-positive Flanke: Timer auslesen.
Startbit erkennen: Nach Einschalten kein Problem, sonst lange Pause
(Timer-Overflow) auswerten.
Zur Not auch noch 3..4 Befehle für Plausibilität in den Interrupt
einbauen (1/2 µs @ 8 MHz).
Startbit - positive Flanke: Zeit als T-Referenz erfassen.
Weitere Bits - positive Flanke: Vergleich mit T-Referenz und als logisch
0, oder logisch 1 in 2..3 reservierte Bytes reinschieben.
(Hab ich alles schon vor einer Woche geschrieben...)
GENAU SO ist es "voll easy"!
"Knetling" hat offenbar einen ähnlichen Weg eingeschlagen.
Schaun wir mal...
Für die, die keine DÜNNBRETTBOHRER sind:
Man könnte sich noch überlegen, ob überhaupt 3 Bytes für die erfassten
Bits nötig sind.
Nur 2 Bytes: Es würden nur 5 Bit vom Hi-Byte, Hi-Parity, das 2.
Startbit, 8 Bits vom Lo-Byte und Lo-Parity erfasst. Vom Hi-Byte sind
aber nur 3 Bit aktiv, davor sind 5 konstante NULL-Bits.
Wenn ich die Parity-Bits auswerte, muss ich einfach die 3 fehlenden
oberen Hi-Bits als empfangene NULLen annehmen. Die Parity-Auswertung
wird da leicht "beschummelt". Das Parity-Bit geht aber auch davon aus,
dass diese Bits NULL sind - und kann sowieso nie sagen, welches Bit
fehlerhaft ist. Nach meiner Einschätzung hat diese Einsparung keinen
Einfluss auf die Datensicherheit. Weiß es jemand besser?
> Oha, die 39 ms Reaktionszeit bei "bingo (Gast)" sind überraschend, das> Bild sieht aber überzeugend aus. Habe dem Datenblatt mit 65...85 ms> vertraut.
Die Zeit zwischen Einschalten und dem ersten Startbit ist tatsächlich
nur etwa 30-45 ms. Ich habe in den letzten Jahren mehr als 20 TSIC
verbaut (Hygrosens), alle getestet, alle lagen zwischen 30 und 42 msec.
Zeiten wie in den Datenblättern habe ich nie erlebt, ich habe allerdings
nicht unter -10°C oder über +50°C gemessen.
Jau, läuft schon!
Tausend Dank schon mal!
Hab es nach Bernies Tip mit nur zwei Emfänger-Bytes gemacht.
Und noch die Tempratur auf die Anzeige, passt gut zum Thermometer.
Die Steuerung klappt wie vorher - naja die muss auch nur alle 8ms
reagiren und der PCINT braucht immer viel weniger wie 10µs.
Benützt ihr die Paritys? Ich schieb die und das 2. Startbit einfach
raus.
Läuft superstabil, hab aber noch die Woche bißchen Zeit. Hey MSP, wie
brauchst du nur ein Interupt für jedes Bit? Mein PCINT kommt aber immer
auf jede Flanke. Und den USART brauch ich aber schon um für die
PC-Verbindung.
Freut mich, dass du fast von allein, zu einer ähnlichen recht effektiven
Lösung gekommen bist. Bin aber nicht sehr überrascht: Es bietet sich
doch einfach an, wenn man das TSIC-Protokoll verstanden hat und es
resourcensparend umsetzen will.
Wir verschwenden allerdings zwei Interrupts pro Bit!
Wenn ich den einen kryptischen Beitrag von "MSP (Gast)" richtig
entschlüsselt habe, macht er es recht umständlich, um nur einen
Interrupt pro Bit zu brauchen:
1) Irgendwie das Startbit abwarten,
2) dessen Low-Zeit (halbe Bitdauer) mit Timer messen,
3) schnell den Timer umdefinieren, dass er mit der doppelten Zeit einen
Interrupt liefert, der dann hoffentlich (!) immer die Bitmitte trifft.
Wäre mir zu unsicher: Die Erfassung (mit 1 MHz) kann leicht 1,5 µs
danebenliegen. Macht 3 µs pro Bit, die sich aufsummieren. Nach 19
weiteren Bit sind das 57 µs = fast eine halbe Bitzeit. Totaler Murks!
Also den ganzen Aufwand für das zweite Byte nochmal! Selbst dann ist es
für die erforderliche Genauigkeit von 1/4 Bitdauer HOFFENTLICH nur nah
der Grenze. Aufwändig, aber unsicher!
Vielleicht komm ich nicht drauf und er hat das Ei des Kolumbus gefunden?
- Aber "MSP (Gast)" bevorzugt leider die Kritik an anderen, gegenüber
eigenen nachprüfbaren Vorschlägen.
Zum Temperatureinfluss habe ich mir ein paar überschlägige Gedanken
gemacht:
Mit der Einschaltung 1 mal pro Sekunde sieht es gut aus!
Typische TO92-Transistoren haben einen R_th von 0,2 K/mW zu ruhender
Luft.
Wird beim TSIC mit dieser Bauform ähnlich sein.
Datenblatt TSIC: < 0,1 mA bei 3,3 V -> < 0,33 mW.
Macht < 0,33 mW * 0,2 K/mW = < 0,07 K
Also knapp 0,1 °C zu viel bei Dauerbetrieb an 3,3 V.
Bei 1/10 Einschaltzeit < 0,01 °C. (Das sieht der TSIC nicht.)
Eine pessimistische Schätzung für 5 V sei 0,2 mA = 1 mW.
Ich messe 15 mV an den vorgeschlagenen 220 Ohm (+ 100 nF nach Masse),
etwa 0,07 mA...
Also wahrscheinlich unter 0,2 °C Fehler bei Dauerbetrieb an 5 V.
Bei 1/10 Einschaltzeit unter 0,02 °C. (Jenseits der Auflösung des TSIC.)
Hi
>Wäre mir zu unsicher: Die Erfassung (mit 1 MHz) kann leicht 1,5 µs>danebenliegen. Macht 3 µs pro Bit, die sich aufsummieren. Nach 19>weiteren Bit sind das 57 µs = fast eine halbe Bitzeit. Totaler Murks!
Unsinn. Mit jeder fallenden Flanke beginnt das Spiel vorn. Da summiert
sich nichts.
MfG Spess
Hey Spess, von dir bin ich aber klügere Beiträge gewohnt!
Hier geht es um die benötigten Interrupts pro Bit bei ZacWire.
"MSP (Gast)" behauptet, dass man es mit EINEM Interrupt pro Bit
schafft.
Um die fallende Flanke zu erfassen, brauch ich einen Interrupt, oder
zeitintensives Polling.
Um den Bitwert (den duty cycle) zu erfassen, brauche ich einen
Timer-Interrupt, oder einen Interrupt von der positiven Flanke, oder
zeitintensives Polling.
Wenn Polling nicht in Frage kommt, weil der µC noch anderes zu erledigen
hat, verbleiben ohne Hexerei immer ZWEI Interrupts pro Bit.
Hab noch gegrübelt, ob es mit Timer-Capture oder so besser wird. Wird
nur mehr Aufwand.
Die Software UART so ungenau laufengelassen, ist mir zu
fehlerfreundlich. Und die wie Spess53 auf jedes Bit zu synchronisieren,
kostet gleichen Aufwand wie die Messung von fallende auf steigende
Flanke.
was meckert MSP nur immer rum? Und die eigene Idee müssen ihm noch
andere hinschreiben.
Was solls! Es funktoniert sauber, jetzt auch mit Paritys.
Danke Jungs!
Hallo Matthias,
beim groben Code-Scan fiel mir folgendes auf:
----------------------------------------
void zac_off() {
ZACPORT &= 1 & ZACPIN;
}
----------------------------------------
Diese Funktion kann den TSIC ausschalten,
muß es aber nicht: wenn ZACPIN == 1 ist,
dann wird die Funktion nichts bewirken.
Außerdem setzt die Funktion bei ZACPIN != 1
den ganzen ZACPORT auf 0 - und das ist
evtl. gar nicht gewollt.
Vermutlich meintest Du eher folgendes:
----------------------------------------
void zac_off() {
ZACPORT &= ~(1 < ZACPIN);
}
----------------------------------------
Trotzdem wird das vermutlich dein Problem noch nicht lösen.
Ich denke, man muß sich sehr genau Gedanken darüber machen,
wie man die TSIC-Abfrage zwischen den USB-Interruptaufrufen
platziert (oder gar beides verschachtelt).
Dann bislang kannst Du nie sicher sein, ob Du eine fallende
oder steigende Flanke rechtzeitig mit Deinem INT1 detektierst -
der Prozessor könnte sich ja zum Zeitpunkt eines Flanken-
wechsels in der USB-Interruptroutine aufhalten (ist alles
noch ein bißchen Mutmaßung - ich muß Deinen Code erst noch
"richtig" sichten).
Bevor ich tiefer einsteige, hätte ich ein paar Fragen:
- Was genau soll Deine Schaltung+Auswerteprogramm tun?
- Welchen ATmega verwendest Du?
- Welche Quarzfrequenz verwendest Du?
- Wie sieht die Software auf dem PC aus?
Viele Grüße
Igel1
Hallo Matthias,
mir fielen noch ein paar Fragen ein:
- Welche Entwicklungsumgebung benutzt Du?
- Welches Entwicklungsboard benutzt Du?
- Welches Betriebssystem hat Dein PC, der per USB die Daten empfangen
soll?
- Könntest Du netterweise kurz skizzieren, wie Du über das
USB/HID-Protokoll die Daten auf dem PC auswertest?
- Könntest Du netterweise nochmals beide Codeversionen hochladen:
1.) das vollständige Programm mitsamt den USB Codeanteilen
2.) die um die USB-Codeanteile "gestrippten" Programmversion
Sodann fiel mir auf, daß in Deinem Code die Angabe der
CPU-Taktfrequenzangabe fehlt:
#define F_CPU 12000000UL
Das könnte ggf. bei Verwendung der delay-Funktionen in Deinem Code
Probleme generieren, siehe:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29
Viele Grüße
Igel1
Hallo Matthias,
hier noch eine Anmerkung zur Motivation:
Ich bin mir sehr sicher, daß wir zumindest den USB-freien Code
ans Laufen bekommen werden.
Was den Code mit USB-Anteilen angeht, so wird das sicher etwas
anspruchsvoller. Aber die Angaben beim Herstellen machen Hoffnung
http://vusb.wikidot.com/troubleshooting
(siehe Punkt 6. Interrupts and Timing)
Dort ist zu lesen, daß man offenbar den USB-Interrupt auch mal ein
paar Millisekunden ausschalten darf (was für ein TSIC-Dateneinlesen
ggf. ausreichen könnte)
Viele Grüße
Igel1
Hallo Matthias,
ich habe soeben Deinen Code in meiner Entwicklungsumgebung übersetzt
(AVRStudio Version 4.19 Build 716) und siehe da, die einzige
Compiler-Warnung lautet:
c:/programme/winavr-20100110/lib/gcc/../../avr/include/util/delay.h:85:3
: warning: #warning "F_CPU not defined for <util/delay.h>"
Build succeeded with 1 Warnings...
Will sagen: das solltest Du unbedingt noch fixen.
Viele Grüße
Igel1
Evtl. hilft es ja jemanden weiter oder kann es wer gebrauchen..
Hab mir mal ein mit Thermometer zusammen gebaut, funktioniert immernoch
einwandfrei... Habe für die Anzeige Schieberegister mit 7 Segmentanzeige
verwendet. Der Mega lief glaub ich mit meinen Code auf 4Mhz. Wenn man
die Frequenz verändert muss man glaub ich ein wenig an der Stelle zum
messen der Strobe-Zeit herumbasteln...
Nicht schimpfen, war mein erstes Lernprojekt. Hatte vorher 0 Ahnung vom
Programmieren und hatt das in 3 Wochen fertig...
Evtl. ist das eine oder andere nicht so optimal, aber fürs erste mal...
Und es funktioniert :)
Hier mal der Code:
Alter Schwede, kaum habe ich hier ein paar Tage nicht hineingeschaut,
geht hier voll die Post ab. ;) Schön, das das Thema von solchem
Interesse ist.
Andreas S. schrieb:> Vermutlich meintest Du eher folgendes:> ----------------------------------------> void zac_off() {> ZACPORT &= ~(1 < ZACPIN);> }> ---------------------------------------->> Trotzdem wird das vermutlich dein Problem noch nicht lösen.
Ja, das habe ich auch schon gesehen. Ist inzwischen behoben, da ich die
Funktion aber eh nicht benutzt habe, gab es an der Stelle kein Problem.
Andreas S. schrieb:> - Welche Entwicklungsumgebung benutzt Du?
Eclipse + CDT + winavr
> - Welches Entwicklungsboard benutzt Du?
Ein Steckbrett. ;)
> - Welches Betriebssystem hat Dein PC, der per USB die Daten empfangen> soll?
Win7 x64 / Ubuntu
> - Könntest Du netterweise kurz skizzieren, wie Du über das> USB/HID-Protokoll die Daten auf dem PC auswertest?> - Könntest Du netterweise nochmals beide Codeversionen hochladen:> 1.) das vollständige Programm mitsamt den USB Codeanteilen> 2.) die um die USB-Codeanteile "gestrippten" Programmversion
Ich werde heute oder morgen mal das vollständige Programm anhängen.
> Sodann fiel mir auf, daß in Deinem Code die Angabe der> CPU-Taktfrequenzangabe fehlt:>> #define F_CPU 12000000UL
Keine Sorge, fehlt nicht, ich hatte nur den Code nicht vollständig
hierhin kopiert.
Andreas S. schrieb:> Bevor ich tiefer einsteige, hätte ich ein paar Fragen:>> - Was genau soll Deine Schaltung+Auswerteprogramm tun?
Zyklisch die Temperatur des TSIC auslesen und in einem Puffer speichern,
der über die USB Schnittstelle ausgelesen werden kann.
> - Welchen ATmega verwendest Du?
ATMega8
> - Welche Quarzfrequenz verwendest Du?
16MHz
> - Wie sieht die Software auf dem PC aus?>
Die entspricht im großen und ganzen dem Beispiel HID-Data aus der
VUSB-Lib, aber ich werde auch das mal mit anhängen.
Ich werde dann jetzt mal den Rest des Threads studieren. ;)
Gruß
MP
@Matze0001:
Danke für den Code. Ich hatte Matthias allerdings so verstanden,
daß die ganze Party in C starten soll.
@Matthias:
Dann sind wir schon mal gespannt auf Deinen Code.
Bitte sowohl den Code mit USB-Anteilen als auch den ohne USB-Anteile
hochladen. Bitte nur vollständig, sonst suchen wir möglicherweise
an der falschen Ecke.
Kleine Frage noch:
Läuft der USB-Host-Part Deines Programms unter Deinem Win7 x64 oder
unter Deinem Ubuntu oder unter beidem?
Viele Grüße
Igel1
@Matthias:
- Habe Deinen Schaltplan nachgebaut:
Dazu habe ich nur den linken Teil Deines Schaltplans nachgebaut und
alles,
was in Deinem Schaltplan Richtung ATmega geht, entsprechend mit meinem
Pollin AVR-Funkboard verbunden - war gerade zur Hand (ATmega8L-8PU,
12MHz Quarz - ein Wunder, dass der MC bei 3,5V noch mit 12MHz läuft
...)
- Habe MinGW heruntergeladen und installiert
- Habe V-USB heruntergeladen
- Habe das HID-Data Beispiel compiliert und auf meinen MC geflashed
(Fuses ebenfalls ...)
- Habe den PC-Part (hidtool) compiliert
- Habe alles zusammengesteckt
- Habe mit "hidtool write" und "hidtool read" Funktionskontrolle gemacht
=> 3x "Alaaf" gebrüllt, als alles funktionierte
Will sagen: Jetzt wäre es supergut, wenn Du Deinen Code hochladen
könntest, denn jetzt könnte ich live und in Farbe testen ...
Viele Grüße
Igel1
Also, ich hab mir die ganze Geschichte nochmal angesehen.
Es hat so absolut keinen Sinn mehr, ich hab' total den Faden verloren.
Ich werde alles wegwerfen und wenn ich Muße habe, nochmal ganz von vorne
anfangen.
Trotzdem Dank an alle, die Ihre Hilfe angeboten haben.
> Also, ich hab mir die ganze Geschichte nochmal angesehen.>> Es hat so absolut keinen Sinn mehr, ich hab' total den Faden verloren.> Ich werde alles wegwerfen und wenn ich Muße habe, nochmal ganz von vorne> anfangen.>> Trotzdem Dank an alle, die Ihre Hilfe angeboten haben.
Hmmm - schade.
Da hatte ich einige Stunden investiert, um eine gleichartige Umgebung
zusammenzuschrauben und nu ist alles "umsonst" ...
Bisschen blöd komme ich mir da schon vor.
Ich tröste mich jetzt einfach mal damit, daß die Fehlersuche vermutlich
kein Zuckerschlecken geworden wäre und uns Matthias bestimmt bald hier
seinen neuen Code vorstellen wird.
Viele Grüße
Igel1
Andreas S. schrieb:> Hmmm - schade.>> Da hatte ich einige Stunden investiert, um eine gleichartige Umgebung> zusammenzuschrauben und nu ist alles "umsonst" ...>> Bisschen blöd komme ich mir da schon vor.
Tut mir leid, ich wollte auf keinen Fall den Eindruck erwecken, ich
würde die Sache hinwerfen.
Ich hatte das Projekt nur so lange liegen lassen, daß ich mich selbst
wieder reindenken musste. Ich habe mich nur dazu entschlossen den Code
neu zu schreiben. Leider habe ich im Augenblick wenig Zeit. Vielleicht
komme ich ja am Wochenende dazu.
Sieh's doch positiv, du hast doch Ruck-Zuck V-USB ans Laufen bekommen.
;)
Schon gut, schon gut - ich war wohl ein wenig übermotiviert.
Sorry, daß ich Dich so gedrängelt habe - schließlich geht's hier ja nur
um Spaß an der Freude.
Viele Grüße
Igel1
So, ich habe das ganze nochmals in Angriff genommen, den Code aufgeräumt
und in lesbare Form gebracht. Ich habe immer noch das selbe Problem,
d.h. es kommt nur Müll bei der Messung raus.
Interessierte können sich die Projekte im Anhang mal ansehen.
hid_temperature.zip ist die Firmware (als Eclipse Projekt mit Makefile)
QTHIDControl ist die PC-Applikation dazu. Dies ist ein QT Projekt.
Wenn man auf den "Read Data" Button klickt, wird der USB Buffer vom
Controller auf den PC übertragen, die ersten beiden Bytes sind die vom
TSIC gelesenen Daten, die wie gesagt nicht stimmen.
@igel1: Falls noch Interesse besteht, kannst Du ja mal reinschauen.
Gruß
MP
Also ich kann inzwischen ausschließen, daß es am USB-Teil liegt, ich
habe jetzt ein LCD Display angeschlossen und bekomme die selben
abstrusen Werte geliefert.
Schliess doch mal ein LCD direkt an den µC an und schau, ob Deine
TSIC-Routine überhaupt stimmt. Nach dem obigen Bildern von bingo (Gast)
ist es doch sonnenklar, wie das Protokoll ist.
Ich hab auch schon 2x oder 3x TSIC verbaut und es gab nie Probleme, ich
arbeite aber mit PICs und nehme die Routine von uxdx
Beitrag "Re: digitaler Thermosensor"
TCCR1B=(1<<WGM12)|(0<<CS12)|(0<<CS11)|(1<<CS10);// ctc, no prescaler
188
//Enable the Output Compare A interrupt
189
TIMSK|=(1<<OCIE1A);
190
}
191
192
voidint1_falling_edge(void){
193
MCUCR&=~(1<<ISC10);
194
GIFR|=(1<<INTF1);// clear external interrupt flag
195
}
196
197
voidint1_rising_edge(void){
198
MCUCR|=(1<<ISC10);
199
GIFR|=(1<<INTF1);// clear external interrupt flag
200
}
201
202
voidint1_enable(void){
203
GICR|=1<<INT1;
204
}
205
206
voidint1_disable(void){
207
GICR&=~(1<<INT1);
208
}
209
210
voidint0_enable(void){
211
GICR|=1<<INT0;
212
}
213
214
voidint0_disable(void){
215
GICR&=~(1<<INT0);
216
}
217
218
219
intmain(void){
220
221
lcd_init(LCD_DISP_ON);
222
lcd_clrscr();
223
224
DDRC=0xFF;
225
226
// enable INT0 and INT1
227
GICR=1<<INT1;
228
// VUSB defaults for INT0 and trigger on falling edge for INT1
229
MCUCR=(1<<ISC11)|(0<<ISC10);
230
231
chardisp[16];
232
233
// turn TSIC on
234
zac_on();
235
// wait for the tsic to settle
236
_delay_us(125);
237
// enable interrupts
238
sei();
239
240
for(;;){
241
_delay_ms(200);
242
sprintf(disp,"%u %u ",buffer[0],buffer[1]);
243
// sprintf(disp,"%u ",strobe);
244
lcd_gotoxy(0,0);
245
lcd_puts(disp);
246
}
247
248
return0;
249
250
}
Weiterhin kein vernünftiges Ergebnis. Der Strobe Wert spielt verrückt
sobald ich die Temperatur am Sensor signifikant ändere.
Die Werte stimmen natürlich vorne und hinten nicht.
Hallo
Ohne alles gelesen zu haben, interpretiere ich den letzten Beitrag mal
als "geht immer noch nicht"
Daher hier mein Code zum auslesen eines TSic306.
Konfiguriert wird mit den #defines am Anfang. Momentan ist es für Timer0
und INT0 Eingang eines attiny2313 eingestellt.
Zur Benutzung einmal TSic_Init aufrufen, sei() und dann mit
TSic_getValue() lesen.
TSic_isResultAvailable() gibt 1 zurück sobald ein noch nicht gelesener
Wert vorliegt.
da1l6
@da1l6 : Dein Posting kam während ich noch am Schreiben war. Danke, ich
werde mir das mal ansehen.
Wie es immer so ist, richtig befriedigend ist das alles nicht, wenn man
nicht selbst auf die Lösung gekommen ist. :(
Die Sache mit dem freilaufenden Timer, wie sie weiter oben auch schon
einmal vorgeschlagen wurde, verstehe ich allerdings nicht wirklich.
Hallo
Das mit dem freilaufenden Timer ist eigentlich ganz einfach:
Du merkst dir den Timer Wert bei der fallenden Flanke (bit Start) und
dann nochmal bei der steigenden (Bit Ende). Die Differenz der Werte
ergibt die Bit Bauer.
Vergleicht man die Bit-Dauer des ersten "Bits" (sync, "50%" Low Dauer)
mit den der folgenden (25% oder 75%) kann man den Bit Wert ermitteln.
da1l6
Ah prima - es geht weiter ...
@Matthias:
Dummerweise habe ich diese Woche 0,0% Zeit.
Sehr ärgerlich - ich würde Dir doch so gerne helfen ...
Solltest Du keinen LogicAnalyzer besitzen, so kannst du gerne den Code
mal etwas mit Debug-Statement aufpoppen (=Debug-Ports setzen/rücksetzen)
und ich schließe die Maschinerie dann an meinen LA an - das öffnet
oftmals die Augen, weil man neben dem TSIC-Signal genau sehen kann,
welcher Code-Bereich wann durchlaufen wird.
Geht bei mir aber leider alles nicht sofort, sondern vermutlich erst in
ein paar Tagen.
Viele Grüße
Igel1
GRAUENHAFT, was hier gefrickelt wird!
Riesige Statusmaschine,
Interrupts und Timer im Betrieb umprogrammieren,
... und und und
- Alles unnötig!
Das macht man mit (z.B.) INT1 auf beiden Flanken und
einem freilaufenden Zähler, der nach jeder negativen
Flanke resettet wird. Dazu noch ca. 6 globale
UINT8-Varablen.
OHNE UMPROGRAMMIEREN!
Erfassung der Bits in der INT1-IRQ-Routine,
Auswertung durch das Hauptprogramm.
Ihr treibt den TO noch in's Irrenhaus!
> GRAUENHAFT, was hier gefrickelt wird!
Tja, was soll ich sagen, der Thread geht ja schon eine Weile, meistens
kommen Vorschläge wie man es nicht tun soll. Du hast ja sicher auch mal
irgendwo angefangen.;)
Bernie schrieb:> Das macht man mit (z.B.) INT1 auf beiden Flanken und> einem freilaufenden Zähler, der nach jeder negativen> Flanke resettet wird. Dazu noch ca. 6 globale> UINT8-Varablen.
Deine Vorschläge sind sicher gut gemeint, aber viel anfangen kann ich
damit nicht, weil mir hier einfach die Erklärung fehlt, das warum und
wie wird mir nicht klar.
Ich hatte bei der Diskussion zwischen Dir und MSP eh schon lange den
Faden verloren.
Es scheint ja alles ganz simpel zu sein, allerdings habe ich das
Internet lange nach einer funktionierenden Interrupt getriebenen Lösung
abgesucht und nichts gefunden. Der erste brauchbare Vorschlag kam erst
von da1l6, leider muss ich mich auch hier erst durchwühlen und
Anpassungen für den ATMega8 vornehmen.
Aber wirklich etwas gelernt oder verstanden habe ich bis hierin nicht.
Ausser vielleicht daß mein Code scheisse ist, aber das wusste ich vorher
schon...
Hallo Matthias,
bitte nicht verzweifeln.
Sobald ich 2 Stündchen Zeit habe, werde ich Dir helfen!
Wir kriegen das hin - und zwar nicht mit irgendeinem Fremdcode (das
ginge schnell, wäre aber sicherlich wenig befriedigend für Dich),
sondern mit Deinem Code.
Also: Kopf hoch - laß Dich nicht unterkriegen.
Wenn die 2 Heißluftproduzenten im Thread keine für Dich verständlichen,
auf Deinen Code zugeschnittenen Tipps geben wollen oder können, so werde
ich es in ein paar Tagen, wenn ich wieder Zeit habe, versuchen - ist
versprochen!
Viele Grüße
Igel1
Andreas S. schrieb:> bitte nicht verzweifeln.
Keine Sorge, ich hab schon ganz andere Projekte gestemmt. ;)
Ich werde mir heute Abend mal die Lösung von da1l6 zu Gemüte führen.
Ich kenne mich mit AVRs nicht sehr gut aus, komme von den Kollegen, die
PICs einsetzen.
M.W. hat auch ein AVR eine Capture-Einheit, mit der man ganz easy Zeiten
messen kann. Z.B. wird bei fallender Flanke ein Interrupt generiert, der
den Timer resetted und startet und bei steigender Flanke übernimmt die
Capture-Einheit die Timerdaten automatisch in einen Zwischenspeicher und
löst wieder einen Interrupt aus. Dort kannst Du dann die Werte weiter
bearbeiten.
Hallo Matthias,
bitte sende mir noch Deine Datei "lcd.h" sowie die zugehörige
Source-Datei ("lcd.c" ?), damit ich Deinen Code in meiner
AVR-Studio-Umgebung kompilieren kann.
Bitte ebenfalls den LCD-Typ sowie die Verkabelung angeben.
Vielleicht kann ich ja auch das noch nachbauen - habe hier
nämlich wenige LCD-Displays rumfliegen.
Viele Grüße
Igel1
Das ist die LCD Lib von Peter Fleury
http://homepage.hispeed.ch/peterfleury/lcdlibrary.zip
Das Display muss dann noch in der lcd.h angepasst werden. Ich habe ein
HD44780 Kompatibles im 4-Modus verwendet. Du musst die Pins RS,RW und E
sowie DB4-DB7 angeben. Die Zeilen- und Spaltenanzahl muss auch angepasst
werden. Ggf. musst du noch die Adressen der Zeilen ändern, das passt
aber meistens.
Weiter oben hatte ich alles in ein zip-Archiv gepackt.
Gruß
MP
Hallo
@Bernie
Wie willst du das Interrupt getrieben machen ohne eine State-Machine zu
benutzen?
Das umprogrammieren des Timers ist übrigens optional, dient aber dazu
die Pause zwischen den Messwerten zu erkennen um den Anfang eine
Übertragung zu finden.
Da der TSic ungefragt sendet wird AVR eventuell mitten in einer
Transmission eingeschaltet/resettet, dann gibt es nur noch Datenmüll.
Alternativ kann man:
- Die Stromversorgung des TSic schalten.
- Einen zweiten Timer verwenden. Wenn man etwa für periodische Aufgaben
sowieso schon einen laufen hat, ist das günstig.
da1l6
Natürlich braucht man etwas, um die erfolgreiche Datenerfassung zu
signalisieren! Aber ich halte es für übertrieben, eine Variable, die
mit dem Wert 20 bekannt gibt, dass der Wert erfasst ist,
"State-Machine" zu nennen.
Das TSIC Telegramm besteht aus 20 positiven Flanken.
Zu Beginn setze ich die Variable ABLAUF auf 21, mit jeder positiven
Flanke wird sie um 1 erhöht.
Bei jeder negativen Flanke wird ein Timer geNULLT.
Nur beim Telegrammstart (Negative Flanke nach einer Pause von >= 500 µs)
wird ABLAUF auf NULL gesetzt. Die nächste positive Flanke liefert die
Referenzzeit, alle weiteren positiven Flanken ergeben durch
Zählerstands-Vergleich die Datenbits.
Wurde der Telegrammstart mitten im Telegramm falsch erkannt, kommt
ABLAUF nicht auf den Wert 20, der nächste "echte" Telegrammstart fängt
wieder bei NULL an.
Nach ordentlicher Erfassung des Telegramms ist ABLAUF = 20 und wenn nun
die Erfassung der Flanken abgeschaltet wird, bleibt dieser Wert stehen.
Sieht das Hauptprogramm den Zustand ABLAUF = 20 kann es die Bits
dekodieren und irgendwann wieder eine neue Messung starten.
---------------------------
Wenn gewünscht, kann ich ein "Papierprogramm" liefern,
da ich beim AVR nur mit ASM arbeite.
Hallo Matthias,
ich habe den Code in Deiner Routine "ISR (INT1_vect)" mit einem
Debug-Signal für meinen LogicAnalyzer angereichert (siehe Code
unten). Danach habe ich das erste Bildchen im Anhang "geschnappt".
Im zweiten Bild sind alle Debug-Makros deaktiviert/auskommentiert.
Es zeigt eine andere Situation.
Erläuterungen zum 1. Bildchen im Anhang:
TSIC306: Signal des TSIC306
TSIC_PROBE: Debug-Pulse, die das DSPIKE()-Makro erzeugt - siehe
unten im Code. Als Argument wird die Puls-Länge in us an
das Makro übergeben.
DTOGGLE: Toggelt bei Eintritt in "ISR (TIMER1_COMPA_vect)"
Andere Signale: Wildes Gemüse - einfach ignorieren
Ich hoffe, das hilft ein Stückchen weiter ...
Alles weitere in Bälde.
Viele Grüße
Igel1
------------------------------------------
Sieht ziemlich chaotisch aus, was da im zweiten Byte passiert. Das
erste Byte sieht ja noch wunderbar aus, warum dann allerdings im
zweiten Byte nochmals alle 4 States aus der ISR durchlaufen werden ist
mir schleierhaft.
Auf jeden Fall hast Du mich dazu gebracht, mir mal einen Logic Analyzer
zu bestellen. ;)
Hallo Matthias,
so - funktioniert.
Im Anhang siehst Du die Signale, die Dein Code vor der Massage und nach
der Massage produziert ...
Vor der Massage hatte ich gemessene -25,99 Grad in meinem Zimmer, nun
sind's immerhin schon 17,90 Grad :-)
Kleiner Wermutstropfen: ich weiß nicht mehr ganz, an welchen Stellen ich
gedreht habe - ich meine es waren 2 Stellen.
Ich muß daher die nächsten Tage nochmals Deinen originalen mit meinem
modifizierten Code vergleichen.
Bis dahin der Tipp: schau mal in die timer1_stop_ctc - Routine!
Du hörst von mir.
Viele Grüße
Igel1
Andreas S. schrieb:> Bis dahin der Tipp: schau mal in die timer1_stop_ctc - Routine!
Alter Schwede, das war der entscheidene Hinweis!!!
es muss natürlich heissen:
Ein paar kleine Änderungen in der ISR (TIMER1_COMPA_vect) waren auch
noch notwendig, da ich das letzte Bit nicht mitgezählt hatte:
1
ISR(TIMER1_COMPA_vect){
2
3
// stop the counter and reset timer count
4
timer1_stop_ctc();
5
TCNT1=0;
6
7
// reading the HIGH byte of a zacwire packet
8
if(state==ZAC_READING_HIGH_BYTE){
9
// read bits ignoring the last bit (parity)
10
// actually reading 9 bits in total
11
if(PIND&(1<<PIND3)){
12
if(zac_current_bit>0){
13
zac_high_byte|=(1<<(zac_current_bit-1));
14
}
15
}
16
// decrement current bit every trigger
17
if(zac_current_bit>0){
18
zac_current_bit--;
19
}
20
// have read all bits from HIGH byte, switch
21
// to LOW byte
22
else{
23
state=ZAC_READING_LOW_BYTE;
24
// now we have one bit more since there comes another stop bit
25
zac_current_bit=9;
26
}
27
}
28
29
// after reading the parity bit of the first byte, we can omit
30
// the stop bit, since the next falling edge does not
31
// happen until the next start bit (LOW byte)
32
33
// reading the LOW byte of a zacwire packet
34
elseif(state==ZAC_READING_LOW_BYTE){
35
// read bits ignoring the first bit (start bit) and the last bit (parity)
36
// actually reading 10 bits in total
37
if(PIND&(1<<PIND3)){
38
if(zac_current_bit>0&&zac_current_bit<9){
39
zac_low_byte|=(1<<(zac_current_bit-1));
40
// PORTC |= ( 1 << PC3 );
41
}
42
}
43
// decrement current bit every trigger
44
if(zac_current_bit>0){
45
zac_current_bit--;
46
}
47
// all bits read => back to the beginning
48
else{
49
zac_current_bit=8;
50
state=ZAC_READING_START_BIT_LOW;
51
}
52
}
53
}
Es läuft endlich!
Danke für Deine Hilfe! Die Diagramme vom Logic Analyzer waren auch sehr
hilfreich an der Stelle.
Jetzt mach ich mich endlich an die USB-Anbindung.
Gruß
MP
So hier nochmals das komplette Projekt ohne USB Anbindung für ATMega8
mit HD44780 LC-Display.
Ein Wermutstropfen bleibt,denn es gibt noch einen Bug:
Ab -25°C wird die Temperatur wieder von 0°C an runtergezählt.
Ich konnte bisher nicht ausmachen, woran es liegt. Wer Lust hat, kann ja
mal reinschauen. Ich mach mich jedenfalls mal an die Fehlersuche.
Sodale, der Fehler war schneller gefunden als gedacht:
statt
1
if(state==ZAC_READING_START_BIT_LOW){
2
// if there was on measurement cycle, store data
3
// from zacwire in usb transfer buffer
4
if(zac_high_byte>0)
5
buffer[0]=zac_high_byte;
6
if(zac_low_byte>0)
7
buffer[1]=zac_low_byte;
muss es nur heissen:
1
if(state==ZAC_READING_START_BIT_LOW){
2
// if there was on measurement cycle, store data
3
// from zacwire in usb transfer buffer
4
buffer[0]=zac_high_byte;
5
buffer[1]=zac_low_byte;
beide Bytes müssen natürlich auch den Wert 0 annehmen dürfen.
Dank an alle, insbesondere an igel1.
@Admin : macht es Sinn für die USB Anbindung bei Bedarf einen neuen
Thread zu eröffnen?
AKtualisierte Version im Anhang, kompletter Schaltplan folgt.
Gruß
MP
Hallo Matthias,
freut mich, daß ich Dir helfen konnte.
Ich gebe zu: ich mußte auch ein ganzes Weilchen suchen ...
Bei der Analyse fielen mir noch folgende Dinge auf:
- Der Code ist vermutlich gegen Leitungsstörungen sehr anfällig:
Eine fallende Flanke zu viel (oder eine verpaßt) und alles
gerät aus dem Takt. Wenn in Kürze bei Dir noch USB-Interrupts
dazukommen, befürchte ich, daß genau dies eintreten könnte:
Du wirst Flanken verpassen, weil sich Dein Code gerade in
USB-ISR's befindet.
- Das Parity-Bit würde ich ebenfalls auswerten - das bringt
zusätzliche Sicherheit.
- Der Code ist (noch) nicht nicht ganz interrupt-sicher.
Wenn Du z.B. in Deiner for-Schleife eine Operation, die
sich über mehrere Maschinen-Zyklen erstreckt, wie z.B.
"temp = buffer[0]*256 + buffer[1]", ausführst, so könnte
Dein eigener Interrupt dazwischenfunken und mittendrin
die buffer-Werte austauschen - das Ergebnis wäre dann
ziemlich willkürlich. Du könntest also ggf. ein atomar
beschreibbares Flag bzw. eine Variable verwenden, die Du
vor Operationen buffer[x] setzt. Das Flag wird dann in
Deiner ISR ausgelesen und verhindert, das buffer[x]
aktualisiert wird. Ich meine einen ähnlichen Ansatz bei
Alternativ-Codevorschlägen in diesem Thread gesehen
zu haben.
Wie dem auch sei:
Ich bin gespannt, wie's nun mit Deinem Projekt Richtung USB
weitergeht. Schreib doch mal, was Du nun vorhast!
Evtl. kann ich ein bisschen Zeitscheibe abschnibbeln und
noch etwas beitragen.
Hast Du tatsächlich schon einen LA bestellt?
Wenn ja - welchen?
Viele Grüße
Igel1
... und noch eine kleine Frage an Dich, Matthias:
Wie - um alles in der Welt - ist Dir der -25 Grad-Bug aufgefallen:
Hast Du die Schaltung in die Tiefkühltruhe gelegt?
Viele Grüße
Igel1
Andreas S. schrieb:> Bei der Analyse fielen mir noch folgende Dinge auf:>> - Der Code ist vermutlich gegen Leitungsstörungen sehr anfällig:> Eine fallende Flanke zu viel (oder eine verpaßt) und alles> gerät aus dem Takt. Wenn in Kürze bei Dir noch USB-Interrupts> dazukommen, befürchte ich, daß genau dies eintreten könnte:>
Ja, daß der Code noch nicht 100% robust ist, ist mir klar, mir ging es
jetzt in der ersten Iteration nur ums Verstehen.
> Ich bin gespannt, wie's nun mit Deinem Projekt Richtung USB> weitergeht. Schreib doch mal, was Du nun vorhast!>
Ich will jetzt in erster Linie mal die gemessene Temperatur über die USB
Schnittstelle auslesen.
> Hast Du tatsächlich schon einen LA bestellt?> Wenn ja - welchen?
Diesen hier:
http://www.batronix.com/versand/logik-analyser/logic-analyser-pla1016.html> Wie - um alles in der Welt - ist Dir der -25 Grad-Bug aufgefallen:> Hast Du die Schaltung in die Tiefkühltruhe gelegt?
Mit Kältespray geht das ganz hervorragend ;)
http://www.reichelt.de/Kaelte-und-Druckluftsprays/KONTAKT-316/3//index.html?ACTION=3&GROUPID=4068&ARTICLE=9518&SHOW=1&START=0&OFFSET=16&
Hallo Matthias, hallo liebe Mitleser,
>> Hast Du tatsächlich schon einen LA bestellt?>> Wenn ja - welchen?>Diesen hier:>http://www.batronix.com/versand/logik-analyser/log...
Den kleinen oder den großen LA? (PLA1016 oder PLA2532)
Interessantes Teil - vor allem schön viel Speicher.
Du wirst sehen: mit einem LA macht das Basteln 10x mehr Spaß.
>Mit Kältespray geht das ganz hervorragend ;)
Och - das war so naheliegend, daß ich niemals darauf gekommen wäre...
> Ich will jetzt in erster Linie mal die gemessene Temperatur> über die USB Schnittstelle auslesen.
Ich habe Deinen Code einfach einmal in das hid-data Beispiel aus der
V-USB Lib eingefrickelt. Und siehe da - ab und an konnte ich die
korrekte Temperatur übertragen. Aber leider eben nicht zuverlässig.
Ich befürchte, daß dies prinzipbedingt auch nicht zuverlässig
funktionieren kann und daß Du für zuverlässige Messungen Deinen Code
ziemlich heftig umstricken mußt.
Damit der Atmega8 das USB-Protokoll sprechen kann, müssen nämlich sehr
strenge Timings eingehalten werden.
Die Kommentare im File "usbdrv.h" von V-USB sind hierzu recht
interessant:
-------------------- schnipp ------------------------------------
Interrupt latency:
The application must ensure that the USB interrupt is not disabled for
more than 25 cycles (this is for 12 MHz, faster clocks allow longer
latency). This implies that all interrupt routines must either have the
"ISR_NOBLOCK" attribute set (see "avr/interrupt.h") or be written in
assembler with "sei" as the first instruction.
Maximum interrupt duration / CPU cycle consumption:
The driver handles all USB communication during the interrupt service
routine. The routine will not return before an entire USB message is
received and the reply is sent. This may be up to ca. 1200 cycles @ 12
MHz (= 100us) if the host conforms to the standard. The driver will
consume CPU cycles for all USB messages, even if they address another
(low-speed) device on the same bus.
--------------------- schnapp -----------------------------------
Nach dieser Lektüre bin ich selber etwas ratlos:
Wie soll man mit hinreichender Genauigkeit die TSIC Impulslängen messen
...
- wenn man ISR's nicht länger als 25 CPU-Zyklen abklemmen darf und
- wenn man während solcher Messungen bis zu 100us von USB-ISR's
unterbrochen werden kann?
Kleine Ansätze habe ich zwar schon, aber nichts wirklich Geniales.
Will sagen: Foren-Leser mit guten Ideen, bitte vortreten !
Viele Grüße
Igel1
soika@gmx.de schrieb:> Den kleinen oder den großen LA? (PLA1016 oder PLA2532)> Interessantes Teil - vor allem schön viel Speicher.> Du wirst sehen: mit einem LA macht das Basteln 10x mehr Spaß.
Den kleinen, ich fange immer erst klein an. ;)
> Ich befürchte, daß dies prinzipbedingt auch nicht zuverlässig> funktionieren kann und daß Du für zuverlässige Messungen Deinen Code> ziemlich heftig umstricken mußt.>> Damit der Atmega8 das USB-Protokoll sprechen kann, müssen nämlich sehr> strenge Timings eingehalten werden.>
Ja, das befürchte ich auch. Ich habe schon darüber nachgedacht, einen
zweiten ATMega
nur für den TSIC zu nehmen und die Daten dann über I2C an den USB ATMega
zu übertragen.
> Will sagen: Foren-Leser mit guten Ideen, bitte vortreten !
Genau!
>> Ich befürchte, daß dies prinzipbedingt auch nicht zuverlässig>> funktionieren kann und daß Du für zuverlässige Messungen Deinen Code>> ziemlich heftig umstricken mußt.>>>> Damit der Atmega8 das USB-Protokoll sprechen kann, müssen nämlich sehr>> strenge Timings eingehalten werden.> Ja, das befürchte ich auch. Ich habe schon darüber nachgedacht,> einen zweiten ATMega nur für den TSIC zu nehmen und die Daten> dann über I2C an den USB ATMega zu übertragen.
Hmmm... Das wäre der brute force Ansatz.
Dann könnte man auch direkt einen Atmega mit integrierter USB-Einheit
nehmen. Aber da wäre die Herausforderung dann ganz futsch.
Ich bin dafür, daß wir es trotzdem mit nur einem Atmega probieren.
@Matthias: Ziehst Du mit?
>> Will sagen: Foren-Leser mit guten Ideen, bitte vortreten !> Genau!
Die Jungs rennen uns nicht gerade die Bude ein ...
Ich befürchte fast, wir sind auf uns allein gestellt.
Im Umfeld USB legen sowieso die meisten die Ohren an.
Hier also meine noch ganz unreifen Ideen:
- Zunächst nochmals das Problem:
Wenn Du bislang mit Deinem INT1 auf fallende Flanken des TSIC reagiert
hast und Deine INT1-ISR aufgerufen hast, so wußtest Du, daß die Flanke
maximal 1-2 Taktzyklen vorher passiert ist. Damit waren also prima
Zeitmessungen möglich.
In dem Moment, wo die INT0-Aufrufe von V-USB dazukommen, weißt Du
das leider nicht mehr: Die fallende Flanke des TSIC könnte nämlich
genau zu einem Zeitpunkt passieren, in dem sich Dein Atmega gerade in
der INT0-ISR zur Abarbeitung der USB-Routinen befindet. Erst wenn
diese Abarbeitung beendet ist, kommt dein INT1-Aufruf dran. Der
ist dann aber quasi nutzlos, denn Du kannst den exakten Zeitpunkt
der fallenden Flanke nicht mehr rekonstruieren.
- Der 1. Lösungsansatz:
Man könnte ggf. die INT0-ISR von V-USB mit einem Flag ausstatten:
Immer wenn ein INT0-Interrupt erfolgt, weil gerade mal wieder ein
USB-Paketchen vorbeiflog, wird in der INT0-ISR dieses Flag gesetzt.
Wenn dann Deine INT1-ISR aufgerufen wird, kannst Du an Hand des
Flags erkennen, ob zwischen dem letzten Aufruf und dem jetzigen
Aufruf ein INT0-Aufruf stattgefunden hat. In diesem Fall verwirfst
Du einfach das Ergebnis - in ca. 100ms kommt wirft der TSIC erneut
die Temperatur raus und dann gilt:
Neue Chance, neues Glück.
Ganz Hartgesottene könnten sogar die Längen von LOW- UND HI-Impuls-
flanken messen, denn aus beiden Messungen kann man ableiten, ob ein
TSIC-Bit nun 0 oder 1 war. Damit würde man die Chancen einer erfolg-
reichen Messung vermutlich dramatisch erhöhen.
- Allgemein:
Allgemein würde ich vermutlich von der etwas komplizierten Status-
Maschine ein wenig abrücken und mir bei INT1-Aufrufen (auf fallende
UND
steigende Flanken) nur noch den Zählstand eines durchlaufenden
Zählers sowie den oben erwähnten Flag-Status merken.
Nach X Flankenwechseln kann dann die Auswertung beginnen.
Soweit mein erster Ansatz.
Was meinst Du/meint Ihr dazu?
Gibt's einfachere Ansätze?
Viele Grüße
Igel1
>> - Der 1. Lösungsansatz:>> Man könnte ggf. die INT0-ISR von V-USB mit einem Flag ausstatten:> Immer wenn ein INT0-Interrupt erfolgt, weil gerade mal wieder ein> USB-Paketchen vorbeiflog, wird in der INT0-ISR dieses Flag gesetzt.>> Wenn dann Deine INT1-ISR aufgerufen wird, kannst Du an Hand des> Flags erkennen, ob zwischen dem letzten Aufruf und dem jetzigen> Aufruf ein INT0-Aufruf stattgefunden hat. In diesem Fall verwirfst> Du einfach das Ergebnis - in ca. 100ms kommt wirft der TSIC erneut> die Temperatur raus und dann gilt:> Neue Chance, neues Glück.>
Ich finde das klingt erstmal plausibel. Das könnten wir versuchen. Es
muss sich dann in der Praxis zeigen, wie oft der Fall eintritt, daß die
Temperaturmessung von einem USB Interrupt unterbrochen wird. Es würde ja
völlig ausreichen, wenn einmal die Sekunde eine brauchbare Messung
herauskommt.
> Allgemein würde ich vermutlich von der etwas komplizierten Status-> Maschine ein wenig abrücken und mir bei INT1-Aufrufen (auf fallende> UND> steigende Flanken) nur noch den Zählstand eines durchlaufenden> Zählers sowie den oben erwähnten Flag-Status merken.>> Nach X Flankenwechseln kann dann die Auswertung beginnen.
Das werde ich jetzt sowieso mal in Angriff nehmen, nachdem die ganze
Sache ja jetzt endlich läuft, sollte das kein großes Problem darstellen.
Sofern ich Zeit finde, werde ich das am Wochenende mal in Angriff
nehmen.
Oh ha - 7:53 Uhr - der frühe Vogel fängt den Wurm ...
Ich habe derweil das Interrupt-Verhalten des Atmega mal etwas näher
untersucht, weil ich wissen wollte:
- ob ein INT1, der während der Abarbeitung einer INT0-ISR auftritt,
dazu führt, dass nahtlos nach der INT0-ISR die INT1-ISR aufgerufen
wird oder
- ob erst noch wieder kurz zum Hauptprogramm zurückgesprungen wird,
bevor in die INT1-ISR verzweigt wird.
Leider scheint Letzteres der Fall zu sein, was eine meiner schönsten
Ideen pulverisiert: ich wollte nämlich in der main-loop einfach das im
letzten Posting erwähnte Flag immer wieder zurücksetzen.
Dadurch könnte man INT0-ISR's ohne "INT1-Störung" in der main-loop per
Flag-Rücksetzung als harmlos kennzeichnen - quasi "neutralisieren -
während eine INT0-ISR mit "INT1-Störung" von der anschließend nahtlos
aufgerufenen INT1-ISR an Hand des Flags als "schlimmer" Vorfall entlarvt
werden könnte.
Letzterer Fall nur müßte zum Verwerfen der aktuellen TSIC-Meßreihe
führen während der erste Fall eben nicht dazu führen müßte.
Nun gut - genug spekuliert: dadurch, daß zwischen INT0-ISR und INT1-ISR
stets ein Mini-Abstecher ins Hauptprogramm gemacht wird, ist obiges
Konzept erst einmal nicht so einfach umzusetzen.
Aaaaber, ich habe eine sehr wichtige Stelle im V-USB-Code gefunden -
Auszug aus usbconfig-prototype.h:
-----------------------schnipp--------------------------
/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken ==
(uchar)USBPID_SETUP) blinkLED(); */
/* This macro is a hook if you want to do unconventional things. If it
is
* defined, it's inserted at the beginning of received message
processing.
* If you eat the received message and don't want default processing to
* proceed, do a return after doing your things. One possible
application
* (besides debugging) is to flash a status LED on each packet.
*/
-----------------------schnapp--------------------------
Damit kann man beliebigen Code (der vermutlich nicht länger als X Zyklen
dauern darf) in die V-USB ISR's einschleusen und das dürfte Gold wert
sein!
Mal sehen, was sich damit machen läßt ...
Viele Grüße
Igel1
Hallo Matthias, liebe Forenteilnehmer,
ich habe inzwischen einige Experimente gemacht und die Vermutungen
erhärten sich, daß alle oben gemachten Annahmen und Befürchtungen wahr
sind:
- Es ist scheinbar korrekt, daß man USB_RX_USER_HOOK verwenden kann,
um im Falle von eingehenden USB-Paketen eigenen Code einzuschleusen.
Das ist ja schon mal gut!
Ich verwende diesen Hook um per Flag zu kennzeichnen, wenn INT0
aufgerufen wurde und somit ggf. die Feststellung des Flanken-
zeitpunktes durch INT1 verworfen werden muss.
- Es ist leider auch korrekt, daß man den INT0 nur gaaaanz kurz von
seiner Arbeit abhalten darf. Will sagen: INT1-Routinen dürfen wirklich
nur Mini-Mini sein. Die oben erwähnten 25 Taktzyklen scheinen auch
Aufruf und Return der Interruptroutine zu beinhalten.
Bislang ist es mir daher nicht gelungen, mehr als ca. 4 C-Befehle in
INT1 unterzubringen, ohne die Stabilität des USB-Protokolls zu
gefährden.
Zwischenfazit:
- Ich tue mich ziemlich schwer damit, den Sensor zuverlässig auszulesen
und gleichzeitig die Timings des USB-Protokolls nicht zu verletzen.
Das Szenario, von dem auszugehen ist, macht dabei Kummer:
Ich gehe davon aus, daß jederzeit ein USB-Paket vorbeifliegen und
INT0 auslösen kann, um anschließend die INT0-Routine unbekannte
Zeit zu beschäftigen.
Ich bin wirklich gespannt, ob Du, Matthias oder andere Forenteilnehmer
eine gute Lösung finden. Mir ist der Heldenstreich bislang jedenfalls
noch nicht gelungen.
Es funktioniert bei mir bislang nur in 9 von 10 Fällen, aber eben
nicht immer.
Viele Grüße
Igel1
Hallo Matthias, hi Leute,
bin fast am Ziel:
TSIC wird vom Atmega ausgelesen und die Daten brav per USB an den
Computer übertragen.
USB Kommunikationsfehler beim Auslesen treten inzwischen bei härtester
Abfragefrequenz "nur" noch in ca. 1 von 10.000 Fällen auf:
"error reading data: Communication error with device"
Will sagen: ein Atomkraftwerk sollte man damit nicht steuern ..
Für eine Haus-/Wohnungs-Heizungssteuerung sollte es aber vielleicht
ausreichen. @Matthias: was ist eigentlich Dein Anwendungszweck?
Viele Grüße
Igel1
Andreas S. schrieb:> Für eine Haus-/Wohnungs-Heizungssteuerung sollte es aber vielleicht> ausreichen. @Matthias: was ist eigentlich Dein Anwendungszweck?
Ich wollte ein Atomkraftwerk damit steuern. ;)
Scherz beiseite, es soll ein Thermometer mit USB-Schnittstelle zum
Datenaufzeichnen werden. Da soll noch ein zweiter TSIC dran, mittels
Umschalter zu schalten, damit ich eine zweite Temperatur
(aussen)erfassen kann.
Ich bin jetzt aber sehr gespannt, wie Du das gelöst hast.
Hallo zusammen,
hier die derzeitige Lage:
- der Code ist noch nicht dokumentiert und nicht aufgehübscht
- ohne Doku/Hübschung ist der Code absolut unverständlich
- ich bin diese Woche leider wieder knapp bei Zeit
- ich möchte Dich/Euch trotzdem nicht ewig warten lassen.
Die Lösung:
- ich poste den Code hier häppchenweise, sobald er kommentiert ist
- ist zwar ein bißchen blöd, aber besser als gar nichts
- außerdem kann man sich so häppchenweise eindenken :-)
- bitte seht's mir nach ...
Viele Grüße
Igel1
PS: Hier schon mal die ersten ca. 50% des Gesamtcodes:
1
// Store timer1 value in global variable "timer" when TSIC-signal flips
2
// This ISR has to be as short as possible in order to avoid USB-timing violations
3
// V-USB website tells us, that INT0-interrupts shall not be disabled longer than 25 CPU cycles !.
4
5
ISR (INT1_vect)
6
{
7
//PORTC ^= (1 << PC0); // uncomment this for debugging purposes
8
//store timer value and reset timer
9
timer = TCNT1; // store content of timer counter 1 (TCNT1) in global variable "timer"
10
// which will be stored in pulselength array later on
11
TCNT1 = 0;
12
int1visits = 1; // this flag tells the main loop to process the above stored timer-value
13
// since processing doesn't fit into this ISR due to USB timing restrictions
14
}
1
// Calculate tsic temperature data using pulse length information (which is stored in array "pulselength")
2
3
uint16_t calctempdata(){
4
5
6
uint8_t i; // internal helper variable
7
uint8_t parity; // tsic's parity information goes in here
8
uint16_t tstrobe; // pulselength to compare with (equals 1st "reference".pulse, called "tstrobe")
9
uint16_t result; // tsic bits will be assembled here to form the 2 byte temperature data
10
11
result = 0; // initialize variable
12
tstrobe = pulselength[1]; // pulselength of one single TSIC pulse sequence is stored in array pulselength[1 ... 39]
13
// the tstrobe value resides in pulselength[1]
14
15
16
// process pulselength information for the first byte (including parity)
17
parity = 0;
18
for(i=3; i<19; i=i+2){ // examine only length of LO-edge of of every TSIC bit
19
//uart_putc('x'); // uncomment this if you want the see the computation's result
20
result = (result << 1); // shift left by one - later insert new bit at the LSB position
21
if(pulselength[i] < tstrobe){ // if LO-edge of pulse < tstrobe => TSCI bit: "1"
22
//uart_putc('1'); // uncomment this if you want the see the computation's result
23
result++; // inserting "1" at LSB can be easily done by incrementing result by one
24
parity++; // count parity bits
25
} else { // if LO-edge of pulse > tstrobe => TSCI bit: "0"
26
//uart_putc('0'); // uncomment this if you want the see the computation's result