Manchester decoding - Arduino & velleman rx433 ontvanger

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • iEase
  • Registratie: April 2009
  • Laatst online: 31-03-2021
Er is ondertussen al veel geschreven over de Arduino en klik aan klik uit (KAKU) apparatuur. Vanwege een eigen domotica project ben ik bezig met het maken van een ontvanger voor 433Mhz signalen van diverse sensoren (waaronder cresta temp & hum.).

Om deze signalen te kunnen ontvangen maak ik gebruik van een Arduino Uno in combinatie met een velleman 433Mhz ontvanger.

Helaas is mijn programmeer kennis met de arduino beperkt waardoor ik ondanks alle bestaande topics geen goede leidraad kan vinden om een dergelijke ontvanger goed te kunnen realiseren.

Daarom de vraag aan de gebruikers hier of hulp geboden kan worden bij het volgende stappenplan:

1. Het detecteren en weergeven van een ontvangen manchester gecodeerd signaal.
2. Het decoderen van het ontvangen signaal en weergeven als binair signaal.
3. Het verwerken van het signaal zodat de daadwerkelijke waarden (temperatuur en luchtvochtigheid) weergegeven kunnen worden.

Met dit stappenplan en het maken van een goede documentatie in dit topic hoop ik ook voor andere liefhebbers een goede leidraad te kunnen maken om een dergelijk project ook voor een 'leek' toegankelijk te maken.

Bekende gegevens:

Cresta protocol: http://members.upc.nl/m.beukelaar/Crestaprotocol.pdf

[ Voor 5% gewijzigd door iEase op 04-04-2011 14:19 ]


Acties:
  • 0 Henk 'm!

  • dj_dysaster
  • Registratie: Januari 2003
  • Laatst online: 21:51

dj_dysaster

Stoom \o/

Doet de bekende pt22xx ook aan manchester coding? Ik ben hier ooit is mee bezig geweest maar nooit voor elkaar gekregen. Dit topic ga ik volgen :)

Acties:
  • 0 Henk 'm!

  • Sprite_tm
  • Registratie: September 2002
  • Laatst online: 11-08 04:52

Sprite_tm

Semi-Chinees

Tuurlijk kan er hulp geboden worden. Hoe ver ben je zelf al gekomen; wat heb je gedaan en waar loop je op vast?

Relaxen und watchen das blinkenlichten. | Laatste project: Ikea Frekvens oog


Acties:
  • 0 Henk 'm!

  • iEase
  • Registratie: April 2009
  • Laatst online: 31-03-2021
Momenteel heb ik een arduino in combinatie met een ontvanger volgens het schema van Fuzzilogic
Hierna heb ik met behulp van het script van Fuzzilogic gekeken of er daadwerkelijk wat wordt ontvangen..

Betreffende code:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <avr/interrupt.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif 

#define BUFSIZE 150
#define NUMBUF  2
#define TRIGGERPIN 12
#define INTERESTING_LOW_SIGNAL 450

volatile uint16_t buffer[NUMBUF][BUFSIZE+1]; //In eerste veld het aantal gevonden edges opslaan

volatile short unsigned int bufIndex,bufFree,bufIn, bufOut;
volatile byte nextPulse;
volatile unsigned int prevTime;
volatile boolean listening=false;


ISR(TIMER1_OVF_vect) {
  stopTimer();
  //Serial.println("Timer overflow");
}

ISR(TIMER1_CAPT_vect) {
  unsigned int newTime=ICR1, duration; //gemeten tijd opslaan

    if (nextPulse) {      
    //wachten op een '0' (neergaande flank)
    cbi(TCCR1B,ICES1);
    nextPulse=0;
  } 
  else {      
    //wachten op een '1' (opgaande flank)
    sbi(TCCR1B,ICES1);
    nextPulse=1;
  }

  //Pas beginnen met opslaan als het signaal lange tijd laag is geweest. Abuse de bufIndex van de opslagarray hiervoor.
  duration=newTime-prevTime;
  if (bufIndex>=1 && bufFree>0) {
    buffer[bufIn][bufIndex]=duration;

    //Was afgelopen puls een lange 0?
    if (nextPulse==0 && duration>=INTERESTING_LOW_SIGNAL) {
      //Ja. We hebben een signaal ontvangen!
      buffer[bufIn][0]=bufIndex;//Aantal edges opslaan
      bufIn=(bufIn+1)%NUMBUF; //Volgende buffer gebruiken
      bufFree--; //Aantal vrije buffers--
      bufIndex=1; //En meteen weer door!
      newTime=TCNT1=0; //Time-out timer resetten        
    } 
    else {
      //Nee. Maar is de buffer nu vol?
      if (bufIndex==BUFSIZE) {
        //Ja. Hm. Dan hebben we niets meer aan de data in deze buffer
        bufIndex=0; //Buffer resetten, en wachten op een nieuwe lange 0.            
        return;
      }
    }
    bufIndex++;
  } 
  else if (duration>=300 && nextPulse==0 && bufFree>0) {
    bufIndex=1; //vanaf nu opslaan     
    newTime=TCNT1=0; //Time-out timer resetten
  }
  prevTime=newTime;
}

void setup() {  
  Serial.begin(115200);

  bufIndex=0;
  bufFree=NUMBUF;
  bufIn=0;
  bufOut=0;

  //Zet interrupts. Zie 14.11

  TCCR1A=0;   //Normal mode (timer)

  TCCR1B=0<<ICES1 | 1<<CS12 | 0<<CS11 | 0<<CS10 | 1<<ICNC1;  //Pre-scaler: 256, noise canceler, interrupt on edge: faling

  TIMSK1=0<<ICIE1;  //Disable timer event interrupt

  pinMode(TRIGGERPIN,INPUT);
  pinMode(13,OUTPUT);

  digitalWrite(TRIGGERPIN,LOW);   //externe pull-up gebruikt; disable interne pull-up

  attachInterrupt(0,startTimer,FALLING); //start de timer als er een goed signaal op RSSI-uitgang is.
}

void loop() {  
  while(bufFree<NUMBUF) {

    //Outputformaat: <buffer> <#edges> <data[0]> <data[1]> <data[2]> ... LF
    Serial.print("Buffer:");
    Serial.print(bufOut,DEC);
    Serial.print(" ");
    Serial.print("Edges:");
    Serial.print(buffer[bufOut][0],DEC);
    Serial.print(" ");
    Serial.print("DATA:");
    for (int i=1;i<=buffer[bufOut][0];i++) {
      Serial.print(buffer[bufOut][i],DEC);
      Serial.print(" ");
    }
    Serial.println("");
    bufOut=(bufOut+1)%NUMBUF;
    bufFree++;
  }
}

void startTimer() {
  //disable interrupts
  cli();

  detachInterrupt(0); //stop luisteren op RSSI-uitgang

  //De timer begint te lopen vanaf het moment dat er een '1' binnenkomt.
  //Het wachten is nu op een '0' (neergaande flank)
  nextPulse=0;
  cbi(TCCR1B,ICES1);

  // reset TCNT1
  TCNT1 = 0;

  //Enable timer interrupt; start timer
  TIMSK1=1<<ICIE1 | 1<<TOIE1; 

  //geef aan dat er eerst gewacht moet worden op een lange 0.
  bufIndex=0; 

  prevTime=0;

  //clear eventuele openstaande interrupts.
  TIFR1=0xff;

  listening=true;

  digitalWrite(13,HIGH); //ledje aan

  //enable interrupts
  sei();
}

void stopTimer() {  
  TIMSK1=0; //Disable timer interrupt; Stop edge timer, stop overflow interrupt
  listening=false;  
  digitalWrite(13,LOW); //ledje uit
  attachInterrupt(0,startTimer,FALLING); //start de timer als er een signaal is.
}


Ik zie hierbij diverse berichten binnen komen, waaruit blijkt dat opstelling zelf werkt.

Een voorbeeld van de ontvangen berichten zijn:

code:
1
2
3
4
Buffer:0 Edges:20 DATA:49 43 16 46 13 48 12 78 59 62 57 65 51 255 30 33 8 174 15 3551 
Buffer:1 Edges:85 DATA:0 37 139 23 98 43 18 35 26 59 33 34 27 34 27 34 26 36 25 35 56 66 27 25 36 17 45 9 51 16 75 64 58 37 24 35 27 18 103 36 146 40 82 42 203 34 88 36 86 35 27 12 414 27 35 10 294 23 160 42 262 36 26 26 95 41 81 43 79 42 80 40 266 24 97 32 335 24 38 8 173 26 37 8 3535 
Buffer:0 Edges:30 DATA:23 39 9 294 24 159 40 265 35 26 19 103 35 87 42 79 43 79 42 264 23 99 29 93 33 272 16 228 20 3547 
Buffer:1 Edges:85 DATA:0 35 142 8 112 42 19 35 26 53 39 34 26 35 26 35 26 35 26 35 56 66 26 27 34 25 37 14 50 3 84 49 73 37 25 24 37 16 105 50 43 11 79 54 68 53 191 39 83 40 82 36 26 15 412 22 41 5 298 22 160 40 265 36 26 18 103 33 89 39 83 39 83 36 269 21 101 29 338 19 224 26 37 7 3536


Hierbij is de data de tijd tussen de verschillende op- en neergaande flanken.

Het is momenteel alleen dat ik niet in staat ben om het manchester gecodeerde bericht van de cresta sensor er uit te pikken en weer te geven. Pas als dit gelukt is kan ik na gaan denken over het decoderen...

Acties:
  • 0 Henk 'm!

  • iEase
  • Registratie: April 2009
  • Laatst online: 31-03-2021
Ik denk de juiste signalen binnen te zien komen, om de zoveel tijd komt er een bericht binnen met meer dan 128 edges... Wanneer ik een kaku knop indruk zie ik 51 edges zoals hieronder zichtbaar. De berichten van rond de 130 edges zijn waarschijnlijk de temperatuur sensoren...

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
Buffer:0 Edges:118 DATA:6206 280 113 282 6878 29 105 16 106 17 91 30 72 20 43 18 40 52 71 51 39 22 68 54 69 53 38 23 68 24 37 54 37 24 37 24 37 24 67 25 36 25 36 25 36 25 36 55 36 25 67 25 35 26 35 26 35 26 35 57 64 57 66 26 34 58 34 26 35 27 34 27 64 27 34 58 64 58 64 58 64 58 63 59 33 28 33 28 33 28 33 28 33 28 63 29 32 59 63 59 63 29 32 59 33 28 32 29 32 29 32 29 32 29 32 29 7 3429 
Buffer:1 Edges:139 DATA:44 69 53 70 52 67 25 36 25 35 57 34 27 35 25 35 27 34 27 35 26 65 57 34 27 34 27 34 26 35 27 64 58 65 26 34 27 34 58 64 58 33 28 64 58 64 58 33 28 33 28 64 58 33 28 33 28 33 28 63 29 32 29 32 29 32 29 32 59 32 29 64 28 33 28 33 28 32 29 32 59 63 59 63 29 32 59 33 28 33 28 33 28 59 40 20 71 53 62 63 65 53 69 53 65 30 29 33 28 32 29 32 30 31 29 63 29 33 27 33 29 32 59 63 59 34 27 63 29 32 29 31 60 33 28 32 30 7 3406 
Buffer:0 Edges:139 DATA:6206 68 55 66 56 65 27 40 20 35 57 35 26 34 27 35 26 34 27 35 26 66 56 35 26 34 27 34 27 39 22 65 57 64 28 33 28 33 59 64 57 33 28 64 59 59 68 23 38 54 63 33 27 33 33 24 38 23 37 55 36 26 32 32 28 33 28 35 56 33 29 62 29 32 29 32 29 33 28 32 59 64 59 63 28 33 57 34 28 33 28 36 25 64 28 33 59 63 58 63 59 63 59 63 60 32 28 33 28 33 29 31 30 32 29 62 28 33 60 32 28 33 28 63 28 33 29 32 29 33 59 62 60 31 30 31 29 9 5892 
Buffer:1 Edges:3 DATA:44 11 746 
Buffer:0 Edges:50 DATA:32 48 29 50 30 50 29 51 29 51 29 51 29 51 30 50 29 50 29 51 30 50 28 52 29 51 68 12 28 52 66 14 27 53 66 14 26 54 66 14 26 54 25 55 25 54 67 14 25 613 
Buffer:1 Edges:51 DATA:44 26 54 26 54 26 53 26 54 26 54 26 54 25 55 26 54 26 54 25 54 27 53 27 53 25 56 64 15 25 55 64 17 23 57 63 16 24 56 64 16 25 55 25 55 25 55 64 15 25 614 
Buffer:0 Edges:51 DATA:32 25 55 25 55 25 54 25 55 26 55 24 55 25 55 25 55 25 55 24 56 25 54 26 55 24 56 64 15 24 57 62 18 23 57 62 17 23 57 64 16 24 56 24 56 24 56 63 17 23 615 
Buffer:1 Edges:51 DATA:44 23 56 25 55 24 56 24 56 24 55 24 56 24 56 25 55 24 56 23 57 24 55 25 56 23 57 63 17 23 57 62 18 22 57 63 18 22 58 62 17 24 56 24 56 24 56 63 18 22 615 
Buffer:0 Edges:51 DATA:32 23 56 24 56 24 56 24 56 24 56 23 56 24 56 24 56 24 56 24 56 24 56 23 57 23 57 63 17 23 57 62 18 22 58 62 18 22 58 63 16 24 56 23 57 24 56 63 17 23 615 
Buffer:1 Edges:51 DATA:44 23 56 24 56 24 56 24 56 24 56 23 57 23 57 24 55 24 56 24 56 24 56 63 17 23 57 63 17 22 58 62 18 22 58 62 18 22 58 63 17 62 17 64 16 63 18 62 18 22 616 
Buffer:0 Edges:51 DATA:32 22 57 23 57 23 57 23 56 24 56 23 57 23 57 24 56 23 57 23 57 23 57 62 18 22 58 62 18 22 58 61 19 21 59 61 18 22 58 63 17 63 17 63 17 62 18 62 18 22 10795 
Buffer:1 Edges:30 DATA:192 104 361 99 690 253 496 259 403 150 266 163 961 152 1200 152 387 154 987 164 6371 265 120 290 2046 242 6097 270 23192 1354 
Buffer:0 Edges:3 DATA:32 716 900


Vraag is nu hoe ik op de een of andere manier alleen het juiste signaal op kan slaan in een buffer waarbij niet de tijden tussen de flanken wordt opgeslagen maar de ontvangen binaire code..

Acties:
  • 0 Henk 'm!

  • Sprite_tm
  • Registratie: September 2002
  • Laatst online: 11-08 04:52

Sprite_tm

Semi-Chinees

Je hebt nu een nette buffer met tijden; hetgeen wat je nu nog mist is een algoritme om de tijden naar binaire data om te zetten. Het plan de campagne lijkt me in ieder geval om eerst iets meer over de de bittijd uit te vogelen, dat is de tijd dat 1 bit inneemt op de lijn. Dat kan je doen door het gemiddelde van alle tijden te nemen. Je kunt nu alle tijden vergelijken met A: als de desbetreffende tijd kleiner is neemt 'ie een halve bittijd in, anders een hele.

Dan moet je de daadwerkelijke Manchester-decodering doen. Je zou bijvoorbeeld die kunnen doen op basis van dat het signaal alleen een hele bit-tijd hoog of laag is als de twee opeenvolgende bits die verzonden zijn verschillend zijn. Zoiets zou volgens mij moeten werken:
code:
1
2
3
4
5
6
7
8
9
10
11
avg=calculateAveragge(buff)
bit=0;
for (x=0; x<bufflen; x++) {
  if (buff[x]>avg) {
     bit=!bit
  } else {
    //bit blijft hetzelfde, maar 'eet' wel de volgende halve bittijd uit buff op.
    x++;
  }
  output_bit(bit);
}

Relaxen und watchen das blinkenlichten. | Laatste project: Ikea Frekvens oog


Acties:
  • 0 Henk 'm!

  • iEase
  • Registratie: April 2009
  • Laatst online: 31-03-2021
@Sprite,

Ik begrijp de denkwijze volledig, maar vraag me af of het niet eerst de bedoeling is dat we de op en neergaande flanken van het signaal weer kunnen geven. Volgens het cresta protocol in het eerste topic zou namelijk het volgende het geval moeten zijn:

"Also, a positive edge translates to a “1”, a negative edge translates to a “0”."

Wanneer ik op een andere website kijk lees ik weer een heel ander verhaal over de decodering van een cresta sensor:

http://jeelabs.org/2010/04/16/cresta-sensor/

[ Voor 19% gewijzigd door iEase op 05-04-2011 13:21 ]


Acties:
  • 0 Henk 'm!

  • Sprite_tm
  • Registratie: September 2002
  • Laatst online: 11-08 04:52

Sprite_tm

Semi-Chinees

Lijkt mij dat er meerdere cresta-sensoren zijn :) Ik zou zeggen: decodeer je metingen met het handje volgens beide methoden en kijk welke daadwerkelijk de temperatuur uitspuugt. Die kan je dan in code omzetten.

Relaxen und watchen das blinkenlichten. | Laatste project: Ikea Frekvens oog

Pagina: 1