Vorgeschichte:
Ich habe vor ca. zwei Jahren in meiner zweiten Heimat Holzminden eine Modellbahner kennen gelernt. Dieser baut seit ca. 20 Jahren an seiner Modellbahnanlage, zusammen mit seinem Schwager an einer recht großen „Platte“ mit Märklin C Gleis, beide sind mittlerweile über 60. Die cs3 von Märklin überfordert sie etwas. Sie suchten dann einer Zufallsbeleuchtung für die Gebäude auf ihrer Anlage, gleich mal 50 Stück.
Über das Forum habe ich dann diesen Link hier im Forum gefunden (Original: herberts-n-projekt.de/basteleien-1/belebtes-haus/).
Beide waren von der Lösung recht angetan. Da ich Anfang des Jahres den Einstieg in KiCAD gewagt habe um ein PCB für ein „sinnloses, spaßiges“ Projekt, im Zusammenhang mit dem Arduino erstellt habe, wagte ich mich an eine überarbeitet Version des „Belebten Hauses“.
Als Baujahr 1966 bin ich kein Freund von SMS Bauteilen, deshalb blieb nur THT, auch hier kann man kleine Boards erstellen, die sich von Hand löten und warten lassen.
Hier die Entwicklung:
Schaltplan (nicht schön, aber funktional).
Zweiseitige Platine (38,1 mm x 26,1 mm):
3D Ansicht in der Simulation:
Bestückte Platine, weicht von der 3D Ansicht in KiCAD ab, da dort andere Bauteile als Grundlage verwendet wurden.
Alles bereit für den Funktionstest, Strippen und 3 mm LEDs dran.
Was kann das Board?
Es liefert „echte“ Zufallszeiten (Zeitspanne einstellbar über den Quellcode des µC) initialisiert durch das Auslesen des offenen ADC Ports, beschreiben des EEPROMS und ein Auslesen des EEPROMS. So schöne Zufallswerte hatte ich noch nie bei einem µC, PC oder einer KI/AI im Debugger.
Anschlüsse:
Einen Ausgang für Dauerlicht
Einen Ausgang für +5 Volt
Vier Ausgänge mit Zufallslicht
Einen Ausgang für TV Simulation.
Eingang für UC 6-20 Volt
Versorgung:
Alles von 6 Volt bis 20 Volt, egal ob AC oder DC, Digital habe ich noch nicht getestet, möchte es jemand testen?
Was ist verbaut:
Attiny85, µC
L4931-05, Spannungsregler
B125C1500G, Brückengleichrichter
6 x Vorwiderstand für LEDs
2 x Keramik Kondensator zum Abblocken
2 x Elko für Glättung und zur Stabilisierung
1 x Schraubterminal 2 pol, 2,54 mm RM
1 x Schraubterminal 14 pol, 2,54 mm RM
Kosten bei 50 Stück / Lieferant, Einzelpreis pro Modul
| 50 Stück | Stückpreis | |
| Digi-Key Corporation, Bauteile | 157,66 € | 3,15 € |
|---|---|---|
| eBay, 300 LEDs | 27,00 € | 0,54 € |
| AliExpress, Schraubklemmen | 56,18 € | 1,12 € |
| JLCPCB, PCB | 11,94 € | 0,24 € |
| AliExpress, Leitung | 11,00 € | 0,22 € |
| Aderendhülsen 600 Stk., Großhandel | 26,50 € | 0,53 € |
| Schrumpfschlauch, Großhandel | 8,00 € | 0,16 € |
| 298,28 € | 5,97 € |
Der Quellcode:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "EEPROM.h"
#define WOHNZIMMER PB0 // Raum zur flimmer LED
#define ZIMMER_1 PB1 // PB1 Zimmer 1
#define FLIMMER PB2 // TV Flimmern
#define ZIMMER_2 PB3 // PB3 Zimmer 2
#define ZIMMER_3 PB4 // PB4 Zimmer 3
#define ADC_PIN A0 // ADC Port Rauschen
#define ANZAHL_ZIMMER 4 // Anzahl Zimmer
#define PWM_PERIODE 500 // PWM Länge für Flimmern
#define FLIMMER_START 2000 // TV an
#define FLIMMER_ENDE 50000 //TV aus
#define RND_MIN 10000 // RND min. Wert
#define RND_MAX 70000 // RND max. Wert
#define LED_TAKT_1 9000 // Länge Takt 1
#define LED_TAKT_2 16000 // Länge Takt 2
#define LED_TAKT_3 25000 // Länge Takt 3
#define LED_TAKT_4 30000 // Länge Takt 4
#define SEED_ADDR 0 // RND Start
/* Simulation "belebtes Haus für die Modellbahn" */
/* Version "Flimmern nur wenn die Pin-2 LED an ist */
unsigned long flimmerStart,flimmerEnd; // Anfangs- und Endzeiten für das Flimmern
// LED Pins für das normale Blinken deklarieren
byte leds[] = {4, 3, 1, 0};
// LED Blinktakt in Millisekunden für diese Pins
unsigned long ledtakt[] = {LED_TAKT_1, LED_TAKT_2, LED_TAKT_3, LED_TAKT_4};
// Variablen zum Merken von millis()-Zeiten beim Schalten/Blinken
unsigned long ledtime[ANZAHL_ZIMMER];
void setup()
{
//Alle verwendeten Pins auf OUTPUT setzen
pinMode(WOHNZIMMER, OUTPUT);
pinMode(ZIMMER_1, OUTPUT);
pinMode(FLIMMER, OUTPUT);
pinMode(ZIMMER_2, OUTPUT);
pinMode(ZIMMER_3, OUTPUT);
//Alle verwendeten Pins auf LOW setzen
digitalWrite(WOHNZIMMER, LOW);
digitalWrite(ZIMMER_1, LOW);
digitalWrite(FLIMMER, LOW);
digitalWrite(ZIMMER_2, LOW);
digitalWrite(ZIMMER_3, LOW);
//PB5 als ADC INPUT, für Random
pinMode(ADC_PIN, INPUT);
//RND Wert aus ADC holen
init_random_seed();
}
boolean milliSekundenTakt(unsigned long dauer, unsigned long &alterWert)
{
// Parameter "dauer": Dauer einer Blinkphase (an bzw. aus)
// Parameter "alterWert": Variable zum Speichern des millis() Timers
// Rückgabewert: true wenn die Zeit bis zum nächsten Umschalten abgelaufen ist, sonst false
if (millis() - alterWert < dauer)
return false;
while (millis() - alterWert >= dauer) alterWert += dauer;
return true;
}
void blinkenImTakt(unsigned long RNDNr)
{
for (byte i = 0; i < ANZAHL_ZIMMER; i++) // alle LEDs in einer Schleife durchgehen
{
if (milliSekundenTakt(ledtakt[i] + RNDNr, ledtime[i])) // Takt für diese LED abgelaufen?
{
ledtakt[i] = random(RND_MIN, RND_MAX);
digitalWrite(leds[i],!digitalRead(leds[i])); // wenn ja ==> Umschalten
if (leds[i] == 0 && digitalRead(leds[i])) // LED wurde gerade eingeschaltet
{
flimmerStart = millis() + FLIMMER_START; // Anfangszeit für das Flimmern setzen
flimmerEnd = millis() + FLIMMER_ENDE; // Endzeit für das Flimmern setzen
}
}
}
}
void flimmernPwmPin()
{
// Die flimmernde LED im Zufallsmodus flimmern lassen
static unsigned long alterWert;
static byte flimmerDauer = 200;
static byte flimmerHelligkeit = 0;
if (milliSekundenTakt(flimmerDauer, alterWert)) // Takt abgelaufen?
{
flimmerDauer = random(1, 200); // neue Flimmerdauer als Zufallswert
if (millis() > flimmerStart && millis() < flimmerEnd)
{
flimmerHelligkeit = random(256); // neue Flimmerhelligkeit als Zufallswert
}
else
{
flimmerHelligkeit=0; // Flimmern aus wenn falsche Zeit zum Flimmern
}
PWMWrite(FLIMMER, flimmerHelligkeit);
}
}
void PWMWrite(byte LedPin, byte dutycycle)
// Pseudo PWM für digitalen Ausgang erzeugen
{
if (dutycycle == 0)
{
digitalWrite(LedPin, LOW);
}
else
{
digitalWrite(LedPin, HIGH);
delayMicroseconds(dutycycle);
digitalWrite(LedPin, LOW);
delayMicroseconds(PWM_PERIODE - dutycycle);
}
}
void loop()
{
blinkenImTakt(random(RND_MIN, RND_MAX));
flimmernPwmPin();
}
void init_random_seed()
{
int seed;
EEPROM.get(SEED_ADDR, seed);
seed += analogRead(ADC_PIN); //Rauschen vom offenen Pin holen
EEPROM.put(SEED_ADDR, seed);
randomSeed(seed);
}
Meine Arbeitszeit, mein Werkzeug und der ISP Programmer für den Attiny85 sind nicht berücksichtigt, das habe ich eh hier, da diese für andere Projekte eingesetzt werden, das ist ein Hobby. 




