Forum: Mikrocontroller und Digitale Elektronik Konfigurationsdaten wie speichern?


von Elias B. (bouni)


Lesenswert?

Hallo zusammen,

ich habe das MDB Protokoll [0] auf einem AtMega644P implementiert und 
das ganze läuft auch eigentlich ganz schön.

Nun bin ich dabei das ganze ein wenig aufzuräumen.

Unter anderem habe ich eine Setup Funktion.
Die empfängt Konfigurationsdaten vom Master und speichert diese.
Darauf antwortet der AtMega mit seinen Konfigurationsdaten.

Nun ist die Frage ob es ein übliches vorgehen gibt um solche Daten 
abzulegen?

Bis jetzt hab ich einfach byte Array's die die Daten aufnehmen.
1
uint16_t justReset[2] = {0x0000,0x0100};

Ist im Code aber nicht wirklich schön zu lesen und wenn man einen Wert 
per Kommando anpassen will das greif ich über den index des jeweiligen 
Array's auf das entsprechende Byte zu. denn passenden Index zu finden 
erfordert aber jedes mal einen Blick in die Spezifikation und ein zählen 
der Bytes um das n'te Byte zu finden das man manipulieren will.

Wäre super wenn jemand da was dazu sagen könnte oder evtl. sogar einen 
Codeschnipsel posten könnte :)

Danke im Voraus

Elias

[0] http://www.vending.org/technology/MDB_Version_4-2.pdf

von Max G. (l0wside) Benutzerseite


Lesenswert?

Du könntest einen struct implementieren und die empfangenen Daten da 
dann reinkopieren.
1
struct daten_t { short wert1, unsigned short wert2 } daten;
2
3
void receive_data(short*);
4
5
[...]
6
7
receive_data(&daten);
8
x = daten.wert1;

Theoretisch besteht zwar die Gefahr, dass der Compiler die Felder nicht 
in der angegebenen Reihenfolge ablegt oder noch irgendwelche Leerbytes 
dazwischenquetscht, so dass der symbolische Zugriff nicht mehr 
funktioniert. Praktisch habe ich das noch nie erlebt.

Max

von Purzel H. (hacky)


Lesenswert?

Das uebliche Vorgehen ist Konfigurationsdaten im EEPROM abzulegen. Dann 
ueberleben sie einen Restart.

von Karl H. (kbuchegg)


Lesenswert?

Elias B. schrieb:

> Bis jetzt hab ich einfach byte Array's die die Daten aufnehmen.

Dann fehlt dir hier ganz einfach eine Zwischenschicht, die den Bytewust, 
den du über die Schnittstelle reinkriegst, erst mal in vernünftig 
benutzbare Konfigurationsvariablen umformatiert.

> per Kommando anpassen will das greif ich über den index des jeweiligen
> Array's auf das entsprechende Byte zu. denn passenden Index zu finden
> erfordert aber jedes mal einen Blick in die Spezifikation und ein zählen
> der Bytes um das n'te Byte zu finden das man manipulieren will.

?
Alles Dinge, die mit ein paar Hilfsfunktionen zu lösen sind. Du scheinst 
noch nicht begriffen zu haben, dass ein Transfer-Protokoll nicht das 
geringste darüber aussagt, wie du die Dinge speicherst, bzw. wie man 
dann im Programm (oder als Benutzer) auf die Werte zugreift.
Leg dir deine Datenstrukturen so zurecht, dass du mit ihnen gut 
programmierern kannst und nicht so, dass du sie möglichst banal über 
eine Leitung verschicken kannst. Während des Programmierens brauchst du 
die Werte ständig, also wirst du diese Zugriffe einfach machen und 
möglichst so, dass man keine oder kaum Fehler machen kann. Transfer sind 
aber genau 2 Funktionen: senden und empfangen. Wenn man dort ein wenig 
Aufwand treiben muss, dann macht man diesen Aufwand nur einmal und nur 
an genau diesen beiden Stellen.

von Elias B. (bouni)


Lesenswert?

Hallo zusammen,

erst mal Dank für eure Antworten!

>Leg dir deine Datenstrukturen so zurecht ...

Hast du mir evtl. einen Ausschnitt wie du so etwas löst, oder ein Open 
Source Projekt wo ich mir Anregung holen könnte?

Vielen Dank schon mal :)

von Max G. (l0wside) Benutzerseite


Lesenswert?

Kernighan/Ritchie. Steht zwar nicht unter GPL, beschreibt aber ein für 
Dich sicher hilfreiches Projekt.

Max

von Karl H. (kbuchegg)


Lesenswert?

Elias B. schrieb:

> Hast du mir evtl. einen Ausschnitt wie du so etwas löst, oder ein Open
> Source Projekt wo ich mir Anregung holen könnte?

Hat doch Max G. weiter oben schon angesprochen.

Du könntest natürlich einen Haufen globaler Variablen haben, oder die 
alle in einer struct sammeln. So wie du das haben möchtest.

Überleg dir ganz einfach, wie du im Programm auf die Werte zugreifen 
willst. Was ist für dich in der Benutzung angenehm? Und das 
implementierst du dann. Oftmals geh ich auch so vor, dass ich erst mal 
das benutzende Programm schreibe (oder zumindest anreisse) um zu sehen, 
welche Verwendung der Konfigurationsdaten ich haben werde. Daraus folgt 
dann, wie ich die Daten strukturiere. Das Pferd wird also von hinten 
aufgezäumt.

Ich erfinde mal was.
Da sei eine Ampel. Diese Ampel soll konfigurierbar sein auf
* Länge der Rotphase (in Sekunden)
* Länge der Gelbphase (in Sekunden)
* Länge der Grünphase (in Sekunden)
* Soll die Ampel Grün-Blinken oder direkt von Grün nach Gelb umschalten?
  (In Österreich blinken die Ampeln 5 mal, in Deutschland nicht)
* Soll es eine Nachtschaltung für Gelb-blinkend geben?
  Wenn ja, wann fängt sie an und wann hört sie auf?


Das sollen meine Konfigurationswerte sein.
So. Jetzt skizziere ich mein Ampelprogramm ungefär. Ich werde es als 
Statemachine implementieren und auf die meisten Konfigurationswerte 
möchte ich ganz einfach über eine Funktion zugreifen können. So ungefähr

  while( 1 )

    switch( state )

      case RED:
        WaitTime = ConfigRedTime();
        nextState = RED_WAIT;
        break;

     ...

daraus ergeben sich Funktionen für den Zugriff: Die Zeiten will ich als 
Integer haben und das soll die Zeit in Sekunden direkt sein.
Die Entscheidungswerte ja/nein sind ganz normale Boolsche Variablen mit 
der C üblichen Bedeutung: 0 bedeutet Nein, 1 bedeutet Ja
Und die Zeiten, die leg ich als 16 Bit Wert ab. Das reicht mir, weil ich 
nicht mehr als Minutenauflösung brauche und ein Tag hat nicht mehr als 
24*60 = 1440 Minuten. Die Zeiten krieg ich direkt als Minuten seit 
Mitternacht.

Damit hab ich dann auch schon eine Vorstellung darüber, was ich alles an 
Konfigurationswerten brauchen werde und auch welche Datentypen ich dafür 
benutzen will.

Also mach ich mir eine erste Version einer Ampel-Konfiguration

struct ConfigLights
{
  uint8_t   redPhase;
  uint8_t   yellowPhase;
  uint8_t   greenPhase;
  uint8_t   doGreenBlink;
  uint8_t   nightlyYellowBlink;
  uint16_t  nightlyBlinkStart;
  uint16_t  nightlyBlinkEnd;
};

und erst dann überleg ich mir, wie jetzt der Datenaustausch mit einem 
Frontend-Programm aussehen wird, mit dem dann der freundliche Polizist 
(oder wer das dann auch immer macht), die Ampel an einer Kreuzung 
konfiguriert. Und der macht das auch nicht, in dem er die Werte direkt 
irgendwo kryptisch eingeben muss, sondern der bekommt ein schönes 
GUI-Tool, welches ihm die Werte übersichtlich präsentiert und auf 
Knopfdruck zur Ampel überträgt.

von Elias B. (bouni)


Lesenswert?

Hallo zusammen,

Danke für die sehr ausführliche Beschreibung Karl Heinz!
Ich denke ich werd das so angehen und schauen was sich ergibt.

Vielen Dank nochmal

Elias

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.