Archiv verlassen und diese Seite im Standarddesign anzeigen : Daten per Funk hin und her senden...
So.
Habe nu nach einigem Basteln ein relativ zuverlässige Funksendeeinheit programmiert.
kann zwar immer nur 4 Bytes auf einmal senden (warum auch immer), doch das ist ja simpel zu umgehen, indem man die Nachricht in 4-Byte-Blöcke zerlegt und dann wegsended.
Nich schön, funktioniert aber.
Ich will nun Daten empfangen, aber da gehe ich scheinbar falsch an die Sache ran.
Hat wer von euch schon mal versucht, so etwas zu programmieren?
Wenn ja, womit; wie seid ihr da rangegangen?
BGMF
:D
Das ist ja sehr lustig . . .
Ich hab zwar noch ncihts dergleich programmiert, aber ich glaube auch nicht, dass dir so jemand helfen kann. Du hast ja eigentlich überhaupt nciht beschrieben wie deine Funksende Einheit aussieht, geschweige denn wie sie funktioniert.
Und was beim empfangen nicht funktioniert hast du auch nciht geschrieben . . . :D Ich glaube nicht, dass dir so viele bei deinem Problem helfen können. :D
Schreib dass doch noch ein bisschen. ;)
Andun
Ist das lustig?
War nicht beabsichtigt...
Aber schön, wenn ich dich unterhalten konnte :-)
Aber zurueck zum Thema:
Mir ging es wirklich eher darum, ob jemand von euch schon so etwas gemacht hat und wenn ja mit welchen Mitteln.
Hab mich da vieleicht, sprich bestimmt, etwas doof ausgedrueckt.
Es ging mir alse eher um allgemeine Tipps, an denen ich vieleicht erkenne, wo mein Denkfehler liegt.
Aber zurueck zur Hardware:
Es handelt sich dabei um die Programmierung eines ATmega128, den ich via SPI dazu ueberreden will sowohl Daten zu senden, als auch zu empfangen.
Zum Uebertragen und Empfangen nutze ich das nRF2401 EVBOARD von Nordic Semiconductors ( http://www.nvlsi.no/ ).
Als Programmierumgebung nutze ich IAR Embedded Workbench IDE und IARs MakeApp hat mir das Grundgeruest mit allen möglichen voreinstellungen und Makros geliefert.
Da weis ich aber, dass es da noch Probleme gibt und da ich eher Anfänger in der HW-Programmierung bin, sehe ich sie oftmals schlichtweg nicht!
Hier mal etwas Code:
void SendAndWait( U8 data )
{
if ( MA_OK != MA_PutChar_SPI( data ) );// cout<<"DAMN!";
//else cout<<"OK! ";
while( MA_OK!=MA_TestChar_SPI() );
//cout<<"LOOP DONE!";
}
void Init_Ism( int send )
{
PORTB |= 0x20; //CS = 1
wait(200); //wait
//char Init_ShockBurst_DATA2W[8]= how much bits do you send? see send-function!
SendAndWait( 0x20 ); //I decided to leave this value unmodified, but write a function, that send only four bytes - 32 bits!
//char Init_ShockBurst_DATA1W[8]=
SendAndWait( 0x20 );
//char Init_ShockBurst_ADDR2[40]= Adress Channel 2
SendAndWait( 0xBB); SendAndWait( 0xBB); SendAndWait( 0xBB);
SendAndWait( 0xBB); SendAndWait( 0xBB);
//char Init_ShockBurst_ADDR1[40]= Adress Channel 1
SendAndWait( 0xBB); SendAndWait( 0xBB); SendAndWait( 0xBB);
SendAndWait( 0xBB); SendAndWait( 0xBB);
//char Init_ShockBurst_ADDRW[6]=
//{0,0,1,0,0,0};
//char Init_ShockBurst_CRC[2]=
//{0,1};
SendAndWait( 0xA1);//84 Binary Add ADDRW & CRC
//char Init_ShockBurst_RFPROG[16]=
//{0,1,0,0,1,1,1,1,0,0,0,0,0,1,0,0}; divide into 2 Byte á 8 bit and send away
SendAndWait( 0x4F);
if ( send == 1 ) SendAndWait( 0x04); //to receive, switch last bit to 1, 0 means transmit
if ( send == 0 ) SendAndWait( 0x05);
PORTB &= ~(0x20); //set CS = 0
wait(200); //wait
}
void sendMsg( char *string )
{
char part[4] = { ' ', ' ', ' ', ' ' };
int length;
int i;
//Message to UART0
cout<<"Sending Message...\n";
length = strlen( string );
for( i = 0; i<length; i++ )
{
if ( i == 0 )
part[0] = string[i];
if ( (i % 4) == 1 && i != 0 )
part[1] = string[i];
if ( (i % 4) == 2 && i != 0 )
part[2] = string[i];
if ( (i % 4) == 3 && i != 0 )
part[3] = string[i];
if ( (i % 4) == 0 && i != 0 )
{
sendMsgPart( part );
part[0] = ' '; part[1] = ' ';
part[2] = ' '; part[3] = ' ';
part[0] = string[i];
}
}
sendMsgPart( part );
//Show the transmitted message
cout<<string<<"\n";
}
void sendMsgPart( char *string )
{
PORTB |= 0x10; //CE = 1
wait(200);
//ShockBurst_ADDR1[40]=
//{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
//0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
//1,1,1,0,0,1,1,1}; prepare the Addess Channel to send some information
SendAndWait(0xBB);
SendAndWait(0xBB);
SendAndWait(0xBB);
SendAndWait(0xBB);
SendAndWait(0xBB);
//lähetettävä viesti Send your information here
SendAndWait( string[0] );
SendAndWait( string[1] );
SendAndWait( string[2] );
SendAndWait( string[3] );
//cout<<string;
PORTB &= ~(0x10); //CE = 0
wait(200);
}
void wait( unsigned long tmr_ms )
{
__tmr_ms=0; //global variable
MA_Start_TMR( 0, 1 ); //parameters: channel & reset on start
while(__tmr_ms !=tmr_ms); //wait
MA_Stop_TMR( 0 ); //no comment
}
SendAndWait ist eine SPI-Funktion und macht genau das, was der Name sagt.
Wie man später in der Init_Ism-Funktion sieht, sendet sie die Infomationen an die Funkstrecke.
Diese Funktion, Init_Ism, funktioniert auch tadellos bei der Initialisierung zum senden, rein theoretisch, laut der Doku die man zum nRF2401 findet, sollte es alles bis auf das letzte Bit so bleiben, wenn man emfangen will, aber ich glaube, dass genau hier was nicht hinhaut.
Ich denke, die anderen Funktionen muss ich nicht erklären.
So ich hoffe, dass hilft jetzt weiter!
Falls nicht: Machts wie Andun - schreibts!
Vielen Dank
BGMF
edit:
Da fällt mir noch ein:
char *getString( void )
{
char *string;
char singleChar;
int i = 0;
while( 1 )
{
singleChar = MA_GetChar_SPI();
if ( singleChar == 0 )
break;
string[i] = singleChar;
i++;
}
cout<<string;
return string;
}
Meine "Vom-SPI-Empfangs"-Funktion...
Die is doch bestimmt Gruetze, oder?
Kritiken und Anmerkungen ausdruecklich Erwuenscht!
edit^2:
Man bin ich ne Pfeife (darauf möchte ich keinen Kommentar hören, bitte!)
Hier noch meine Main-Funktion:
void main( void )
{
char *string;
MA_Init_CPU();
MA_Init_SPI();
MA_InitCh0_USART();
MA_Reset_SPI();
MA_Init_IO();
MA_Init_TMR();
__enable_interrupt();
DDRB |= 0x30; //Prepare the DDRB for input of the CS and CE signal
wait(100); //wait, maybe not neccessary
//Init_Ism( 1 );
//sendMsg( "This is a teststring!" );
Init_Ism( 0 );
PORTB |= 0x10; //CE = 1
wait(200);
while( 1 )
{
if ( PINB & 0x40 )
{
//while ( cout<<MA_GetChar_SPI() );
//break;
string = getString();
if ( string != "" ) break;
}
}
PORTB &= ~(0x10); //CE = 0
wait(200);
} /* main */
Ne kurze Erklärung ist hier noch fällig, glaube ich:
CS, das is in der Init-Fkt zu finden, sagt dem nRF2401, dass jetzt Konfigurationsdaten kommen, die also nicht weggesendet werden muessen.
CE bedeutet, jetzt ist Zeit fuer Daten, sowohl beim senden, als auch beim Empfangen.
Die Aktion mit (PINB & 0x40) sagt aus, das auf ein "Startsignal" von der Funkstrecke gewartet wird, dort wird ein Bit gesetzt, nennt sich DR1, welches ich vom 5ten Pin am Port B ablesen will.
Ich hatte an dieser Stelle vorher nur (PORTB & 0x40) zu stehen, das hat nicht geklappt, jetzt springt er da rein - also scheint die Konfiguration doch zu stimmen.
Bleibt die Frage: Was empfängt er? Empfängt er ueberhaupt? Wie komme ich an die Daten ran... Puh...
Meine "Vom-SPI-Empfangs"-Funktion...
Die is doch bestimmt Gruetze, oder?
Kritiken und Anmerkungen ausdruecklich Erwuenscht!
Diese Funktion hab ich jetzt mal in zwei unterteilt:
char *getString( void )
{
char *string;
char singleChar;
int i = 0;
while( 1 )
{
singleChar = getChar();
if ( singleChar == 0x00 )
break;
string[i] = singleChar;
i++;
}
cout<<string;
return string;
}
char getChar( void )
{
char r;
while ( MA_OK != MA_TestChar_SPI() );
r = MA_GetChar_SPI();
return r;
}
Es läuft jetzt bis zu der While-Schleife in der getChar-Fkt., doch aus dieser kommt er nie heraus!
Ich habe mal nachgeschaut und in der entsprechenden c-Datei fuer das ganze SPI-Zeug steht, das ich fuer die MA_GetChar_SPI-Fkt. halt die MA_TestChar_SPI-Fkt. nutzen soll, doch hängt er scheinbar immer in dieser sich an dem SPIF-Flag auf (im AVRStudio hab ich gesehen, dass dieses nie gesetzt wird)
Hier mal die TestChar-Fkt.:
S8 MA_TestChar_SPI( void )
/*
**---------------------------------------------------------------------------
**
** Abstract:
** Test if serial transfer is complete.
**
** Parameters:
** None
**
** Returns:
** MA_OK Serial transfer is complete
** MA_EMPTY Serial transfer is not complete
**
**---------------------------------------------------------------------------
*/
{
S8 Status;
/*--- Handle user code on function entry ---*/
ENTER_MA_TESTCHAR_SPI;
if( SPSR & __BIT_MASK( SPIF ) )
{
/*--- Serial transfer is complete ---*/
Status = MA_OK;
}
else
{
/*--- Serial transfer is not complete ---*/
Status = MA_EMPTY;
}
/*--- Handle user code on function exit ---*/
EXIT_MA_TESTCHAR_SPI;
/*--- Thread safe return ---*/
return Status;
} /* MA_TestChar_SPI */
Ich schau hier echt wien Schwein ins Uhrwerk, wenn ihr nen Tipp habt...
BITTE MELDEN!!!
BGMF[/b]
Boah,
schreibt nur nicht alle auf einmal!
:-/
Aber erst ma Wurscht, ich hab nun weiter gebastelt, die getChar-Fkt. ein wenig umgeschrieben
char getChar( void )
{
char r;
MA_PutChar_SPI( 0x00 );
while ( MA_OK != MA_TestChar_SPI() );
r = MA_GetChar_SPI();
return r;
}
und jetzt empängt er wenigstens schon irgendwas.
Auch wenn das totaler Muell ist (ich sende "test" er empfäng "øþ " auf dem Hyperterminal), gebe ich die Hoffnung natuerlich nicht auf, doch noch vernuenftige Daten zu empfangen.
Falls irgendwer noch was beizusteuern hat, ich wuerde mich darueber freuen, falls nich....
Am ende, wenn es irgendwann mal laufen sollte, kann ich ja, wenn interesse besteht den Quelltext mal halbwegs ordentlich Dokumentieren und dann mal hochladen.
Sagt bescheid.
BGMF
P.S.: Hilfe ist wirklich gern gesehen, auch wenn vieleicht keiner von euch so was schon mal gemacht hat, so habt ihr doch garantiert, den einen oder anderen sinnvollen Vorschlag, oder?
Hallo,
ich kom einfach nicht mit dem Empfang klar.
Auch wenn es zwischendurch schon mal so aus sah, als wuerde es langsam in die richtige Richtung weitergehen, so kam das Ganze nun doch wieder zum erliegen.
Etwas, das eigentlich schon mal richtig funktuioniert hat, macht nun wieder Probleme:
Meine "receiveAndWait()"-Funktion soll eingentlich nur warten, ob eine Nachricht ankommt, und wenn ja, dann soll diese ausgegeben werden.
Theoretisch fäng eine Nachricht dann an, wie ich schon mal erwähnte, wenn DR1 vom nRF2401 gesetzt wird, bei mir auf PINB.6 (also 0x40 - fängt man bei null oder eins an zu zählen? Ich geh mal von null aus).
Bei mir im Code...
void receiveAndWait( void )
{
char *_string;
//char r;
delay(2);
PORTB |= 0x10; //CE = 1
delay(2);
wait(250);
delay(2);
while ( !(PINB & 0x40) );
//if ( PINB & 0x40 )
//{
//while ( r = getChar() ) cout<<r;
//break;
_string = getString();
//if ( _string != "" ) break;
//}
//cout<<MA_GetChar_SPI();
cout<<_string;
cout<<"\n";
PORTB &= ~(0x10); //CE = 0
wait(250);
}
...aber, wird mysteriöserweise der Wert 1 gesetzt, sobald CE=1 gesetzt worden ist, also auf Emfang gestellt wurde - das sollte so nicht sein...
Ich versteh es nicht mehr!
Wenn jemand Rat wuesste.... Bitte!
BGMF
SprinterSB
07.11.2005, 12:16
Wie sieht denn getString() aus?
Die sieht noch genauso wie zwei Einträge höher aus.
(Unter dem Zitat)
Hab grade trotz einigermassen viel Debuggen nicht herausgefunden, warum grad nach dem Befehl "PORTB |= 0x10;" PINB.6 gesetzt wird.
Puh. Also ich kapier's echt nicht mehr...
SprinterSB
07.11.2005, 13:05
string zeigt doch auf keinen definierten Speicherbereich, oder irr ich mich da? Auch wenn da nicht dein Fehler ist, aber wenn du so was machst, kann string irgendwohin zeigen und du überpinselst irgendwo irgendwelche Datem im RAM.
Jep, jetzt wo du's sagtst.
Da hast du recht, hatte das auch schon mal geändert, ich hatte irgendwann ja schon mal irgendwelchen Datenmuell ausgegeben bekommen, daraufhin habe ich - zu Testzwecken - daraus ein char-Array gemacht, dessen grösse ich auf 4 beschränkt habe und mir selbst gesagt, ich versuch erst mal nur 4 Bytes zu empfangen.
Das ist beseitigt.
Was das andere angeht. Tja. Irgendwie schon seltsam, da es ja so schon mal funktioniert hat und auf das Signal gewartet hat.
Muss vieleicht nochmal die Verdrahtung checken, vieleicht hab ich da was falsch gemacht...
BGMF
Also die Verdrahtung muss stimmen.
Sie sieht bei mir wie folgt aus (Anmerkung - SPI!!!):
AVR --- nRF2401 EVBOARD
--------------------------------------------------------
PORTB.0 = SS* ---
PORTB.1 = SCK --- PIN 3 - CLK1
PORTB.2 = MOSI --- PIN 1 - DATA
PORTB.3 = MISO --- PIN 1 - DATA
PORTB.4 --- PIN 12 als CE
PORTB.5 --- PIN 6 als CS
PORTB.6 --- PIN 5 als DR1
PORTB.7 ---
PORTB.8 = GND --- PIN 16 - GND
PORTB.9 = PWR_UP --- PIN 13 - PWR_UP
senden tut er, wie gesagt.
Als Anhang mal nen Paper von der Sende-/Empfangseinheit.
SprinterSB
07.11.2005, 14:06
Hast du SS als OUT?
Die Verwirrung, ob 0x40 bit 6 ist oder nicht, vermeidest du. indem du anstatt 0x40 zB hinschreibst (1<< PB6). Welche defines es gibt, siehst du in deiner ioxxxx.h. Welcher AVR ist es denn?
Hm.
Ja, ich denke, das SS* als out ist - ja - definitiv; hab grad noch mal in AVRStudio nach dem DDRB geschaut und da ist das auf 1, also out gesetzt.
Gut, ok, dass mit dem Pin ist wohl EyeCandy, dass werde ich später machen, erst einmal will ich verstehen, was hier schief läuft...
Ich nutze den ATmega128.
So und fuer heute mach ich mal Schluss.
Hab mich mit dem Teil den ganzen Tag rumgeärgert.
Antworten bekomm ich natuerlich gerne, aber beantworten werde ich sie sicher erst morgen - sorry!
BGMF
So.
Hallo nochmal!
Die Lösung kam leise daher - nach Tagen eigentlich sinnlosen Rumprobierens, wurde ich heute auf eine Funktion der "ma_spi.c" hingewiesen, die eine Richtung des MOSI-Pins angibt (halt in- oder output).
Gesagt getan, wurde diese mal schnell in die getChar-Methode rein geschrieben - und siehe da: Es ging!
Ich galub es nicht, das Ärgerliche ist, das ich diese Funktion schon letzte Woche sah, aber sie als nicht Sinnvoll einstufte, da ich doch mit dem MISO-Pin Daten reinbekomme (dachte ich)...
So was Ärgerliches!
Also wenn jemand Interesse an dieser (leider noch unkommentierten) Lösung hat, könnte ich das ganze gezipt mal hier rein stellen (mit Bilbiotheken und allem was dazu gehört...).
Ich weiss, dass das kein ordenlticher Stil ist, aber die Doku wuerde ich dann später nachschieben und auch hier veröffentlichen.
Natuerlich nur wenn Interesse besteht...
BGMF
tristate
09.11.2005, 14:42
also ich hätte da ein gewisses interesse dran...
doch bräucht noch so ein paar infos:
woher hast du das board? selbstgebaut(ist ja in dem pdf genauestens beschrieben)? wenn ja was kostet der chip/board?
wie siehts mit der max reichweite aus? sendet ja auf 2,4GHZ
überhaupt erlaubt?
spinnt dann mein wlan router?
fragen über fragen...
mfg
SprinterSB
09.11.2005, 14:45
2,4 GHz? Da sendet meine Mikrowelle ;-)
tristate
09.11.2005, 14:51
das wär mal zu überlegen
ob man wohl eine alte mikrowelle zu nem transceiver umbauen kann...
mit der leistung kommt man bestimmt ziemlich weit...:Haue
Sorry, dass ich gestern nicht mehr geantwortet habe, aber mein Laptop spinnt grade rum, deswegen kann ich erst jetzt wieder von der Arbeit was schreiben...
Auf der Seite http://www.nvlsi.no/index.cfm?obj=product&act=display&pro=64 findet ihr alle notwendigen Informationen zu diesem Chipsatz.
Da ich das Board in der Form, wie es im PDF beschrieben wurde, hier auf Arbeit zur Verfuegung gestellt bekommen habe, kann ich nicht sagen, wie hoch der Preis ist.
Allerdings wird auf der o.g. Seite immer wieder betont, wie kostenguenstig dieser Chip ist...
Tut mir leid, dass ich da leider nicht weiterhelfen kann!
Ich habe auf jeden Fall gelesen, dass die Frequenzen, die man in diesem Bord einstellen kann, alle freigegeben sind, also sollte es kein Problem sein, damit zu Senden bzw. zu Empfangen, ausserdem ruehmt sich der Hersteller damit, welche grosse Unternehmen, wie Logitech, diesen Chipsatz fuer ihre Wireless-Anwendungen verwenden.
Ich denke, da dass eine Niedrig-Energie-Lösung ist, wird die Reichweite stark begrenzt sein.
Hier in der Entwicklungsumgebung senden wir etwa 2 Meter, wie es sich darueber hinaus verhält - tut mir leid, dass weiss ich nicht.
Auch habe ich darauf auf den o.g. Seiten nichts gefunden - falls jemand dort etwas findet, kann er ja gerne den Link posten - interessieren wuerde es mich auch schon.
Ich glaube kaum, dass ein WLAN-Router davon beeinträchtig wird, da sowohl die Sendeleistung sehr gering ist, als auch das Frequenzspektrum von WLAN weit oberhalb von 2,4 GHz liegt - bei irgendwas von 5 GHz, glaube ich.
So, ich hoffe, ich konnte ein wenig weiter helfen!
Zum Programm:
Das Grundgeruest wurde mittels IARs MakeApp erstellt (bietet schon vielfältige Konfigurationsmöglichkeiten).
Bearbeitet habe ich das Ganze mit IARs Embedded Workbench IDE.
Mittels Atmels AVR Studio und nem JTagIce Mk II hab ich dann das Board programmiert.
Genutzt wird SPI (PortB) und jetzt bin ich grad noch dran, das ganze ueber Interrupt 7 (PortE.7) als eine Art Exception zu machen, dass er auf ein Signal lauscht.
An dieser Stelle angemerkt sollte vieleicht angemerkt werden, dass der Compiler auch mit C++ klarkommen sollte (Einstellungen), da ein Befehl aus C++ entnommen wurde.
Ich hoffe, dass ich alle IAR spezifischen Bibliotheken hinzugefuegt habe, falls etwas fehlt, sagt bescheid.
(Im Unterverzeichniss IAR sind alle Libs, von denen ich denke, dass sie notwendig sind.)
Ein kleines Update:
Ich habe jetzt mal etwas Quellcode-Documentierung im Doxygen-Stil gemacht (lehnt nich mitunter recht start an JavaDoc an und kommt mit nem kleinen Programm daher, welches einem mittelprächtige HTML- oder andere Stile als ausgabe anbietet).
Ich hab nicht benötigte Funktionen gelöscht und die Sende-Funktion stark abgespeckt, da es mir hier mehr um Testzwecke ging, nichtsdestotrotz sollte es auch mit dieser sehr leicht sein, zu verstehen, wie es funktioniert, ausserdem gibts immer noch die alte Version zum Download.
Ebenso enthalten ist die HTML-Variante der Doku, mal ganz nett sich das mal anzuschauen.
Viel Spass damit!
BGMF
P.S. Erwartet aber keinen Meilenstein in der Geschichte der Quellcode-Dokumentierung!
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.