Hi an all die Profis,
Ich habe Probleme mit meinen Code und komme einfach nicht weiter.
Ich nutze ein Mega als Master und ein Nano als Slave. Der Master sendet
Text zum Slave, dieser kommt auch an und der Slave soll ein Text
zurücksenden doch beim Master kommt nur genau das an was der Master
sendet.Das der Slave was sendet muss ok sein, da der Master beim nicht
senden kein Text zusammensetzten kann. Sendedaten und Empfangsdaten
haben aber keinen Bezug. Weswegen der Master dann aber das zusammensetzt
was er sendet ist für mich nicht nachvollziehbar. Hier der Code:
//Master
#include <SPI.h>
volatile boolean senden;
volatile char Paket_vom_Slave;
volatile char Paket_zum_Slave;
char buf [100];
volatile byte pos;
String Paket = "";
void setup (void)
{
Serial.begin(9600);
// pinMode(53, OUTPUT);
pinMode(SS, OUTPUT);
// digitalWrite(SS, HIGH); //SS Pin auf HIGH setzten
SPI.begin (); //Verbindung starten
SPI.setClockDivider(SPI_CLOCK_DIV8); //Geschwindigkeit verlangsamen
}
void loop (void)
{
//Text_erstellen();
digitalWrite(SS, LOW); //starten der Kommunikation mit Slave
for (const char * p = "TxT v Master\n" ; Paket_zum_Slave = *p; p++)
{
//Text_erstellen();
Paket_vom_Slave = SPI.transfer(Paket_zum_Slave); //senden von Text
Text_erstellen();
delayMicroseconds (500);
Serial.print("sent: ");
Serial.print(Paket_zum_Slave);
Serial.print("\t empfangen: ");
//Serial.println(Paket_vom_Slave);
Serial.println(Paket);
delay(200);
}
digitalWrite(SS, HIGH); //beenden der Kommunikation
delay (1000); //kurze pause
}
void Text_erstellen()
{
if (pos < sizeof buf)
{
char c = Paket_vom_Slave; //kopieren der Daten von SPI Buffer
buf [pos++] = c; //hinzufuegen des naechsten Zeichens
if (c == '\n')
senden = true;
}
if (senden)
{
buf[pos] = 0;
Paket = (buf);
Paket.trim();
Serial.println (("empfangen :--->") + (Paket));
Serial.println (("empfangen :--->") + (Paket));
Serial.println (("empfangen :--->") + (Paket));
pos = 0;
senden = false;
}
}
//Slave
#include <SPI.h>
volatile boolean senden;
volatile boolean versandbereit;
//volatile byte Paket_Master,Sendung_Slave;
volatile char Paket_Master;
volatile char Sendung_Slave;
String Paket = "";
String Sendung = "";
int i = -1;
char buf [20];
char buf1 [20];
volatile byte pos;
volatile byte pos1;
void setup(void)
{
Serial.begin(9600);
// pinMode(12, OUTPUT);
pinMode(MISO, OUTPUT);
SPCR |= _BV(SPE); // turn on SPI in slave mode
//SPCR |= bit (SPE);
senden = false;
SPCR |= _BV(SPIE); // turn on interrupts
SPI.attachInterrupt();
}
void loop(void)
{
if ((versandbereit) == false);
{
Paket_Text();
}
if (senden)
{
i = i + 1;
buf[pos] = 0;
Paket = (buf);
buf1[pos] = 0;
Sendung = (buf1);
if (i == 12)
{
SPDR = "\n";
}
else
{
SPDR = (buf1[i]);
}
Paket.trim();
Sendung.trim();
Serial.println (("empfangen :--->") + (Paket));
Serial.println (buf1[i]);
Serial.println (i);
Serial.println (("gesendet :--->") + (Sendung));
pos = 0;
senden = false;
}
if (i == 12) i = -1;
}
ISR(SPI_STC_vect)
{
byte c = SPDR; //kopieren der Daten von SPI Buffer
if (pos < sizeof buf)
{
buf [pos++] = c; //hinzufuegen des naechsten Zeichens
if (c == '\n')
senden = true;
}
}
void Paket_Text()
{
if (pos1 < sizeof buf1)
for (const char * p = "Paket--Slave\n" ; char c = *p; p++)
{
buf1 [pos1++] = c;
Serial.println (buf1);
if (c == '\n')
versandbereit = true;
}
}
Bin zwar kein Arduino-Profi, arbeite meistens direkt auf Register level
mit Microcontrollern aber versuche mal hier zu helfen.
Der erste Tipp den ich habe ist, dass du das nächste Datenbit beim Slave
schon im Interrupt in das SPDR schreibts. Denn sonst kann es passieren,
dass der Slave in der main loop den SPDR setz code nicht zwischen 2 SPI
transfers erreicht.
Aber das kann ja nicht das eigentliche Problem sein. Schau nochmal ob du
beim Slave MISO als output gesetzt hast. Dass der Master das gleiche
empfängt kann nämlich auch an der verkabelung liegen. Wenn zwei
Leitungen nebeneinander laufen (was bei dir der Fall sein wird) dann
gibt es dazwischen Übersprechen, besonders wenn eine auf beiden Seiten
Eingänge (hochohmig) hängen hat, und die andere halbwegs hohe Frequenzen
(sieht ja nach 2MHz aus) hat. Sonst auch noch mal die Steckverbindung
selbst überprüfen.
So geht das nicht.
Beim Senden muß der Slave nach jedem Byte warten, bis der Master es
abgeholt hat (Interrupt Flag).
Und der Master muß nach jedem Byte eine Wartezeit abwarten, damit der
Slave das nächste Byte in SPDR schreiben kann. Die AVRs haben nämlich
keinen Sendebuffer.
Kannst du mir ein Tipp gegen wie ich das in meinen Code wo und wie
einsetzen kann ich glaube auch das rs das ist. Leider bin ich hier sehr
unerfahren hab versucht mich schlau zu lesen komme aber nicht weiter.
Ich komme langsam voran :-)
Aber hab momentan ein Problem mit der Datenübergabe.
Ich übergebe beim Start: char Paket_zum_Master [50] = "Starten vom
Slave.";
und ändere in der SPI interrupt routine den Inhalt in "neuer Text"
Gesendet wird aber "Starten vom Slave."
Wie muss ich das ändern.
1
// Slave
2
charPaket_zum_Master[50]="Starten vom Slave.";
3
volatileintpos;
4
volatileboolactive;
5
StringSend_Paket;
6
7
8
ISR(SPI_STC_vect)// SPI interrupt routine
9
{
10
Send_Paket="neuer Text";
11
charSendung=((Send_Paket+"\n").c_str());
12
Paket_zum_Master[50]=Sendung;
13
bytec=SPDR;
14
if(c==1)// starting new sequence?
15
{
active = true;
pos = 0;
SPDR = Paket_zum_Master [pos++]; // sendet erste byte
return;
}
if (!active)
{
SPDR = 0;
return;
}
SPDR = Paket_zum_Master [pos];
if (Paket_zum_Master [pos] == 0 || ++pos >= sizeof (Paket_zum_Master))
active = false;
} // end of interrupt service routine (ISR) SPI_STC_vect
Dieter T. schrieb:> Wie muss ich das ändern.
Wie musst du was ändern um was zu erreichen?
Das schaut so schrecklich und chaotisch aus dass man wirklich
keine Lust hat darauf einzusteigen.
Bring erst mal Ordnung und Übersicht in dein Leben und deine
Programmier-Planung sowie die Code-Darstellung.
Ich denke, du solltest dringend zuerst auf einem PC die Sprache C
lernen, dann C++, dann die Besonderheiten von Arduino.
Das hier macht nie und nimmer das, was du erwartest:
he: Auh Weia "Bring erst mal Ordnung und Übersicht in dein Leben " ist
ja wohl eine sehr persönliche Aussage, die muss ich mir von sone Wurst
bestimmt nicht sagen lassen.
Bin 60 Jahre alt und denke, dass ich mein Leben sehr gut im Griff habe.
Zudem hab ich vor 30 Jahren schon einiges programmiert, das war da
leider noch nicht so objekt gebunden, wie es heute ist.
Ich bin vor 1 Monat wieder angefangen mich mit Programmieren zu
beschäftigen und momentan erschlagen mir förmlich die Mengen an
Funktionen.
Aber ganz abgesehen davon:
Es gibt im Netz kein vernünftiges Beispiel einer SPI Übertragung, wo der
Master ein String überträgt und gleichzeitig ein String empfängt.
Es bietet sich hier ja an, gemeinsam was vernümftiges zusammenzustricken
und sei es nur dafür, das ein anderer es nutzen kann.
Und Stefanus F. mein Code ist außer die Variabel Namen ein Code von Nick
Gammon und er funktioniert auch. Ich glaube so unübersichtlich
programmiert Nick Gammon auch nicht.
Was ich momentan ändern will, ist das der String der oben deklariert ist
variabel änderbar ist.
Bin ich irgendwo von der Welt Stefanus, ich weiss das irgendwo ein
Fehler ist deswegen bin ich ja hier. In der Regel erwartet man ja
Unterstützung und nicht eine Aussage wie oben das man erst mal sein
Leben in Ordnung bringen soll. Und auch keine Aussage das da ein Fehler
drin ist. Sondern wo der Fehler sein könnte und wie man ihn beseitigt.
Ich glaub Stefanus auf deine Hilfe kann ich auch gut verzichten.
Dieter T. schrieb:> Es gibt im Netz kein vernünftiges Beispiel einer SPI Übertragung, wo der> Master ein String überträgt und gleichzeitig ein String empfängt.
Ohhh, es gibt keine fertige Wichsvorlage... Das ist ja richtig
schlimm... Da muss man doch tatsächlich wirklich selber programmieren...
Das Leben kann ja so hart sein...
De facto ist es allerdings so: es gibt Unmassen solcher Beispiele. Man
muss nur wenigstens soviel von der Sache verstehen, dass man sie auch
finden kann. D.h.: man muss ubedingt das Grundkonzept der
SPI-Kommunikation verstanden haben...
> Bin 60 Jahre alt
So what? Gerade mal drei Jahre älter als ich. Nö: das kann ich definitiv
nicht als Ausrede gelten lassen...
Ich bin nichtmal sicher, ob das überhaupt wahr ist. Die KI sagt:
definitiv NEIN, geschätztes Alter 2x. Ich schwanke noch, aus meiner
Sicht: könnte zumindest so sein. In etlichen Fällen musste ich aber
lernen, dass die KI beim Schätzen des Alters deutlich bessere
Trefferraten erzielt als ich selber...
c-hater schrieb:> man muss ubedingt das Grundkonzept der> SPI-Kommunikation verstanden haben...
Dieter, du brauchst die Grundlagen, wie man Zeichenketten in C, C++ und
Arduino verwendet. Mit dem Thema SPI lenkst du oder wirst du vom Kern
des Problems abgelenkt.
Spiele erstmal mit einem ganz "normalen" Arduino Uno Board und der
Serial Klasse herum. Dabei wirst du einiges lernen, was du dann auf die
SPI Klasse übertragen kannst.
Ich habe weiter oben ein paar fragwürdige Zeilen von deinem Quelltext
zitiert. Bringe die mal auf dem Arduino Uno mit der Serial Klasse ans
Laufen. Dann sehen wir weiter.
Dieter T. schrieb:> Gesendet wird aber "Starten vom Slave."> Wie muss ich das ändern.
Aufhören in der ISR irgendetwas zu ändern.
In der ISR wird nur gesendet, bzw. empfangen, die Position wird
geprüft und entsprechende Flags gesetzt.
Alles andere führt meistens zu Fehlern.
Also ihr beiden Profis,
anstatt sich mal mit der Sache zu beschäftigen und mal sich mit ein
Problem überhaupt mal auseinander zu setzen, sucht ihr glaub ich nur
nach irgendwelchen Ausreden, um euer beklopptes Verhalten zu
rechtfertigen.
Nochmal ich suche hier eigentlich nur nach einen Tipp, aber anscheinend
seit ihr selber zu dumm, den Code zu lese.
Ich habe diese beiden Zeilen ausgetauscht und auch wenn ihr beiden es
nicht glauben wollt, es läuft so wie es soll.
Send_Paket = "neuer Text";
strcpy(Paket_zum_Master, Send_Paket.c_str());
Serial.print ("Text vom Slave :----> ");
Ich werde den Code noch ein wenig ausarbeiten und hier als Beispiel
einsetzen, für diejenigen die nach einen guten Beispiel suchen.
Auf weitere Fachmeinungen von euch beiden kann ich gut verzichten.
MfG
Dieter
Dieter_T schrieb:> Der Master sendet Text zum Slave, dieser kommt auch an und der Slave> soll ein Text zurücksenden doch beim Master kommt nur genau das an was> der Master sendet.
Aus deiner Formulierung entspringt ein grundlegendes Verständnisproblem
bzgl. SPI. Über das SPI wird auf Ansage des Masters (Clock vom Master)
zwei Bytes zwischen Master und Slave ausgetauscht. Der Slave sendet
nie selbständig, sondern der Master holt sich etwas vom Slave.
Dieter T. schrieb:> Ich werde den Code noch ein wenig ausarbeiten und hier als Beispiel> einsetzen, für diejenigen die nach einen guten Beispiel suchen.
Ich bin sicher, die weltweite Gemeinde der C-Programmierer wird mit
Begeisterung ihre nun alten und wertlosen Bibliotheken und Programme
wegwerfen und von da an nur deinen ausgezeichneten Code benutzen...
Ich glaube auch, daß hier ein grundlegende Verständnis-Problem vorliegt.
Ganz gut wird das in dieser Grafik erklärt.
Mit jedem Zyklus "tauschen" Master und Slave den Inhalt ihrer
Datenregister.
Entnommen aus dem Ddatenblatt des ATMega328p
Dieter T. schrieb:> Also ihr beiden Profis,> anstatt sich mal mit der Sache zu beschäftigen und mal sich mit ein> Problem überhaupt mal auseinander zu setzen, sucht ihr glaub ich nur> nach irgendwelchen Ausreden, um euer beklopptes Verhalten zu> rechtfertigen.
Meinst du das wirklich ernst? Ich helfe Dir jetzt nicht mehr weiter.
Lerne mal, Dich zu benehmen! Demut und Dankbarkeit wären die ersten
Themen für Dich. Als nächste käme Selbsterkenntnis, denn das ist der
Erste Weg zur Besserung.
Meinst du das wirklich ernst?
Stefanus für dich nehm es zurück, aber das läuft soo, nie!! stimmt ja
auch nicht.
Beim durchlesen hätte ich von einen Profi erwartet, das er auf die
Fehlerstelle hinweist und nicht "das wird nie laufen."
Mittlerweile läuft es super.
"Spiele erstmal mit einem ganz "normalen" Arduino Uno Board"
Also das Netz und die Gruppen bieten sich zusätzlich zum Lernen, an,
auch Fragen zu stellen und so seine Kenntnisse zu erweitern.
Wer sagt denn, dass ich nicht zusätzlich mich auch mit C-Programmierung:
Zeichenkettenfunktionen uvm. beschäftige.
Aber auf eine Frage die Antwort "Lern erst mal....." passt ja auch
nicht.
Hilfreicher wäre einfach nur ein Hinweis in der Sache ein Tipp ...
Dieter T. schrieb:> Hilfreicher wäre einfach nur ein Hinweis in der Sache ein Tipp ...
Da war so viel auf einmal nicht in Ordnung, dass ein "Hinweis" oder
"Tipp" gar nicht möglich war. Zuerst muss man eine gemeinsame Sprache
haben, bevor man miteinander reden kann.
Dieter T. schrieb:> Ich übergebe beim Start: char Paket_zum_Master [50] = "Starten vom> Slave.";> und ändere in der SPI interrupt routine den Inhalt in "neuer Text"
Nein, tust Du nicht.
Du initialisierst mit "Starten vom Slave.", was ein großer Unterschied
ist.
Dann mit "Paket_zum_Master [50] = Sendung;" schreibst Du ein Zeichen
hinter die Variable, d.h. in einen ungültigen Bereich.
Ich kenne mich mit C++ nicht aus, aber in C kopiert man Strings mit
strcpy(). Und die Länge ermittelt man mit strlen(). Schau mal ins Manual
zur <string.h>.
sizeof() gibt Dir nur Anzahl Bytes einer Variablen, in diesem Fall
konstant 50.
Dieter T. schrieb:> ISR (SPI_STC_vect) // SPI interrupt routine> {> Send_Paket = "neuer Text";> char Sendung = ((Send_Paket + "\n").c_str());
Ich hab absolut keine Ahnung, was das bezwecken soll.
Send_Paket = "neuer Text";
strcpy(Paket_zum_Master, Send_Paket.c_str());
Macht mehr Sinn,
Hiermit läuft es auch die Nachricht "neuer Text" wird vom Master
empfangen.
Ich habe beim Slave jetzt die Möglichkeit je nach Ereignis einen
passenden Text vom Master abholen zu lassen.
Peter D. schrieb:> Ich hab absolut keine Ahnung, was das bezwecken soll.
Wann wirst auch du begreifen dass du einen Troll fütterst?
Oder ist das reine Absicht? Sorry, so blind kann keiner sein.
Aber vielleicht gehörst du zu der Seite die den Troll
initiiert hat.