www.mikrocontroller.net

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


Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: R. W. (quakeman)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, das klingt doch gut. Dann werd ich das mal so machen...
Danke!

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Claudio H. (Firma: BLS-Electronics) (hedie)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Mirko (Gast)
Datum:

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

Der Code sieht so aus:

/* Correct functions are enabled for HW SPI*/
#if MYRFM12_CONF_SPI == MYRFM12_CONF_SPI_HW
/* HW SPI specific init function */
void myrfm12_port_init_hw_spi(void);
#define myrfm12_spi_init  myrfm12_port_init_hw_spi

/* HW SPI specific transfer function */
uint16_t myrfm12_trans(uint16_t wert)
{
#if(MYRFM12_CONF_DEBUG == MYRFM12_CONF_DEBUG_YES)
  myrfm12_debug(cmd);
#endif

  CONVERTW val;
  val.w=wert;
  cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS);
  SPDR = val.b[1];
  while(!(SPSR & (1<<SPIF)));
  val.b[1]=SPDR;
  SPDR = val.b[0];
  while(!(SPSR & (1<<SPIF)));
  val.b[0]=SPDR;
  sbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS);
  return val.w;

  /* Implementation without union usage, needs more ROM */
  /*
  uint16_t feedback = 0x00;
  cbi(MYRFM12_PORT, MYRFM12_CS);
  SPDR = (uint8_t)(wert&0x00FF);
  while(!(SPSR & (1<<SPIF)));
  feedback |= SPDR;
  SPDR = (uint8_t)((wert&0xFF00)>>8);
  while(!(SPSR & (1<<SPIF)));
  feedback |= (SPDR << 8);
  sbi(MYRFM12_PORT, MYRFM12_CS);
  return feedback;
  */
}
#endif

/* Correct functions are enabled for SW SPI*/
#if MYRFM12_CONF_SPI == MYRFM12_CONF_SPI_SW
/* SW SPI specific init function */
void myrfm12_port_init_sw_spi(void);
#define myrfm12_spi_init  myrfm12_port_init_sw_spi

/* SW SPI specific transfer function */
uint16_t myrfm12_trans(uint16_t cmd)
{
#if(MYRFM12_CONF_DEBUG == MYRFM12_CONF_DEBUG_YES)
  myrfm12_debug(cmd);
#endif

  unsigned char i;

  cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS);        // Select RFM12
  for (i=0; i<16; i++)      // Iterate 16 times (for 16 bits)
  {
    if (cmd&0x8000)
      sbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SDI);
    else
      cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SDI);
    cmd<<=1;

    if (MYRFM12_CONF_PIN&(1<<MYRFM12_CONF_SDO))
      cmd|=1;

    sbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SCK);
    //_delay_us(0.2);
    asm("nop");
    asm("nop");
    cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SCK);
  }
  sbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS);        // Deselect RFM12
  //cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SDI);        // SDI to low

  return cmd;          // Return received value
}
#endif

void myrfm12_cmd_datarate(uint16_t baud)
{
  if (baud<5400)
    myrfm12_trans(0xC680|MYRFM12_CALC_R_WITH_PRESCALER(baud));
  else
    myrfm12_trans(0xC600|MYRFM12_CALC_R_WITHOUT_PRESCALER(baud));
}

#if (MYRFM12_CONF_SETUPMETHOD == MYRFM12_CONF_SETUPMETHOD_STD)
void myrfm12_setup()
{
  /* Setup connection to RFM12 */
  myrfm12_spi_init();

  /* wait until POR is done */
  uint8_t i;
  for (i=0; i<20; i++)
    _delay_ms(10);

  /* Setup basic configration, base frequency, capacitor */
  myrfm12_cmd_config(MYRFM12_CONF_SETUP_BASEFREQ|MYRFM12_CONF_SETUP_CAPACITOR|MYRFM12_CMD__CONFIG__RXFIFO_ON|MYRFM12_CMD__CONFIG__TXFIFO_ON);

  /* Setup power management, enable oscillator pin */
  myrfm12_cmd_powermanagement(MYRFM12_CMD__POWER__ENABLEOSCILLATOR);

  /* Setup frequency */
  myrfm12_cmd_frequencysetting(MYRFM12_CONF_SETUP_ADDFREQ);

  /* Setup baud rate */
  myrfm12_cmd_datarate(MYRFM12_CONF_SETUP_BAUDRATE);

  /* Setup receiver part */
  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);

  /* Setup data filer */
  myrfm12_cmd_datafilter(MYRFM12_CMD__DF__CLKRECAUTOLOCK_ENABLE | MYRFM12_CMD__DF__DQDTHRESH(3) | MYRFM12_CMD__DF__FILTERTYPE_DIGITAL);

  /* Setup the fifo */
  myrfm12_cmd_fifo(MYRFM12_CMD__FIFO__FIFOIRLEVEL(8)| MYRFM12_CMD__FIFO__HSRESETMODE_ENABLE | MYRFM12_CMD__FIFO__FIFO_FILL);

   /* Setup the AFC */
  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);

  /* Setup TX power,frequency deviation,modulation polarity */
  myrfm12_cmd_modulation_power(MYRFM12_CONF_SETUP_POWER,MYRFM12_CONF_SETUP_FREQDEV,MYRFM12_CONF_SETUP_MODULATIONPOLARITY);

  /* Setup Wakeup */
  myrfm12_cmd_wakeuptimer(MYRFM12_CMD__WAKEUP__BASE(0)|MYRFM12_CMD__WAKEUP__EXPONENT(0));

  /* Setup low duty cycle */
  myrfm12_cmd_lowdutycycle(MYRFM12_CMD__LOWDUTY__DUTY(0));

  /* Setup Low Battery Detector and clock divider */
  myrfm12_cmd_lowbatandclockdivider(MYRFM12_CMD__LOWBATCLOCK__CLOCK_10MHZ|MYRFM12_CMD__LOWBATCLOCK__LOWBATVOLT(0));
}
#endif

void myrfm12_ready()
{
  cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_SDI);
  cbi(MYRFM12_CONF_PORT, MYRFM12_CONF_CS);
  asm("nop");
  while (!(MYRFM12_CONF_PIN&(1<<MYRFM12_CONF_SDO)));
}

void myrfm12_sendsyncrobytes()
{
  uint8_t i;
  for(i=0;i<3;i++)
  {
    myrfm12_ready();
    myrfm12_trans(0xB8AA);
  }
}

void myrfm12_sendsyncbytes()
{
    myrfm12_ready();
    myrfm12_trans(0xB82D);
    myrfm12_ready();
    myrfm12_trans(0xB8D4);
}

void myrfm12_txdata(uint8_t* data, uint8_t number)
{
  MYRFM12_CONF_SETUP_TX_START

  /* Enable transmitter */
  myrfm12_cmd_powermanagement(MYRFM12_CMD__POWER__ENABLEOSCILLATOR | MYRFM12_CMD__POWER__ENABLETRANSMITTER | MYRFM12_CMD__POWER__ENABLESYNTHESIZER);

  /* Send Syncro Bytes */
  myrfm12_sendsyncrobytes();

  /* Send Sync Bytes */
  myrfm12_sendsyncbytes();

  /* Send Length Byte */
  myrfm12_ready();
  myrfm12_cmd_txbyte(number);

  /* Send Data */
  uint8_t i;
  for (i=0; i<number; i++)
  {
    myrfm12_ready();
    myrfm12_cmd_txbyte(*data++);
  }

  /* Send Syncro Bytes */
  myrfm12_sendsyncrobytes();

  _delay_us(10);

  /* Disable transmitter */
  myrfm12_cmd_powermanagement(MYRFM12_CMD__POWER__ENABLEOSCILLATOR);

  MYRFM12_CONF_SETUP_TX_STOP
}

Verwenden tue ich ihn so:
myrfm12_setup();

unsigned char test[]="This is a myrfm12 test.";
for (;;)
{
    myrfm12_txdata(test,23);

    //<uart_puts_P("sende...\n");
    for ( i=0; i<100; i++)
      _delay_ms(10);
}



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:
/*! \def MYRFM12_PORT
     *  \brief Port of the AVR on which the module is connected to */
    #define MYRFM12_CONF_PORT    PORTB
    /*! \def MYRFM12_DDR
     *  \brief Data direction register of the used port */
    #define MYRFM12_CONF_DDR      DDRB
    /*! \def MYRFM12_PIN
     *  \brief Pin assignment */
    #define MYRFM12_CONF_PIN    PINB
    /*! \def MYRFM12_SDI
     *  \brief The Pin-Number of the AVR that is connected with the SDI-Pin MOSI
     *  of the RFM12 */
    #define MYRFM12_CONF_SDI    5
    /*! \def MYRFM12_SCK
     *  \brief The Pin-Number of the AVR that is connected with the SCK-Pin SCK
     *  of the RFM12 */
    #define MYRFM12_CONF_SCK    7
    /*! \def MYRFM12_CS
     *  \brief The Pin-Number of the AVR that is connected with the nSEL-Pin
     *   of the RFM12 */
    #define MYRFM12_CONF_CS      4
    /*! \def MYRFM12_SDO
     *  \brief The Pin-Number of the AVR that is connected with the SDO-Pin MISO
     *   of the RFM12 */
    #define MYRFM12_CONF_SDO    6
    /*! \def MYRFM12_NIRQ
     *  \brief Optional Pin-Assignments; The Pin-Number of the AVR that is
     *  connected with the nIRG-Pin of the RFM12 */
    #define MYRFM12_CONF_NIRQ    3

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

Autor: Claudio H. (Firma: BLS-Electronics) (hedie)
Datum:

Bewertung
0 lesenswert
nicht 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 :)

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :-(

Autor: Claudio H. (Firma: BLS-Electronics) (hedie)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: Claudio H. (Firma: BLS-Electronics) (hedie)
Datum:

Bewertung
0 lesenswert
nicht 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 :)

Autor: Mirko (Gast)
Datum:

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

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: R. W. (quakeman)
Datum:

Bewertung
0 lesenswert
nicht 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/

Autor: Claudio Hediger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mirko schrieb:
> Hedie scheint mich leider vergessen zu haben :-(

Sorry.... Du hast post :)

Autor: Claudio Hediger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat es egklappt mit meiner Software?

Autor: tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Mirko (Gast)
Datum:

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

Autor: Claudio Hediger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Merkwürdig...

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.