Forum: Mikrocontroller und Digitale Elektronik Arduino: page-write in I2C eeprom verliert sporadisch ein Byte


von Joachim B. (jar)


Angehängte Dateien:

Lesenswert?

Peter D. schrieb:
> Wie oben schon gesagt, ich sammele alle Zeichen in einen Puffer und
> bearbeite sie erst nach dem CR.

genau so!

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Peter D. schrieb:
> Eine Task darf alle anderen
> nicht auf unbestimmte Zeit blockieren.
Aus dem Grund hat meine I2C Klasse, welche ich vor einiger Zeit in 
diesem Thread vorgestellt habe, einen CallBack um die EEPROM Wartezeit 
eben nicht zu verplempern.

: Bearbeitet durch User
von Kai (ksb)


Lesenswert?

Hallo Nemopuk, Helmut H, Joachim B, Klaus (feelfree) und Veit,

vielen herzlichen Dank für eure hilfreichen Anregungen und Antworten.

Nemopuk:
1
Wo kommen die 20ms Verzögerung her? Ich würde das Problem dort beheben, 
2
denn das ist nicht normal.
Wichtigster Punkt: Die 20ms sind der ausgewogenen Reaktion auf die 
Fernbedienung geschuldet. Nichts nervt hier mehr, als verzögerte 
Reaktion oder wenn Tastendrücke verloren gehen.
Das Gesamtprogramm ist nicht blockierend. Jede Funktion in der Loop wird 
zyklisch aufgerufen und arbeitet dann einen ihre Aufgabe ab.
So kann zum Beispiel das LED-Fading oder eine Melodie ungestört 
weiterlaufen, während beliebige andere Funktionen ausgeführt werden.

Helmut:
1
Vielleicht schaust Du dir mal diese Arduino lib an: https://docs.arduino.cc/libraries/at24c/
2
Die kümmert sich um I2C transfer buffer limit 32 Byte AT24 page size 64 Byte Aufruf mit beliebigem bytecount byc, z.B. beginned ab buffer[4] nach EEPROM adr:
Vielen Dank - super Lib - nur leider ist mein Flash fast voll.....
Beim nächsten Projekt bestimmt.

Joachim:
1
dann nutze den ATmega1284p mit 16KB Ram, Leerplatinen gibt es bei OSH Park, fertig aufgebaute leider nicht mehr zu finden.
Der ATMEGA 1284 ist ein 40-Pinner. Meine Platine mit ATMEGA328P (28-Pin) 
ist bereits gefertigt und funktioniert einwandfrei.
Alle Funktionen bis auf das Einlesen der Dateien sind fertig. Wenn diese 
Funktioniert ist das Projekt abgeschlossen.
Eine Frage am Rande, welche ich dir schon immer mal stellen wollte: Hast 
du eine 1977 eine Ausbildung bei der Deutschen Bundespost in Düsseldorf 
gemacht?

Klaus:
1
Richtig wäre c) in der Empfangsroutine immer nur so viele Bytes aufsammeln wie halt da sind. Erst wenn sich z.B. 32 Bytes angesammelt haben werden diese weggeschrieben.
Genau das meinte ich damit: bestimmen, wie viel Platz für den Page-Write 
bleibt, diese Anzahl abwarten und dann Schreiben.
Es muss aber ein Timeout geben, wenn das Ende der Übertragung erreicht 
ist, aber bis zum Erreichen des Page-Endes noch Daten fehlen.

Veit:

diese Antwort fällt mir schwer - es tut mir leid, wenn ich dir das 
Gefühl vermittelt habe, deine Vorschläge zu ignorieren. Das ist 
definitiv nicht so!
 Nochmal: wirklich vielen Dank für deine Mühe mit dem Testen und 
Verbessern meines Minimal-Sketches!

Ich habe deine Vorschläge nicht ignoriert und bin in den vorherigen 
Antworten auf meine Beweggründe bereits geschildert:

1. Ich habe dein abgespecktes Minimal-Programm (ohne EEPROM-Zugriff 
mittlerweile 100 Mal getestet - es kommt bei mir nie durcheinander.
2. Ich habe deine wirklich sehr elegantes Einlese-Routine getestet. Sie 
funktioniert perfekt. ABER: das verbliebene RAM in der Applikation 
reicht höchstens für 200 Zeichen....


a) Der Sketch von Veit arbeitet ohne externes EEPROM - daher ist das 
Timing völlig anders.... - habe ich daher nicht weiter untersucht.
1
Deine Argumentation verstehe ich nicht. Versteht bestimmt niemand. Ich weiß nicht wie du Fehlersuche betreibst wenn das Offensichtliche 
2
ignoriert wird. Ich habe gezeigt das deine Einleseroutine fehlerhaft ist. Wenn man das ohne EEprom nachvollziehen kann, dann umso besser. Es 
3
gibt dabei genau so einen Versatz wie Eingangs von dir festgestellt.
Antwort siehe oben
1
Wie eine saubere Einleseroutine aussehen kann bzw. aussieht habe ich mit Link und Code gezeigt. Warum das alles ignoriert verstehe ich echt nicht mehr.
Habe ich keinesfalls ignoriert, denn ich habe sie getestet. Sie 
funktioniert perfekt, nur leider habe ich nicht so viel RAM.
Die Dateien sind mindestens 2kB groß, was einer Arraygröße von 2000 
Bytes entspricht.

Hier der Speicherbedarf meines realen Programmes (mit der bisheriger 
Einlese-Routine):
Der Sketch verwendet 32222 Bytes (99%) des Programmspeicherplatzes. Das 
Maximum sind 32256 Bytes.
Globale Variablen verwenden 1580 Bytes (77%) des dynamischen Speichers, 
468 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

1
Dein festhalten am paarweisen einlesen ist jedenfalls Mist. Du suchst lieber an anderen Baustellen und versaust dir den Code mit Zwangswartezeiten u.ä.. Wenn ich dann Ideen lese wie "Empfangsroutine nicht mehr verlassen" oder "Warteroutine" ...

Ich muss schon 2 ASCII-Zeichen lesen und zu einem Byte zusammensetzen, 
bevor ich es ins EEPROM schreiben kann - siehst du das anders?
Die Zwangswartezeit gibt es nur nach dem ersten Byte - ab hier darf die 
Einlese-Routine nicht verlassen werden, da andernfalls durch die 
doppelte Zykluszeit von 20ms der Puffer überläuft.
Mit "Warteroutine" meinte ich konkret das Warten auf eine ausreichende 
Anzahl von Daten für den Page-Write.
1
Ich denke du hast keine Zeit? Aber möchtest noch mehr blockieren? Mein wiederholter Rat. Fang nochmal sauber von vorn an.
Nicht "mehr blockieren" sondern lediglich an der richtigen Stelle mit 
Timeout auf das 2. ASCII-Zeichen warten.
Habe ich - es gibt dann ein Problem am Ende - der Puffer läuft hier 
über.
Die Ursache ist die Zykluszeit in Verbindung der geringen Anzahl 
geschriebener Daten.

Deshalb die Routine, welche auf das Eintreffen eine ausreichender Anzahl 
von Daten wartet.

Ich hoffe, ich konnte alle Missverständnisse beseitigen und habe 
niemanden mit meinen Antworten "vor den Kopf gestoßen", was keinesfalls 
gewollt wäre!

Viele Grüße
Kai

: Bearbeitet durch User
von Kai (ksb)


Lesenswert?

Hallo zusammen,

es läuft endlich - bisher jedoch nur im Uno getestet, dafür mit mehr 
Daten (512 ASCII-Zeichen = 256 Bytes). Jetzt bin ich mit diesem an der 
Grenze der Logging-Kapazität....

Ein Delay von 50ms in der Loop bringt die Routine nicht durcheinander.
Die Anzahl der zu sammelnden Bytes musste ich oberhalb von 25 Bytes 
begrenzen, da der serielle Puffer andernfalls auf 60 hochläuft, was mir 
zu unsicher war. Mit der Begrenzung liegt der Maximalwert bei 48.
1
+++++++++++-
2
3
Max. buffer fill state: 48 number real received bytes: 256 variable cnt: 256 OK  Char left in serial buffer 0 Remaining -1 Timeout 0 Checksum 0
4
5
1. page-write: cnt 0  cur_byte 24  -> 24 status 0 written 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17   read 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 
6
2. page-write: cnt 24  cur_byte 8  -> 32 status 0 written 18 19 1A 1B 1C 1D 1E 1F   read 18 19 1A 1B 1C 1D 1E 1F 
7
3. page-write: cnt 32  cur_byte 24  -> 56 status 0 written 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37   read 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 
8
4. page-write: cnt 56  cur_byte 24  -> 80 status 0 written 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F   read 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 
9
5. page-write: cnt 80  cur_byte 16  -> 96 status 0 written 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F   read 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 
10
6. page-write: cnt 96  cur_byte 24  -> 120 status 0 written 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77   read 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 
11
7. page-write: cnt 120  cur_byte 24  -> 144 status 0 written 78 79 7A 7B 7C 7D 7E 7F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F   read 78 79 7A 7B 7C 7D 7E 7F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 
12
8. page-write: cnt 144  cur_byte 16  -> 160 status 0 written 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F   read 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F 
13
9. page-write: cnt 160  cur_byte 24  -> 184 status 0 written A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7   read A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 
14
10. page-write: cnt 184  cur_byte 24  -> 208 status 0 written B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF   read B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF 
15
11. page-write: cnt 208  cur_byte 16  -> 224 status 0 written D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF   read D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF 
16
12. page-write: cnt 224  cur_byte 24  -> 248 status 0 written E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF F0 F1 F2 F3 F4 F5 F6 F7   read E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF F0 F1 F2 F3 F4 F5 F6 F7 
17
13. page-write: cnt 248  cur_byte 8  -> 256 status 0 written F8 F9 FA FB FC FD FE FF   read F8 F9 FA FB FC FD FE FF 
18
19
Log of combined values (val): 
20
 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF 00
21
22
EEPROM Settings
23
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  16
24
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F  32
25
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F  48
26
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F  64
27
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F  80
28
50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F  96
29
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F  112
30
70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F  128
31
80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F  144
32
90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F  160
33
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF  176
34
B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF  192
35
C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF  208
36
D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF  224
37
E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF  240
38
F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF  256
39
40
RAM rx_test
41
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  16
42
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F  32
43
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F  48
44
30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F  64
45
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F  80
46
50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F  96
47
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F  112
48
70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F  128
49
80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F  144
50
90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F  160
51
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF  176
52
B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF  192
53
C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF  208
54
D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF  224
55
E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF  240
56
F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF  256
57
58
EEPROM clear
59
60
RX-RAM clear
61
62
BUFFER clear

Ich werde jetzt die Routine zunächst in den fliegenden Aufbau mit 
Arduino Mega integrieren und dann die Datenmenge erhöhen.

Viele Grüße
Kai

von Kai (ksb)


Lesenswert?

Hallo Peter d,

entschuldige, dass ich erst jetzt antworte, aber ich habe noch mit der 
Routine gekämpft.

Auch dir vielen Dank für alle hilfreichen Tipps und Beispiele.
1
Dann mach doch das EEPROM Zeugs einfach mit in die schnellen Tasks vor 
2
der 20ms Wartezeit:
Guter Vorschlag - es gibt aber in dem Sinne keine Wartezeit von 20ms. 
Diese Zeit ist die Zykluszeit aller nacheinander aufgerufenen Funktionen 
der Loop.
1
Nein, das ist (fast) immer eine Sackgasse. Eine Task darf alle anderen 
2
nicht auf unbestimmte Zeit blockieren.
3
Wenn eine Task gerade auf etwas warten muß, dann verlasse sie einfach 
4
und setze sie beim nächsten Aufruf fort. Mit einem switch/case kann man 
5
sich merken, wo weitergemacht werden soll.
6
Wie oben schon gesagt, ich sammele alle Zeichen in einen Puffer und 
7
bearbeite sie erst nach dem CR.
Das Warten passiert nur im Datenübertragungsmenü und das auch nur, wenn 
Mindestens nur ein Zeichen eingetroffen ist. In diesem Fall warte ich 
eine gewisse Zeit auf das 2. Zeichen. Kommt das nicht, wird die 
Wartezeit beendet.

Viele Grüße
Kai

von Joachim B. (jar)


Lesenswert?

Kai schrieb:
> Hallo

selber, was ist mit:

Wichtige Regeln - erst lesen, dann posten!

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

von Falk B. (falk)


Lesenswert?

Kai schrieb:
> Das Warten passiert nur im Datenübertragungsmenü und das auch nur, wenn
> Mindestens nur ein Zeichen eingetroffen ist. In diesem Fall warte ich
> eine gewisse Zeit

Wieviel? Wenn man es richtig macht, wartet man exakt GAR NICHT, sondern 
holt das nächste Zeichen beim nächsten Aufruf der Statemachine ab. 
Siehe Multitasking. Und wenn man den RX Interrupt benutzt, 
wartet man mal sicher nicht.

von Kai (ksb)


Lesenswert?

Hallo Joachim,

Entschuldigung - hatte ich nicht als so lang empfunden - kann es leider 
nicht mehr ändern.

Viele Grüße
Kai

von Kai (ksb)


Lesenswert?

Hallo Falk,
1
Wieviel? Wenn man es richtig macht, wartet man exakt GAR NICHT, sondern
2
holt das nächste Zeichen beim nächsten Aufruf der Statemachine ab.
3
Siehe Multitasking. Und wenn man den RX Interrupt benutzt,
4
wartet man mal sicher nicht.

2 ms

Viele Grüße
Kai

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Kai schrieb:
> 2 ms

Ist deutlich mehr, als "gar nicht".
(eben waren es noch 20ms)

von Kai (ksb)


Angehängte Dateien:

Lesenswert?

Hallo und einen schönen Restsonntag,

der aktuelle Stand ist, dass Dateien bis 1900 Byte (mehr Daten habe ich 
zurzeit noch nicht) fehlerfrei abgespeichert und wieder eingelesen 
werden können und die eingelesenen funktional sind
(dies bedeutet, dass mit den eingelesenen Daten die exakt identische 
Funktion gegeben ist, wie mit dem Original). Sicherheitshalber gibt es 
noch eine Checksumme.

Zwischendurch hatte ich eine riesige Schrecksekunde, als das Logging 
jede Menge Fehler zeigte - das lag aber daran, dass Arrays des Logging 
überliefen.
Der darauf folgende Absturz hat es geschafft, falsche Daten in die RTC 
zu schreiben und alle Kalenderdaten zu verfälschen. Da zahlte es sich 
aus, dass ich endlich ein Backup einlesen konnte....

Die Daten werden über die Eingabeaufforderung (CMD) eingelesen und 
ausgegeben (siehe Screenshot).
Anbei ein auch ein Screenshot des Logging der Datenübertragung - jedes + 
in der obersten Zeile bedeutet, dass genug Daten von der seriellen 
Schnittstelle kamen, das - am Ende, dass hier ein Timeout auftrat, da 
die Anzahl geringer war, als die mögliche Anzahl für Page-Write
(für dieses Logging wurden die Daten über den seriellen Monitor 
gesendet).

Beim Erstellen des Screenshots dachte ich darüber nach, ob Veit evtl. 
mit anderen Einstellungen (CR, CR+LF) getestet hat? Mein Sketch verträgt 
diese nicht.

@Arduino F:
1
Ist deutlich mehr, als "gar nicht".
2
(eben waren es noch 20ms)
20ms ist die Zykluszeit des Gesamtprogrammes - 2ms ist der Wert für das 
Timeout, wenn nur 1 Zeichen eintrifft.

Ist auf jeden Fall ein riesiges Erfolgserlebnis....

Viele Grüße
Kai

von Kai (ksb)


Angehängte Dateien:

Lesenswert?

Jetzt hatte ich doch glatt die Datei ohne Schrecksekunde vergessen.....

von Kai (ksb)



Lesenswert?

Hallo zusammen,

anbei der aktuelle Stand:

Mittlerweile ist der Datenbestand angestiegen, so dass ich die 
Übertragung von Dateien oberhalb von 8 kB (cnt = 8605 Bytes entsprechend 
40 Melodien mit je 215 Bytes + 1 Byte Präambel + CRC) erfolgreich prüfen 
konnte.

Interessant ist, dass sich das Verhalten der Datenübertragung mittels 
Eingabeaufforderung (CMD) geringfügig ändert. Nicht eindeutig 
verifizierte Hypothese ist, je nachdem ob man vorher mittels Arduino-Ide 
Programme übertragen hat oder nicht. Es funktioniert, jedoch erkennt der 
PC teilweise das Dateiende-Zeichen nicht und es vergehen einige Sekunden 
bis zum Timeout durch den PC. Danach befinden sich die Daten in der 
angegebenen Datei (Test.txt).

Nachdem ich bei der Datenübertragung einige Male nicht darauf achtete, 
den richtigen Bereich anzuwählen, habe ich eine automatische Erkennung 
des Datentyps implementiert.
Beim Senden wird den Daten ein Zeichen vorangestellt, welches den Typ 
repräsentiert (S=Setting, C=Kalender, M=Melodie, T=Text, A=Alle). Beim 
Empfang wird anhand dieses Zeichens die EEPROM-Adresse umgeschaltet.

Dabei wäre ich fast in die böse Falle gelaufen, dass die Definitionen 
der einzelnen EEPROM Bereiche nicht an der selben Page-Anfangs-Adresse 
lagen. Das wurde mir bewusst, als ich diese Funktion in den PAP aufnahm.
Hier hat mich (bzw. die Daten) zufälligerweise aber die eingebaute 
Begrenzung der Anzahl zu schreibender Bytes zwecks Limitierung der 
maximalen Anzahl von Zeichen im seriellen Puffer gerettet.
Bei der ersten Neudefinition der EEPROM-Bereiche ereilte mich dann ein 
typischer Rechenfehler, so dass von der jeweiligen Anfangs-Adresse nur 
noch 1 Byte bis zur Page-Grenze verblieben, wodurch es dann zu 
Schreibfehlern kam.
Anmerkung: Eine erneute Ermittlung der erlaubten Anzahl ist zum 
Zeitpunkt der Bereichsumschaltung nicht mehr möglich, da die Daten 
bereits aus dem Puffer gelesen wurden. Dazu müsste die Routine so 
geändert werden, dass zuerst nur 1 Byte gelesen wird.
Versehentlich habe ich natürlich auch mehrfach alte (Test-)Daten (ohne 
Präambel) übertragen, wobei dann doch Daten überschrieben wurden. Als 
Abhilfe - sowie auch um weiterhin Testdaten einlesen zu können, wurde 
die Adresse als Default auf einen 8k großen Testbereich gelegt.

Jetzt bleibt noch die Frage offen, wie ich es denn schaffen will, alle 
Funktionen in den 32kB des ATMEGA 328P unterzubringen.....

Nach erster Sichtung aller Funktionen schien es recht aussichtslos und 
darauf hinauszulaufen, auf einige Funktionen verzichten zu müssen.
So habe ich beispielsweise erst einmal die Funktion, Daten innerhalb des 
internen EEPROM umzukopieren, zu vergleichen und zu löschen, welche 
bisher als Ersatz für eine Datensicherung diente, deaktiviert, wodurch 
ich 1kB gewann.
Weiteres Potenzial fand ich in der Tastenauswertung der Fernbedienung 
für die 18 Menüs. Hier war es beispielsweise möglich, die Auswertung für 
einige Menüs zusammenzufassen.

Dann habe ich alle Funktionen daraufhin überprüft, ob diese in der 
Stand-Alone-Variante (ohne permanent angeschlossenen PC) überhaupt 
sinnvoll sind (beispielsweise EPROM-DUMP). Das brachte nochmal fast 1kB.

Die Idee, alle Textkonstanten ins externe EEPROM zu verlagern, habe ich 
deshalb verworfen, weil das Gerät im Falle des Ausfalls des EEPROMS 
nicht mehr bedienbar wäre (zurzeit fallen dann nur die Melodien von 
Robson Couto und die Datensicherung aus). Das wären weitere 500 Bytes 
gewesen.

Ebenso habe ich auf zu tiefe Schachtelung von Funktionen verzichtet, um 
sporadischen Abstürzen vorzubeugen.

Intensive Überarbeitung aller Texte ergaben noch einmal ein paar Bytes, 
so dass nun alle Funktionen (einschließlich der Kopierroutine) 
integriert sind.

Ob dieser Aufwand nun sinnvoll ist oder nicht, ist die Frage der 
Sinnhaftigkeit eines jeden Hobbys. Auf jeden fall war es sehr lehrreich 
und hat auch viel Spaß gemacht.

Nun kann ich mich der optisch ansprechende Gestaltung des Gerätes 
widmen. Ideen zur Erweiterung verschiebe ich erst einmal, obwohl es da 
schon einige gibt.

Viele Grüße
Kai

von Kai (ksb)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

weshalb nicht mal versuchen, das ganze EEPROM zu sichern um die Daten in 
ein neues und unprogrammiertes zu übertragen? Gedacht, getan und es 
funktioniert (siehe cnt_32k.png).

Da blieb dann noch die Frage, wie sicher die Übertragung funktioniert 
bzw. wie viel "Luft" noch bis zum nicht mehr funktionieren ist. Daher 
habe ich die Übertragungsgeschwindigkeit zunächst auf 19200 Baud erhöht. 
Diese Funktionierte immer noch ohne Fehler.
Eine zu optimistische Erhöhung auf 57600 Baud schlug (fast 
erwartungsgemäß) fehl. 38400 Baud führt sporadisch zu Fehlern.
Da ich mich aber schon mit 9600 BAUD abgefunden hatte, ist die doppelte 
Übertragungsrate ein netter Bonbon (All_send.png).

Viele Grüße
Kai

von Wastl (hartundweichware)


Lesenswert?

Kai schrieb:
> Viele Grüße
> Kai

Eine Datenübertragung ist erst dann als sicher (funktionierend)
zu betrachten wenn sie unabhängig von der Datenrate arbeitet.

Stell dir vor du kannst bei 10MBit Ethernet im Internet surfen,
aber bei 100MBit nicht. Würdest du das akzeptieren?

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Wastl schrieb:
> Eine Datenübertragung ist erst dann als sicher (funktionierend)
> zu betrachten wenn sie unabhängig von der Datenrate arbeitet.

Nein!
Sie hat unter definierten Bedingungen zu funktionieren.
Außerhalb dieser definierten Rahmenbedingungen darf sie versagen.

von Wastl (hartundweichware)


Lesenswert?

Arduino F. schrieb:
> Außerhalb dieser definierten Rahmenbedingungen darf sie versagen.

Na gut. Chacun à son goût.

von Joachim B. (jar)


Lesenswert?

Wastl schrieb:
> Eine Datenübertragung ist erst dann als sicher (funktionierend)
> zu betrachten wenn sie unabhängig von der Datenrate arbeitet.
>
> Stell dir vor du kannst bei 10MBit Ethernet im Internet surfen,
> aber bei 100MBit nicht. Würdest du das akzeptieren?

komische Logik, neuerdings bekomme ich bei meinem AVR NETIO immer 
Fehlermeldungen (timeout) weil es zu langsam ist. Wenn mein LTE 
Kontingent aufgebraucht ist bekomme ich gedrosselt keine Webseite mehr 
über GSM (auch timeout) obwohl der Vertrag Flatrate mit runterschalten 
verspricht.

von Falk B. (falk)


Lesenswert?

Kai schrieb:
> Eine zu optimistische Erhöhung auf 57600 Baud schlug (fast
> erwartungsgemäß) fehl. 38400 Baud führt sporadisch zu Fehlern.

Dann ist dein Protokoll oder Handshake Schrott.

von Nemopuk (nemopuk)


Lesenswert?

Falk B. schrieb:
> Dann ist dein Protokoll oder Handshake Schrott.

Er hat ja keins. Insofern bleibt wohl kaum anderes übrig, als eine 
passende Baudrate festzulegen.

von Falk B. (falk)


Lesenswert?

Nemopuk schrieb:
>> Dann ist dein Protokoll oder Handshake Schrott.
>
> Er hat ja keins. Insofern bleibt wohl kaum anderes übrig, als eine
> passende Baudrate festzulegen.

Das nennt der Zeitgeist dann wohl "fail".

von Kai (ksb)


Lesenswert?

Hallo Wastl, Arduino F, Joachim, Nemopuk und Falk,

vielen Dank für eure Antworten.

der Zweck der seriellen Datenübertragung ist in diesem Fall eine 
gelegentliche Datensicherung auf dem PC sowie das Zurückschreiben ins 
EEPROM und zwar "On the Fly".
Das bedeutet, dass die eintreffenden Daten sofort mittels Page-Write ins 
EEPROM geschrieben werden. Für diesen Zweck ist aus meiner Sicht eine 
Übertragung mit fixen Parametern vollkommen ausreichend.


@Arduino F:
1
Nein!
2
Sie hat unter definierten Bedingungen zu funktionieren.
3
Außerhalb dieser definierten Rahmenbedingungen darf sie versagen.
Stimme ich 100% zu

@Falk:
1
Das nennt der Zeitgeist dann wohl "fail".
Aus deiner Sicht mag dies zutreffen - für meine Zwecke ist es vollkommen 
ausreichend

Eventuell war das im LCD angezeigte "Auto-Detect" missverständlich: es 
bezieht sich hier auf die automatische Erkennung des Datentyps und 
daraus resultierender Einstellung der Speicheradresse.

Viele Grüße
Kai

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.