Forum: Mikrocontroller und Digitale Elektronik RFM12 und AVR: Wie nach Fehlern suchen?


von Mirko (Gast)


Lesenswert?

Hallo zusammen!
Ich versuche einen AVR (TINY2313) über ei RFM12 senden zu lassen.
Als Code verwende ich einen einfachen Sendecode aus einer RMF-Library. 
Die Beschaltung hab ich wie in den vielen Google-Ergebnissen 
vorgeschlagen vorgenommen ;-)
Leider funktioniert das ganze nicht (es kommt nichts am Empfänger an). 
Nun bin ich auf Fehlersuche...

Nun aber zu meiner konkreten Frage: es scheint keine Kommunikation 
zwischen AVR und RFM stattzufinden. Wenn ich das richtig verstanden habe 
werden die 3 Pins MISO, MOSI und SCK (bzw. SDO, SCI und SCK am RFM) zur 
Übertragung verwendet.
Müsste man da was messen können? Mein Multimeter zeigt zumindest 
konstant 0V an allen 3 Pins an...
"Muss dat so?"

Oder liegt da schon der Hund begraben?

Danke,
Mirko

von R. W. (quakeman)


Lesenswert?

Ein Multimeter ist keine gute Möglichkeit die SPI Signale zu messen. Du 
brauchst ein Digitalspeicheroszilloskop oder einen Logic Analyzer.
Aber als Anhaltspunkt zum testen könntest du natürlich per SPI einfach 
mal 0xFF dauerhaft senden und schauen ob du am MOSI Pin annähernd 
3,3V/5V messen kannst. Falls das nicht der Fall ist, dann stimmt schon 
etwas mit deiner SPI Kommunikation nicht.

Ciao,
     Rainer

von Mirko (Gast)


Lesenswert?

OK, das klingt doch gut. Dann werd ich das mal so machen...
Danke!

von Mirko (Gast)


Lesenswert?

Sooo, leider hat das nicht hingehauen. Das mit dem dauerhaft senden 
scheint nicht möglich zu sein, da der Sendecode den ganzen 
Programmablauf blockiert. Es wird nichts gesendet, und das Programm 
steckt an der Stelle fest.

Muss ich mir das wie einen Unfall auf der Autobahn vorstellen, der einen 
Stau verursacht?

Der Code selber sollte eigentlich funktionieren, da ich ja nur ein 
Beispielprojekt aus dem Internet verwende...
Könnte es an der Hardware, also der Verbindung zwischen den beiden 
Geräten liegen?
Was passiert, wenn z.B. der Gesprächspartner vom AVR falsch 
angeschlossen oder sogar tot ist? (in diesem Fall das RFM12 Modul)

von C. H. (hedie)


Lesenswert?

Mirko schrieb:
> Könnte es an der Hardware, also der Verbindung zwischen den beiden
> Geräten liegen?
> Was passiert, wenn z.B. der Gesprächspartner vom AVR falsch
> angeschlossen oder sogar tot ist? (in diesem Fall das RFM12 Modul)

Es könnte sein, das dein Code auf die Reaktion des RFM12 wartet... Poste 
doch mal die Sende Funktion...

Hast du zudem das RFM Korrekt verbunden? nSel muss auch verbunden 
werden!

Übrigens... ein bisschen werbung muss sein :)
Du könntest dir ja meinen LogicAnalyzer nachbauen... Ich habe mit diesem 
auch kommunikationsprobleme mit meinem RFM aufgedeckt!

http://endasmedia.ch/projects/openlogic.php

von Mirko (Gast)


Lesenswert?

Also, die Sende-Funktion habe ich von hier: 
http://www.mydani.com/dl/myrfm12/help/

Der Code sieht so aus:
1
/* Correct functions are enabled for HW SPI*/
2
#if MYRFM12_CONF_SPI == MYRFM12_CONF_SPI_HW
3
/* HW SPI specific init function */
4
void myrfm12_port_init_hw_spi(void);
5
#define myrfm12_spi_init  myrfm12_port_init_hw_spi
6
7
/* HW SPI specific transfer function */
8
uint16_t myrfm12_trans(uint16_t wert)
9
{
10
#if(MYRFM12_CONF_DEBUG == MYRFM12_CONF_DEBUG_YES)
11
  myrfm12_debug(cmd);
12
#endif
13
14
  CONVERTW val;
15
  val.w=wert;
16
  cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS);
17
  SPDR = val.b[1];
18
  while(!(SPSR & (1<<SPIF)));
19
  val.b[1]=SPDR;
20
  SPDR = val.b[0];
21
  while(!(SPSR & (1<<SPIF)));
22
  val.b[0]=SPDR;
23
  sbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS);
24
  return val.w;
25
26
  /* Implementation without union usage, needs more ROM */
27
  /*
28
  uint16_t feedback = 0x00;
29
  cbi(MYRFM12_PORT, MYRFM12_CS);
30
  SPDR = (uint8_t)(wert&0x00FF);
31
  while(!(SPSR & (1<<SPIF)));
32
  feedback |= SPDR;
33
  SPDR = (uint8_t)((wert&0xFF00)>>8);
34
  while(!(SPSR & (1<<SPIF)));
35
  feedback |= (SPDR << 8);
36
  sbi(MYRFM12_PORT, MYRFM12_CS);
37
  return feedback;
38
  */
39
}
40
#endif
41
42
/* Correct functions are enabled for SW SPI*/
43
#if MYRFM12_CONF_SPI == MYRFM12_CONF_SPI_SW
44
/* SW SPI specific init function */
45
void myrfm12_port_init_sw_spi(void);
46
#define myrfm12_spi_init  myrfm12_port_init_sw_spi
47
48
/* SW SPI specific transfer function */
49
uint16_t myrfm12_trans(uint16_t cmd)
50
{
51
#if(MYRFM12_CONF_DEBUG == MYRFM12_CONF_DEBUG_YES)
52
  myrfm12_debug(cmd);
53
#endif
54
55
  unsigned char i;
56
57
  cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS);        // Select RFM12
58
  for (i=0; i<16; i++)      // Iterate 16 times (for 16 bits)
59
  {
60
    if (cmd&0x8000)
61
      sbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SDI);
62
    else
63
      cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SDI);
64
    cmd<<=1;
65
66
    if (MYRFM12_CONF_PIN&(1<<MYRFM12_CONF_SDO))
67
      cmd|=1;
68
69
    sbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SCK);
70
    //_delay_us(0.2);
71
    asm("nop");
72
    asm("nop");
73
    cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SCK);
74
  }
75
  sbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS);        // Deselect RFM12
76
  //cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SDI);        // SDI to low
77
78
  return cmd;          // Return received value
79
}
80
#endif
81
82
void myrfm12_cmd_datarate(uint16_t baud)
83
{
84
  if (baud<5400)
85
    myrfm12_trans(0xC680|MYRFM12_CALC_R_WITH_PRESCALER(baud));
86
  else
87
    myrfm12_trans(0xC600|MYRFM12_CALC_R_WITHOUT_PRESCALER(baud));
88
}
89
90
#if (MYRFM12_CONF_SETUPMETHOD == MYRFM12_CONF_SETUPMETHOD_STD)
91
void myrfm12_setup()
92
{
93
  /* Setup connection to RFM12 */
94
  myrfm12_spi_init();
95
96
  /* wait until POR is done */
97
  uint8_t i;
98
  for (i=0; i<20; i++)
99
    _delay_ms(10);
100
101
  /* Setup basic configration, base frequency, capacitor */
102
  myrfm12_cmd_config(MYRFM12_CONF_SETUP_BASEFREQ|MYRFM12_CONF_SETUP_CAPACITOR|MYRFM12_CMD__CONFIG__RXFIFO_ON|MYRFM12_CMD__CONFIG__TXFIFO_ON);
103
104
  /* Setup power management, enable oscillator pin */
105
  myrfm12_cmd_powermanagement(MYRFM12_CMD__POWER__ENABLEOSCILLATOR);
106
107
  /* Setup frequency */
108
  myrfm12_cmd_frequencysetting(MYRFM12_CONF_SETUP_ADDFREQ);
109
110
  /* Setup baud rate */
111
  myrfm12_cmd_datarate(MYRFM12_CONF_SETUP_BAUDRATE);
112
113
  /* Setup receiver part */
114
  myrfm12_cmd_rxcontrol(MYRFM12_CMD__RXCTRL__PIN20_VDIOUT | MYRFM12_CMD__RXCTRL__VDIRESPTIME_FAST | MYRFM12_CMD__RXCTRL__BASEBANDWITH_200KHZ | MYRFM12_CMD__RXCTRL__LNAGAIN_MIN6DB | MYRFM12_CMD__RXCTRL__DRSSI_M79DB);
115
116
  /* Setup data filer */
117
  myrfm12_cmd_datafilter(MYRFM12_CMD__DF__CLKRECAUTOLOCK_ENABLE | MYRFM12_CMD__DF__DQDTHRESH(3) | MYRFM12_CMD__DF__FILTERTYPE_DIGITAL);
118
119
  /* Setup the fifo */
120
  myrfm12_cmd_fifo(MYRFM12_CMD__FIFO__FIFOIRLEVEL(8)| MYRFM12_CMD__FIFO__HSRESETMODE_ENABLE | MYRFM12_CMD__FIFO__FIFO_FILL);
121
122
   /* Setup the AFC */
123
  myrfm12_cmd_afc(MYRFM12_CMD__AFC__AUTOMODE_MCU|MYRFM12_CMD__AFC__AUTOMODE_OFFSETKEEP | MYRFM12_CMD__AFC__RANGE_NARROW|MYRFM12_CMD__AFC__ENABLEHIGHACCURACY|MYRFM12_CMD__AFC__ENABLEOUTREG|MYRFM12_CMD__AFC__ENABLEAFC);
124
125
  /* Setup TX power,frequency deviation,modulation polarity */
126
  myrfm12_cmd_modulation_power(MYRFM12_CONF_SETUP_POWER,MYRFM12_CONF_SETUP_FREQDEV,MYRFM12_CONF_SETUP_MODULATIONPOLARITY);
127
128
  /* Setup Wakeup */
129
  myrfm12_cmd_wakeuptimer(MYRFM12_CMD__WAKEUP__BASE(0)|MYRFM12_CMD__WAKEUP__EXPONENT(0));
130
131
  /* Setup low duty cycle */
132
  myrfm12_cmd_lowdutycycle(MYRFM12_CMD__LOWDUTY__DUTY(0));
133
134
  /* Setup Low Battery Detector and clock divider */
135
  myrfm12_cmd_lowbatandclockdivider(MYRFM12_CMD__LOWBATCLOCK__CLOCK_10MHZ|MYRFM12_CMD__LOWBATCLOCK__LOWBATVOLT(0));
136
}
137
#endif
138
139
void myrfm12_ready()
140
{
141
  cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SDI);
142
  cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS);
143
  asm("nop");
144
  while (!(MYRFM12_CONF_PIN&(1<<MYRFM12_CONF_SDO)));
145
}
146
147
void myrfm12_sendsyncrobytes()
148
{
149
  uint8_t i;
150
  for(i=0;i<3;i++)
151
  {
152
    myrfm12_ready();
153
    myrfm12_trans(0xB8AA);
154
  }
155
}
156
157
void myrfm12_sendsyncbytes()
158
{
159
    myrfm12_ready();
160
    myrfm12_trans(0xB82D);
161
    myrfm12_ready();
162
    myrfm12_trans(0xB8D4);
163
}
164
165
void myrfm12_txdata(uint8_t* data, uint8_t number)
166
{
167
  MYRFM12_CONF_SETUP_TX_START
168
169
  /* Enable transmitter */
170
  myrfm12_cmd_powermanagement(MYRFM12_CMD__POWER__ENABLEOSCILLATOR | MYRFM12_CMD__POWER__ENABLETRANSMITTER | MYRFM12_CMD__POWER__ENABLESYNTHESIZER);
171
172
  /* Send Syncro Bytes */
173
  myrfm12_sendsyncrobytes();
174
175
  /* Send Sync Bytes */
176
  myrfm12_sendsyncbytes();
177
178
  /* Send Length Byte */
179
  myrfm12_ready();
180
  myrfm12_cmd_txbyte(number);
181
182
  /* Send Data */
183
  uint8_t i;
184
  for (i=0; i<number; i++)
185
  {
186
    myrfm12_ready();
187
    myrfm12_cmd_txbyte(*data++);
188
  }
189
190
  /* Send Syncro Bytes */
191
  myrfm12_sendsyncrobytes();
192
193
  _delay_us(10);
194
195
  /* Disable transmitter */
196
  myrfm12_cmd_powermanagement(MYRFM12_CMD__POWER__ENABLEOSCILLATOR);
197
198
  MYRFM12_CONF_SETUP_TX_STOP
199
}

Verwenden tue ich ihn so:
1
myrfm12_setup();
2
3
unsigned char test[]="This is a myrfm12 test.";
4
for (;;)
5
{
6
    myrfm12_txdata(test,23);
7
8
    //<uart_puts_P("sende...\n");
9
    for ( i=0; i<100; i++)
10
      _delay_ms(10);
11
}


Die Verbindung (hardwaremäßig) zwischen ATTINY2313 und RFM12 sieht so 
aus:

RFM -> AVR
---------------------------
SDO -> MISO (PB6)
nIRQ -> PCINT3 (PB3)
FSK -> über 10kOhm an VCC (3,3V)
DCLK - > ?
CLK -> ?
nRES -> ?
GND -> GND
ANT -> 16cm Antenne
VDD -> VCC (3,3V)
GND -> GND
nInt -> ?
SDI -> MOSI (PB5)
SCK -> SCL (PB7)
nSEL -> über 10kOhm an VCC und an PCINT4 (PB4)


Dem entsprechend initialisiere ich die RFM library so:
1
/*! \def MYRFM12_PORT
2
     *  \brief Port of the AVR on which the module is connected to */
3
    #define MYRFM12_CONF_PORT    PORTB
4
    /*! \def MYRFM12_DDR
5
     *  \brief Data direction register of the used port */
6
    #define MYRFM12_CONF_DDR      DDRB
7
    /*! \def MYRFM12_PIN
8
     *  \brief Pin assignment */
9
    #define MYRFM12_CONF_PIN    PINB
10
    /*! \def MYRFM12_SDI
11
     *  \brief The Pin-Number of the AVR that is connected with the SDI-Pin MOSI
12
     *  of the RFM12 */
13
    #define MYRFM12_CONF_SDI    5
14
    /*! \def MYRFM12_SCK
15
     *  \brief The Pin-Number of the AVR that is connected with the SCK-Pin SCK
16
     *  of the RFM12 */
17
    #define MYRFM12_CONF_SCK    7
18
    /*! \def MYRFM12_CS
19
     *  \brief The Pin-Number of the AVR that is connected with the nSEL-Pin
20
     *   of the RFM12 */
21
    #define MYRFM12_CONF_CS      4
22
    /*! \def MYRFM12_SDO
23
     *  \brief The Pin-Number of the AVR that is connected with the SDO-Pin MISO
24
     *   of the RFM12 */
25
    #define MYRFM12_CONF_SDO    6
26
    /*! \def MYRFM12_NIRQ
27
     *  \brief Optional Pin-Assignments; The Pin-Number of the AVR that is
28
     *  connected with the nIRG-Pin of the RFM12 */
29
    #define MYRFM12_CONF_NIRQ    3

Das mit dem logic analyzer übersteigt im Moment noch meine Fähigkeiten 
;-)

von C. H. (hedie)


Lesenswert?

ok und wie hast du 0xFF übertragen um die Leitungen zu prüfen?



Mirko schrieb:
> Das mit dem logic analyzer übersteigt im Moment noch meine Fähigkeiten
> ;-)

Es wird in absehbarer zeit eine käufliche version geben :)

von holger (Gast)


Lesenswert?

>  SPDR = val.b[1];
>  while(!(SPSR & (1<<SPIF)));

Tiny2313 kennt keines von diesen beiden Registern.
Du hast den Code also für einen falschen Prozessor
übersetzt und in den Tiny gebrannt.

von Mirko (Gast)


Lesenswert?

Argh! Danke für den Hinweis!
Gibt es denn irgendwo einen Tiny kompatiblen sample Code (AVR<->RFM12) 
den man verwenden könnte?
Leider finde ich nichts brauchbares :-(

von C. H. (hedie)


Lesenswert?

Mirko schrieb:
> Argh! Danke für den Hinweis!
> Gibt es denn irgendwo einen Tiny kompatiblen sample Code (AVR<->RFM12)
> den man verwenden könnte?
> Leider finde ich nichts brauchbares :-(

Ich hab meines genau mit dem Attiny2313 verwendet

Ich kann dir den Code zukommen lassen sobald ich wieder zuhause bin
das wäre morgen nachmittag

von Mirko (Gast)


Lesenswert?

Das wäre wirklich super. Dank dir!
Meine Adresse ist VanKurt at gmx.de

Hast du auch noch eine Liste der verbundenen Pins? Einen Schaltplan oder 
ähnliches? Das wäre das Sahnehäubchen ;-)

von C. H. (hedie)


Lesenswert?

Mirko schrieb:
> Hast du auch noch eine Liste der verbundenen Pins? Einen Schaltplan oder
> ähnliches? Das wäre das Sahnehäubchen ;-)

Ja natürlich... Hab ich alles... Aber eben zuhause...
Sende ich dir alles morgen nachmittag - abend :)

von Mirko (Gast)


Lesenswert?

Hat vielleicht noch jemand ein bisschen Code/einen Schaltplan?
Hedie scheint mich leider vergessen zu haben :-(

von Mirko (Gast)


Lesenswert?

Und gleich noch eine Frage: Ist es eigentlich richtig, dass der nIRQ Pin 
des RFM12 auf 0V liegt? Ich habe ihn über einen Pullup an VCC 
angeschlossen, aber trotzdem liegt er auf 0V...

von R. W. (quakeman)


Lesenswert?

nIRQ ist ein Ausgang und benötigt keinen Pull-up. Wenn er low ist, dann 
liegt ein Ereignis im RFM12 an, welches noch nicht abgefragt wurde. Aber 
zum testen würde ich sowieso erst mal Polling beutzen und nicht den 
Interruptbetrieb (also nIRQ ignorieren).
Ich habe damals zum Testen ein paar sehr simple Sende- und 
Empfangsprogramm geschrieben gehabt. Diese sind für einen LPC935 
(8051er) und dementsprechend kann der Code nicht 1:1 auf einen AVR 
übernommen werden. Aber die eigentlichen Steuerbefehle sind ja identisch 
und dadrin gut zu erkennen. Du findest sie unter [1] mit den Namen 
Test_RFM12_*.

Ciao,
     Rainer

[1] https://quakeman.homelinux.net/viewvc/uVision/trunk/

von Claudio Hediger (Gast)


Lesenswert?

Mirko schrieb:
> Hedie scheint mich leider vergessen zu haben :-(

Sorry.... Du hast post :)

von Claudio Hediger (Gast)


Lesenswert?

Hat es egklappt mit meiner Software?

von tom (Gast)


Lesenswert?

Um zu sehen ob der Sender wirklich sendet hab ich die Stromaufnahme 
gemessen.
Also eine Sekunde irgendwas senden, dann ne Pause und wieder senden.
Dann sollte man mit einem Messgerät schön sehen können ob der RFM 
sendet.
Dann weißt du zumindest, dass die SPI Kommunikation schonmal stimmt. Ob 
das
Modul dann richtig konfiguriert ist kannst du dann aber noch nicht 
sagen...

von Mirko (Gast)


Lesenswert?

Hi Claudio!
Leider nicht. Er kommt bis zum Sendebefehl, darin bleibt der AVR dann 
leider hängen...

von Claudio Hediger (Gast)


Lesenswert?

Merkwürdig...

Bei mir funktioniert der Code einwandfrei so wie ich ihn dir gesendet 
habe :S

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.