Forum: Mikrocontroller und Digitale Elektronik 433Mhz Sender Code


von Tobi (Gast)


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

: Verschoben durch Moderator
von Mario M. (thelonging)


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.

von Abel (Gast)


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

von Tobi (Gast)


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?

von Mario M. (thelonging)


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.

: Bearbeitet durch User
von Abel (Gast)


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.

von Tobi (Gast)


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?

von Tobi (Gast)


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".

von Michael U. (amiga)


Lesenswert?

Hallo,

wenn ich oben am Schluß richtig gelesen habe, benutzt der TO keinen 
Quarz. Also läuft der Mega8 mit internen 1MHz. Damit stimmt F_CPU nicht.

Ich habe jetzt nicht geschaut, ob das Timing mit 1MHz überhaupt gehen 
könnte.

Gruß aus Berlin
Michael

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.