LED Würfel + Schlange

Vorwort


In diesem Artikel werden wir (da der Artikel von einem Projekt von 2 Personen geschrieben und erstellt wurde) Ihnen erzählen, wie wir dem alten Spiel Leben eingehaucht haben, das von allen vergessen wurde.

Bild

Vorbereitung


Beginnen wir mit dem Würfel. Wir haben uns kein „Fahrrad“ ausgedacht und uns entschlossen, nach vorgefertigten Lösungen zu suchen. Der Artikel basierte auf einem Artikel eines norwegischen Autors, obwohl einige Änderungen vorgenommen wurden, die meiner Meinung nach von Vorteil waren.

Erstellen Sie Ihren eigenen LED-Würfel


Nachdem einige Punkte besprochen worden waren, wurde beschlossen, einen 8x8x8-Würfel herzustellen. Wir haben es geschafft, 1000 LEDs in loser Schüttung zu einem guten Preis zu kaufen, genau das, was Sie brauchen, obwohl dies keine wirklich geeigneten LEDs waren. Optisch würden blaue LEDs mit einer matten Linse besser aussehen, das Leuchten ist nicht so hell und gleichmäßiger. Bei transparenten LEDs gibt es ein weiteres Problem: Die untere Schicht hebt die oberen hervor. Trotz alledem müssen die LEDs hell genug sein, um das Bild klar zu machen. Für mehr Transparenz des Würfels ist es besser, kleine LEDs zu nehmen, beispielsweise 3 mm. Ein weiterer Punkt bei der Auswahl von LEDs ist die Länge der Beine. Wir werden den Würfelrahmen aus den Beinen der LEDs herstellen, damit sie nicht kleiner als die Größe des Käfigs sind.

Ein weiterer wichtiger Punkt beim Erstellen eines Würfels ist seine Größe. Wir fertigen den Rahmen mit den Beinen der LED, obwohl es Möglichkeiten gibt, Metallstangen oder Draht zu verwenden. Die Länge der Kathoden unserer LEDs betrug ungefähr 25 mm, daher wählten wir eine Zellengröße von 20 mm und entschieden uns, den Rest zum Löten zu verwenden, damit der Würfel stärker wird. Dies ist nur ein kleiner Unterschied zum Design des Autors des obigen Artikels.

Der nächste Schritt besteht darin, ein Layout für das Löten von Würfelschichten zu erstellen. Dies erleichtert das Löten und der Würfel ist gleichmäßiger. Das Layout ist sehr einfach, ich nahm ein Stück Sperrholz, zeichnete es auf die Größe meines Würfels und bohrte Löcher am Schnittpunkt der Linien in der Größe der LEDs.

Bild

Beim Löten mehrerer Schichten wurde mir klar, dass dieses Design nicht ausreicht, um als lange Schrauben zu dienen.

Bevor Sie mit dem Löten des Würfels beginnen, empfehle ich Ihnen, alles vorzubereiten. Aus persönlicher Erfahrung kann ich sagen, dass es viel bequemer ist, dies zusammen zu tun, weil Es gibt wirklich nicht genug Hände, eine Person setzt Kathoden ein und die zweite speist Lötmittel und Lote. Sie müssen dies schnell tun, die LEDs sind klein und haben Angst vor Überhitzung. Auch in verschiedenen Handbüchern heißt es, jede LED vor dem Löten zu überprüfen. Ich verstehe den Punkt nicht, verbringe viel Zeit mit einer im Wesentlichen bedeutungslosen Operation. Wir haben neue LEDs gekauft und alle haben funktioniert. Aber wenn Sie die Schicht gelötet haben, lohnt es sich bereits, alles gut zu überprüfen, da das Löten der LED von der Mitte aus eine unangenehme Aufgabe ist. Dies wurde durch persönliche Erfahrung überprüft.

Fahren wir also direkt mit dem Löten fort. Ich kann nicht sagen, dass dies der sicherste Weg ist, aber wir haben es so gemacht. Zunächst haben wir alle LEDs in unserem Layout. Es ist ratsam, sie reibungslos zu installieren. Dann gibt es keine Möglichkeit, etwas zu reparieren.

Bild

Bild

Dann biegen wir die Kathoden so, dass sie sich überlappen. Wenn alles fertig ist, können Sie mit dem Löten beginnen. Sie sollten sich jedoch an eine mögliche Überhitzung erinnern. Wenn das Löten fehlschlägt, beeilen Sie sich nicht zum Löten. Lassen Sie die LED besser abkühlen.

Wenn wir alle LEDs löten, erhalten wir 8 Streifen mit 8 LEDs. Um alles in eine Schicht zu verwandeln, verwendeten wir gewöhnlichen Aluminiumdraht, der zuvor begradigt wurde. Wir haben uns entschieden, nur 2 dieser „Stangen“ zu verwenden, um das Design nicht zu komplizieren, da es sich als ziemlich stark herausstellte.

Das Löten der letzten Schicht muss nicht erfolgen, da Sie sie dann wieder einfügen müssen. Jetzt, da wir alle 8 Schichten haben, müssen wir sie irgendwie zu einem Würfel kombinieren. Um den Würfel mehr oder weniger gleichmäßig zu machen, musste ich die Anoden wie in der Abbildung gezeigt biegen, jetzt geht es um die LED und kann sauber gelötet werden.

Bild

Bild

Wir löten den Würfel von der obersten bis zur untersten Schicht, während wir ständig die Funktion der LEDs überprüfen. Es ist besser, nicht faul zu sein, da es dann schwieriger ist, den Fehler zu beheben. Es ist besser, die Höhe zwischen den Ebenen mit Hilfe einiger Vorlagen einzustellen. Der Autor des obigen Artikels verwendete gewöhnliche Kronen. Wir hatten nichts Passendes, aber wir waren zu zweit, also beschlossen wir, alles manuell einzurichten. Es stellte sich ziemlich reibungslos heraus, aber nicht perfekt.

Nachdem Sie alle diese Aktionen ausgeführt haben, erhalten Sie den gesammelten LED-Würfel und einige verbrannte Finger. Dies hängt jedoch bereits von Ihrer Genauigkeit ab.

Bild

Bild

Schaltungsdesign


Um unsere Ideen umzusetzen, brauchten wir eine Art Mikrocontroller. Wir haben uns entschieden, auf dem Arduino Leonardo Mikrocontroller zu bleiben. Wir wollten uns nicht um Programmierer und die notwendige Software kümmern, nur brauchen wir keinen leistungsstarken Prozessor für unsere Aufgaben. Nachdem wir das fertige Gerät hatten, stellten wir fest, dass es möglich war, Nano zu verwenden, aber das ist nicht so kritisch. Um den Würfel zu steuern, haben wir uns für ein Telefon entschieden, das über Bluetooth mit dem Arduino verbunden ist. In unserem Fall wird der HC-05 verwendet, Sie können jedoch auch ein anderes verwenden.

Bild

Was aber wirklich wichtig ist, ist die Anzahl der Mikrocontroller-Pins, da wir 64 Anoden- und 8 Kathodenstifte haben, aber wir werden später darüber sprechen, sie anzuschließen. Wir haben uns entschlossen, die IO-Ports mit Hilfe von Schieberegistern zu erweitern. In unserem Fall sind dies die TI 74HC595-Register im DIP-Gehäuse, um die Sockel auf die Platine zu löten und die Mikroschaltungen selbst in diese einzufügen. Weitere Informationen zu diesen Registern finden Sie im Datenblatt. Ich möchte nur sagen, dass wir alles außer dem Register-Reset-Signal verwendet haben. Wir haben eine Einheit darauf angewendet, da es invers ist und wir den Ausgang für die Freigabe des Ausgangs auf Masse gedreht haben. Es ist auch invers und wir wollten es immer Daten von Registern empfangen. Sie könnten auch sequentielle Register verwenden, aber dann müssten Sie einen Decoder einsetzen, um auszuwählen, in welches Register Informationen geschrieben werden sollen.

Bild

Um den Stromkreis gegen Masse zu schließen und den Pegel zu wählen, den wir zünden möchten, benötigen wir Transistorschalter, na ja, oder nur Transistoren. Wir haben gewöhnliche NPN-Bipolartransistoren mit geringer Leistung verwendet, die in 2 parallel geschaltet sind. Ich bin mir nicht sicher, ob dies sinnvoll ist, aber es ist so, als würde der Strom besser fließen. Die Basis ist über einen Pull-up-Widerstand von 100 Ohm mit dem Mikrocontroller verbunden, der unsere Transistoren öffnet. Die Würfelschichten sind mit dem Kollektor verbunden, und die Emitter sind mit der Erde verbunden.

Bild

Bild

Den Würfel zusammensetzen


Sie konnten nichts Besseres finden, um den Würfel zu versorgen als das Netzteil des Tablets, dessen Parameter 5 V und 2 A betragen. Vielleicht reicht dies nicht aus, aber der Würfel leuchtet ziemlich hell. Um die LEDs nicht zu verbrennen, sind alle Anodenanschlüsse über einen Strombegrenzungswiderstand mit den Registern verbunden. Nach meinen Berechnungen hätten sie ungefähr 40 Ohm betragen sollen, aber ich hatte keine, also habe ich 100 Ohm verwendet.

Wir haben das alles auf 2 kleine Leiterplatten gelegt. Sie haben aus Mangel an Übung nichts absichtlich vergiftet, sondern einfach alles mit gewöhnlichen Dirigenten verbunden. Die Register mit den Anoden des Würfels wurden mit den Kabeln verbunden, die wir aus dem alten Computer herausgenommen hatten. Es ist einfacher, durch die Drähte zu navigieren.

Bild

Sie beschlossen, den Prototyp nach dem für das Löten verwendeten Layout zusammenzubauen.

Bild

Nachdem wir alles getestet und die Fehler korrigiert hatten, machten wir den Körper aus unserem Laminat, es stellte sich als gut heraus, weil es nicht lackiert werden musste. Hier ist das Endergebnis:

Bild

Lass es hell sein!


Es gibt einen Würfel, der bleibt, um ihn zum Leuchten zu bringen. Als nächstes werden verschiedene Modi (Modi) des Cubes beschrieben, um zu wechseln, welches Bluetooth + Android verwendet wurde. Die Telefonanwendung wurde mit Cordova geschrieben. Der Anwendungscode wird hier nicht beschrieben, aber der Link zum Repository wird in der Schlussfolgerung dargestellt.

Cube-Algorithmus


Da wir nicht auf alle LEDs gleichzeitig zugreifen können, können wir sie nicht alle gleichzeitig beleuchten. Stattdessen müssen wir sie in Schichten beleuchten.

Der Algorithmus ist wie folgt:

  1. Die aktuelle Ebene ist 0.
  2. Registrieren Sie die Maske für die aktuelle Ebene
  3. Schließen Sie den Transistor für die vorherige Schicht. Wenn die aktuelle Ebene Null ist, ist die vorherige Ebene die 7. Ebene
  4. Wir klicken Werte in Register. Der Wert erscheint an den Ausgängen der Register
  5. Öffnen Sie den Transistor für die Stromschicht. Hurra, eine Schicht leuchtet!
  6. Aktuelle Schicht ++. gehe zu: 2

Insgesamt wiederholt sich dieser Algorithmus ziemlich schnell, was uns die Illusion gibt, dass alle LEDs gleichzeitig leuchten (aber wir wissen, dass dies nicht so ist). Masken werden in einem 64x8-Byte-Array gespeichert.

Mods schreiben

Diese Modi wurden nicht in der Reihenfolge angezeigt, in der sie hier dargestellt werden. Bitte bestrafen Sie sie nicht mit einer Nummerierung im Code. Beginnen wir mit dem Einfachsten: Leuchten Sie alle LEDs auf.

Zünde den Würfel an
void Mode_2_Init() {
	for (byte z = 0; z < CUBE_EDGE_SIZE; z++) {
		for (byte y = 0; y < CUBE_EDGE_SIZE; y++) {
			for (byte x = 0; x < CUBE_EDGE_SIZE; x++) {
				cube->data[z * CUBE_LEVEL_SIZE + y * CUBE_EDGE_SIZE + x] = 1;
			}
		}
	}
}


Der "klebrige" Mod

Idee: Nur zwei Schichten von Null und Sieb brennen und sie sind zueinander invers (die LED in Position X leuchtet nur auf einer der Schichten). Die Position wird zufällig ausgewählt (aus irgendeinem Grund versucht jeder, einen Algorithmus zum Auswählen der Position zu finden), und die LED an dieser Position „kriecht“ zur oberen Ebene, wenn sie auf der unteren Ebene leuchtet, und entsprechend zur unteren, wenn sie auf der oberen Ebene leuchtet.

Sticky Code
void Mode_0() {
	byte positionToMove = random(CUBE_LEVEL_SIZE);
	byte fromLevel = cube->data[positionToMove] == 1 ? 0 : 7;
	bool top = fromLevel == 0;
	cube->ShowDataXTimes(5);
	while (true) {
		byte toLevel = top ? fromLevel + 1 : fromLevel - 1;
		if (toLevel >= CUBE_EDGE_SIZE || toLevel < 0) break;
		cube->data[fromLevel * CUBE_LEVEL_SIZE + positionToMove] = 0;
		cube->data[toLevel * CUBE_LEVEL_SIZE + positionToMove] = 1;
		cube->ShowDataXTimes(2);
		fromLevel = toLevel;
	}
}

void Mode_0_Init() {
	cube->Clear();
	for (byte i = 0; i < CUBE_LEVEL_SIZE; i++) {
		byte value = random(0, 2);  // max - 1
		cube->data[i] = value;  //first level
		cube->data[i + (CUBE_EDGE_SIZE - 1) * CUBE_LEVEL_SIZE] = !value;  //last level
	}
}


Wie es im Leben aussieht:



"Ein weiterer klebriger Mod"

Dieser Mod ähnelt dem vorherigen, außer dass die Ebene nicht brennt, sondern das Gesicht und die Lichter von diesem Gesicht nacheinander zum Gegenteil und dann zurück.

Ein weiterer klebriger Code
void Mode_3_Init() {
	cube->Clear();
	positions->clear();
	new_positions->clear();
	mode_3_direction = NORMAL;
	for (short y = 0; y < CUBE_LEVEL_SIZE * CUBE_EDGE_SIZE; y += CUBE_LEVEL_SIZE) {
		for (byte x = 0; x < CUBE_EDGE_SIZE; x++) {
			cube->data[x + y] = 1;
			positions->push_back(x + y);
		}		
	}
}

void Mode_3() {
	if (positions->size() == 0) {
		delete positions;
		positions = new_positions;
		new_positions = new SimpleList<short>();
		mode_3_direction = mode_3_direction == NORMAL ? INVERSE : NORMAL;
	}
	byte item = random(0, positions->size());
	short position = *((*positions)[item]);
	positions->erase(positions->begin() + item);
	byte i = 1;
	while(i++ < CUBE_EDGE_SIZE ) {
		cube->data[position] = 0;
		if(mode_3_direction == NORMAL) position += CUBE_EDGE_SIZE;
		else position -= CUBE_EDGE_SIZE;
		cube->data[position] = 1;
		cube->ShowDataXTimes(1);
	}
	new_positions->push_back(position);
}




Würfel in einem Würfel

Idee: Leuchten Sie die LEDs im Inneren des Würfels in Form von Flächen des Würfels mit Größen von 1 bis 8 LEDs und umgekehrt.

Würfel in einem Würfel
void Mode_1() {
	cube->Clear();
	for (byte cube_size = 0; cube_size < CUBE_EDGE_SIZE; cube_size++) {
		for (byte level = 0; level <= cube_size; level++) {
			for (byte x = 0; x <= cube_size; x++) {
				for (byte y = 0; y <= cube_size; y ++) {
					cube->data[level * CUBE_LEVEL_SIZE + y * CUBE_EDGE_SIZE + x] =
						(y % cube_size == 0 || x % cube_size == 0)
						&& level % cube_size == 0 ||
						(y % cube_size == 0) && (x % cube_size == 0) ? 1 : 0;
				}
			}
		}
		cube->ShowDataXTimes(5);
	}
	for (byte cube_size = CUBE_EDGE_SIZE - 1; cube_size > 0; cube_size--) {
		for (byte level = 0; level <= cube_size; level++) {
			for (byte x = 0; x <= cube_size; x++) {
				for (byte y = 0; y <= cube_size; y++) {
					cube->data[level * CUBE_LEVEL_SIZE + (CUBE_EDGE_SIZE - 1 - y) * CUBE_EDGE_SIZE + (CUBE_EDGE_SIZE - 1 - x)] =
						(((y % (cube_size - 1) == 0 || x % (cube_size - 1) == 0) && (level % (cube_size - 1) == 0))
						|| ((y % (cube_size - 1) == 0) && (x % (cube_size - 1) == 0) && level % cube_size != 0))
						&& x < (cube_size) && y < (cube_size) ? 1 : 0;
				}
			}
		}
		cube->ShowDataXTimes(5);
	}
}


Wie sieht es aus:



Und schließlich die Schlange

Von den Merkmalen der Implementierung der Schlange ist anzumerken, dass es keine Einschränkungen für das Feld gibt, und dementsprechend erscheinen Sie auf der anderen Seite, wenn Sie den Würfel einerseits verlassen. Sie können nur verlieren, wenn Sie auf sich selbst stoßen (in Wahrheit können Sie nicht gewinnen).
Es lohnt sich auch, separat über das Management zu sprechen:

Bei einer zweidimensionalen Implementierung dieses Spiels gibt es keine Probleme mit dem Management: vier Schaltflächen und alles ist offensichtlich. Bei einer dreidimensionalen Implementierung ergeben sich mehrere Steuerungsoptionen:

1.6 Tasten. Mit dieser Option hat die Taste ihre eigene Bewegungsrichtung: Bei den Auf- und Ab-Tasten ist alles offensichtlich, und der Rest der Tasten kann an die Kardinalpunkte „gebunden“ werden. Wenn Sie die Taste „Links“ drücken, ändert sich der Bewegungsvektor immer „West“ usw. Bei dieser Option treten Situationen auf, in denen sich die Schlange nach Osten bewegt und wir auf West klicken. Weil Die Schlange kann sich nicht um 180 Grad drehen. Sie müssen solche Fälle separat behandeln.

2.4 Tasten (Up Down Left Right). Die Aktionen dieser Schaltflächen ähneln denen einer zweidimensionalen Implementierung, außer dass alle Änderungen relativ zur aktuellen Richtung des Bewegungsvektors vorgenommen werden. Lassen Sie mich anhand eines Beispiels erklären: Wenn Sie sich in der horizontalen Ebene bewegen und die Taste „Auf“ drücken, gelangen Sie zur vertikalen Ebene. Wenn Sie sich in einer vertikalen Ebene durch Drücken von „Auf“ bewegen, bewegen wir uns in einer horizontalen Ebene gegen die Richtung der X-Achse, für „Ab“ - in Richtung der X-Achse usw.

Natürlich haben beide Optionen ein Existenzrecht (es wäre interessant, andere Steuerungsoptionen zu kennen). Für unser Projekt haben wir das zweite gewählt.

Richtungscode
void Snake::ApplyUp() {
	switch (direction) {
	case X:
	case Y:
		direction = Z;
		directionType = NORMAL;
		break;
	case Z:
		direction = X;
		directionType = INVERSE;
	}
}

void Snake::ApplyDown() {
	switch (direction) {
	case X:
	case Y:
		direction = Z;
		directionType = INVERSE;
		break;
	case Z:
		direction = X;
		directionType = NORMAL;
	}
}

void Snake::ApplyLeft() {
	switch (direction) {
	case X:
		direction = Y;
		directionType = directionType == NORMAL ? INVERSE : NORMAL;
		break;
	case Y:
		direction = X;
		directionType = directionType;
		break;
	
	case Z:
		direction = Y;
		directionType = NORMAL;
	}
}

void Snake::ApplyRight() {
	switch (direction) {
	case X:
		direction = Y;
		directionType = directionType;
		break;
	case Y:
		direction = X;
		directionType = directionType == NORMAL ? INVERSE : NORMAL;
		break;
	case Z:
		direction = Y;
		directionType = INVERSE;
	}
}

void Snake::ChangeDirection(KEY key) {
	switch(key) {
	case UP:
		ApplyUp();
		break;
	case LEFT:
		ApplyLeft();
		break;
	case RIGHT:
		ApplyRight();
		break;
	case DOWN:
		ApplyDown();
		break;
	}
}


Das Ergebnis des Programms:





Links zum Quellcode des Würfels und die Firmware für die Telefon - Anwendung:

Anwendung
Firmware

Ergebnis


Als Ergebnis erhielten wir eine primitive Konsole und eine Art Lampe mit der Möglichkeit einer dynamischen Beleuchtung. In Zukunft planen wir die Entwicklung einer Leiterplatte und die Verbesserung der Firmware. Es ist auch möglich, zusätzliche Module hinzuzufügen.

Source: https://habr.com/ru/post/de388369/


All Articles