Forum: Mikrocontroller und Digitale Elektronik MCP2515 schon wieder. Fehlererkennung abschalten o.Ä


von Alex A. (Gast)


Lesenswert?

Abend! :=)
Habe nun endlich den Fehler bei mir gefunden.

Zum Problem:
Ich benutze 2 Can-Controller vom Typ MCP2515 und lese mehrere Sachen vom 
Can-Bus mit dem 1. MCP.
Wenn ich alle interessanten Werte habe, rechne ich alles um, und sende 
es in gewünschter Form mit dem 2. MCP weiter.

Lesen funktioniert problemlos. Senden auch.

Ein Fehler tritt aber auf. Und zwar beim Senden (2. MCP), darf das 
Unterprogramm durch den Interrupt (der vom 1. MCP kommt, wenn neue Daten 
empfangen wurden) auf keinen Fall gestört werden.
Desswegen habe ich den Interrupt für die Zeit wo ich sende deaktiviert.
Das Senden ist für sich selbst eine Kunst, und darf nicht zu schnell 
passieren, sonst ist der Empfänger irritiert und steigt aus.
Das Senden kann dadurch schon mal 200ms dauern.
In der Zeit kommen natürlich immer wieder neue Nachrichten in den 1. 
MCP.
Diese werden durch den deaktivierten Interrupt nicht wahrgenommen und 
nicht ausgelesen.

Nach dem Senden, wird der Interrupt wieder aktiviert und neue Daten 
gesammelt. Dann wird wieder gesendet und dann alles von vorne.

Da die Nachrichten beim Senden nicht ausgelesen werden, steigt der 1.MCP 
irgendwann mal aus. Der Interrupt bleibt immer auf LOW und es passiert 
natürlich Nichts.

Was bleiben mir das für Möglichkeiten?
Beim Senden, darf ich nicht mal ein Bit Ändern, da es leicht zu 
Fehlfunktionen des Empfängers kommen kann.
Nachrichten muss ich aber trotzdem auslesen, da sonst der 1. MCP 
Irgendwann mal nicht mehr will.
Ich denke das kommt davon, dass zu viele Nachrichen einfach ignoriert 
werden.

Kann ich den MCP so konfigurieren, dann ihm der Overflow Nichts 
ausmacht?

Jemand eine Idee?

Gruss Alex S.

von crazy horse (Gast)


Lesenswert?

Mir scheint, du hast ein grundlegendes Verständnisproblem.
Prinzipiell hast du die Möglichkeit, den MCP2515 über die SPI deutlich 
schneller zu bedienen, als eine CAN-Botschaft dauert (ok, bei 1MBit und 
2 MCP2515 kann es je nach MC-Takt eng werden). Das gilt sowohl fürs 
Lesen einer Botschaft als auch das Absenden.
Die Sendegeschwindigkeit auf CAN-Seite hat nichts damit zu tun, wie 
schnell oder langsam da das über die SPI erledigst.
Also - Butter bei die Fische.
Welche Busgeschwindigkeit?
Welche SPI-Frequenz?
Wieviele Botschaften/s?
Software?
Hardware?

von crazy horse (Gast)


Lesenswert?

PS: Symptome zu bekämpfen ist eigentlich immer der falsche Weg :-)

von Alex A. (Gast)


Lesenswert?

1. MCP läuft mit 16Mhz bei 500kbit (lesen)
2. Mcp läuft mit 16Mhz bei 100kbit (Schreiben)
Die MCPs sind beide an der selben SPI dran, nur die CS Leitung ist 
unterschiedlich.
Somit kann ich den 1. oder 2. MCP ansprechen, indem ich die 
entsprechende CS Leitung auf masse ziehe.

Angenommen bekommt der 2. MCP gerade die Daten über SPI. CS leitung vom 
2. MCP ist gerade auf Masse. Wenn ich jetzt (auf wenn das so schnell 
geht) den Register vom 1. MCP auslese, dann bekommt der 2. MCP 
"falschen" Daten über SPI, weil der 1. parallel sitzt.

Wie gesagt, ab besten wäre es, den Error Counter zu löschen, aber ich 
finde den richtigen Register nicht.

von crazy horse (Gast)


Lesenswert?

SPI-Frequenz?

von Alex A. (Gast)


Lesenswert?

1Mhz
Hast du eine Idee?
Habe schon so ziehmlich alles probiert, was ich denken konnte.
Gruss Alex

von crazy horse (Gast)


Lesenswert?

Kurzer Überschlag:
SPI-Frequenz 8MHz möglich.
Eine komplette CAN-Botschaft bei 8 Datenbytes sind ca. 130Bit, dauert 
also beim 500kBit-Bus 260µs, zum kompletten Lesen sind ca. 20 
SPI-Transfers nötig, das dauert 20µs. Bedeutet im Klartext: selbst wenn 
der Bus komplett vollgestopft ist (also Botschaft an Botschaft, was in 
der Praxis nicht vorkommt) lastet der SPI-Transfer den MC nicht mal zu 
10% aus, wenn man auf die SPI wartet.
Der 100kBit-Bus entsprechend weitere 2% bei full-traffic.
Natürlich muss man zwischendurch auch irgendwas anderes tun, aber da ist 
genug Luft. SPI-Interrupt bringt weiteren Freiraum, falls nötig.
Du hast keinen Engpass, du hast allenfalls schlecht programmiert :-)

von crazy horse (Gast)


Lesenswert?

Bei 1MHz kann es langsam eng werden - aber warum nimmst du 1MHz?

von Alex A. (Gast)


Lesenswert?

Was bedeutet Engpass?
Falsch/nicht optimal programmiert kann ja sein.
1MHz auf der SPI habe ich genommen, weil die SPI Leitungen durch den 
Flachbandkabel nicht optimal sind.
Habe jetzt auf 4Mhz umgestellt, funktioniert auch.

Habe jetzt noch eine andere Idee:
Die Daten werden in der Do-Loop Schleife ständig gesammelt und 
umgerechnet.
Mit einem Timer wird die ISR beim Überlauf aufgerufen, und die 
gesammelten Daten werden verschickt.

Wenn das Programm in der ISR von Timer ist, werden doch die anderen 
Interrupts deaktiviert, und beim Verlassen wieder aktiviert, RICHTIG?

Dann habe ich aber immer noch das Problem, dass nicht alle Nachrichten 
abgerufen werden.

Gruss Alex

von crazy horse (Gast)


Lesenswert?

Wie gesagt - für das Abholen der Nachrichten brauchst du 20 (bzw. jetzt 
bei dir 40µs), neue Nachrichten kommen aber max. alle 260µs. Macht 
mindestens 220µs Zeit dazwischen bzw. ca. 3500 Prozessortakte. Damit 
kann man ne Menge machen :-)
Der MCP kann ja auch 2 Botschaften speichern (RXB0 und RXB1, Stichwort 
rollover), ein Problem taucht erst auf, wenn beide Buffer gefüllt sind 
und die 3. Nachricht komplett empfangen ist. Andersherum: die empfangene 
Botschaft muss nicht sofort abgeholt werden, man hat da schon Luft, wenn 
also z.B. gerade eine andere ISR läuft.
Kurz und knapp: ohne deine Software gehts hier nicht weiter.

von Alex A. (Gast)


Lesenswert?

Ok, danke dir.
Werde ich mal mein Program überdenken.

kannst du, oder jemand anderer sagen, ob der Hardware interrupt während 
Timer ISR automatisch deaktiviert wird?

Gruss Alex

von Falk B. (falk)


Lesenswert?

@  Alex S. (dj_beat)

>Ein Fehler tritt aber auf. Und zwar beim Senden (2. MCP), darf das
>Unterprogramm durch den Interrupt (der vom 1. MCP kommt, wenn neue Daten
>empfangen wurden) auf keinen Fall gestört werden.

Warum?

>Desswegen habe ich den Interrupt für die Zeit wo ich sende deaktiviert.

Klingt nicht gut.

>Das Senden ist für sich selbst eine Kunst, und darf nicht zu schnell
>passieren, sonst ist der Empfänger irritiert und steigt aus.

Dann ist er Schrott.

>Das Senden kann dadurch schon mal 200ms dauern.

Eine Ewigkeit.

>In der Zeit kommen natürlich immer wieder neue Nachrichten in den 1.
>MCP.

Eben.

>Diese werden durch den deaktivierten Interrupt nicht wahrgenommen und
>nicht ausgelesen.

Schlecht.

>Nach dem Senden, wird der Interrupt wieder aktiviert und neue Daten
>gesammelt. Dann wird wieder gesendet und dann alles von vorne.

>Da die Nachrichten beim Senden nicht ausgelesen werden, steigt der 1.MCP
>irgendwann mal aus.

Nö, es gibt nur ein paar Datenverluste.

> Der Interrupt bleibt immer auf LOW und es passiert
>natürlich Nichts.

Das ist ein Fehler in deinem Programm.

>Was bleiben mir das für Möglichkeiten?

Es richtig machen.

a) Der Empfänger darf nicht so mimosenhaft sein.
b) Interrupts sperrt man nicht für 200ms.
c) Du musst durch gescheites Timing und Puffern per FIFO die 
Meldungen vom 1. MCP empfangen, während Daten über den 2. MCP rausgehen. 
Sprich. Wenn das AUSLESEN des 1. MCP z.B. maximal 100us dauert muss du 
spätestens 100us VOR dem Senden des nächsten Datenpaktes über MCP #2 die 
Interrupts sperren, nicht eher. Dann kannst du EXAKT per Timer den 
Sendetermin des nächsten Datenpakets auslösen. Während der 
Interruptsperre muss MCP #1 die Nachrichten zwischenpuffern.
d) Warum eigentlich zwei MCP? Sind das zwei getrennte CAN-Busse? Wenn 
nein, sind zwei MCPs Unsinn.

>Beim Senden, darf ich nicht mal ein Bit Ändern, da es leicht zu
>Fehlfunktionen des Empfängers kommen kann.

Schrott. Welches Bit soll sich denn ändern? CAN überträgt SEHR sicher.

>Nachrichten muss ich aber trotzdem auslesen, da sonst der 1. MCP
>Irgendwann mal nicht mehr will.

Siehe oben.

>Ich denke das kommt davon, dass zu viele Nachrichen einfach ignoriert
>werden.

Nö.

>Kann ich den MCP so konfigurieren, dann ihm der Overflow Nichts
>ausmacht?

Macht er sowieso nicht.

Udn wie bereits gesat, es gibt keinen Grund, die SPI mit 
schnarchlangsamen 1 MHz zu betreiben.

MFG
Falk

von Falk B. (falk)


Lesenswert?

@  Alex S. (dj_beat)

>kannst du, oder jemand anderer sagen, ob der Hardware interrupt während
>Timer ISR automatisch deaktiviert wird?

Ja, siehe Interrupt. Und für dein Problem siehe auch 
Multitasking. Dann erkennst du, warum 200ms Interruptsperre nicht 
gut sind.

MFG
Falk

von Peter D. (peda)


Lesenswert?

Alex S. schrieb:
> Ich benutze 2 Can-Controller vom Typ MCP2515

Das heißt also, Du mußt 2 CAN-Busse bedienen.
Jeder MCP2515 kriegt seine eigene Interruptleitung und seine eigenen 2 
FIFOs.

Ein Empfangsinterrupt liest ein Paket in den FIFO ein und das wars dann.
Ein Sendeinterrupt guckt nach, ob ein weiteres Paket im Sende-FIFO ist 
und sendet dieses. Ist keins da, sperrt er sich.

Die FIFOs werden dann im Main ausgelesen bzw. beschrieben. Die MCP2515 
interessiert nicht, wann das passiert und sie müssen auch nicht gesperrt 
werden.
Lediglich nach dem Schreiben in den Sende-FIFO muß der MCP2515 wieder 
seinen Sendeinterrupt freigeben.

Nirgends 200ms Interruptsperre, sondern wenige µs.


Peter

von Alex A. (Gast)


Lesenswert?

Danke für die Antworten.
Habe den Fehler gefunden. Es war ein schlechter Kontakt beim 
Flachbandkabel.

Bin schon etwas weiter und gleich wieder ein Problem.
Die Werte lese ich vom Motor Can-Bus.
Bis jetzt habe ich Wassertemperatur, Öltemperatur, Tankinhalt, 
Geschwindigkeit.

Der Bus läuft mit 500kbit.
Die Wasser- und Öltemperatur sind auf einer ID, in einer 
Nachricht(verschiedene Bytes). ca. 300ms Widerholung
Der Tankinhalt ist auch kein Problem. 200-400ms Widerholung.
Die Geschwindigkeit kommt vom ABS Steuergerät und wird VIEL,VIEL,VIEL 
öfters geschickt, als Temp, Tankinhalt usw.
Das hat nun zur Folge, dass ich fast immer nur Geschwindigkeit empfange.

Hört sich jetzt nicht nach einem riesen Problem an, ist aber doch etwas 
komplizierter.

Habe das nun so gemacht, dass ich jeweils nach einem empfangenen Wert 
eine Variable auf 1 setze, um zu wissen, dass ich den Wert schon habe.
Sieht quasi so aus:
1
Dim q1, q2, q3 as byte
2
3
do
4
5
if Filter = 0 and q1 = 0 and q2 = 0 and q3 = 0 then
6
wasser_temp = (meine Candaten für Temp)
7
Öl_temp = (meine Candaten für Temp)
8
q1 = 1
9
end if
10
11
12
if Filter = 1 and q1 = 1 and q2 = 0 and q3 = 0 then
13
Tank_Inhalt = (meine Candaten für tank)
14
q2 = 1
15
end if
16
17
if Filter = 2 and q1 = 1 and q2 = 1 and q3 = 0 then
18
wasser_temp = (meine Candaten für Geschwindigkeit)
19
q3 = 1
20
end if
21
22
23
if q1 = 1 and q2 = 1 and q3 = 1 then  'wenn ich alle Werte habe
24
gosub Umrechnen_senden          'unterprogramm zum Umrechnen und versenden
25
q1 = 0
26
q2 = 0
27
q3 = 0
28
29
loop

Beim Interrupt werden Filter erkannt (welcher ausgelöst hat) und Daten 
vom MCP2515 ausgelesen. So kann ich feststellen, welche Daten das sind.

Mein Problem ist aber wie gesagt, dass die Geschwindigkeit zu oft 
übertragen wird.
Diese Nachricht muss ich ja immer auslesen, um dann fest zu stellen, 
dass ich diesen Wert schon habe, und jetzt eigentlich die Öltemp. haben 
möchte.
Dann verwerfe ich halt die Nachricht und warte auf die nächte.... und 
DANN.... bekomme ich schon wieder die Geschwindigkeit, und wieder, und 
wieder, bis irgendwann mal doch das Richtige dazwischen kommt.

Tja, und nun die Frage, nach welcher Logik/welchem Verfahren sollte ich 
die Daten auslesen, um dann möglichst schnell alle zu haben?
Meine If-Then Variante scheint in dem Fall nicht ganz zu passen.

Danke
Gruss Alex S.

von Peter D. (peda)


Lesenswert?

Wenn Du 4 Nachrichten empfangen willst, legst Du 4 Puffer an.
Jede Nachricht legst Du dann in dem zugehörenden Puffer ab, eine alte 
gleiche Nachricht wird einfach überschrieben.

Dann legst Du noch 4 Bits an, jede Nachricht setzt das zugehörende Bit. 
Sind alle 4 gesetzt, weißt Du, daß jede Nachricht mindestens einmal 
empfangen wurde und kannst damit irgendwas machen.


Peter

von Falk B. (falk)


Lesenswert?

@  Alex S. (dj_beat)

>Die Wasser- und Öltemperatur sind auf einer ID, in einer
>Nachricht(verschiedene Bytes). ca. 300ms Widerholung
>Der Tankinhalt ist auch kein Problem. 200-400ms Widerholung.

Gähn. Da schläft jeder Controller ein.

>Die Geschwindigkeit kommt vom ABS Steuergerät und wird VIEL,VIEL,VIEL
>öfters geschickt, als Temp, Tankinhalt usw.

Logisch, dein Tacho sollte ja etwas flüssiger reagieren.

>Das hat nun zur Folge, dass ich fast immer nur Geschwindigkeit empfange.

Und? Kann man problemlos ignorieren.

>Hört sich jetzt nicht nach einem riesen Problem an,

Eben.

> ist aber doch etwas komplizierter.

Warum?

Ohh, du machst das in BASCOM? Hmmm, geht auch.

>Mein Problem ist aber wie gesagt, dass die Geschwindigkeit zu oft
>übertragen wird.

Nö. Das kann man igrnorieren, schon direkt im MCP, per Filter.

>Dann verwerfe ich halt die Nachricht und warte auf die nächte.... und
>DANN.... bekomme ich schon wieder die Geschwindigkeit, und wieder, und
>wieder, bis irgendwann mal doch das Richtige dazwischen kommt.

Ja und? Dein Controller macht do sowieso nichts großartiges nebenbei.

>Tja, und nun die Frage, nach welcher Logik/welchem Verfahren sollte ich
>die Daten auslesen, um dann möglichst schnell alle zu haben?

Filter im MCP setzen und nur alle 200ms freigeben, bis einmal die 
passenden Nachrichten empfangen wurden. Das Ganze per Timer-Interrupts 
steuern.

MFG
Falk

von Alex A. (Gast)


Lesenswert?

>Dann legst Du noch 4 Bits an, jede Nachricht setzt das zugehörende Bit.
>Sind alle 4 gesetzt, weißt Du, daß jede Nachricht mindestens einmal
>empfangen wurde und kannst damit irgendwas machen.

Genau so habe ich das im Moment auch.
Funktioniert aber wie gesagt nicht so gut. Warum? Kommt unten.


>Nö. Das kann man igrnorieren, schon direkt im MCP, per Filter.

Der Filter ist ja schon so eingestellt, dass ich die ID für 
Geschwindigkeit durch kommt. Oder soll ich nach dem ich die 
Geschwindigkeit empfangen habe, den Filter für Geschwindigkeit löschen, 
und nach dem Versenden wieder aktivieren?

>Filter im MCP setzen und nur alle 200ms freigeben, bis einmal die
>passenden Nachrichten empfangen wurden.
Etwas genauer,bitte, wenn es geht.


Zum Problem noch mal:

Ich will die Geschwindigkeit haben.
Die passende Nachricht bekomme ich, und habe nun meinen Wert für 
Geschwindigkeit.

Jetzt möchte ich den Tankinhalt haben, also warte ich auf die Can 
Nachricht. Ich bekomme einen Interrupt, dass eine Nachricht im MCP 
bereit liegt.
Dann lese ich den Inhalt aus und sofort danach gucke ich, welcher Filter 
durchgelassen hat. Anhang des Filters kann ich die Nachricht zuordnen.
(Denn ich weiss dass, zum Beispiel Filter 0 Geschwindigkeit, Filter 1, 
Tankinhalt, Filter 2 Temperaturen sind.)

Bei der nächsten Nachricht sehe ich, dass schon wieder Filter 0 
ausgelöst hat. Diesen brauche ich nicht mehr, da ich den Wert schon 
habe, und warte auf die nächste Nachricht.
Und dann bekomme ich wieder die Geschwindigkeit.

Natürlich erwische ich irgendwann mal den Tankinhalt und die Temperatur, 
aber das kann je nach Zufall 0.1 - 2 Sekunden dauern. 2 Sekunden ist zu 
lange.

Das Problem ist wie gesagt, das der µC von der wiederholten Nachricht 
für Geschwindigkeit abgelenkt wird, und somit den Tankinhalt verpasst.

Ich verstehe es natürlich, dass ich einfach Alles empfangen kann, und 
die Nachrichten entsprechend speichern kann, Geschwindigkeit wird dabei 
einfach überschrieben, aber das funktioniert, warum auch immer, nicht.

Gruss Alex

von Martin (Gast)


Lesenswert?

Irgendwie haut dein gesamtes Softwarekonzept nicht hin.

Dein Prozessor ist schnell genug um alle Nachrichten zu empfangen, zu 
verarbeiten und wieder zu senden. Evtl. wartet den Programm viel zu viel 
ohne etwas zu machen.

von Alex A. (Gast)


Lesenswert?

Den Code hier zu Posten würde nicht viel Sinn machen, da es viel zu lang 
ist und es ist auch nicht sofort klar, was da passiert.

Ich möchte einfach nur einen Vorschlag, wie ich das Ganze logisch und 
schnell machen kann, ohne dass sich das was verhackt.
Also kein Sorcecode, sondern den richtigen Ablauf/Idee.

Gruss Alex S.

von Falk B. (falk)


Lesenswert?

@  Alex S. (dj_beat)

>Geschwindigkeit durch kommt. Oder soll ich nach dem ich die
>Geschwindigkeit empfangen habe, den Filter für Geschwindigkeit löschen,
>und nach dem Versenden wieder aktivieren?

Ja.

>Natürlich erwische ich irgendwann mal den Tankinhalt und die Temperatur,
>aber das kann je nach Zufall 0.1 - 2 Sekunden dauern. 2 Sekunden ist zu
>lange.

Wieso "erwischen"? Die Nachrichten empfängst du doch aus so, der MCP hat 
doch mehrere Empfangsboxen, nicht wahr?

>Das Problem ist wie gesagt, das der µC von der wiederholten Nachricht
>für Geschwindigkeit abgelenkt wird, und somit den Tankinhalt verpasst.

Nö. Dein Programm hat ein Problem.

>Ich verstehe es natürlich, dass ich einfach Alles empfangen kann, und
>die Nachrichten entsprechend speichern kann, Geschwindigkeit wird dabei
>einfach überschrieben, aber das funktioniert, warum auch immer, nicht.

Programmfehler. Böse Zungen würden hier jetzt einen BASCOM-Witz 
einwerfen . . . ;-)

MfG
Falk

von crazy horse (Gast)


Lesenswert?

Falk Brunner schrieb:

> Filter im MCP setzen und nur alle 200ms freigeben, bis einmal die
> passenden Nachrichten empfangen wurden. Das Ganze per Timer-Interrupts
> steuern.

Was fürn Quark...

von Falk B. (falk)


Lesenswert?

@  crazy horse (Gast)

>> Filter im MCP setzen und nur alle 200ms freigeben, bis einmal die
>> passenden Nachrichten empfangen wurden. Das Ganze per Timer-Interrupts
>> steuern.

>Was fürn Quark...

Deine fundierte Kritik ist immer wieder gern gesehen hier . . .

von Alex A. (Gast)


Lesenswert?

>>Oder soll ich nach dem ich die
>>Geschwindigkeit empfangen habe, den Filter für Geschwindigkeit löschen,
>>und nach dem Versenden wieder aktivieren?
>Ja.

Funktioniert nicht.
Habe schon erlebt, dass Konfigurationsmodus im laufenden Betrieb 
schlecht ist. Der Sender erkennt den "Bus-OFF".

von cskulkw (Gast)


Lesenswert?

Martin schrieb:
> Irgendwie haut dein gesamtes Softwarekonzept nicht hin.
>
>
>
> Dein Prozessor ist schnell genug um alle Nachrichten zu empfangen, zu
>
> verarbeiten und wieder zu senden. Evtl. wartet den Programm viel zu viel
>
> ohne etwas zu machen.Beitrag melden | Bearbeiten | Löschen |

Ja Martin, wie Recht du hast.

Das Problem vom Alex ist, dass er im BASIC nicht die Kontrolle auf den 
Controler zu haben scheint, wie man es unter C im AVR-Studio hätte.

Seine Probleme bei der Logistik der Daten ist der Programmiersprache 
geschuldet. Sie sind hausgemacht. Aber da muß er schon selbst drauf 
kommen.

Deshalb halte ich mich in diesem Thread zurück.

von crazy horse (Gast)


Lesenswert?

@Falk:
der Wortlaut wurde durchaus mit Absicht so gewählt - mit etwas 
Selbstreflektion solltest du was erkennen :-)

Zur Sache: es gibt keinerlei Grund, im laufenden Betrieb die 
Konfiguration zu ändern. Neben unnötig ist das sogar problematisch. Will 
ich die Geschwindigkeit, lasse ich die entsprechende Botschaft durch. 
Die nicht benötigten Daten sind schneller weggeschmissen, als jedesmal 
die Filtereinstellungen zu ändern. Tut doch nicht weh, die alle 10ms zu 
bekommen, aber nur alle 200ms auch auszuwerten.

von Falk B. (falk)


Lesenswert?

@  cskulkw (Gast)

>Das Problem vom Alex ist, dass er im BASIC nicht die Kontrolle auf den
>Controler zu haben scheint, wie man es unter C im AVR-Studio hätte.

Mit BASCOM kann man per SPI genauso arbeiten wie mit C.

>Seine Probleme bei der Logistik der Daten ist der Programmiersprache
>geschuldet.

Nö, es sind seine begrenzten Kenntnisse und Fähigkeiten bezüglich 
Programmierung allgemein.

> Sie sind hausgemacht. Aber da muß er schon selbst drauf
> kommen.

Was nur bedingt Sinn eines Forums ist. Ein paar gute Tipps und Hinweise 
sind schon das Mittel der Wahl und auch Sinn eines Forums.

MfG
Falk

von Alex A. (Gast)


Lesenswert?

>Das Problem vom Alex ist, dass er im BASIC nicht die Kontrolle auf den
>Controler zu haben scheint, wie man es unter C im AVR-Studio hätte.

Basic ist da vielleicht auch teilweise das Problem, aber es muss damit 
auch zu machen sein.
Denn wenn meine Strategie/Idee/Vorstellung etwas daneben ist, dann hilft 
ja nur die Vorgehensweise zu ändern.
Und ich komme im Moment nicht drauf, wie ich das anders machen kann.
Desswegen auch die Frage, wie Ihr das machen würdet.
Gruss Alex S.

von Falk B. (falk)


Lesenswert?

@  crazy horse (Gast)

>der Wortlaut wurde durchaus mit Absicht so gewählt - mit etwas
>Selbstreflektion solltest du was erkennen :-)

;-)
Wobei ich schon mein Urteil begründe . . .

>Zur Sache: es gibt keinerlei Grund, im laufenden Betrieb die
>Konfiguration zu ändern. Neben unnötig ist das sogar problematisch.

Mag sein, so genau kenn ich den MCP2515 nicht, hab ihn nur vor einer 
Weile mal auf die Schnelle in Betrieb genommen, dem Herrn vom kreativen 
Chaos sei Dank.

http://www.kreatives-chaos.com/artikel/ansteuerung-eines-mcp2515

> Will
>ich die Geschwindigkeit, lasse ich die entsprechende Botschaft durch.
>Die nicht benötigten Daten sind schneller weggeschmissen, als jedesmal
>die Filtereinstellungen zu ändern. Tut doch nicht weh, die alle 10ms zu
>bekommen, aber nur alle 200ms auch auszuwerten.

Sicher.

MfG
Falk

von Simon K. (simon) Benutzerseite


Lesenswert?

Alex S. schrieb:
> Den Code hier zu Posten würde nicht viel Sinn machen, da es viel zu lang
> ist und es ist auch nicht sofort klar, was da passiert.

Wenn dein Code zu lang ist, sodass andere Leute in nachvollziehen 
können, dann hast du schon viel grundlegendere Probleme bei deiner 
Software! Vermutlich auch noch Spaghetti-Code.

von crazy horse (Gast)


Lesenswert?

Alex S. schrieb:
> Den Code hier zu Posten würde nicht viel Sinn machen, da es viel zu lang
> ist und es ist auch nicht sofort klar, was da passiert.
>
> Ich möchte einfach nur einen Vorschlag, wie ich das Ganze logisch und
> schnell machen kann, ohne dass sich das was verhackt.
> Also kein Sorcecode, sondern den richtigen Ablauf/Idee.
>
> Gruss Alex S.

Versuchen wir es mal. Basicspezifisches kann ich aber nichts beitragen.
Als erstes solltest du versuchen, dir eine passende Variable anzulegen:

typedef struct
{   unsigned int  id;
    unsigned char rtr;
    unsigned char length;
    unsigned char data[8];
} CANMessage;
definiert einen Variablen-Typ CANMessage, in dem du alle relevanten 
Daten unterbringen kannst (ob das in Basic geht??, ansonsten musst du 
dir mit einem array irgendwie helfen.

Jetzt erzeugst du eine Variable CANreceive
CANMessage CANreceive;
In diese werden alle hereinkommenden Botschaften gespeichert.

interrupt [EXT_INT0] void ext_int0_isr(void)
{ can_get_message(&CANreceive);    //holt per SPI alle CAN-Daten ab
  CAN_message_received=1;        //zeigt an, dass eine Botschaft 
empfangen wurde
}

Das heisst jetzt, dass du alle Botschaften, die den Filter des MCP2515 
passieren, interruptgesteuert im MC landen.

Wie es jetzt weitergeht, hängt von deiner Anwendung ab. Normalerweise 
gibt es weitere Variablen CANMessage, beispielsweise:
CANMessage motor_receive[5];   //wenn du 5 Botschaften empfangen willst

Im Hauptprogramm dann:

while (1)
       {if (CAN_message_received)   //Botschaft empfangen?
           {CAN_message_received=0;
            switch (CAN_receive.ID)   //Verzweigen anhand der ID
                {case 0x200: motor_receive[0]=CANreceive;
                             break;
                 case 0x223: motor_receive[1]=CANreceive;
                             break;
                 .
                 .
                default: break;       //alles andere wegschmeissen
                 }
           }
       }

Jetzt hast du ständig die aktuellen Werte in den Variablen 
motor_receive[?] und kannst damit weiterarbeiten.
Beispielsweise willst du die Geschwindigkeit haben. Die steht in z.B. 
bei ID 0x200, Byte 3 und 4
unsigned int Geschwindigkeit;
Geschwindigkeit=(unsigned int)motor_receive[0].data[3] + (unsigned 
int)motor_receive[0].data[4]<<8;

von Alex A. (Gast)


Lesenswert?

Habe gerade was ausprobiert.
Ist leider Basic, aber ich denke das kann man so leicht lesen und 
verstehen, was im Programm passiert.

Fangen wir an.
Beim Interrupt bekommt eine Variable O den Wert 1. Das ist für nachher 
wichtig.

Ausserdem habe ich an 2 Pins LEDs dran.
Eine habe ich LED_RX und die andere LED_TX genannt, damit ich ungefähr 
sehen kann, was im Programm überhaupt passiert.

wenn Filter = 0 ist, dann heisst das der RXF0 die Nachricht durch 
gelassen hat.
Wenn Filter = 1 ist, heisst der RXF1 hat die Nachricht durchgelassen.
Filter2 = 1 heisst RXF2 (Buffer1) hat die Nachricht akzeptiert.

das Programm sieht aktuell so aus.
1
do 
2
 
3
if O = 1 then 'wenn Interrupt ausgelöst wurde, ist O = 1, ansonsten 0
4
   Set LED_RX  'LED einschalten
5
   Filter_erkennen  'im Subprogramm wird geschaut welcher F. ausgelöst hat
6
   Read_register_b0 'RXB0 wird ausgelesen
7
   Read_register_b1 'RXB1 wird ebenfalls ausgelesen,weil es ja schnell geht
8
   Reset LED_RX     'LED geht aus
9
10
     if Filter = 0 then
11
        H2O = Wert2  'Wertx ist der entsprechende Byte nach dem Auslesen
12
        OEL = Wert3
13
        W1 = 1       'hilfsvariable dass Temp. vorhanden ist
14
        O = 0        'Da ausgelesen, O für Interrupt freigeben
15
        Goto evtl._senden 'siehe unten
16
     end if
17
18
     if Filter = 1 then
19
        Tank = Wert2  'Wertx ist der entsprechende Byte nach dem Auslesen
20
        W2 = 1       'hilfsvariable dass Tank vorhanden ist
21
        O = 0        'Da ausgelesen, O für Interrupt freigeben
22
        Goto evtl._senden   'siehe unten
23
     end if
24
25
     if Filter = 1 then
26
        Speed = Wert5_b1  ' Byte für Geschw. im Buffer1
27
        W3 = 1       'hilfsvariable dass Tank vorhanden ist
28
        O = 0        'Da ausgelesen, O für Interrupt freigeben
29
        Goto evtl._senden   'siehe unten
30
     end if
31
32
33
     evtl._senden:
34
if w1 = 1 and w2 = 1 and w3 = 1 then  'wenn alle Werte vorhanden
35
  Set LED_TX 'Led ein
36
  gosub umrechnen_senden  'subprogramm zum Umrechnen und senden
37
  Read_register_b0 'RXB0 wird ausgelesen, um Interrupt zu löschen
38
  Read_register_b1 'RXB1 wird ausgelesen, um Interrupt zu löschen
39
  w1 = 0  'Variablen wieder freigeben, da gesendet wurde
40
  w2 = 0 
41
  w3 = 0
42
  O = 0  'O muss 0 sein, da Interrupt gelöscht wurde
43
  Reset LED_TX 'Led aus
44
end if
45
46
end if
47
48
loop

In diesem Fall geht die LED_TX gar nicht an, als ob wie w1, w2, w3 != 1 
sind, obwohl alle Daten vorhanden sein sollten.

Die Filter funktionieren, die Nachrichten werden richtig empfangen, 
irgendwo hackt das aber immer noch.

Sieht Jemand den Fehler?
Es muss mit der Logik was nicht stimmen.

Danke

von Alex A. (Gast)


Lesenswert?

>if Filter = 1 then
>        Speed = Wert5_b1  ' Byte für Geschw. im Buffer1

Sorry, es muss
if Filter2 = 1 then
        Speed = Wert5_b1
heissen

Gruss Alex

von H.Joachim S. (crazyhorse)


Lesenswert?

Warum hängst du dich an den Filtern auf? Ist doch schnurzegal, ob die 
von RXBUF0 oder 1 kommen. Spätestens, wenn du mal an den 
Filtereinstellungen rumspielst oder die Sache als Grundlage für ein 
neues Projekt nehmen willst oder eine 3. zu empfangene Botschaft 
dazukommt, hast du ein Problem.

Die Grundlage der Sache ist und bleibt die ID der Botschaft. Emfange die 
Botschaft, schau nach, welche ID die hat und entscheide danach, was 
damit zu tun ist. Nicht mehr und nicht weniger.
Und wenn du es so machst wie oben beschrieben, brauchst du überhaupt 
keine Filter im CAN-Controller. Du bekommst alles rein und kannst auch 
später schnell noch eine weitere Botschaft mit auswerten, alles, was 
nicht ausdrücklich benutzt wird, landet im Papierkorb.
Die Filter sind nützlich, wenn der Prozessor stark beschäftigt ist und 
durch das Empfangen unnützer Nachrichten ausgebremst würde. Das ist bei 
dir mit Sicherheit nicht der Fall. Und ob du nun ständig nur wartest 
oder zwischendurch auch ein paar Nachrichten einliest und verwirfst, ist 
doch schnuppe.
Wenn die ganze Sache dann mal fertig ist, kannst du die Filter immer 
noch setzen. Erstmal erschwert es die Sache nur und bringt nichts.

von Christoph (Gast)


Lesenswert?

Stimmt, du hast Recht, anhang der ID kann ich die Nachricht auch 
zuordnen.
Aber mit den Filter ist doch quasi das Gleiche?!
Wenn ich weiss, das Filter0 nur die ID 280h durchlässt, dann weiss ich 
automatisch, wenn Filter0 ausgelöst hat, dass die Nachricht die ID 280 
hat.

Filter komplett ausschalten, und Alles empfangen, halte ich für etwas 
übertrieben.
Auf dem Motor-Can ist eine Menge los, und das Ganze läuft mit 500kbit.
Meinst du ich soll erst mal Alles empfangen, und ID vergleichen?

Ich werde erst mal versuchen, die Nachrichten nicht nach Filter ordnen, 
sondern nach IDs.
Vielleicht geht das dann besser.

Andere Vorschläge sind sehr erwünscht.

Gruss Alex S.

von H.Joachim S. (crazyhorse)


Lesenswert?

Ich hab ne Anwendung, da liegt mein Teil als bridge zwischen 
Motorsteuergerät und dem Rest des Autos. Beide laufen mit 500kBit und 
die beiden Seiten sind quasi null-kompatibel. D.h. ne ganze Menge wird 
auf beiden Seiten empfangen, umsortiert, umgerechnet und auf der anderen 
Seite wieder verschickt. Nebenbei noch ein paar Analogsensoren auslesen 
und die Werte auch mit verwursten. Arbeitet komplett ohne Filter und 
problemlos. Eigentlich wollte ich die am Schluss noch einbauen - aber 
warum? Hab spasseshalber einen Pin wackeln lassen, wenn nichts zu tun 
ist - MC-Auslastung (ATMega32@16MHz, SPI 8MHz) liegt  bei ca. 60%...

von Christoph (Gast)


Lesenswert?

@H.joachim Seifert
Mein Respekt!!!
Gruss Alex

von Alex A. (Gast)


Lesenswert?

Sorry, Christoph ist mein Büronachbar.
Gruss Alex S.

von Obelix X. (obelix)


Lesenswert?

Wenn ich es richtig verstanden habe, soll auf CAN2 alle 200ms der 
berechnete Wert gesendet werden, oder?

Zum Konzept.

*Interrupt 1 (CAN1 Empfangen)
schauen welche Nachricht wurde empfangen (egal ob per Filter Nr. oder 
ID)
Den benötigten Wert in eine entsprechende Variable (H2O, OEL, TANK, 
Speed) speichern.
Fertig

*Interrupt 2 (Timmer, löst alle 200ms aus)
Die Variablen nehmen, Wert berechnen, in Nachricht packen und senden.

*Hauptprogramm
Mach was, was auch immer, z.B. langweilen


Habe ich jetzt was wichtiges übersehen?

von Obelix X. (obelix)


Lesenswert?

PS.

Da du beide CAN-Controller an einer SPI Schnittstelle betreist musst du 
natürlich verhindern, dass während der eine CAN-Controller angesprochen 
wird auch der andere aktiviert wird.

Allso noch eine abgeänderte Version:

*Interrupt 1 (CAN1 Empfangen)
Timerinterrupt sperren
schauen welche Nachricht wurde empfangen (egal ob per Filter Nr. oder
ID)
Den benötigten Wert in eine entsprechende Variable (H2O, OEL, TANK,
Speed) speichern.
Timerinterrupt freigeben
Fertig

*Interrupt 2 (Timer, löst alle 200ms aus)
CAN1-Interrupt sperren
Die Variablen nehmen, Wert berechnen, in Nachricht packen und 
senden.CAN1-Interrupt freigeben


Der Prozessor hällt sich so nur sehr kurz in den Interruptroutinen auf.

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.