Forum: Mikrocontroller und Digitale Elektronik atmaga2560 + Interrupt + lan = abbruch.


von DAVID B. (bastler-david)


Lesenswert?

Hallo
Da der 2560 voll zulange brauch um meine Sensoren aus zu lesen und aus 
zuwerten so wie auf Displays anzuzeigen,
und das an das Ethernet schilt weiter zugeben.
habe ich versucht es mit einen Interrupt pin der mit dem int pin vom 
enc28j60 zu verbinden.
die Erkennung wenn ein client sich verbinden zuwollen scheint auch zu 
laufen leider bricht der 2560 noch vor der ersten Daten Übertragung zum 
Browser einfach ab. und macht bei der letzten Aufgabe vor dem 
unterbrechen weiter ODER bleibt in der int schleife hängen.

Wie habt ihr das gelöst ?
Vielen dank

von Chaoschaot (Gast)


Lesenswert?

DAVID -. schrieb:
> Wie habt ihr das gelöst ?

Wir haben unsere Probleme klar und ausführlich dargestellt
und einen sauberen Schreibstil gewählt, inklusive einigermassen
korrekter Grammatik und Gross/Kleinschreibung.

von Stefan F. (Gast)


Lesenswert?

> Wie habt ihr das gelöst ?

Mit anderer Hardware und vermutlich auch anderer Software.

von DAVID B. (bastler-david)


Angehängte Dateien:

Lesenswert?

DANKE für die Hilfe :- )
Ich habe schon extra auf Rechtschreibung gedachtet na gut groß und klein 
Schreibung ist untergegangen aber egal.

Ich habe mal den code für Ethernet angefügt dieser ist noch nicht 
fertig.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

DAVID -. schrieb:
> Ich habe schon extra auf Rechtschreibung gedachtet na gut groß und klein
> Schreibung ist untergegangen aber egal.

Worauf Du bei all diesem Achten aber nicht geachtet hast, ist eine 
verständliche Darstellung Deines Problems.

Ganz sicher ist Dein µC nicht zu langsam, das wird Dein Programm sein.

von DAVID B. (bastler-david)


Lesenswert?

Hmm ich habe 2 Code teile die einzeln stabil und fehlerfrei laufen.
Code eins ist zum auslesen von Temperatur Sensoren und Magnet Schaltern 
und anzeigen der werte auf Displays.

Code teil 2 ist der LAN teil wo die Sensoren Daten auf eine Ethernet 
karte gesendet werden sollen.

wie sagt beides einzeln geht.

Versuche ich jetzt nur EIN der 12 DS18B20 auszulesen und übergebe nur 
ein Sensor wert der Ethernet karte geht das auch GRADE noch so
mit ein paar sec Ladezeit der Seite.

Übergebe ich jetzt aber alle 12 temp werte und lasse diese auch noch auf 
ein Display zusätzlich ausgeben bekomme ich Natürlich keine Verbindung 
mehr.

Da kam mir die Idee mit dem Interrupt pins.
Der enc28j60 gibt bei Verbindungsaufbau aufbau ja 3,8 Volt welche sich 
für für die Erkennung eignen.


Ich habe also ein void bereich für lan gemacht der nur gestartet wird 
wenn der int pin vom enc28j60 auf LOW geht.

Soweit geht das auch er 2560 erkennt den LOW Pegel springt zu dem void 
lan bereich und bricht dann irgendwo ab.(kann ich nicht nachvollziehen)
Der enc28j60 sendet aber weiterhin ein LOW Signal da dieser ja auf seine 
Daten wartet und keine bekommt.

Ich hoffe das ist verständlicher.

von Stefan F. (Gast)


Lesenswert?

Vergiss mal die Interrupt Leitung, die brauchst du nicht. Der Ethernet 
Controller puffert die Kommunikation und wenn der Puffer nicht 
ausreicht, werden die Pakete durch das TCP Protokoll automatisch 
wiederholt.

Zwischen Ethernet Controller und Mikrocontroller ist das Timing völlig 
entspannt.

In deinem Programmteil mit der Displayausgabe hast du möglicherweise 
lange Warteschleifen, die dazu führen, dass der andere programmteil für 
die LAN Kommunikation gar nicht mehr ausgeführt wird. Falls das der Fall 
ist, musst Du Dir überlegen, wie du dein Programm Multi-Taksing fähig 
machst (Suchwort: Zustandautomat oder Endlicher Automat).

Es könnte auch sein, dass du einen Watchdog verwendest, der durch die 
Zeitaufwändige Kommunikation mit dem Display nicht mehr schnell genug 
bedient wird. Dann musst du das Zeitintervall des Watchdogs entsprechend 
erhöhen.

Mehr kann man nur sagen, wenn du das komplette Projekt inclusive 
Schaltplan veröffentlichst.

> kann ich nicht nachvollziehen

Dafür gibt es ICE Debugger, oder Log-Meldungen die du auf eine serielle 
Konsole ausgibst.

von DAVID B. (bastler-david)


Angehängte Dateien:

Lesenswert?

eins vor weg:
Ich bin noch nicht sehr weit mit Programmierer Fähigkeiten dies bitte 
ich zu berücksichtigen.

Ich habe dein post aufmerksam gelesen und und bin für deine Anmerkungen 
sehr dankbar.
Ich selber habe aber kein Watchdog verwendet.
Und eine wartezeit gibt es nur bei den Temperatur fühlern von 550 ms das 
ist der Kompromiss zwischen fehlerhafter Übertragung und Geschwindigkeit

Die bepinung wäre wie folgt:

die 3 Displays vom typ LCD2004 Display sind mit 11, 10 ,(9 bis 6), 5, 4 
verbunden.
Lan am 2560:  53 SS) /51 MOSI /50 MISO /52 SCK
Lan karte     10 SS  /11 MOSI /12 MISO /13 SCK
Inter. 0 = Digitaler Pin 2
Temperatur Sensoren hängen am pin 22
0-15A Spannungsmessung (Füllzustände)

von Alex W. (a20q90)


Lesenswert?

DAVID -. schrieb:
> Ich habe mal den code für Ethernet angefügt dieser ist noch nicht
> fertig.

Dann kann es auch nicht gehen!

von DAVID B. (bastler-david)


Lesenswert?

SEHR gute Hilfe ! meinst du will ich die lokale IP geXXX habe ?
Danke fürs nicht lesen mit nicht fertig meinte ich damals das noch nicht 
alles eingebaut ist was ich mir vorstelle und die botton noch nicht an 
der richtigen stelle sind.

von Alex W. (a20q90)


Lesenswert?

DAVID -. schrieb:
> und die botton noch nicht an
> der richtigen stelle sind.

Dann kann es nicht gehen!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ich habe übrigens ein paar Fehler im Code gefunden. Die sehen alle in 
etwa so aus:
1
float spannung8 = sensorValue8 * (4.9 / 1023.0);
Heute hatte ich das schon mal geschrieben, aber man kann es nicht oft 
genug wiederholen: 1023 ist genauso falsch wie 2047 und 4095. Dort muss 
immer eine Zweierpotenz stehen. Lies mal den 
Beitrag "1023 oder 1024"
Und dann nimm weiterhin die 1023, weil die dir besser gefällt. Aber 
falsch ist sie trotzdem. Und im Datenblatt des ADC steht sicher auch was 
Anderes.

Und zudem MUSS der kleine AVR zu langsam sein, wenn du ihn als 8-Bitter 
so unnötig mit 32-Bit-Fließkommaoperationen zutextest.

von Stefan F. (Gast)


Lesenswert?

Die loop() Funktion enthält eine Menge Displayausgaben.

Ich sehe aber nicht, wo die LAN() Funktion aufgerufen wird. Anscheinen 
gar nicht. Du hast geschrieben, dass dein Programm ausfällt, wenn du 
beides kombinierst. Aber ich kann nicht sehen, wie du die beiden 
Programmteile kombiniert hast.

Die LAN() Funktion enthält eine while() Schleife, die wiederholt wird, 
solange der Client verbunden ist. Aber innerhalb der Schleife wird die 
Verbindung getrennt (was auch so sein soll). Die Schleife wird also 
immer genau ein mal durchlaufen, daher kannst du sie weglassen.

Der generierte HTML Text ist voller Fehler. Du solltest das mal mit 
deinem Web-Browser in eine Datei abspeichern und durch ein 
Kontroll-Programm laufen lassen, dass alle Fehler meldet 
(https://validator.w3.org/#validate_by_upload).

von Stefan F. (Gast)


Lesenswert?

> float temp1 = (12,34);

Was ist das eigentlich für eine komische Syntax?
Das kenne ich so nicht. Fließkommazahlen schreibt man so:

> float temp1 = 12.34;

Siehe http://en.cppreference.com/w/cpp/language/floating_literal
Und https://www.arduino.cc/en/reference/float

von DAVID B. (bastler-david)


Lesenswert?

Danke Lothar Miller du hast vollkommen recht an das habe ich gar nicht 
mehr gedacht.
ich werde es auf HIGH und LOW Erkennung (digitalRead) umbauen was 
ohnehin besser zu mein vorgaben passt.

Und danke auch dir Stefan die LAN Funktion wird durch den Interrupt Pin 
0 vom Ethernet Schild gestartet.

Ich habe auch dein Radschlag berücksichtigt und verzichte auf den 
interrupt.
Zum Testen habe ich mal alles einzeln zusammen gebaut bis es nicht mehr 
lief und über geblieben ist das auslesen der 18b20 nehme ich das raus 
und ändere sonst nix läuft es super.

Displays zeigen nur test an
Spannung werden noch unverändert gemessen
Und LAN läuft auch super.

Wäre meine Schlussfolgerung ich muss erreichen das ich anstellen bei 
jeden Durchgang die Sensoren auszulesen immer nur ein wert hochzählen 
lasse und nach sagen wir 100 Durchläufe eine abfrage mache.
Eine Messung pro Minute reicht mehr wie aus.


Noch eine Überlegung zusätzlich wenn ich anstelle float einfach int 
nehme weil ich auf die Kommastelle der Temperaturen verzichten kann 
würde es reichen alle float werte der Berechnung auf int zu ändern ?

PS
Stimmt Stefan das ist ein Tippfehler von mir wird geändert.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

> Und danke auch dir Stefan die LAN Funktion wird durch den
> Interrupt Pin 0 vom Ethernet Schild gestartet.

Diese Arduino Library baut auf uIP auf, damit kenne ich mich gut aus. 
uIP erfordert, dass eine Reihe von Funktionen des Treiber immer wieder 
aufgerufen werden.

In der Ardunio Library ist der entsprechende Code in 
UIPEthernetClass::tick();

Diese Methode wird wiederum von zahlreichen anderen Methoden der Library 
aufgerufen. Die Ethernet Schnittstelle wird nur funktionieren, wenn du 
wuasi ununterbrochen immer wieder Funktionen der Ethernet Library 
aufrufst.

In deinem Fall wird die Ethernet Library nach der Initialisierung 
zunächst gar nicht mehr aufgerufen. Deswegen hat dein Server (der 
Arduino) keine Verbindungen angenommen.

Du hast einen Interrupt benutzt, um die LAN Funktion zu starten. Dein 
Problem ist, dass du nach dem Erzeugen der Webseite noch viele male 
UIPEthernetClass::tick() aufrufen musst, bis die Ethernet Kommunikation 
vollständig abgeschlossen ist.

Aber das wäre ein unsauberer Ansatz. uIP ist nicht dafür ausgelegt, nur 
ab und zu bei Bedarf ausgeführt zu werden - schon gar nicht in einer 
Interruptroutine. Sondern du sollst es ständig ausführen. Das 
Hauptprogramm (loop) soll immer wieder bei jedem Schleifendurchlauf eine 
Funktion der Ethernet library aufrufen, welche UIPEthernetClass::tick() 
enthält. Zum Beispiel UIPServer::available().

Auf https://www.arduino.cc/en/Reference/ServerAvailable findest du ein 
korrektes Minimalbeispiel:
1
void loop()
2
{
3
  EthernetClient client = server.available();
4
  if (client) {
5
    server.write(client.read());
6
  }
7
}

Hier wird praktisch immer wieder server.available() aufgerufen, auch 
wenn gar keine Verbindung besteht. Diese Funktion beinhaltet wiederum 
einen Aufruf der tick() Funktion, welche der Kern des Netzwerktreiber 
ist.

Außerdem: AVR Mikrocontroller können Interruptroutinen nicht durch 
weitere Interrupts unterbrechen. Da du sehr viel Code in der 
LAN-Interruptroutine untergebracht hast, werden alle anderen Interrupts 
entsprechend lamge stehen bleiben - zum Beispiel der Systemtimer. Das 
ist auch Käse.

Schreibe dein Hauptprogramm (loop) als Zustandsautomat um, so dass es 
deine beiden Programmteile quasi parallel ausführt. Und vergiss die 
Interrupt-Leitung, die schafft nur weitere noch komplexere Seiteneffekte 
die du nicht haben willst.

By the way: Die Dokumentation der Library ist schrecklich unvollständig. 
Kein Wunder, dass du damit nicht klar kommst.

von Stefan F. (Gast)


Lesenswert?

> Und zudem MUSS der kleine AVR zu langsam sein

Für den relativ kleinen Mikrocontroller sind diese vielen float 
Operationen ein großer Brocken Arbeit, aber das ist 100% sicher nicht 
die Problemursache.

Wie gesagt ist das Timing der Kommunikation AVR<->Ethernet Controller 
sehr entspannt. Es wäre völlig egal, wenn der AVR sich zwischendurch 
mehrere hundert Millisekunden Rechenpausen genehmigt.

Problemursache ist hier, dass der ganze Ethernet Treiber nach dem 
Erzeugen der Webseite gar nicht mehr aufgerufen wird. Das ist aber kein 
Timing Problem, sondern ein Designfehler im Programmablauf.

> Zum Testen habe ich mal alles einzeln zusammen gebaut bis es nicht mehr
> lief und über geblieben ist das auslesen der 18b20 nehme ich das raus
> und ändere sonst nix läuft es super.

Das könnte auf einen Heap oder Stack Speicherüberlauf hindeuten. Was 
mich nicht wundert, da ja die Interruptroutine (LAN) ebenfalls sehr 
umfangreich ist.

> Wäre meine Schlussfolgerung...

Die ist falsch. Verzichte auf den Interrupt und benutze einen 
Zustandsautomaten. Mit etwas Glück löst sich dadurch auch dein 
Speicherproblem in Luft auf. Es könnte helfen, eine automatische 
Kontrolle des SPeichers einzubauen. Da wurde hier schonmal ausführlich 
diskutiert (-> Suchfunktion nutzen).

> würde es reichen alle float werte der Berechnung auf int zu ändern

Auch das könnte dein Speicherproblem lösen. Ich würde den Code erstmal 
auf weniger reduzieren. Lies einen Sensor aus, zeige dessen Wert auf dem 
Display an und mach eine minimale LAN Ausgabe (ohne Aktions-Buttons und 
dem entsprechenden Code zu Auswertung). Und erst wenn das zuverlässig 
läuft, erweitere den Code.

von Stefan F. (Gast)


Lesenswert?

Um das Verständnis für uIP zu Vertiefen, könnte ein Blick in die 
Quelltexte der Arduino Library und der uIP Dokumentation helfen.

Auf der Seite 
https://github.com/adamdunkels/uip/blob/master/doc/example-mainloop-with-arp.c 
findest du eine Hauptschleife für uIP, so wie dessen Entwickler Adam 
Dunkels es empfiehlt. So sehen auch meine uIp basierten Programme aus.

In deiner Arduino Library findest du den entsprechenden Code in der 
tick() Funktion wieder. Und da kannst du auch sehen, welche anderen 
Library Funktione tick() aufrufen.

Wichtig ist letztendlich, das tick() immer wieder aufgerufen wird - auch 
wenn der Server gerade nichts zu tun hat oder auf eine Verbindung 
wartet. Ohne regelmäßige tick() Aufrufe kann uIP nicht funktionieren.

von DAVID B. (bastler-david)


Lesenswert?

Vielen DANK für deine ausführlichen Beschreibung die ist sehr gut !
Ich bin jetzt nach vielen andren versuchen und deiner großen Hilfe zum 
erfolg gekommen.

nämlich mit

  (t++); //(Zählt t immer eins hinzu)

  if ( t > 1000) //(fragt ab ob 1000 erreicht sind dann wird gelesen)
  {
    temp1 = getTemperature(sensor1);
    temp2 = getTemperature(sensor2);
    temp3 = getTemperature(sensor3);
    temp4 = getTemperature(sensor4);
    temp5 = getTemperature(sensor5);
    temp6 = getTemperature(sensor6);
    temp7 = getTemperature(sensor7);
    temp8 = getTemperature(sensor8);
    temp9 = getTemperature(sensor9);
    temp10 = getTemperature(sensor10);
    temp11 = getTemperature(sensor11);
    temp12 = getTemperature(sensor12);
    (t = 0);
  }

Damit jagt der 2560 durch sein Programm das ist ganz neu :-)
Jetzt muss ich noch bremsen einbauen sonst zeigen die Displays nur 
Striche :-) ahh ist das toll ein erfolg.

Sind solch großen zahlen 1000 oder mehr eigentlich ein großes Problem 
?(belasten den RAM zustark) ?

Ich mache noch die spannungs abfrage anderes zurzeit liege ich noch gut 
bei:

Der Sketch verwendet 31622 Bytes (12%) des Programmspeicherplatzes. Das 
Maximum sind 253952 Bytes.
Globale Variablen verwenden 5782 Bytes (70%) des dynamischen Speichers, 
2404 Bytes für lokale Variablen verbleiben. Das Maximum sind 8192 Bytes.

Stefan Us du bist mein Held !

Eine frage noch was genau bewirk eigentlich delay ?
Ja klar es wird eine pause gemacht aber pausen gibt es doch eigentlich 
nicht ?
Wird das was sinnloses gerechnet oder was macht der Chip da genau ?

Vielen dank!

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

> Sind solch großen zahlen 1000 oder mehr eigentlich ein großes Problem?

Integer belegen 2 Bytes.
Floats belegen 4 Bytes.

Mit deinem Zähler löst du das Problem aber nicht wirklich. Du hast damit 
lediglich die Wahrscheinlichkeit des Aufhängens um Faktor 1000 
reduziert.

Wie wäre es, wenn du nur bis 12 Zählst und bei jedem Durchlauf nur einen 
Sensor abfragst?
1
DeviceAddress sensor[] = {
2
  /*1*/  { 0x28, 0xFF, 0x86, 0x2E,  0x74, 0x16, 0x3, 0xAF }
3
  /*2*/  { 0x28, 0xFF, 0x5, 0x72, 0x74, 0x16, 0x3, 0xE0 },
4
  ...
5
};
6
7
float temp[12];
8
9
...
10
11
t++;
12
temp[i] = getTemperature(sensor[i]);
13
if (t>12) t=0;

Du müsstest dann die 12 temp Variablen und die 12 Sensor Variablen durch 
Arrays ersetzen.


Aaaaber: Das geht völlig an meinem Verbesserungsvorschlag vorbei! Es 
wird dein Programm nicht wirklich zuverlässig machen. Du wirst auf den 
Interrupt verzichten müssen und einen Zustandsautomaten verwenden 
müssen.

Aber das kennen wir, eine gewisse Beratungsresistenz ist bei gewissen 
leuten ja bekannt.

von Stefan F. (Gast)


Lesenswert?

Was mit bei dieser Arduino Library noch völlig unklar ist, wie deren 
Entwickler sich vorstellen, mehrere Connections gleichzeitig zu 
bedienen. Denn das machen Web Browser ja. Sie bauen mehrere Verbindungen 
gleichzeitig auf, um Dateien/Webseiten herunterzuladen.

Soweit ich beim schnellen durchschauen der Quelltexte und Beispiele 
sehen konnte, ist aber wohl nur eine gleichzeitige Verbindung 
vorgesehen. Ich habe daher Zweifel, ob die Library überhaupt geeignet 
ist, Webbrowser zu bedienen.

von Einer K. (Gast)


Lesenswert?

Stefan U. schrieb:
> Was mit bei dieser Arduino Library noch völlig unklar ist, wie deren
> Entwickler sich vorstellen, mehrere Connections gleichzeitig zu
> bedienen. Denn das machen Web Browser ja. Sie bauen mehrere Verbindungen
> gleichzeitig auf, um Dateien/Webseiten herunterzuladen.
>
> Soweit ich beim schnellen durchschauen der Quelltexte und Beispiele
> sehen konnte, ist aber wohl nur eine gleichzeitige Verbindung
> vorgesehen. Ich habe daher Zweifel, ob die Library überhaupt geeignet
> ist, Webbrowser zu bedienen.

Um die Browser muss man sich keinen Kopf machen.
Die machen die Verbindungen auch nacheinander, wenns gleichzeitig nicht 
gelingt.
Streckt sich dann halt nur....
Und irgendwann hagelt es Timeouts, wenn es gar nicht gelingt, aber auch 
das dauert etwas...

von DAVID B. (bastler-david)


Lesenswert?

Sorry das es so lange gedauert hat aber.
Die Idee mit dem immer nur ein Sensor auslesen klingt auch gut und 
sinnvoll. werde noch mal drüber nachdenken.

Und auf den interrupt pin verzichte ich schon.
Hat wie du auch angedeutet hast nur ärger gemacht.

Und nur weil ich es nicht gleich verstehe oder ich ein andern weg der 
für mich auch ok ist gefunden habe,
Bin ich nicht gleich beratungsresistent ok ? DANKE


Wäre auch sehr nett wenn für noch jemand die frage von oben beantworten 
könnte.

>>Eine frage noch was genau bewirk eigentlich delay ?
>>Ja klar es wird eine pause gemacht aber pausen gibt es doch eigentlich nicht ?
>>Wird das was sinnloses gerechnet oder was macht der Chip da genau ?


Ich bedanke mich bei allen die mir geholfen haben.
VIELEN LIEBEN DANK!!

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

Das delay(x); lässt wohl eine Schleife laufen, Die x ms Zeit braucht.
In der Zeit macht der µC aber nichts Anderes - außer vll. auf Interrupts 
reagieren.

MfG

von Stefan F. (Gast)


Lesenswert?

> Wird das was sinnloses gerechnet

Genau das. In der Regel lässt man einfach ein paar zahlen in 
verschachtelten Wiederholschleifen hoch zählen, bis der gewünschte 
Zählwert (=zeit) erreicht ist. Im Prinzip funktioniert das wie ein 
mechanischer Küchentimer, nur mit Zählern statt Zahnrädern.

http://thumbs4.picclick.com/d/l400/pict/400660001207_/Kr%C3%A4hender-K%C3%BCchentimer-Hahn-Kikeriki-K%C3%BCchenwecker-Eieruhr-Kurzzeitmesser-Kr%C3%A4ht.jpg

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.