Forum: Mikrocontroller und Digitale Elektronik Aurel AM 433MHz Empfänger - Signal auswerten


von Mattias K. (Gast)


Lesenswert?

Hallo,

ich baue derzeit einen Empfänger (Sender ist schon fertig), der über das 
Aurel 433MHz-Modul ein Rechteckssignal ausgibt. Ich würde gerne den 
AtTiny13 dafür verwenden, um das Digitale Signal aufnehmen und auf seine 
"richtigkeit" und reihenfolge zu prüfen - sprich, stimmt das Empfangene 
Signal mit dem von mir vorgegebenen Signal überein, so so er eine LED 
testweise einschalten.

Bis jetzt habe ich folgendes:
1
#define F_CPU 960000UL
2
#include <avr/io.h>
3
#include <avr/interrupt.h> 
4
#include <util/delay.h>
5
6
  // Sendefolge: 11110001 Binär: 0b10001111
7
8
volatile uint8_t code = 0x00;
9
volatile uint8_t breakcount = 0;
10
uint8_t ready = 0;
11
uint8_t active = 0;
12
13
ISR(INT0_vect) {
14
  TCNT0 = 0;            //Rücksetzen des "Auszähltimers"
15
  code = 0x00;
16
  breakcount = 1;
17
  GIMSK &= ~(1<<INT0);      //deaktivieren des externen Interrupts, wenn
18
  ready = 0;
19
  active = 1;
20
}
21
22
ISR(TIM0_OVF_vect) {
23
  if(active) {
24
    PORTB |= (1<<PB0);
25
    if (breakcount <= 7) {
26
      if(PINB & (1<<PB1))
27
        code |= 0x01;
28
      code = code << 1;
29
      breakcount++;
30
    //  return;
31
    }
32
    else
33
    {
34
      GIMSK |= (1<<INT0);    //aktivieren des ext. Int.
35
      breakcount = 0;
36
      ready = 1;
37
      code = 0x00;
38
      active = 0;
39
    }
40
    PORTB &= ~(1<<PB0);
41
  }
42
}
43
44
int main(void) {
45
  DDRB &= ( ~(1 << PB1) | (1 << PB2)); // PB1 Eingang, PB2 Ausgang
46
  PORTB = 0xFF;
47
  PORTB &= ~(1<<PB2);
48
49
  //Interrupt bei steigender Flanke
50
  MCUCR |= (1 << ISC01) | (1 << ISC00);
51
  GIMSK = (1 << INT0);
52
  PCMSK = 0x00;
53
54
  TCCR0B = (1<<CS00) | (1<<CS02);
55
  TIMSK0 |= (1<<TOIE0);
56
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.625);
57
58
  sei();
59
60
  while(1) {
61
    if(ready) {
62
      if(code == 0x8F)      
63
        PORTB |= (1<<PB2);
64
    }
65
  }
66
  return 0;
67
}

Klappt aber nicht so ganz, wie ich mir das vorstelle, habt ihr eine 
Idee, wie ich das mit dem Tiny lösen kann? Oder muss ich doch zu einem 
anderen µController greifen?

Habe bereit im Forum ca. 5 Stunden lang herum gesucht, wurde aber nicht 
fündig. Vielleicht habe ich auch nur nach den falschen Begriffen 
gesucht.

Ich danke euch trotzdem schoneinmal im vorraus für euere Unterstützung.

Mfg
Mattias

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Dein Controller läuft tatsächlich mit 960 Khz ?

Mattias Köpke schrieb:
> #define F_CPU 960000UL

von Mattias K. (Gast)


Lesenswert?

Ohhh nein, habe den Oszilator (intern) auf 9,6MHz eingestellt. 
Verdammt^^
Mir passieren immer so kleine Fehler.
1
#define F_CPU 9600000UL
2
#include <avr/io.h>
3
#include <avr/interrupt.h> 
4
#include <util/delay.h>

Bin C++ Programmierer für Windows, habe mit dem µC erst angefangen.
Erkennt sonst noch jemand einen Fehler? habe es nocheinmal versucht, 
funktioniert trotzdem nicht.
Danke!

von Mattias K. (Gast)


Lesenswert?

Änderung:
1
ISR(INT0_vect) {
2
  TCNT0 = 0;            //Rücksetzen des "Auszähltimers"
3
  code = 0x00;
4
  breakcount = 0;
5
  GIMSK &= ~(1<<INT0);      //deaktivieren des externen Interrupts, wenn
6
  ready = 0;
7
  active = 1;
8
}

von Mattias K. (Gast)


Lesenswert?

Kann mir niemand Helfen, oder mir einen Tipp geben, nach was ich suchen 
könnte? Bin irgendwie ratlos.

Danke.

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

was gibt dein Empfangsmodul aus wenn dein Sender nicht sendet?
Nach kurzem Blick ins Datenblatt - wenn ich das richtige erwicht habe - 
kommt dort in dem Falle ein digitales Rauschen raus. Damit decodiert 
deine Software ständig irgendwas und es währe Zufall wenn während einer 
Sendephase die Auswertung an der richtigen Bitposition beginnt.
Am Sender brauchst du also ein Startbit das du aufgrund seiner Dauer am 
Empfänger eindeutig idendifizieren kannst. Dann kannst du auch nicht 
damit rechnen, das bei einer Funkübertragung das Signal störungsfrei am 
Empfänger ankommt - einfach den Bitzustand einlesen wird daher auch 
nicht funktionieren.
Schau dir mal die IR-Protolle an - die kannst du auch für Funk nehmen 
und es gibt auch schon passenden Routinen.

Sascha

von Mattias K. (Gast)


Angehängte Dateien:

Lesenswert?

Zuerst einmal - danke.

Im Anhang habe ich das Datenblatt des Empfängers eingefügt, das ich zu 
dem Modul erhalten habe. Das Modul habe ich übrigens bei Conrad gekauft. 
Bei der Artikelbeschreibung des Moduls sind auch Datenblätter, die sind 
jedoch anders als die, die ich hier habe.

Mfg

von Sascha W. (sascha-w)


Lesenswert?

... gut dann hatte ich das richtige Datenblatt.
Der Ausgang des Moduls liefert nur dann ein stabiles Signal wenn ein 
Träger auf der entsprechenden Frequenz gesendet wird. Ansonsten hast du 
nach einigen 10..100ms nur Rauschen am Ausgang. Deshalb sollte man die 
Daten auch nicht so senden wie du, da dort zu viel 
'Gleichspannungsanteil' vorhanden ist (u.u. viele aufeinanderfolgende 
0'en oder 1'sen).


Sascha

von Mattias K. (Gast)


Lesenswert?

Okay, d.h. ich soll die Übertragungsgeschwindigkeit erhöhen!?
Derzeit liegt die Länge für ein Bit bei 10,05ms. (War eigentlich nur zum 
Test)

Also fasse ich nochmal meine Änderungen zusammen:
* Übertragungsgeschwindigkeit erhöhen auf max. 250µS/Bit also 4KHz
* Startbits setzten z.b. 2ms High (VCC)
* Dann z.b. ein 8 Bit Datensatz übertragen

Könnte das dann so ungefähr klappen?

Lg

von ich da (Gast)


Lesenswert?

Gleichspannungsfrei senden bedeutet, eine andere Codierform benutzen, 
das meint er.

Z.B. Manchestercode. Schau mal bei Wikipedia danach, dort findest du 
dieser Code ist Gleichspannungsfrei. Alternativen ebendort.

von Mattias K. (Gast)


Lesenswert?

Achso! Ok - werde ich tun. Ich danke euch :)

von Sascha W. (sascha-w)


Lesenswert?

Mattias Köpke schrieb:
> Okay, d.h. ich soll die Übertragungsgeschwindigkeit erhöhen!?
nicht unbedingt
> Derzeit liegt die Länge für ein Bit bei 10,05ms. (War eigentlich nur zum
> Test)
nicht die Bits direkt kodieren, sondern den Bitzustand in der 
Sendedauer, oder Pausenlänge kodieren

schau mal hier bei den IR-Protokollen
http://www.mikrocontroller.net/articles/IRMP#Die_IR-Protokolle_im_Detail
Die angegebene Frequenz kannst du natürlich vergessen, die ist bei dir 
ja 433MHz.

>
> Also fasse ich nochmal meine Änderungen zusammen:
> * Übertragungsgeschwindigkeit erhöhen auf max. 250µS/Bit also 4KHz
Wenn du nicht viele Daten zu übertragen hast, kann die Sendendauer ruhig 
ein paar ms dauern

> * Startbits setzten z.b. 2ms High (VCC)
ja - auf jeden Fall so, das es sich von einem Datenbit deutlich 
unterscheidet

> * Dann z.b. ein 8 Bit Datensatz übertragen
z.B.

> Könnte das dann so ungefähr klappen?
mit der zum Protokoll passenden Auswertung auf jeden Fall
Die Pulse-Distance Protokolle währen sicher ein Ansatz für dich, mit dem 
Timer lassen sich die Signal- und Pausenlängen gut messen, eine gewisse 
Filterung gegen Störungen musst du aber einbauen, so das kurze Spikes 
die Messung nicht sofort beenden.

Sascha

von elektronikbastler (Gast)


Lesenswert?

warum greifen nur so viele zu den AM-Modulen ...
Hab mit den Dingern vor Jahren mal rumgespielt, der Haken daran ist,
dass wenn die Sendung für kurze Zeit aussetzt die Geschichte ausschwingt 
und bei Wiederaufnahme der Sendung die ersten paar ms der Übertragung 
ins Nirvana gehen. Darum sendet man bei AM erst ne Präambel und danach 
in Manchester Code wenns Daten sein sollen.
Es gibt aber auch FM-Module von Aurel, die hatten das in meinen 
versuchen nicht.

von Mattias K. (Gast)


Lesenswert?

Danke ihr seid mir eine große Hilfe!

Ich werde das in den kommenden Tagen in Angriff nehmen.

@elektronikbastler:

Sorry, das ist mein erstes Projekt mit Funk, ich habe damit wenig 
Erfahrung.

Trotzdem danke für eure Tollen, Ausführlichen und schnellen Antworten!
Meld mich wieder.

Lg
Mattias

von Mattias K. (Gast)


Lesenswert?

Soo,

ich habe mir das IR-Protokoll mal angesehen, ihr meintet mir dem 
"Gleichspannungsanteil" nehme ich mal an folgendes:

Start-Bit   2400µs Puls, 600µs Pause
0-Bit      600µs Puls, 600µs Pause
1-Bit      1200µs Puls, 600µs Pause

Ich habe ja jeweils für das Bit 0 und 1    10ms "Bitdauer" gehabt. Und 
das soll ich ändern!?

lg
Mattias

von Sascha W. (sascha-w)


Lesenswert?

Mattias Köpke schrieb:
> Soo,
>
> ich habe mir das IR-Protokoll mal angesehen, ihr meintet mir dem
> "Gleichspannungsanteil" nehme ich mal an folgendes:
>
> Start-Bit   2400µs Puls, 600µs Pause
> 0-Bit      600µs Puls, 600µs Pause
> 1-Bit      1200µs Puls, 600µs Pause
genau - jedes übertragene Bit sollte aus einer Sendephase und einer 
Sendepause bestehen.

> Ich habe ja jeweils für das Bit 0 und 1    10ms "Bitdauer" gehabt. Und
> das soll ich ändern!?
Die Zeiten kannst du relativ frei wählen, nur die Pause sollte nicht zu 
lang werden sonst kommt in der Zwischenzeit wieder Rauschen am Ausgang 
raus.

Sascha

von Mattias K. (Gast)


Lesenswert?

Okay, das werde ich versuchen.
Meint ihr das würde mit dem AtTiny13 klappen? Der hat leider nur 2 
Timer.

lg
Mattias

von Jürgen (jliegner)


Lesenswert?

Ich denke da brauchst du nur einen Timer für. Und vermeide gleich von 
Anfang an mit dem Ausgang vom Aurel einen Interrupt auszulösen. Der hat 
am Ausgang genügend kurze Spikes die dich in den Wahnsinn treiben 
werden. Lass den Timer z.b. mit 100us oder mehr einen zyklischen 
Interrupt auslösen und sample dann. Dann sind die Spikes kein Problem 
mehr und auch das Rauschen, wenn lange kein Signal anliegt, wird nicht 
zur unkalkulierbaren Interruptquelle. Die benötigte Zeit im Interrupt 
dürfte bei geschickter Programmierung vetretbar sein.

von Sascha W. (sascha-w)


Lesenswert?

du brauchst ja nur einen Timer, mit dem du die Zeiten misst. Man könnte 
immer bis zu einem Signalwechsel warten und dann den Timerwert lesen 
(Impus- oder Pausendauer), und diesen anschließend wider auf Null 
zurücksetzen. Und auf den nächsten Signalwechsel warten. Das Problem bei 
diesem Ansatz ist nur, das auch sehr kurze Störimpulse als Signalwechsel 
erkannt werden. Bei einem IR-Empfäger geht das noch bei Funk nur bei 
sehr gutem Empfang.

Für das Auslesen eines Funkaußensensors einer Wetterstation hab ich 
folgenden Ansatz gewählt.
Bsp: Startbit 5ms, Bitpause 1ms, 0-Bit 1ms, 1-Bit 2ms

Das Eingangssignal wird mit einem Timer im Abstand von 0.1ms eingelesen 
(1/10 der kürzesten Bit/Pausenzeit).
Mit einem Zähler lässt sich erst mal das Startbit recht zuverlässig 
erfassen.
Für jeden 1ms-Abschnitt gibts im RAM ein Byte.
Nach dem erkennen des Startbit's, wird der Wert im korrespondierenden 
Byte im RAM je nach Eingangssignal um eins erhöht oder verrigert. Nach 
10 Messungen wird ins nächste Byte geschrieben. Dadurch ergibt sich eine 
einfache Majoritätsfunktion, mit der sich Störungen rech gut filtern 
lassen.
Die Erfassung läuft immer bis zum Ende durch, auch wenn das 
Eingangssignal aufgrund der unterschiedlichen Bitdauern mal kürzer, oder 
länger sein kann.
Danach kannst du die gespeicherten Daten in Ruhe auswerten.

Sascha

von Mattias K. (Gast)


Lesenswert?

Soll ich den Timer dann im CTC Mode laufen lassen?

lg

von Sascha W. (sascha-w)


Lesenswert?

Mattias Köpke schrieb:
> Soll ich den Timer dann im CTC Mode laufen lassen?
Kommt darauf an an welcher Messmethode du dich versuchen willst.
Für das Sampling mit konstanter Zeit - ja
Für das einfache Messen der Bitdauer - nein

Sascha

von Mattias K. (Gast)


Lesenswert?

Ich würde gerne das Messen der Bitdauer versuchen, kommt mir sinnvoller 
vor.

Danke.

Lg

von Sascha W. (sascha-w)


Lesenswert?

Mattias Köpke schrieb:
> Ich würde gerne das Messen der Bitdauer versuchen, kommt mir sinnvoller
> vor.
ja bitte - Versuch mach kluch ;-)

Dann lass den Timer mit einer Geschwindigkeit laufen (Vorteiler), das 
bei den Zeiten die du messen willst der Timer (8- o. 16-Bit) möglichst 
weit ausgeschöpft wird aber kein Überlauf auftritt. Ein Überlauf währe 
dann schon mal ein Anzeichen, das das Signal nicht gültig sein kann. Die 
'krume' Messdauer die sich aus dem Vorteiler ergibt brauch dich ja nicht 
interessieren - das kann der Compiler ja bei der Erstellung des 
Programms für dich berechnen.

Sascha

von Mattias K. (Gast)


Lesenswert?

Sascha Weber schrieb:
> Dann lass den Timer mit einer Geschwindigkeit laufen (Vorteiler), das
> bei den Zeiten die du messen willst der Timer (8- o. 16-Bit) möglichst
> weit ausgeschöpft wird aber kein Überlauf auftritt.

D.h. wenn mein
Bit 1: 300µs lang,
Bit 0: 400µs lang
meine Pause 600µs lang wäre, müsste mein Timer an der Grenze von 1000µs 
= 1ms oder an der Grenze 600µs liegen?

Lg

von Mattias K. (Gast)


Lesenswert?

4800000    ms          µs

clk         5,333E-05  5,333E-02  5,333E+01
clk/8         0,000426667  0,426666667  426,6666667
clk/64         0,003413333  3,413333333  3413,333333
clk/256         0,013653333  13,65333333  13653,33333
clk/1024       0,054613333  54,61333333  54613,33333

Das sind die möglichen Zeiten, die ich nutzten könnte, bevor der Timer 
einen Overflow aufruft.

Lg

von Mattias K. (Gast)


Lesenswert?

So ich habe mich nocheinmal an die Software gesetzt und habe bis jetzt 
folgendes:
1
#define F_CPU 4800000UL
2
#include <avr/io.h>
3
#include <avr/interrupt.h> 
4
#include <util/delay.h>
5
6
  // Sendefolge: 11110001 Binär: 0b10001111
7
8
volatile uint8_t code = 0;
9
volatile uint8_t startbit = 0;
10
volatile uint8_t rec[8];
11
12
13
14
ISR(TIM0_OVF_vect) {
15
16
}
17
18
19
int main(void) {
20
  DDRB &= ( ~(1 << PB1) | (1 << PB2)); // PB1 Eingang, PB2 Ausgang
21
  PORTB = 0xFF;
22
  PORTB &= ~(1<<PB2);
23
24
  TCCR0B = (1<<CS01); // Prescaler 8 Alle 426µs ein Overflow-Interrupt
25
  TIMSK0 |= (1<<TOIE0);
26
27
  sei();
28
29
  while(1) {
30
    uint8_t i = 0;
31
32
    TCNT0 = 0;
33
    while(PINB & (1<<PB1)) {}
34
    startbit = TCNT0;
35
36
    if(startbit == 240) {
37
    
38
      while(i < 7) {
39
        TCNT0 = 0;
40
41
        while(PINB & (1<<PB1)) {} //Warten solange Pin 1 High ist
42
        rec[i] = TCNT0;
43
        i++;
44
      }
45
    }
46
  }
47
48
  return 0;
49
}

Lg
Mattias

von Jürgen (jliegner)


Lesenswert?

Ich denke der Ansatz ist immer noch nicht optimal. Du verpulverst im 
deiner main-Schleife alle Zeit des mc und es bleibt nichts mehr für was 
anderes übrig. Ausserdem fällt dein Code wieder auf jeden Spike herein 
den er erwischen kann.


Im Beitrag:

Beitrag "S555HT AVR Beispielcode"

habe ich mal einen Weg für die ELV Wetterdatensender beschrieben. Das 
Protokoll findest du hier:

http://www.dc3yc.privat.t-online.de/protocol.htm

Hier macht ein Timer einen zykl. Interrupt von 100us. Darin wir der Pin 
abgefragt und festgehalten wieviel mal 0 oder 1 hintereinander kommen. 
Dann wird dann bei jedem Wechsel von 0 auf 1 getestet ob die Zähler für 
0 und 1 in dem Bereich liegen den eine Tabelle vorgibt. Daran wird dann 
entschieden ob die Sequenz als 0 oder 1 oder Müll gewertet wird.

von Mattias K. (Gast)


Lesenswert?

@Jürgen:

Was wird hier beschrieben:
1
#define WS300_HIGHMIN 15
2
#define WS300_HIGHMAX 40
3
#define WS300_LOWMIN   4
4
#define WS300_LOWMAX  15
5
6
7
#define EM100_LONGMIN  19
8
#define EM100_LONGMAX  26
9
#define EM100_SHORTMIN  8
10
#define EM100_SHORTMAX 14

Ist das Zeit? Oder ein Pegel?

Lg
Mattias

von Jürgen (jliegner)


Lesenswert?

der Interrupt kommt nicht wie oben geschrieben mit 100us sonder mit 32us
und die #defines beschreiben mein Zeitfenster

Sollwert lt. Protokoll: 854.5µs

#define WS300_HIGHMIN 15  ->  15*32 =  480us
#define WS300_HIGHMAX 40  ->  40*32 = 1280us

Sollwert lt. Protokoll: 366.2µs

#define WS300_LOWMIN   4  ->  4*32  = 128us
#define WS300_LOWMAX  15  ->  15*32 = 480us

für den WS300

von Mattias K. (Gast)


Lesenswert?

Okay.

Wie lange dauert denn der Interrupt?

Lg

von Jürgen (jliegner)


Lesenswert?

ca 10% d.h. im Schnitt 3-4us.

von Mattias K. (Gast)


Lesenswert?

Aber wieso hast du ein "großes" Zeitfenster?

von Jürgen (jliegner)


Lesenswert?

Ich teste im Interrupt den Pin alle 32us. Ist er 1 wird c1 erhöht, ist 
er 0 wird c0 erhöht. Der Zustand am Pin wird sich gemerkt und der 
Interrupt verlassen. Wenn im nächsten Interrupt der Pin 1 ist und der 
gemerkte Zustand 0 (0-1 Flanke), dann sehe ich nach ob die Werte in c0 
und c1 zum Protokoll passen, merke mir das gefundene Bit und verlasse 
den Interrupt. Das wiederholt sich bis ich alle Bits habe. Das ist jetzt 
nur eine grobe Beschreibung, für eine komplette Doku fehlt mir die Zeit.

von Klaus D. (kolisson)


Lesenswert?

in Verbindung mit den Aurel OOk Modulen bietet sich ein NE567 an.

Klaus

von Mattias K. (Gast)


Lesenswert?

@ Jürgen

kann und darf ich deinen Code verwenden und umschreiben?

Lg

von Mattias K. (Gast)


Lesenswert?

Hallo,
ich hab mich nochmals an den Code gesetzt, und bin zu folgendem TEST 
Ergebnis gekommen:

Ich sende erst mein Startbit (35us lang) dann eine 1 (120us Lang) und 
dann eine 0 (30us).
1
#define F_CPU 9600000UL
2
#include <avr/io.h>
3
#include <avr/interrupt.h> 
4
#include <util/delay.h>
5
6
  // Sendefolge: 11110001 Binär: 0b10001111
7
  //PB4 Data in
8
9
10
volatile uint8_t code = 0;
11
volatile uint8_t code2 = 0;
12
volatile uint8_t rec[8];
13
volatile uint8_t ready = 0;
14
uint8_t startrec = 0;
15
uint8_t high = 0;
16
uint8_t low = 0;
17
18
uint8_t in = 0;
19
uint8_t bitcount = 0;
20
21
// Sollwert für High: 116,725µs
22
//Sollwert für Low: 50,025µs
23
#define O_HIGHMAX 20 // 20*6,67µs = 133,4µs
24
#define O_HIGHMIN 15 // 15*6,67µs = 100,05µs
25
#define O_LOWMAX 10  // 10*6,67µs = 66,7µs
26
#define O_LOWMIN 5  // 5*6,67µs  = 33,35µs
27
28
29
ISR(TIM0_OVF_vect) {
30
  in<<=1;
31
  if(PINB & (1<<PB4))
32
    in|=1;
33
34
  if((in & 0x1F) == 0x1F) // 0x7 = 0b11111 Startbit müsste dann 5*6,67µs= 33,35µs lang sein
35
    startrec = 1;
36
37
  if(startrec) {
38
    if(bitcount <= 2) {
39
    if(high>O_HIGHMAX && high<O_HIGHMIN) {
40
      if(PINB & (1<<PB4)) 
41
        high++; 
42
    } else
43
    {
44
      code<<=1;
45
      code |= 0x1;
46
      high = 0;
47
      bitcount++;
48
    }
49
50
    if(low>O_LOWMAX && low<O_LOWMIN) {
51
      if((!PINB & (1<<PB4)))
52
        low++;
53
    } else
54
    {
55
      code<<=1;
56
      code &= 0x1;
57
      low = 0;
58
      bitcount++;
59
    }
60
    }
61
    else
62
    {
63
      ready = 1;
64
    }
65
  }
66
  else
67
  {
68
    low = 0;
69
    high =0;
70
    bitcount =0;
71
    code2 = code;
72
    code = 0;
73
  }
74
  
75
}
76
77
78
int main(void) {
79
  DDRB &=  ~(1 << PB4) | (1<<PB3); // PB4 Eingang PB3 Ausgang
80
  PORTB = 0xFF;
81
  PORTB &= ~(1<<PB4);
82
83
  TCCR0B = (1<<CS01 | 1<<CS00); // Prescaler 64 Alle 6,67µs ein Overflow-Interrupt
84
  TIMSK0 |= (1<<TOIE0);
85
86
  sei();
87
88
  while(1) {
89
    if(ready) {
90
      if(code2 == 0x2)
91
        PORTB^= (1<<PB3);
92
      ready = 0;
93
    }
94
  }
95
96
  return 0;
97
}

Mattias

von Mattias K. (Gast)


Lesenswert?

Ich habe es dank Jürgens Ansatz hinbekommen. Aber ein fehler habe ich 
noch.. es funktioniert zwar, aber nur wenn ich am Sender Lange auf den 
Knopf drücke und das ist ja nicht sinn der Sache, könnte mir da noch 
jemand helfen?
1
#define F_CPU 4800000UL
2
#include <avr/io.h>
3
#include <avr/interrupt.h> 
4
#include <util/delay.h>
5
6
  // PB4 Data in
7
  // 8 Bit übertagung
8
9
uint8_t code = 0;
10
volatile uint8_t code2 = 0;
11
volatile uint8_t ready = 0;
12
uint8_t startrec = 0;
13
uint8_t bitcnt = 0;
14
15
uint8_t in = 0;
16
uint8_t il = 0;
17
uint8_t ih = 0;
18
19
// Sollwert für High: 700µs
20
// Sollwert für Low : 1000µs
21
// Pause      : 500µs
22
23
#define LOWMAX     20  // 20*53,33µs = 1066,6µs
24
#define LOWMIN     18   // 18*53,33µs = 959,94µs
25
26
#define HIGHMAX   14  // 14*53,33µs = 746,62µs
27
#define HIGHMIN   12  // 12*53,33µs = 639,96µs
28
29
#define PAUSEMAX   11  // 11*53,33µs = 586,63µs
30
#define PAUSEMIN  8  // 8*53,33µs  = 426,64µs
31
32
ISR(TIM0_OVF_vect) {
33
34
  //starten der Bitaufnahme
35
  if(in > 36)
36
    startrec = 1;
37
38
  //Bitaufnahme gestartet
39
  if(startrec == 1) {
40
    if((PINB & (1<<PB4)))
41
      ih++;
42
    else
43
      il++;
44
    
45
    if(bitcnt == 8) {
46
      if(!ready)
47
        code2 = code;
48
      ready = 1;
49
      ih=0;
50
      il=0;
51
      bitcnt=0;
52
      startrec = 0;
53
      in=0;
54
    }
55
    
56
    if(ih < HIGHMAX && ih > HIGHMIN) {
57
      ih = 0;
58
      il = 0;
59
      code<<=1;
60
      code |= 1;
61
      bitcnt++;
62
    }
63
    if(il < LOWMAX && il > LOWMIN) {
64
      ih = 0;
65
      il = 0;
66
      code<<=1;
67
      bitcnt++;
68
    }
69
  }
70
  else
71
  {
72
    if((PINB & (1<<PB4)))
73
      in++;
74
  }
75
}
76
77
78
int main(void) {
79
  DDRB |= (1<<PB3);
80
  DDRB &=  ~(1 << PB4); // PB4 Eingang PB3 Ausgang
81
  PORTB &= ~(1<<PB4);
82
  PORTB &= ~(1<<PB3);
83
84
  PORTB |= (1<<PB3);
85
  _delay_ms(100);
86
  PORTB &= ~(1<<PB3);
87
88
  TCCR0B = (1<<CS02); // Prescaler 256 Alle 53,33µs ein Overflow-Interrupt
89
  TIMSK0 |= (1<<TOIE0);
90
91
  sei();
92
93
  while(1) {
94
    if(ready) {
95
      if((code2 & 0x66) == 0x66)
96
        PORTB ^= (1<<PB3);
97
      ready = 0;
98
    }
99
  }
100
101
  return 0;
102
}
Danke !!!

Lg
Mattias

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

das Startbit sollte immer wesentlich länger sein als die Datenbits, 
sonst kann es sein das sich die Auswertung auf ein Datenbit als Startbit 
syncronisiert und dann stimmt nix mehr.

Sascha

von Mattias K. (Gast)


Lesenswert?

Ich habe gerade nocheinmal eine andere Alternative programmiert, die 
leider nicht klappt, aber eigentlich klappen sollte..:
1
#define F_CPU 9600000UL
2
#include <avr/io.h>
3
#include <avr/interrupt.h> 
4
#include <util/delay.h>
5
6
  // PB4 Data in
7
8
9
uint8_t code = 0;
10
volatile uint8_t code2 = 0;
11
volatile uint8_t ready = 0;
12
uint8_t bitcnt = 0;
13
14
uint8_t start = 0;
15
uint32_t li = 0;
16
17
// Sollwert für High: 700µs    bei 106,66µs = 6 = 0x3F
18
// Sollwert für Low : 1000µs  bei 106,66µs = 9 = 0x1FF
19
// Pause      : 500µs    bei 106,66µs = 4 = 0xF
20
// Startbit      : 2500µs  bei 106,66µs = 23 = 0x7FFFFF
21
22
23
ISR(TIM0_OVF_vect) {
24
  li<<=1;
25
26
  if(PINB & (1<<PB4))
27
    li|=1;
28
29
  //Startbit und die erste Pause erkannt
30
  if((li & 0x3FFF0) == 0x3FFF0){
31
    start = 1;
32
    code = 0;
33
    bitcnt=0;
34
    ready=0;
35
  }
36
37
  if(start == 1) {
38
                //PORT zum test des Startbits einschalten..
39
    PORTB |= (1<<PB3);
40
41
    if(bitcnt == 8) {
42
      if(!ready)
43
        code2 = code;
44
      bitcnt=0;
45
      start=0;
46
    }
47
48
    code<<=1;
49
50
    //High erkannt
51
    if((li & 0x3F) == 0x3F){
52
      code|=1;
53
    }
54
    bitcnt++;
55
  }
56
  else
57
    start=0;
58
}
59
60
61
int main(void) {
62
  DDRB |= (1<<PB3);
63
  DDRB &=  ~(1 << PB4); // PB4 Eingang PB3 Ausgang
64
  PORTB &= ~(1<<PB4);
65
  PORTB &= ~(1<<PB3);
66
67
  PORTB |= (1<<PB3);
68
  _delay_ms(100);
69
  PORTB &= ~(1<<PB3);
70
71
  TCCR0B = (1<<CS02 | 1<<CS00); // Prescaler 1024 Alle 106,66µs ein Overflow-Interrupt
72
  TIMSK0 |= (1<<TOIE0);
73
74
  sei();
75
76
  while(1) {
77
    if(ready) {
78
      if((code2 & 0x66) == 0x66)
79
        PORTB ^= (1<<PB3);
80
      ready = 0;
81
    }
82
  }
83
84
  return 0;
85
}

Irgendwie erkennt er mein startbit und meine Pause gar nicht..

von Klaus D. (kolisson)


Lesenswert?

Hi,
so ein Infrarot Protokol ist ja als Beispiel auch nicht falsch.
Natürlich kann man bei Funk tie einzelnen Zeiten deutlich verkürzen
aber es stellt doch deutlich die Verhältnisse dar.

Fürs NEc protocol hat man hier

    * a 9ms leading pulse burst (16 times the pulse burst length used 
for a logical data bit)

    * a 4.5ms space

    * the 8-bit address for the receiving device     'erstes Datenbyte

    * the 8-bit logical inverse of the address    'invers zur 
fehlerkontrolle

    * the 8-bit command            '2 tes Datenbyte

    * the 8-bit logical inverse of the command  ' und wieder invers zur 
kontrolle

    * a final 562.5µs pulse burst to signify the end of message 
transmission.


genaueres steht hier:
http://wiki.altium.com/display/ADOH/NEC+Infrared+Transmission+Protocol
und auch hier:
http://www.mcselec.com/index.php?option=com_content&task=view&id=223&Itemid=57

Gruss Klaus

von Mattias K. (Gast)


Lesenswert?

Wie schnell darf ich denn Maximal übertragen (laut Datenblättern)?
Bzw. wie kurz darf mein Pegel maximal sein?

Im Datenblatt steht was von 3KHz beim Empfänger, hat das etwas mit der 
Übertragungsgeschwindigkeit zu tun?

@Klaus, die Protokolle kannste vergessen, ich kann keine Interrupts bei 
steigender oder fallender Flanke benutzen wegen den Spikes. (Siehe 
erster betrag).


Mattias

von Mattias K. (Gast)


Lesenswert?

Ich hab mir gerade nochmal das Manchester Protokoll genau unter die Lupe 
genommen - das ist mit dem Aurel Modulen gar nicht möglich, da ich mit 
dem Pegel nicht ins negative gehen kann.

Lg
Mattias

von Sascha W. (sascha-w)


Lesenswert?

Mattias Köpke schrieb:
> Ich hab mir gerade nochmal das Manchester Protokoll genau unter die Lupe
> genommen
WO?
> - das ist mit dem Aurel Modulen gar nicht möglich, da ich mit
> dem Pegel nicht ins negative gehen kann.
wieso braucht man da negative Pegel??
0=GND und 1=+Ub genügen

Sascha

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.