433Mhz Sender Code

Gast #4308563
Lesenswert?

Hallo zusammen,

ich habe hier ein 433MHZ Sendemodul. Dieses hatte ich bis jetzt mit 
einem Raspberry Pi angesteuert, mit Hilfe von 
https://github.com/r10r/rcswitch-pi. Das hat immer sehr gut geklappt.
Nun wollte ich das ganze mit meinem Atmega8 machen. Ich habe hier so ein 
myAVR Board MK2.

Ich habe also die Funktionen, die ich auf dem Raspberry genutzt habe 
übertragen und angepasst. Dabei kam das raus:
1
#ifndef F_CPU
2
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 3686400"
3
#define F_CPU 3686400UL  // Systemtakt in Hz - Definition als unsigned long beachten
4
#endif
5

6
#include <stdbool.h>
7
#include <util/delay.h>
8

9
int nReceiveTolerance = 60;
10
int nPulseLength = 350;
11
int nRepeatTransmit = 10;
12

13
//Prototypes
14
void sendTriState(char*);
15
char* getCodeWordA(char const* nAddressCode, int nChannelCode, bool bStatus);
16
void switchOn(char const* nAddressCode, int nChannelCode);
17
void switchOff(char const* nAddressCode, int nChannelCode);
18
void transmit(int nHighPulses, int nLowPulses);
19
void send0(void);
20
void send1(void);
21
void sendT0(void);
22
void sendTF(void);
23
void sendT1(void);
24
void sendSync(void);
25
/**
26
 * Switch a remote switch on (Type A with 10 pole DIP switches)
27
 *
28
 * @param sGroup        Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
29
 * @param nChannelCode  Number of the switch itself (1..4)
30
 */
31
void switchOn(char const* sGroup, int nChannel) {
32
  sendTriState( getCodeWordA(sGroup, nChannel, true) );
33
}
34

35
/**
36
 * Switch a remote switch off (Type A with 10 pole DIP switches)
37
 *
38
 * @param sGroup        Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
39
 * @param nChannelCode  Number of the switch itself (1..4)
40
 */
41
void switchOff(char const* sGroup, int nChannel) {
42
  sendTriState( getCodeWordA(sGroup, nChannel, false) );
43
}
44

45
/**
46
 * Like getCodeWord  (Type A)
47
 */
48
char* getCodeWordA(char const* sGroup, int nChannelCode, bool bStatus) {
49
   int nReturnPos = 0;
50
   static char sReturn[13];
51

52
  char const* code[6] = { "FFFFF", "0FFFF", "F0FFF", "FF0FF", "FFF0F", "FFFF0" };
53

54
  if (nChannelCode < 1 || nChannelCode > 5) {
55
      return '\0';
56
  }
57
  
58
  for (int i = 0; i<5; i++) {
59
    if (sGroup[i] == '0') {
60
      sReturn[nReturnPos++] = 'F';
61
    } else if (sGroup[i] == '1') {
62
      sReturn[nReturnPos++] = '0';
63
    } else {
64
      return '\0';
65
    }
66
  }
67
  
68
  for (int i = 0; i<5; i++) {
69
    sReturn[nReturnPos++] = code[ nChannelCode ][i];
70
  }
71
  
72
  if (bStatus) {
73
    sReturn[nReturnPos++] = '0';
74
    sReturn[nReturnPos++] = 'F';
75
  } else {
76
    sReturn[nReturnPos++] = 'F';
77
    sReturn[nReturnPos++] = '0';
78
  }
79
  sReturn[nReturnPos] = '\0';
80

81
  return sReturn;
82
}
83

84

85

86
/**
87
 * Sends a Code Word
88
 * @param sCodeWord   /^[10FS]*$/  -> see getCodeWord
89
 */
90
void sendTriState(char* sCodeWord) {
91
  for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) {
92
    int i = 0;
93
    while (sCodeWord[i] != '\0') {
94
      switch(sCodeWord[i]) {
95
        case '0':
96
          sendT0();
97
        break;
98
        case 'F':
99
          sendTF();
100
        break;
101
        case '1':
102
          sendT1();
103
        break;
104
      }
105
      i++;
106
    }
107
    sendSync();    
108
  }
109
}
110

111
void transmit(int nHighPulses, int nLowPulses) {
112
    PORTB = 0x01; //Pin anschalten
113
  switch(nHighPulses)
114
  {
115
    case 1: _delay_us(350); break;
116
    case 3: _delay_us(350*3); break;
117
  }
118
  PORTB = 0x00; //Pin ausschalten
119
  switch(nLowPulses)
120
  {
121
    case 1: _delay_us(350); break;
122
    case 3: _delay_us(350*3); break;
123
    case 31: _delay_us(350*31); break;
124
  }
125
}
126
/**
127
 * Sends a "0" Bit
128
 *                       _    
129
 * Waveform Protocol 1: | |___
130
 *                       _  
131
 * Waveform Protocol 2: | |__
132
 */
133
void send0() {
134
  transmit(1,3);
135
}
136

137
/**
138
 * Sends a "1" Bit
139
 *                       ___  
140
 * Waveform Protocol 1: |   |_
141
 *                       __  
142
 * Waveform Protocol 2: |  |_
143
 */
144
void send1() {
145
  transmit(3,1);
146
}
147

148

149
/**
150
 * Sends a Tri-State "0" Bit
151
 *            _     _
152
 * Waveform: | |___| |___
153
 */
154
void sendT0() {
155
  transmit(1,3);
156
  transmit(1,3);
157
}
158

159
/**
160
 * Sends a Tri-State "1" Bit
161
 *            ___   ___
162
 * Waveform: |   |_|   |_
163
 */
164
void sendT1() {
165
  transmit(3,1);
166
  transmit(3,1);
167
}
168

169
/**
170
 * Sends a Tri-State "F" Bit
171
 *            _     ___
172
 * Waveform: | |___|   |_
173
 */
174
void sendTF() {
175
  transmit(1,3);
176
  transmit(3,1);
177
}
178

179
/**
180
 * Sends a "Sync" Bit
181
 *                       _
182
 * Waveform Protocol 1: | |_______________________________
183
 *                       _
184
 * Waveform Protocol 2: | |__________
185
 */
186
void sendSync() {
187
  transmit(1,31);
188
}

Das ganze rufe ich so auf:
1
#include <avr/io.h>
2
#include "rcSwitch.h"
3

4
int main(void)
5
{
6
    DDRB = 0x01;
7
    while(1)
8
    {  
9
    switchOn("10011",1);
10
    _delay_ms(1000);
11
    }
12
}

Leider funktioniert es einfach nicht.. Externen Quarz oder sowas benutze 
ich nicht. Da fehlt mir noch ein wenig was an Wissen.

Ich hoffe jemand findet meinen Fehler oder kann mich in die richtige 
Richtung führen!

Viele Grüße
Tobi
#4308701
Lesenswert?

Zitat avr-libc user manual:

void _delay_us ( double __us )

The maximal possible delay is 768 us / F_CPU in MHz.

If the user requests a delay greater than the maximal possible one, 
_delay_us() will automatically call _delay_ms() instead. The user will 
not be informed about this case.

Zitat Ende.


Ich vermute, es verhagelt Dir das Timing, wenn er die Zeiten auf volle 
Millisekunden rundet.
Gast #4308734
Lesenswert?

> Ich vermute, es verhagelt Dir das Timing, wenn er die Zeiten auf volle
> Millisekunden rundet.

> In this mode _delay_ms() will work with a resolution of 1/10 ms

Was genau bedeutet das jetzt für mein Programm? Was muss ich wie 
verändern? us in ms umwandeln und _delay_ms() aufrufen?
#4308742
Lesenswert?

Hab mal nachgeschaut. Laut Sourcecode nimmt der Compiler dann 
__builtin_avr_delay_cycles. Damit dürften die delays einigermaßen 
stimmen.

Dann liegt es vielleicht an den Programmlaufzeiten zwischen den delays. 
Der Prozessortakt von 3,68 MHz ist ja ein bisschen weniger als bein RPi.

Ich würde mir das Ausgangssignal mal näher ansehen. Zur Not mit einem 
Soundkarten-Oszi.
Gast #4308771
Lesenswert?

Tobi schrieb:
>> Ich vermute, es verhagelt Dir das Timing, wenn er die Zeiten auf volle
>> Millisekunden rundet.
>
>> In this mode _delay_ms() will work with a resolution of 1/10 ms
>
> Was genau bedeutet das jetzt für mein Programm? Was muss ich wie
> verändern? us in ms umwandeln und _delay_ms() aufrufen?

D. h., dass das Timing - bei Werten größer 768 µs - mit einer Auflösung 
von 100 µs erfolgt.

Ob dies ein Problem ist musst du prüfen. Was dein Sender überträgt 
kannst du mit einem DVB-T Dongle (10 Euro) und dem PC-Programm SDR# 
sehen.
Gast #4308772
Lesenswert?

Mario M. schrieb:
> Ich würde mir das Ausgangssignal mal näher ansehen. Zur Not mit einem
> Soundkarten-Oszi.

So etwas habe ich noch nie gemacht... Die Anleitung hier hilft mir auch 
nicht sonderlich weiter. Was für eine Schaltung braucht man? Wie 
schließt man das an die Soundkarte an?
Gast #4308783
Lesenswert?

Abel schrieb:
> D. h., dass das Timing - bei Werten größer 768 µs - mit einer Auflösung
> von 100 µs erfolgt.
>
> Ob dies ein Problem ist musst du prüfen. Was dein Sender überträgt
> kannst du mit einem DVB-T Dongle (10 Euro) und dem PC-Programm SDR#
> sehen.

Ich habe zufällig noch so einen kleinen USB DVB-T Empfänger hier 
rumliegen gehabt. Die Software von airspy.com sagt leider nur "Cannot 
open AirSpy device".

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren