Forum: Mikrocontroller und Digitale Elektronik (Aquariencomputer) Zeitschaltuhr mit mehreren Kanälen


von Marcel K. (marcel_kr)


Lesenswert?

Hallo beisammen,

ich bin gerade dabei mir einen Aquariencomputer zu bauen mit allem was 
man da so brauchen kann.
Unter anderem z.B.:

* 8 230V Schaltkanäle
* 8 Düngerpumpenkanäle
* 8 PWM Kanäle

Die Anforderungen sind, dass man für jeden Wochentag mehrere Ein- und 
Ausschaltzeiten für die 230V Kanäle festlegen kann bzw für die 
Düngerkanäle mehrere Aufrufe pro Tag möglich sind. Ich habe allerdings 
noch keine gute Idee, wie ich das ganze im Speicher abbilden soll. Eine 
Idee wäre für jeden Kanal und Wochentag im EEPROM beispielsweise 3 
Zeiten zu speichern. Was mir daran nicht gefällt, ist das das ganze dann 
doch recht unflexibel und speicherplatzraubend ist. Wäre es evtl 
schlauer soetwas wie [Wochentag, Stunde, Minute, AuszuführendeAktion] 
mit "AuszuführendeAktion" als Nummer einer Funktion zu speichern?

Ein anderes Feature, dass ich gerne bauen möchte ist eine Dimmung für 8 
Kanäle. Einerseits, soll es einen Modus geben, bei dem es eine 
Sonnenauf- und Untergangszeit gibt mit zwischendrin einer 
Wolkensimulation (das ist mehr oder minder schon im Programm vorhanden) 
und andererseits möchte ich gerne einen für den Tag festgelegten 
Helligkeitsverlauf abfahren können. Dieser soll dann (irgendwann mal) 
per PC-Programm an den µC gesendet werden können.
Zu dieser Geschichte dachte ich mir ich könnte eine bestimmte Anzahl an 
Tripeln aus Stunde, Minute und PWM-Wert im EEPROM ablegen und zwischen 
diesen interpolieren. Gibts da noch bessere Ideen?

Ich hoffe mal ihr könnt mir ein paar hilfreiche Tipps geben.

Viele Grüße,
Marcel

von Stefan (Gast)


Lesenswert?

Was ist daran unflexsibel die Werte im EEprom
zu speichern ? Wenn du ein EEprom von 1 K nimmst,
reicht das vollkommen aus um deine paar Daten zu
speichern. Abspeichern mußte, Tag,Monat, Uhrzeit,
Programmplatz und vielleicht das Jahr noch.
Diese dann im EEprom speichern und bei Bedarf wieder abrufen.

von Lehrmann M. (ubimbo)


Lesenswert?

Marcel Kr. schrieb:
> * 8 PWM Kanäle

Hier geht es wohl um die Dimmung von Licht oder? Da musst du nochmal 
differenzieren. Musst du Wechselspannung dimmen, so solltest du dich mit 
Phasenan- und Phasenabschnittssteuerung beschäftigen. Macht man dann mit 
einem Triac. Da braucht man den Komparator für die 
Nulldurchgangserkennung. 
http://de.wikipedia.org/wiki/Phasenanschnittsteuerung

Wenn du Gleichstrom-Lampen (ergo LEDs) hast, dann passt die PWM, musst 
halt vernünftige Mosfets verbauen.

Marcel Kr. schrieb:
> Die Anforderungen sind, dass man für jeden Wochentag mehrere Ein- und
> Ausschaltzeiten für die 230V Kanäle festlegen kann bzw für die
> Düngerkanäle mehrere Aufrufe pro Tag möglich sind. Ich habe allerdings
> noch keine gute Idee, wie ich das ganze im Speicher abbilden soll. Eine
> Idee wäre für jeden Kanal und Wochentag im EEPROM beispielsweise 3
> Zeiten zu speichern. Was mir daran nicht gefällt, ist das das ganze dann
> doch recht unflexibel und speicherplatzraubend ist. Wäre es evtl
> schlauer soetwas wie [Wochentag, Stunde, Minute, AuszuführendeAktion]
> mit "AuszuführendeAktion" als Nummer einer Funktion zu speichern?

Also Grundsätzlich wirst du ja sicher eine RTCC verwenden. Eine RTCC 
(real time calendar clock) ist ein unabhäniger Uhrenbaustein der dir an 
einer Schnittstelle die aktuelle Uhr zur Verfügung stellt. Das ganze ist 
sehr genau. Bei den meisten ist auch ein Kalender dabei.
Schau dir mal den  DS1337 (Reichelt 2,10) an. Der ist über I2C 
angebunden und hat nen Kalender dabei.

Grundsätzlich stellt sich die Frage, ob du irgendwo repetetive Sequenzen 
hast. Ergo jeden Tag um 0700 Licht an, um 2000 Licht aus. Jeden zweiten 
Tag düngen, etc. Das musst du wissen. Da solltest du dir vorher einen 
Plan machen.

Ansonsten holst du dir halt jede Sekunde (oder Minute) die Uhrzeit von 
deiner RTCC ab und holst dir beim Anschalten deiner Steuerung die Daten 
aus dem EEPROM in den RAM. Keinesfalls solltest du zu viele Zugriffe auf 
den EEPROM haben - darum lade es beim Systemstart in den RAM wenn du die 
RAM-Kapazitäten dazu hast.

So kannst du dir deinen eigenen Stack von Abläufen bauen. Im FIFO 
Prinzip: http://de.wikipedia.org/wiki/First_In_%E2%80%93_First_Out
Also das aktuellste Element (die nächstgelegene Uhrzeit) wird mit der 
aktuellen Uhrzeit verglichen. Das genügt ja wenn es sekündlich (oder 
wenn du willst auch minütlich) passiert.

Nachdem ich davon ausgehe, dass du wirklich wiederholende Sequenzen hast 
sollte das kein großer Aufwand sein. Ich würde mir da Funktionen zur 
Datumsberechnung machen. Wenn du z.B. alle 5 Tage düngen möchtest, so 
kannst du die 5 ja im EEPROM ablegen (zwecks Veränderlichkeit) und dir 
eine Funktion gibt dir das nächste Datum für die Düngung an. Das letzt 
Datum wird ebenfalls im EEPROM gepeichert. Beim Einschalten, lässt du 
also die Funktionen durchlaufen und erstellst dir so einen Stack (wie 
oben besprochen). Diese Datumsfunktionen gibt es bereits fertig oder man 
kann sie sich echt einfach schreiben. Schaltjahre sind schnell bestimmt 
siehe Wikipedia, die Anzahl der Tage im Monat sollte ebenfalls bekannt 
sein.

So würde ich das jetzt mal lösen. Wenn deine Fischlein natürlich jeden 
Tag eine neus Programm brauchen musst du dir was überlegen.

Marcel Kr. schrieb:
> Zu dieser Geschichte dachte ich mir ich könnte eine bestimmte Anzahl an
> Tripeln aus Stunde, Minute und PWM-Wert im EEPROM ablegen und zwischen
> diesen interpolieren. Gibts da noch bessere Ideen?

Das passt schon. Ich weiß nur immer nicht was du mit deinem EEPROM 
willst. Da legst du ja nur feste Basiswerte ab, die in Laufzeit ohne 
Neuprogrammierung veränderbar sein müssen. So viele sind das in meinen 
Augen allerdings nicht. Die Frage ist inwiefern du überhaupts was 
verändern musst. Das musst aber du wissen. Ich würde schon auch einen 
EEPROM verwenden. Im EEPROM legst du ja nur die Anfangszeit und Endzeit 
der Dimmung und Anfangs- und Endwert ab. Den Rest interpoliert ja wie du 
schon gesagt hast eine Funktion. Dazu noch eine Zufallsfunktion für die 
Wolken wie rand() und srand() mit einer Variable um auch wirklich 
halbwegs zufällig zu bleiben 
(http://www.cplusplus.com/reference/clibrary/cstdlib/rand/) und das 
war's eigentlich. Ich würde da nie und nimmer tausende Werte in den 
EEPROM legen.

Wenn du noch Fragen / Probleme hast melde dich gerne.

von Marcel K. (marcel_kr)


Lesenswert?

Hey,

also die Dimmung selbst ist kein Problem, für jeden Kanal wird das PWM 
Signal raus geführt und für 4 der Kanäle gibt es noch eine 1-10V 
Rausführung für dimmbare EVGs.
Die 8 PWM Kanäle will ich auf einen ATtiny auslagern, der das ganze per 
Soft-PWM macht und die Befehle vom Haupt-µC per I²C empfängt. So muss 
ich dem nur Kanal und Helligkeitswert schicken und der kümmert sich um 
den Rest.

Das mit den festen Zeiten ist so ne Sache. Ich wollte das Gerätchen gut 
dokumentiert bauen, so dass es auch andere Leute nachbauen können. 
Deshalb wollte ich sehr flexibel sein in den Zeiten.
Ich denke ich muss mir jetzt nochmal genau die Funktionen überlegen, die 
ich haben will und mir einen detaillierten Plan machen und Schritt für 
Schritt vorgehen. Bei so einem - für mich doch recht großen Projekt - 
bringt es wenig einfach drauf los zu programmieren hab ich festgestellt 
:)

Morgen mach ich mir mal ein paar genauere Gedanken dazu, was genau ich 
jetzt brauche.

Gute Nacht,
Marcel

von MaWin (Gast)


Lesenswert?

> Ich hoffe mal ihr könnt mir ein paar hilfreiche Tipps geben.

EEPROM hilft, die Daten wenigstens bei Stromausfall nicht zu vergessen. 
Klar kostet es ein paar Byte mehr Programm.

Aber du baust nichts anderes, als SPS schon seit 30 Jahren machen 
können, oder eben Aquariencomputer für 1 Becken statt deiner 8 Becken.

Schaltpläne für Relaisausgang und TRIAC-Ausgang sind ja wohl hinlänglich 
im Netz, Tasten und alphanumerisches LCD an einem per Trafo versorgten 
uC auch kein Problem.

Im Moment sehe ich vor allem, daß die immense Zahl an Daten den Benutzer 
überfordert und die Übersicht leiden lässt. Immerhin willst du nicht 
auch noch nach Wochentag differenzieren.

Wenn man sich schon die Mühe macht, so eine Schaltung zu entwerfen, 
sollte man darauf achten, daß sie auch für andere Einsatzzwecke nützlich 
sein kann, und das heisst neben der immensen Zahl von Ausgängen auch 
Eingänge: Optokoppler zur potentialgetrennten Erfassung von 5V, 24V und 
230V~ Signalen je nach Bestückung, und Analogeingänge nicht nur für 
0-10V, sondern auch für verstärkte Signale z.B. aus Pt100 oder KTY 
Temperatursensoren, also mit OpAmps so angeordnet daß die üblichen 
Schaltungen daraus bestückt werden können. Vielleicht willst du die 
Temperaturregelung ja dem uC überlassen (wovon ich bei teuren Fischen 
Abstand nehmen würde, der uC stürzt leichter ab als ein Heizstab, aber 
er könnte überwachen und bei Abweichung Alarm schlagen).

Wenn dann die Platine noch in ein orndentliches Gehäuse passt, kann sie 
auch für andere Leute (mit verändertem Programm) nützlich sein.

von Jens (Gast)


Lesenswert?

Hallo Marcel!

Um flexibel zu bleiben würde ich mir einzelne „Zeit Kanäle“ im EEprom 
einrichten, die dann z.B. 1x pro Minute abgefragt werden.

Aufteilung im EEprom:
Wochentag = Byte (1 Bit für jeden Wochentag)
Zeit = Word (Werte von 0 bis 2359)
Befehl = Byte (Ansteuerung/Aufruf der einzelnen Ports)
Daten = Byte (Zahlenwert für den Aufruf/Ansteuerung vom Port)

Damit würde man 5 Bytes im EEprom für einen „Zeit Kanal“ benötigen. Bei 
einem Mµ mit 1K EEprom könnte man so ca. 200 „Zeit Kanäle“ einrichten, 
dass sollte mehr als ausreichend sein. Durch die Verwendung eines Bits 
beim Wochentag kann man zusätzlich entscheiden ob der „Zeit Kanal“ nur 
an einem Tag der Woche, oder die ganze Woche verwendet werden soll. Und 
man kann dieses Byte auch gleich zur Auswertung „Zeit Kanal aktiv“ 
heranziehen (alle Bits 0 = nicht aktiviert). Wenn Dir eine Zeitschaltuhr 
mit Wochenprogramm und 200 verschiedenen Schaltzeiten ausreicht, dann 
könnte das ein Lösungsansatz sein.

Beispiele:
127;600;1;30
Jeden Tag der Woche um 6:00 Uhr Sonnenaufgang1 (Befehl1 = 
Dimmeransteuerung Nr.1 hoch zählen) mit einer Geschwindigkeit von 30 
(z.B. 30 Minuten).

127;2030;2;30
Jeden Tag der Woche um 20:30 Uhr Sonnenuntergang1 (Befehl2 = 
Dimmersteuerung Nr1 runter zählen) mit einer Geschwindigkeit von 30.

42;900;3;1
Di, Do und Sa wird um 9:00 Uhr gefüttert (Befehl3 = Futtern), bei der 
Station Nr1.

0;1200;4;5
Wird nicht ausgeführt, da kein Wochentag aktiviert wurde. Ansonsten um 
12:00 Uhr Programm4 abfahren (z.B. Gewitter) mit einer Laufzeit von 5 
Minuten.

Insgesamt würden Dir so 256 verschieden Befehle (Programme) zur 
Verfügung stehen, mit einem Übergabewert (Daten) von 0 bis 256. Damit 
kann man schon ordentlich Ballet veranstalten. Die Einstellungen würde 
ich über einen PC vornehmen und dann in den EEprom schieben...

LG Jens

von Jens (Gast)


Lesenswert?

Nachtrag, einen habe ich noch...

Im Byte „Wochentag“ wird ja das Bit7 (achte Bit) nicht verwendet. Wenn 
Du dieses Bit mit setzt, dann kannst Du auch noch eine Monatsabfrage mit 
einbauen, ohne dass Du etwas am Aufbau/Aufteilung im EEprom ändern 
musst. Ist Bit7 gesetzt, dann wertest Du einfach die Tage im Monat aus.

Beispiel:
132;1200;4;5
Es wird am 4. des Monats um 12:00 Uhr Programm4 abfahren (z.B. Gewitter) 
mit einer Laufzeit von 5 Minuten.

Damit kannst Du ganz einfach entscheiden ob ein „Zeit Kanal“ monatlich 
oder wöchentlich ausgeführt werden soll. Dir steht so also eine 
Zeitschaltuhr mit Monat und Wochentagsprogramm zur Verfügung...

LG Jens

von Marcel K. (marcel_kr)


Lesenswert?

Hi ihr,
danke für eure ausführlichen Antworten!

@Mawin:
Klar, es soll auch Eingänge zur Temperaturmessung geben, auch für z.B. 
einen Pegelschalter oder PH-Elektrode und Leitwertmessung, wobei ich das 
selbst nicht am Aquarium hab und von daher hat das bisher noch nicht so 
hohe Priorität.

Ja klar kann das schon jede SPS, aber ich will das hier ja speziell 
auf's Aquarium münzen. Und außerdem ne SPS kaufen kann jeder, aber denen 
entgeht dann der Spaß an der Entwicklung und der Löterei ;)

@Jens, danke für die Ideen, vor allem das mit dem Byte für den Wochentag 
finde ich super - auch die Monatserweiterung ist eine super Idee. 
Maximale Speicherplatznutzung :D
Ich hatte auch ein Byte für den Wochentag eingeplant, allerdings wäre da 
dann nur 1, 2, ..., 7 drin gestanden für eben diese Tage. Mit deiner 
Version spart man sich da dann noch speicher, wenn man ein Programm an 
mehreren Tagen haben möchte.

Außerdem habe ich jetzt, nach deinem Vorschlag, die 220V Kanäle und 
Düngung zu einer Struktur im Speicher gemacht, so hat man volle 
Flexibilität.

Hier mal die Strukturen die ich mir ausgedacht habe:
1
Lichtautomatik
2
8 mal folgende Struktur
3
1B Modus
4
1B PWM-Wert
5
1B Wolkensimulation an/aus
6
2B Sonnenaufgang Minute
7
1B Sonnenaufgang Dauer
8
2B Sonnenuntergang Minute
9
1B Sonnenuntergang Dauer
10
1B Max. Helligkeit
11
1B Min. Helligkeit
12
1B 220V Kanal (um EVGs komplett abzuschalten)
13
[8 x 12B = 96B]
14
15
Lichtprogramm
16
20 mal (oder mehr?) folgende Struktur
17
2B Minute
18
1B PWM-Wert
19
[20 x 3B = 60B]
20
21
220V Schaltkanäle und Düngung
22
1B Tag
23
2B Minute
24
1B Funktion   (220V Schalter/Düngung und jeweils Kanal)
25
1B Parameter  (220V: ein/aus - Düngung: zeit)
26
[Rest des EEPROM: 1024B - 156B = 868B -> 868B / 5 = 173 mögliche Zeiten]

Speziell für die Beleuchtung will ich das so machen, dass man folgende 
Modi zur Verfügung hat:
Manuell: Dürfte klar sein
Lichtautomatik: Ein und Aus zu fester Zeit mit bestimmter Dauer für 
Sonnenauf- und untergang. Zwischendrin wenn gewünscht Wolkensimulation
Lichtprogramm: Abfahren einer vorher festgelegten Reihe an Werten

Zur Erklärung für die Speicherstruktur für die "Lichtautomatik" ist zu 
sagen, dass hier auch gleich die sonstigen Einstellungen zu diesem 
Lichtkanal abgelegt sind, da diese Struktur ja nur ein mal pro Kanal vor 
kommt und es mir logisch erschien da einfach den rest noch dazu zu 
legen.

So weit so gut, ich glaube da könnte man schon gut Ballett veranstalten, 
wie du so schön sagtest ;)
Noch Ideen?

Viele Grüße,
Marcel

von ano2011 (Gast)


Lesenswert?

Für meine Timer hab ich diese Struktur geplant:

Stunde -> 5bit (0-31)
Minute -> 6Bit (0-63)
Tag -> 6Bit (0-63)
Monat -> 6Bit (0-63)
Kanal -> 3Bit (0-7)
Programm -> 4Bit (0-15)

macht 30Bit und somit 4Byte in denen 2Bit Reserve sind (für mehr 
Kanäle/Programme/oder was anderes)

Tag:
0-30 -> Tag (+1)
(Ausbaustufe 3)
31-37 -> Wochentag
41-47 -> Wochentag gerade Woche
51-57 -> Wochentag ungerade Woche

Monat:
0-11 -> Monat (+1)
(Ausbaustufe 3)
12-63 -> Kalenderwoche

Das spart Platz (4 statt 6 bis 10Byte).

Bisher hab ich micht jedoch noch nicht mit eeprom über i2c beschäftigt, 
aber ich hoffe, das ich das auch da drin so speichen kann.

von Marcel K. (marcel_kr)


Lesenswert?

Ok, das ist nochmal etwas komprimierter, dafür musst du das mühevoll 
wieder auseinander klabustern. Ich bin grad recht zufrieden mit der 
Möglichkeit, die ich oben beschrieben habe und wenn keiner noch ne 
bessere Idee hat dann werd ich das so in Angriff nehmen. Ich denke bei 
der Möglichkeit oben hat man noch genügend programmierbare Schaltzeiten 
und auch nicht zu viel Programmierarbeit ;) (Ok, ein paar Byte werden 
noch für andere zu speichernde Einstellungen drauf gehen bei mir, aber 
ob es jetzt 173 oder 160 Schaltzeiten sind ... ich glaub das ist 
genügend)

EEPROM über I²C sollte kein Problem sein. Da kann man sich ja Funktionen 
zum schreiben und abholen von Bytes aus dem EEPROM schreiben.

Viele Grüße

von MaWin (Gast)


Lesenswert?

> Klar, es soll auch Eingänge zur Temperaturmessung geben, auch für z.B.
> einen Pegelschalter oder PH-Elektrode und Leitwertmessung

Achte drauf, daß Eingänge, die elektrisch im Wasser hängen, 
potentialfrei sein müssen, es darf nicht sein, daß z.B. Strom von der 
Leitwertelektrode zur pH-Elektrode fliesst, weil zwischen ihnen eine 
Spannung liegt.

von Klaus D. (kolisson)


Lesenswert?

Lehrmann Michael schrieb:
> Also Grundsätzlich wirst du ja sicher eine RTCC verwenden. Eine RTCC
> (real time calendar clock) ist ein unabhäniger Uhrenbaustein der dir an
> einer Schnittstelle die aktuelle Uhr zur Verfügung stellt. Das ganze ist
> sehr genau. Bei den meisten ist auch ein Kalender dabei.
> Schau dir mal den  DS1337 (Reichelt 2,10) an. Der ist über I2C
> angebunden und hat nen Kalender dabei.

Da würde ich gern einhaken. Dieser Vorschlag von Michael ist bestimmt 
gut
gemeint aber wird dich durch die Ungenauigkeit dann doch nerven.

Wenn also ne RTC eingebaut wird dann doch besser etwas gutes wie DS3232.

Gruss Klaus de Lisson

von ano2011 (Gast)


Lesenswert?

> Ok, das ist nochmal etwas komprimierter, dafür musst du das
> mühevoll wieder auseinander klabustern.

nö, ich finde das recht einfach:
-> http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Bitfelder

struct
{
    unsigned Stunde:5
    unsigned Minute:6
    unsigned Tag:6
    unsigned Monat:6
    unsigned Kanal:3
    unsigned Programm:4
} TIMER[20];

so sieht das bei mir aus und rankommen geht über

TIMER[0].Stunde
...
TIMER[20].Programm

von Jens (Gast)


Lesenswert?

Hallo Marcel!

> Außerdem habe ich jetzt, nach deinem Vorschlag, die 220V Kanäle und
> Düngung zu einer Struktur im Speicher gemacht, so hat man volle Flexibilität.

Da fällt mir noch was zu den Ausgängen ein. Hier wolltest Du die PWM 
Ausgänge über einen ATtiny realisieren, per Software PWM. Ich würde hier 
lieber einen ATmega (z.B. den ATmega48) verwenden, dann kannst Du auf 
das TWI-Modul zurückgreifen. Des Weiteren würde ich alle Ausgänge (im 
ATmega48) als PWM Ausgänge programmieren und so 16 PWM-Ports zur 
Verfügung stellen. Der Vorteil wäre dass Du so per I2C-Bus um 16 Ports 
erweitern kannst und hier kann dann jeder Port alles (ist also egal 
wofür Du ihn verwendest). Benötigest Du PWM-Ports, dann steuerst Du sie 
mit Daten von 0 bis 256 an. Und benötigst Du nur Ein-Aus-Ports, dann 
steuerst Du sie mit 0 = Aus und 256 = Ein an. Beim „Master Mµ“ würde ich 
alle Ports als Eingang definieren (bzw. für Messfühler) und die Ausgänge 
eben über I2C zur Verfügung stellen. Da die Ausgänge hier nicht all zu 
schnell reagieren müssen wäre eine I2C Lösung durchaus möglich.

In dem Zusammenhang währe vielleicht auch eine „Modulare Programmierung“ 
interessant. Dazu müsstest Du allerdings noch ein weiteres Byte zur 
Ansteuerung opfern (fehlt dann also im EEprom). Insgesamt würden Dir 
dann 6 Bytes an Stelle der 5 Bytes (pro „Zeit Kanal“) zur Verfügung 
stehen, wodurch Du dann eine gezielte Modulzuweisung aufrufen kannst.

Beispiel: Wochentag, Zeit, Modul, Port, Daten
127;600;1;5;30
Jeden Tag der Woche um 6:00 Uhr wird das Modul1 (Programm1) mit Port5 
und den dazugehörigen Daten = 30 aufgerufen. Im Modul1 wird dann 
festgelegt was für eine Ansteuerung der Port erhält. Das Modul1 wäre 
hier also der Dimmer „Sonnenaufgang“, der den Port5 in der gewünschten 
Zeit30 hoch fährt. Von diesen Modulen brauchst Du dann nur so viel zu 
programmieren wie Du maximal benötigst (z.B. 10 Module mit Sonnenaufgang 
und 10 Module mit Sonnenuntergang). Und genau so machst Du es dann auch 
mit den Futterpumpen, hier wäre es ein Modul „Zeitglied“, welches für 
eine Zeit X dann einen Port einschaltet. Maximal könntest Du so 256 
verschiedene Module für verschiedene Aufgaben programmieren. Und jedes 
Modul könnte mit jedem Port verknüpft werden, flexibler geht es dann 
wirklich nicht mehr. Der Nachteil wäre dann aber dass Du selber darauf 
achten musst das ein Modul nicht mehrfach verwendet wird (oder Du 
programmierst die PC Eingabesoftware so dass sie darauf achtet).

> Hier mal die Strukturen die ich mir ausgedacht habe:
> Rest des EEPROM: 1024B - 156B = 868B -> 868B / 5 = 173 mögliche Zeiten

Ich würde den internen EEprom vom Mµ für die Zeitkanäle nutzen, denn der 
ist schön schnell. Bei der Änderung auf 6 Bytes pro „Zeit Kanal“ würden 
Dir dann immer noch ca. 166 Einträge zur Verfügung stehen. Alle anderen 
„Einstellungen“ würde ich in einen I2C-Bus EEprom hinterlegen, denn hier 
spielt die Geschwindigkeit keine große Rolle. Hier könntest Du dann auch 
die Daten für „Wolken“ hinterlegen, die müssen ja auch nicht sehr 
schnell nachgeladen werden...

ano2011 schrieb:

> struct
> {
>    unsigned Stunde:5
>    unsigned Minute:6
>    unsigned Tag:6
>    unsigned Monat:6
>    unsigned Kanal:3
>    unsigned Programm:4
> } TIMER[20];

Kann ich so eine Struktur auch im EEprom anlegen? Wenn ja, wie? Wenn 
nein, wie lade ich die EEprom Daten in die Struktur?

LG Jens

von ano2011 (Gast)


Lesenswert?

@Jens

weiter oben hatte ich schon geschrieben:

> Bisher hab ich micht jedoch noch nicht mit eeprom über i2c beschäftigt,
> aber ich hoffe, das ich das auch da drin so speichen kann.

also kann ich es dir noch nicht aus eigener Erfahrung sagen. Ich denke 
aber, das man die Arrays als Block im eeprom lesen/speichern kann.

Ich hab derzeit aber noch nicht die TLC-Hardware fertig, erst wenn die 
fertig ist, will ich mit der Programmierung weiter machen.

von Marcel K. (marcel_kr)


Lesenswert?

Hey,

tolle Ideen tun sich hier auf, freut mich ;)

Im Moment bin ich gerade in er Klausurphase, deshalb mach ich keine 
wirkliche Soft- oder Hardwareentwicklung, sonder sammel mal nur die 
Erkenntnisse wie ich was mache und was ich gerne hätte und so weiter. 
Nur falls sich einer wundert, dass es hier mehr oder minder nur um die 
graue Theorie geht. Aber am 29.9. is die Klausuphase rum und die 
Entwicklung kann los gehen :D

@MaWin, wie realisiere ich eine solche potentialfreiheit?

@Klaus, DS3232 als RTC, ist aufgenommen

@Jens
Stimmt, das mit dem Mega48 ist ne gute Idee, da die I/O Ports eh zu 
knapp sind und ich sonst noch einen Portexpander auf die Platine hätte 
packen müssen. Mit dem Mega48 sollte es glaube ich auch ohne gehen 
gehen.
Das mit den Modulen ist auch eine gute Idee, aber ich glaube das wäre 
fast schon wieder zu viel des guten ;)
Ein zusätzlicher EEPROM, darüber hab ich auch schon nachgedacht, dann 
muss man sich keine großen Gedanken mehr machen, alles so kompakt wie 
möglich zu speichern.
Ich glaube die Geschwindigkeit des abrufens aus dem EEPROM ist bei 
dieser Art der Anwendung relativ unkritisch oder?

@ano, also wenn man diese Struktur so im EEPROM speichern kann wäre das 
natürlich super, aber wie wüsste ich jetzt spontan auch nicht. Man 
müsste halt wissen wie dieses struct intern behandelt wird. 
Wahrscheinlich verwurstet der Compiler das in einzelne 8 bit Variablen, 
aber keine Ahnung wie man die einzeln speichert und wieder in das struct 
rekonstruieren kann.

Viele Grüße,
Marcel

von ano2011 (Gast)


Lesenswert?

schau dir mal das an:

Beitrag "EEPROM array of struct"

evtl. ist das genau das, was wir brauchen! ich komm leider vorerst nicht 
dazu (die Hardware für die LED Stripes muß erst stehen, bevor ich mit 
der Software weiter machen kann)

von Lehrmann M. (ubimbo)


Lesenswert?

Klaus De lisson schrieb:
> Lehrmann Michael schrieb:
>> Also Grundsätzlich wirst du ja sicher eine RTCC verwenden. Eine RTCC
>> (real time calendar clock) ist ein unabhäniger Uhrenbaustein der dir an
>> einer Schnittstelle die aktuelle Uhr zur Verfügung stellt. Das ganze ist
>> sehr genau. Bei den meisten ist auch ein Kalender dabei.
>> Schau dir mal den  DS1337 (Reichelt 2,10) an. Der ist über I2C
>> angebunden und hat nen Kalender dabei.
>
> Da würde ich gern einhaken. Dieser Vorschlag von Michael ist bestimmt
> gut
> gemeint aber wird dich durch die Ungenauigkeit dann doch nerven.
>
> Wenn also ne RTC eingebaut wird dann doch besser etwas gutes wie DS3232.
>
> Gruss Klaus de Lisson

Alternativ wäre ein PIC18  -  da gibt es einige mit eingebauter RTC oder 
zusätzlich ein DCF77 Empfänger.

von Marcel K. (marcel_kr)


Lesenswert?

@ano2011, so wie's aussieht wird da im Quellcode schon festgelegt, was 
ins EEPROM kommt. Das ist doch folgende Zeile aus dessen Quellcode wenn 
ich mich nicht irre:
1
Preset_str eePresets[6] EEMEM =
2
...
Ich weiß nicht ob das schreiben eines solchen structs in den EEPROM 
während der Laufzeit möglich ist.
Wenn ich jetzt hier mist erzähle, verbessert mich :)

@Michael, auf PIC werde ich wohl nicht mehr umsteigen, hab mich schon an 
die Atmels gewöhnt ;)

Über DCF77 hab ich auch schon nachgedacht, aber in einem anderen Thread, 
hat einer den DS3232 in einer Uhr verbaut und die ging nach einem Jahr 
um 3 Sekunden falsch. Von daher wäre mir das zu viel Aufwand, wenn ich 
auch mit dem RTC-Baustein eine so genaue Uhr bekomme.

Viele Grüße,
Marcel

von Karl H. (kbuchegg)


Lesenswert?

Marcel Kr. schrieb:
> @ano2011, so wie's aussieht wird da im Quellcode schon festgelegt, was
> ins EEPROM kommt. Das ist doch folgende Zeile aus dessen Quellcode wenn
> ich mich nicht irre:
>
1
Preset_str eePresets[6] EEMEM =
2
> ...

Das stimmt schon.

> Ich weiß nicht ob das schreiben eines solchen structs in den EEPROM
> während der Laufzeit möglich ist.

Natürlich ist das möglich. Sonst wäre ja ein EEPROM nicht sehr sinnvoll, 
wenn man es zur Laufzeit nicht beschreiben könnte.

von Marcel K. (marcel_kr)


Lesenswert?

Du darfst uns auch gerne an deiner Weisheit teilhaben lassen :)
Zeig doch mal einen Codeschnipsel, wie man solch einen Struct in das 
EEPROM schreibt.
Das man das EEPROM grundsätzlich während der Laufzeit beschreiben kann 
ist mir klar, wie man einen Struct da rein drückt jedoch nicht.

von Karl H. (kbuchegg)


Lesenswert?

Marcel Kr. schrieb:
> Du darfst uns auch gerne an deiner Weisheit teilhaben lassen :)
> Zeig doch mal einen Codeschnipsel, wie man solch einen Struct in das
> EEPROM schreibt.

Rate mal :-)

Wenn man es mit der Funktion
   eprom_read_block
ausliest, wie wird wohl die Funktion heißen, mit der man es beschreibt?


http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#EEPROM

von Master S. (snowman)


Lesenswert?

ohne alles gelesen zu haben: ich habe für die düngung eine 
autoscheibenwischerpumpe genommen (eBay für 10.-), und die steuere ich 
1x/tag für 0.x sekunden an. die düngflüssigkeit habe ich massiv mit 
wasser verdünnt, und auf den pumpeneinlass umgekehrt eine Petflasche 
gesteckt. passt alles wunderbar und günstiger geht es wohl kaum :-) viel 
glück und spass beim basteln!

von Marcel K. (marcel_kr)


Lesenswert?

Ok Karl Heinz, ich habs mir fast schon gedacht, als ich kurz im AVR-GCC 
Tut vorbei geschaut hab ;)
Hier mal ein Fetzen, den ich schnell geschrieben habe um zu gucken wie 
das funktioniert:
1
#include <avr/io.h>
2
#include <avr/eeprom.h>
3
#include <stdlib.h>
4
5
typedef struct
6
{
7
  unsigned stunde:5;
8
  unsigned minute:6;
9
} struct_lichtkanal;
10
  
11
struct_lichtkanal lichtkanal_preset[8] EEMEM;
12
13
int main (void)
14
{
15
  struct_lichtkanal lichtkanal[8];
16
  lichtkanal[0].stunde = 12;
17
  
18
  eeprom_write_block(&lichtkanal, &lichtkanal_preset[0], sizeof(struct_lichtkanal));
19
}
Wenn ich was im EEPROM gespeichert hab hab ich das bisher immer mit 
manuell festgelegten Adressen gemacht, irgendwie war mir das ein 
bisschen suspekt das dem Compiler zu überlassen. Kann mich einer 
aufklären was der da im Hintergrund macht? Sprich wo hin schreibt der 
das und woher weiß der beim nächsten mal kompilieren, das dieses eine 
Byte wieder an die selbe Adresse kommt?

@Master Snowman, bei ebay bietet ein sogenannter "xtronmann" immer 
wieder Dosierpumpen an. Teils als Auktion, teils als Sofortkauf. Ich 
denke die sind für den Zweck optimal (40ml/min bei 12V)

von Jens (Gast)


Lesenswert?

Hallo!

> Preset_str eePresets[6] EEMEM =
> > ...

Ich habe das gestern mal versucht ein zu geben, bin aber an der 
Umsetzung jämmerlich gescheitert. Mein Verständnisproblem liegt bei der 
Array, denn die Struktur ist ja eine Array und damit komme ich nicht 
klar.
Dazu habe ich mal eine Frage an die Fachleute. Kann man eine Struktur 
nicht „zwei mal“ aufteilen? Zum einen in die Struktur wie ich sie haben 
will und zum anderen z.B. in 5 Bytes (unsignet Char) auf die ich 
zugreifen kann. Das währe dann quasi wie eine Doppelbelegung der 5 
Bytes, nur dass man die 5 Bytes mit Hilfe der Struktur unterschiedlich 
beschreiben kann. Wenn das funktionieren würde, dann wäre das universal 
und auch EEprom unabhängig. Wenn ich zugriff auf die 5 Bytes hätte, dann 
könnte ich die z.B. mit „eeprom_write_byte()“ in den internen EEprom 
schreiben, oder mit „I2C_Write()“ in einen externen EEprom. Wäre so eine 
Strukturaufteilung möglich?

LG Jens

von Karl H. (kbuchegg)


Lesenswert?

Marcel Kr. schrieb:

> Hier mal ein Fetzen, den ich schnell geschrieben habe um zu gucken wie
> das funktioniert:


Fast perfekt.

Wenn du ein Array hast, brauchst du kein & um seine Adresse 
festzustellen. Ein Array wird immer so übergeben, dass seine 
Startadresse übergeben wird. Und beim sizeof solltest du dir angewöhnen, 
die Variable zu benutzen und nicht explizit den Datentyp. Das ist bei 
Änderungen des Datentyps einfacher, weil dir der Compiler einen 
Arbeitsschritt abnimmt.

D.h.
1
// das ganze Array
2
   eeprom_write_block( lichtkanal, lichtkanal_preset, sizeof(lichtkanal_preset) );
3
4
// oder nur 1 Element davon
5
   eeprom_write_block( &lichtkanal[2], &lichtkanal_preset[2], sizeof(*lichtkanal_preset) );


> Wenn ich was im EEPROM gespeichert hab hab ich das bisher immer mit
> manuell festgelegten Adressen gemacht, irgendwie war mir das ein
> bisschen suspekt das dem Compiler zu überlassen. Kann mich einer
> aufklären was der da im Hintergrund macht? Sprich wo hin schreibt der
> das und woher weiß der beim nächsten mal kompilieren, das dieses eine
> Byte wieder an die selbe Adresse kommt?

Na ja. Der Compiler (eigentlich der Linker) benutzt ja keinen Würfel um 
die Adressen zu vergeben. Der allokiert einfach von 0 beginnend die 
EEMEM-Variablen. D.h. wenn du noch was im EEPROM brauchst, schreibst du 
es einfach hinten an die Auflistung der EEMEM Variablen drann und gut 
ists.

von Marcel K. (marcel_kr)


Lesenswert?

Ok, danke für die Tipps!

Nutzt der Linker dann eigentlich jedes einzelne Bit aus?
Also wenn ich ein Struct mit meinetwegen zwei 3 Bit variablen habe und 
das nächste Struct mit zwei 5 Bit Variablen, werden dann genau 2 Byte 
aus dem EEPROM Benutzt? Prinzipiell ja wahrscheinlich nicht, da ich ja 
in eeprom_write_block eine Zieladresse angebe. Aber wird dann wenigstens 
bei einem Struct-Array jedes Bit genutzt?
Ich frage, weil ich ja auch wissen muss, wieviel Platz ich noch habe um 
die Anzahl der möglichen Zeitschaltuhren auszurechnen.

Viele Grüße,
Marcel

von Jens (Gast)


Angehängte Dateien:

Lesenswert?

Hallo alle Miteinander!

Die Geschichte mit der Struktur hat mir keine ruhe gelassen und so ist 
dann doch noch etwas „universelles“ entstanden. Ausgangspunkt waren 
hierbei die alten Daten:

Wochentag   --->   Wochentag oder Tag des Monats
Stunde   --->   Stunden
Minute   --->   Minuten
Programm   --->   bis 63 unterschiedliche Programme programmierbar
Port   --->   maximal erweiterbar bis 128 Ausgangsports
Daten   --->   Zahlen von 0 bis 255

Alle Bits zusammengerechnet ergeben 5 Bytes. Es werden also 5 Bytes pro 
„Zeit Kanal“ im EEprom benötigt (nicht wie vorher 6 Bytes). Daraus ist 
nun folgende Struktur entstanden:

union Zeit_Kanal_Maske {           // Maske für Zeit-Kanal
   struct ZK_Byte {                // Aufteilung für Maske
      unsigned long Stunde:5;      // Zahlen von 0 bis 31
      unsigned long Minute:6;      // Zahlen von 0 bis 63
      unsigned long Programm:6;    // Zahlen von 0 bis 63
      unsigned long Port:7;        // Zahlen von 0 bis 127
      unsigned long Daten:8;       // Zahlen von 0 bis 255
      unsigned char Wochentag:8;   // Zahlen von 0 bis 255
   } ZK_Maske;                     // Aufruf Maske
   unsigned char ZK_Byte[5];       // Aufteilung für Bytes
} ZK;                              // Aufruf Zeit-Kanal

Die Struktur kann nun wie folgt beschrieben werden:

ZK.ZK_Maske.Stunde = 22;
ZK.ZK_Maske.Minute = 31;
ZK.ZK_Maske.Programm = 2;
ZK.ZK_Maske.Port = 9;
ZK.ZK_Maske.Daten = 158;
ZK.ZK_Maske.Wochentag = 47;

Und wie folgt ausgelesen werden:

Variable1 = ZK.ZK_Maske.Stunde;
Variable2 = ZK.ZK_Maske.Minute;
Variable3 = ZK.ZK_Maske.Programm;
Variable4 = ZK.ZK_Maske.Port;
Variable5 = ZK.ZK_Maske.Daten;
Variable6 = ZK.ZK_Maske.Wochentag;

Darüber hinaus besteht nun aber auch noch die Möglichkeit an die 
einzelnen Bytes heran zu kommen (also ohne Maske). Man kann die Struktur 
wie folgt befüllen:

ZK.ZK_Byte[0] = eeprom_read_byte(&Daten1[0]);
ZK.ZK_Byte[1] = eeprom_read_byte(&Daten2[0]);
ZK.ZK_Byte[2] = eeprom_read_byte(&Daten3[0]);
ZK.ZK_Byte[3] = eeprom_read_byte(&Daten4[0]);
ZK.ZK_Byte[4] = eeprom_read_byte(&Daten5[0]);

Die Daten könnten z.B. aus dem EEprom stammen und so in die Struktur 
geladen werden. Und anders herum geht es natürlich auch, so könnte man 
z.B. Daten in einen EEprom schreiben:

eeprom_write_byte(&Daten1[0], ZK.ZK_Byte[0]);
eeprom_write_byte(&Daten2[0], ZK.ZK_Byte[1]);
eeprom_write_byte(&Daten3[0], ZK.ZK_Byte[2]);
eeprom_write_byte(&Daten4[0], ZK.ZK_Byte[3]);
eeprom_write_byte(&Daten5[0], ZK.ZK_Byte[4]);

Da nun auf jedes der einzelnen 5 Bytes zugegriffen werden kann, besteht 
nun auch die Möglichkeit die Daten in einen externen EEprom zu schreiben 
(oder ein anderes externes Medium). Bei einem 24C256 EEprom könnte die 
Ansteuerung z.B. so aussehen:

I2C_Start(160);   // Adresse
I2C_Write(0);   // High-Register
I2C_Write(0);   // Low-Register
I2C_Write(ZK.ZK_Byte[0]);   // Byte1
I2C_Write(ZK.ZK_Byte[1]);   // Byte2
I2C_Write(ZK.ZK_Byte[2]);   // Byte3
I2C_Write(ZK.ZK_Byte[3]);   // Byte4
I2C_Write(ZK.ZK_Byte[4]);   // Byte5
I2C_Stop()

Anbei noch ein Bild von einem Terminalprogramm, wo ich die Struktur 
getestet habe...

LG Jens

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.