lastprogramm brauchst nur in readADXL.
dort machst die statisch - allerdings hatte ioch vorhin schon angefangen aufzuteilen, ich weiss noch nicht, wie sich das insgesamt ausgewirkt hat.
Musste das leider beiseite legen. Aber es wird.
[edit]
Du wertest die Seite nur an zwei Stellen im control aus.
Wenn ich das vorhin nicht ganz verkackt habe, war das der letzte Stand:
Der Sketch verwendet 7068 Bytes (92%)
Globale Variablen verwenden 314 Bytes (61%)
// +----------+ +---------+
// Pixel | 51 52 53 | Fläche | ^ |
// | 48 49 50 | | 5 |
// | 45 46 47 | | |
// +----------+----------+----------+----------+ +---------+---------+---------+---------+
// | 33 34 35 | 36 39 42 | 06 07 08 | 09 12 15 | | ^ | | ^ | |
// | 30 31 32 | 37 40 43 | 03 04 05 | 10 13 16 | | 3 | 4 > | 0 | 1 > |
// | 27 28 29 | 38 41 44 | 00 01 02 | 11 14 17 | | | | | |
// +----------+----------+----------+----------+ +---------+---------+---------+---------+
// | 18 21 24 | | |
// | 19 22 25 | | 2 > |
// | 20 23 26 | | |
// +----------+ +---------+
#if (F_CPU>7370000) //neopixel library required 7.37MHz minimum clock speed; this line is used to skip this sketch in internal testing. It is not needed in your sketches.
#include <tinyNeoPixel_Static.h> // ATTiny WS2812b Bibliothek
#include <TinyWireM.h> // ATTiny I2C Bibliothek
#include <avr/power.h>
// ATTiny WS2812b Initialisierung
const uint8_t datenPin = 4; // WS2812b DatenPin
const uint8_t ledAnzahl = 54; // WS2812b LED Anzahl
uint8_t pixels[ledAnzahl * 3]; // Array für jede LED und dessen Farbe
tinyNeoPixel strip = tinyNeoPixel(ledAnzahl, datenPin, NEO_GRB, pixels);
enum : uint8_t // Programme in der Reihenfolge Nummeriert, gleichzeitig die Reihenfolge der Programme
{
Cube,
Dice,
FadeOnSite,
Disco,
Rainbow,
Flash,
Snake,
Rain,
HeartBeat
};
struct Control // Struktur zum kontrolliern der Programme
{
bool fadeinout;
bool demoaktiv;
};
const Control controlArray[] = // Eigenschaften der Programme (faden, demoaktiv)
{
//{FadeInOut, Demoaktiv}
{false, false}, //Cube
{false, false}, //Dice
{false, false}, //FadeOnSite
{true, true}, //Disco
{true, true}, //Rainbow
{false, true}, //Flash
{false, true}, //Snake
{false, true}, //Rain
{false, true} //HeartBeat
};
uint8_t brightness = 50; // Variable für die Helligkeit; 0 bis 50, Aus bis Volle Heligkeit
uint8_t fadebrightness; // Zwischenspeicher der Helligkeit bei Szenenwechsel
uint8_t intdata; // Variable für Interupts vom ADXL345b
uint16_t mem = 0; // Zwischenspeicher
uint8_t program = 0; // Welches Programm ist aktiv
// # uint8_t last_program = 0; // Programmspeicher welches vor Demo aktiv war
//bool tap; // Klopfen erkannt
//bool doppletap; // Doppelklopfen erkannt
//bool freefall; // Freier Fall erkannt
bool inaktiv = false; // Inaktivität erkannt
// # uint8_t top; // Welche Seite ist oben
int16_t x, y, z; // Achsen Variablen
uint8_t red = 255, green = 255, blue = 255; // Farbvariablen für den Strip
uint32_t millis_merker_demo; // Zwischenspeicher für Millis zum Programmwechsel im Demomodus
uint32_t millis_merker_prog; // Zwischenspeicher für Millis um die Programme etwas zu bremsen
// # uint32_t demotime = 100000; // Zeitschwelle zum wechseln zum nächsten Programm im Demo-Modus (Millisekunden)
uint8_t viper[] = {4, 54, 54, 54, 54, 54}; // Schlangen Position Array
uint8_t raincolor[12][4]; // Zwischenpeicher der Farbwerte für Regenmuster
const uint64_t Sequenz[] PROGMEM // Bitmuster der Zahlen die gezeigt werden entsprechend wie der Würfel sich dreht, verwendung im Programm cube() //bitRead von rechts nach links^^
{
0b101010101101000101000010000100000001100010001111000111, // µC-PCP zeigt 6 //top=0
0b101000101000010000100000001100010001111000111101010101, // µC-PCP zeigt 5 //top=1
0b000010000100000001100010001111000111101010101101000101, // µC-PCP zeigt 4 //top=2
0b100000001100010001111000111101010101101000101000010000, // µC-PCP zeigt 1 //top=3
0b100010001111000111101010101101000101000010000100000001, // µC-PCP zeigt 2 //top=4
0b111000111101010101101000101000010000100000001100010001, // µC-PCP zeigt 3 //top=5
};
enum : uint8_t // Oben, Rechts, Links, Unten durchnummeriert
{
Oben, // = 0b00
Rechts, // = 0b01
Links, // = 0b10
Unten // = 0b11
};
const uint8_t partner[6][4] PROGMEM // Erstellt ein FlächenArray (0-5) wo von jede anliegende Fläche (oben, rechts, links, unten) (0-3) die Fläche und welche Kante (oben, rechts, links, unten) anliegt Bitweise (0bKKFFF) hinterlegt ist
{
// Oben liegt // Rechts liegt // Links liegt // Unten liegt
{5 + (Rechts << 3), 1 + (Unten << 3), 4 + (Oben << 3), 2 + (Unten << 3)}, // Fläche 0 // Bsp: An Fläche 0 liegt oben Fläche 5 an mit seiner rechten Kante
{3 + (Links << 3), 2 + (Links << 3), 5 + (Oben << 3), 0 + (Rechts << 3)}, // Fläche 1 // Bsp: An Fläche 1 liegt rechts Fläche 2 an mit seiner linken Kante
{3 + (Unten << 3), 4 + (Rechts << 3), 1 + (Rechts << 3), 0 + (Unten << 3)}, // Fläche 2
{5 + (Links << 3), 4 + (Unten << 3), 1 + (Oben << 3), 2 + (Oben << 3)}, // Fläche 3
{0 + (Links << 3), 2 + (Rechts << 3), 5 + (Unten << 3), 3 + (Rechts << 3)}, // Fläche 4
{1 + (Links << 3), 0 + (Oben << 3), 3 + (Oben << 3), 4 + (Links << 3)} // Fläche 5
};
// I²C Register am ADXL
/* registers */
#define ADXL345_ADDRESS 0x53
#define ADXL345_DEVID 0x00
#define ADXL345_THRESH_TAP 0x1D
#define ADXL345_OFSX 0x1E
#define ADXL345_OFSY 0x1F
#define ADXL345_OFSZ 0x20
#define ADXL345_DUR 0x21
#define ADXL345_LATENT 0x22
#define ADXL345_WINDOW 0x23
#define ADXL345_THRESH_ACT 0x24
#define ADXL345_THRESH_INACT 0x25
#define ADXL345_TIME_INACT 0x26
#define ADXL345_ACT_INACT_CTL 0x27
#define ADXL345_THRESH_FF 0x28
#define ADXL345_TIME_FF 0x29
#define ADXL345_TAP_AXES 0x2A
#define ADXL345_ACT_TAP_STATUS 0x2B
#define ADXL345_BW_RATE 0x2C
#define ADXL345_POWER_CTL 0x2D
#define ADXL345_INT_ENABLE 0x2E
#define ADXL345_INT_MAP 0x2F
#define ADXL345_INT_SOURCE 0x30
#define ADXL345_DATA_FORMAT 0x31
#define ADXL345_DATAX0 0x32
#define ADXL345_DATAX1 0x33
#define ADXL345_DATAY0 0x34
#define ADXL345_DATAY1 0x35
#define ADXL345_DATAZ0 0x36
#define ADXL345_DATAZ1 0x37
#define ADXL345_FIFO_CTL 0x38
#define ADXL345_FIFO_STATUS 0x39
/* Register bits */
#define ADXL345_FULL_RES 0x03
#define ADXL345_SUPPRESS 0x03
#define ADXL345_LOW_POWER 0x04
void setup()
{
pinMode(datenPin, OUTPUT);
pinMode(A3, INPUT);
randomSeed(analogRead(A3));
TinyWireM.begin(); // Beginnt eine I²C Verbindung als Master
if (brightness > 50) brightness = 50; // Helligkeit auf 50 begrenzen, Hardwarebedingt, sonnst zu großer Strom
fadebrightness = brightness; // Helligkeit dem Zwischenspeicher übergeben
strip.setBrightness(brightness); // Helligkeit setzen
strip.clear(); // Alle LEDs auschalten
strip.show(); // geänderte Werte der LEDs anzeigen
/* Register setzen. Mehr information im Datenblatt*/
writeTo(ADXL345_DATA_FORMAT, B00001000); // B3 == Volle Auflösung = 1, 10-Bit Auflösung = 0 | B1B0 == Sensibilität, siehe Datenblatt
writeTo(ADXL345_BW_RATE, B00001101); // Setzt 800Hz Ausgangs Datenrate (nicht I²C), B4B3B2B1, siehe Datenblatt Tabelle 7 und 8, Seite 14
writeTo(ADXL345_POWER_CTL, 0); // Always be sure to zero out register, don't asume it's zero
writeTo(ADXL345_POWER_CTL, B00001000); // 0 | 0 | Verknüpfen von In-/Aktivität | Automatisch schlafen | Messen Aktiv | Sleep | Wake Up | Wake Up
writeTo(ADXL345_INT_ENABLE, B01111100); // Interupts aktivieren DATA_READY | SINGLE_TAP | DOUBLE_TAP | Activity | Inactivity | FREE_FALL | Watermark | Overrun
writeTo(ADXL345_THRESH_TAP, 50); // Klopf Schwelle (guter Wert ist 200)
writeTo(ADXL345_DUR, 0x30); // Klopf Dauer einstellen, 0 = Klopfen deaktiviert
writeTo(ADXL345_LATENT, 0x30); // Latenz - Zeit bis zum erwarten des zweiten Klopfens, davor wird ignoriert, 0 = Doppelklopfen deaktiviert
writeTo(ADXL345_WINDOW, 0xFF); // Zeit Spanne wo ein zweites Klopfen passieren muss, damit es ein Doppelklopfen wird, 0 = Doppelklopfen deaktiviert
writeTo(ADXL345_TAP_AXES, B00001111); // Achsen zum (Klopfen) aktivieren: 0 | 0 | 0 | 0 | Unterdrückung bei Bewegung An/Aus | X-Achse Tap An/Aus | Y-Achse Tap An/Aus | Z-Achse Tap An/Aus
/* Freier Fall wird erkannt wenn Z, X und Y gleichzeitig den Wert nahe 0 haben, dazu müssen X, Y und Z im ADXL ein Offset haben damit der Free Fall Detektor das korrekt an den Interupt gibt */
writeTo(ADXL345_THRESH_FF, 4); // Freier Fall Schwelle (0-255), 5-9 wird empfohlen laut Datenblatt
writeTo(ADXL345_TIME_FF, 50); // Freier Fall Mindestzeit (0-255), 20 für 100mSec - 70 für 350mSec wird empfohlen laut Datenblatt
writeTo(ADXL345_OFSX, 255); // internen Offset setzen, 0 Aus, 1-123 = +, 255-124 = - // im 2g Modus ~4Einheiten pro Bit
writeTo(ADXL345_OFSY, 42); // internen Offset setzen, 0 Aus, 1-123 = +, 255-124 = - // im 2g Modus ~4Einheiten pro Bit
writeTo(ADXL345_OFSZ, 187); // internen Offset setzen, 0 Aus, 1-123 = +, 255-124 = - // im 2g Modus ~4Einheiten pro Bit
writeTo(ADXL345_THRESH_ACT, 30); // Schwellwert zum erkennen einer Aktivität
writeTo(ADXL345_THRESH_INACT, 30); // Schwellwert zum erkennen einer Inaktivität
writeTo(ADXL345_TIME_INACT, 255); // Zeit die der Schwellwert der Inaktivität überschritten werden muss 0-255 Sekunden
writeTo(ADXL345_ACT_INACT_CTL, B11111111); // Einstellungen ACT 0=DC 1=AC | ACT (erkennen) X 0=Aus 1=An | ACT Y | ACT Z | INACT 0=DC 1=AC | INACT (erkennen) X 0=Aus 1=An | INACT Y | INACT Z
}
void loop()
{
readADXL(); // Funktion zum Daten auslesen
if (fadebrightness > brightness) fadebrightness = brightness; // Zwischenspeicher zum Helligkeitsfaden auf maximale Helligkeit begrenzen
strip.setBrightness(fadebrightness); // Helligkeit setzen
control(); // Funktion zum Programmablauf steuern
}
void control()
{
if (bitRead(intdata, 2))
{
freefallprog(); // Wenn Freier Fall erkannt, LED Muster für Freien Fall starten
intdata = read8(ADXL345_INT_SOURCE); // ADXL Interupt Speicher auslesen und damit leeren, verhindert doppeltes ausführen von freefallprog()
nextProgram(); // Erhöhe den Programzähler oder setzt auf Null Wenn Programmanzahl überschritten
}
if (inaktiv && !controlArray[program].demoaktiv) // Wenn inaktiv und aktuelles Programm nicht für DemoModus
{
nextProgram(); // Erhöhe den Programzähler oder setzt auf Null Wenn Programmanzahl überschritten
}
else
{
switch (program) // Programm nach Programmzähler wählen
{
case Cube: // Sechs immer oben
if (millis() - millis_merker_prog > 55)
{
cube(seiteADXL());
millis_merker_prog = millis();
}
break;
case Dice: // WürfelModus
dice();
break;
case FadeOnSite: // Farbwechsel abhängig der oben liegenden Seite
fadeonsite();
break;
case Disco: // Disco, zufällige Farbwiedergabe
if (millis() - millis_merker_prog > 55)
{
disco();
millis_merker_prog = millis();
}
break;
case Rainbow: // Farbwechsel nach Regenbogen
if (millis() - millis_merker_prog > 35)
{
rainbow();
millis_merker_prog = millis();
}
break;
case Flash: // Zufälliges Aufblitzen
if (millis() - millis_merker_prog > mem)
{
flash();
mem = random(750);
millis_merker_prog = millis();
}
break;
case Snake: // Schlange
if (millis() - millis_merker_prog > 250)
{
snake();
millis_merker_prog = millis();
}
break;
case Rain: // Simuliert Regen, Farbe abhängig der oben liegenden Seite
if (millis() - millis_merker_prog > 7)
{
rain(seiteADXL());
millis_merker_prog = millis();
}
break;
case HeartBeat: // Simuliert Herzklopfen
heartbeat();
break;
default:
break;
}
fadeInOut(); // Funktion zum gemütlichen Übergang, wenn eingestellt
}
}
void fadeInOut()
{
const uint32_t demotime = 100000; // Zeitschwelle zum wechseln zum nächsten Programm im Demo-Modus (Millisekunden)
if (controlArray[program].fadeinout)
{
if (millis() - millis_merker_demo > demotime && inaktiv)
{
if (--fadebrightness == 0)
{
millis_merker_demo = millis();
nextProgram();
}
}
else if (fadebrightness < brightness) fadebrightness++;
}
else
{
fadebrightness = brightness;
if (millis() - millis_merker_demo > demotime && inaktiv)
{
millis_merker_demo = millis();
nextProgram();
fadebrightness = 0;
}
}
}
void nextProgram()
{
if (++program >= (sizeof(controlArray) / sizeof(controlArray[0]))) program = 0;
}
uint8_t readNachbarPixel(uint8_t pixel, uint8_t orientation)
{
uint8_t side = pixel / 9; // vom übergebenen Pixel die Flächennummer 0-5
uint8_t index = pixel % 9; // vom übergebenen Pixel die Indexnummer auf seiner Fläche 0-8
uint8_t result = 0; // Rückgabewertvariable
switch (orientation) // an welcher Kante liegt die abfragende Seite
{
case Oben: // 0
switch (index) // welches obere Pixel auf der Fläche sucht den oberen Nachbar
{
case 6: // Ecke oben links
result = callPixel(side, Oben, 0); // callPixel(Fläche des Fragenden Pixels, Kannte des Fragenden Pixels, Position im Bezug zur Kante wenn man von der Mitte schaut (0=Rechts, 1=Mitte, 2=Links));
break;
case 7: // Seite oben mitte
result = callPixel(side, Oben, 1);
break;
case 8: // Ecke oben rechts
result = callPixel(side, Oben, 2);
break;
default:
result = pixel + 3;
break;
}
break;
case Rechts: // 1
switch (index)
{
case 8: // Ecke oben rechts
result = callPixel(side, Rechts, 0);
break;
case 5: // Seite rechts mitte
result = callPixel(side, Rechts, 1);
break;
case 2: // Ecke unten rechts
result = callPixel(side, Rechts, 2);
break;
default:
result = pixel + 1;
break;
}
break;
case Links: // 2
switch (index)
{
case 0: // Ecke unten links
result = callPixel(side, Links, 0);
break;
case 3: // Seite links mitte
result = callPixel(side, Links, 1);
break;
case 6: // Ecke oben links
result = callPixel(side, Links, 2);
break;
default:
result = pixel - 1;
break;
}
break;
case Unten: // 3
switch (index)
{
case 2: // Ecke unten rechts
result = callPixel(side, Unten, 0);
break;
case 1: // Seite unten mitte
result = callPixel(side, Unten, 1);
break;
case 0: // Ecke unten links
result = callPixel(side, Unten, 2);
break;
default:
result = pixel - 3;
break;
}
break;
}
return result;
}
uint8_t callPixel(uint8_t aufruferFlaeche, uint8_t aufruferKante, uint8_t index)
{
uint8_t pgm = pgm_read_byte(&partner[aufruferFlaeche][aufruferKante]); // Holt Daten über anliegende Fläche mit ihrer anliegenden Kante aus dem PROGMEM
uint8_t flaeche = pgm & 0b111; // Beispiel [0][1] (Fläche rechts von 0) // 0b00001 + 0b11000 = 0b11001 // 0b11001 & 0b111 = 0b1 = 1 // Fläche 1
uint8_t kante = pgm >> 3; // schiebt Bits des Arrays partner [Fläche] [Kante] um 3 Bits nach rechts, Es bleibt die anliegende Kante übrig // 0b11001 >> 3 = 0b11 = 3 = Unten
uint8_t result = 0; // Rückgabewertvariable
switch (kante) // abhängig davon, welche Kante an der Aufruferfläche liegt
{
case Oben: //0
result = 8 - index; // errechnet anhand des index, das Pixel auf der Fläche. Möglich 6, 7 oder 8
break;
case Unten: //3
result = 0 + index; // errechnet anhand des index, das Pixel auf der Fläche. Möglich 0, 1 oder 2
break;
case Rechts: //1
result = 2 + index * 3; // errechnet anhand des index, das Pixel auf der Fläche. Möglich 2, 5 oder 8
break;
case Links: //2
result = 6 - index * 3; // errechnet anhand des index, das Pixel auf der Fläche. Möglich 0, 3 oder 6
break;
}
result = result + flaeche * 9; // errechnet nahand der Fläche die Pixelnummer
return result;
}
/*ADXL345 Komunikation*/
uint8_t seiteADXL()
{
uint8_t top;
x = read16(ADXL345_DATAX0); // X Achsenwert auslesen und x übergeben
y = read16(ADXL345_DATAY0); // Y Achsenwert auslesen und y übergeben
z = read16(ADXL345_DATAZ0); // Z Achsenwert auslesen und z übergeben
/* Würfelseitenerkennung*/
if (x > 200) top = 1; //Fläche 1 oben // µC-PCP zeigt 4
if (y > 200) top = 2; //Fläche 2 oben // µC-PCP zeigt 1
if (z > 200) top = 3; //Fläche 3 oben // µC-PCP zeigt 2
if (x < -200) top = 4; //Fläche 4 oben // µC-PCP zeigt 3
if (y < -200) top = 5; //Fläche 5 oben // µC-PCP zeigt 6
if (z < -200) top = 0; //Fläche 0 oben // µC-PCP zeigt 5
return top;
}
// Hier teilen?
void readADXL()
{
static uint8_t lastProgram = 0; // Programmspeicher welches vor Demo aktiv war
intdata = read8(ADXL345_INT_SOURCE); // Interups Auslesen und im ADXL leeren
if (bitRead(intdata, 3) && !inaktiv) // Wenn Inaktivität erkannt (keine Änderung über ADXL345_TIME_INACT eigestellte Sekunden)
{
inaktiv = true;
millis_merker_demo = millis();
lastProgram = program; // Aktives Program im ProgramMerker hinterlegen
}
if (bitRead(intdata, 4) && inaktiv) // Wenn Aktivität erkannt
{
inaktiv = false;
program = lastProgram; // Letztes aktives Program aus dem ProgramMerker holen
}
}
uint16_t read16(uint8_t address)
{
uint8_t MSByte = 0, LSByte = 0;
int16_t regValue = 0;
TinyWireM.beginTransmission(ADXL345_ADDRESS);
TinyWireM.write(address);
TinyWireM.endTransmission();
TinyWireM.requestFrom(ADXL345_ADDRESS, 2);
if (TinyWireM.available())
{
LSByte = TinyWireM.read();
MSByte = TinyWireM.read();
}
regValue = (MSByte << 8) + LSByte;
return regValue;
}
uint8_t read8(uint8_t address)
{
uint8_t regValue = 0;
TinyWireM.beginTransmission(ADXL345_ADDRESS);
TinyWireM.write(address);
TinyWireM.endTransmission();
TinyWireM.requestFrom(ADXL345_ADDRESS, 1);
if (TinyWireM.available())
{
regValue = TinyWireM.read();
}
return regValue;
}
void writeTo(uint8_t address, uint8_t val)
{
TinyWireM.beginTransmission(ADXL345_ADDRESS);
TinyWireM.write(address);
TinyWireM.write(val);
TinyWireM.endTransmission();
}
/*LED Programme*/
void heartbeat()
{
if (red > 55) red = 0; // Wenn der RotWert über 55 dann RotWert auf 0 setzen
if (red == 55) mem++; // Wenn RotWert 55 erreicht hat, Merker um eins erhöhen (damit später Rot reduziert wird bei mem gleich 1 oder 3)
if (red == 0) mem++; // Wenn RotWert 0 erreicht hat, Merker um eins erhöhen (damit später Rot erhöht wird bei mem gleich 0 oder 2) und damit der Merker für die Pause erhöht wird
if (mem >= 4) delay(100); // Wenn Merker über 4, eine Pause einlegen (Also 50-4= 46mal 0,1s Pause)
if (mem >= 50) mem = 0; // Wenn Merker über 50, dann Merker wieder auf 0, was die Pause beendet, und Rot wieder erhöht
if (mem == 0 || mem == 2) red++; // Wenn Merker 0 oder 2 Rot erhöhen
else if (mem == 1 || mem == 3) red--; // Wenn Merker 1 oder 3 Rot verringern
else red = 0; // Sicherstellen das Rot 0 ist wenn Merker einen anderen Wert hat (Kann durch andere Funktionen (LED-Programme) geändert werden
strip.clear(); // Alle LEDs ausschalten
for (uint8_t side = 0; side < 6; side++) // Auf jeder Würfelseite ausführen
{
if (red >= 40) for (uint8_t i = 0; i < 9; i += 2) strip.setPixelColor(i + 9 * side, red - 40, 0, 0); // Wenn rot größer 40 (verspäteter start) schreibe jedes gerade pixel auf der Würfelseite (Ecken und Mitte (Mitte wird später überschrieben)
if (red >= 20) for (uint8_t i = 1; i < 8; i += 2) strip.setPixelColor(i + 9 * side, red - 20, 0, 0); // Wenn rot größer 20 (verspäteter start) schreibe jedes ungerade pixel auf der Würfelseite (oben, unten, links, rechts)
strip.setPixelColor(4 + 9 * side, red, 0, 0); // schreibe auf die mitte (Pixel 4) der Seite
}
strip.show(); // Zeigt die gesetzten Werte an den LEDs
}
void freefallprog() // lässt jedes zweite Pixel 6mal rot blinken
{
for (uint8_t j = 0; j < 6; j++)
{
strip.clear();
for (uint8_t i = 0; i < ledAnzahl; i += 2)
{
strip.setPixelColor(i, 255, 0, 0);
}
strip.show();
delay(100);
strip.clear();
strip.show();
delay(100);
}
}
void rain(uint8_t side)
{
uint8_t rainPixel[12]; // Speichert die 12 obenliegenden Regenpixel
int8_t changer[4]; // Speichert die Verechenoberratoren für die nach unten folgenden Pixel
for (uint8_t i = 0; i < 4; i++) // Für alle 4 anliegenden Seiten (oben = 0, rechts = 1, links = 2, unten = 3)
{
for (uint8_t j = 0; j < 3; j++) // Für alle 3 anliegenden Pixel der Seite (Index 0, 1, 2)
{
rainPixel[i * 3 + j] = callPixel(side, i, j); // Übergebe die 12 Pixel in das rainPixelArray // i*3+j ergibt die Nummerierung für das Array(0-11)
}
uint8_t upsite = pgm_read_byte(&partner[side][i]); // Liest die Information von der anliegenden Fläche (BitArray)
upsite = upsite >> 3; // gibt von der anliegenden Fläche die obere Kante wieder (schiebt die FlächenInfo Bits raus)
changer[i] = upsite * 2 - 3; // Seite 5, index 852 -1 // Seite 1, 012 +3 // Seite 4, 678 -3 // Seite 2, 012 +3 // gibt gibt anhand der oben liegenden Kante, den verrechen operator für die darunter folgenden Pixel aus (0*2-3=-3, 1*2-3=-1, 2*2-3=1, 3*2-3=3)
} // bei "oben" liegenden Pixel darunter liegende Pixel 3 kleiner, bei "rechts" liegenden Pixel, darunter liegende 1 kleiner, etc
switch (side) // Farbwahl nach Seite
{
case 0: red = 255; green = 0; blue = 0; break;
case 1: red = 0; green = 255; blue = 255; break;
case 2: red = 255; green = 0; blue = 255; break;
case 3: red = 255; green = 255; blue = 0; break;
case 4: red = 0; green = 0; blue = 255; break;
case 5: red = 0; green = 255; blue = 0; break;
}
strip.clear();
mem = random(0, 150); // erstellt merker zum zufälligen Starten
for (uint8_t row = 0; row < 12; row++) // row steht für eine der 12 möglichen senkrechten Reihen
{
if (raincolor[row][3] > 49) // wenn Zähler über 49
{
strip.setPixelColor(rainPixel[row] + changer[row / 3] + changer[row / 3], raincolor[row][0], raincolor[row][1], raincolor[row][2]); // setze Farbe aufs untere pixel
strip.setPixelColor(rainPixel[row] + changer[row / 3], raincolor[row][0] / 1.1, raincolor[row][1] / 1.1, raincolor[row][2] / 1.1); // setze Farbe aufs zweite Pixel von oben mit 90% Leuchtkraft
strip.setPixelColor(rainPixel[row], raincolor[row][0] / 1.1 / 1.1, raincolor[row][1] / 1.1 / 1.1, raincolor[row][2] / 1.1 / 1.1); // setze Farbe aufs obere Pixel mit 90% von 90% Leuichtkraft
for (uint8_t i = 0; i < 3; i++)
{
raincolor[row][i] = raincolor[row][i] / 1.1; // reduziere die Leuchtkraft um 90%
}
if (raincolor[row][0] < 1 && raincolor[row][1] < 1 && raincolor[row][2] < 1) // wenn alle Farbwerte unter 1
{
for (uint8_t i = 0; i < 4; i++)
{
raincolor[row][i] = 0; // Zähler zurücksetzen und sicherstellen das Farbwerte gleich 0
}
}
}
if (raincolor[row][3] < 50 && raincolor[row][3] > 24) // wenn Zähler 25 bis 49
{
strip.setPixelColor(rainPixel[row] + changer[row / 3], raincolor[row][0], raincolor[row][1], raincolor[row][2]); // setze Farbe aufs zweite pixel von oben
strip.setPixelColor(rainPixel[row], raincolor[row][0] / 1.1, raincolor[row][1] / 1.1, raincolor[row][2] / 1.1); // setzt Farbe aufs obere pixel mit 90% Leuichtkraft
++raincolor[row][3];
}
if (raincolor[row][3] < 25 && raincolor[row][3] > 0) // wenn Zähler 1 bis 24
{
strip.setPixelColor(rainPixel[row], raincolor[row][0], raincolor[row][1], raincolor[row][2]); // setze Farbe aufs obere Pixel der Reihe
++raincolor[row][3]; // Zähler um 1 erhöhen
}
if (mem == row && raincolor[row][3] == 0) // wenn Zufalsmerker gleich j, und Zähler der Reihe gleich 0
{
raincolor[row][0] = red; raincolor[row][1] = green; raincolor[row][2] = blue; // setze übergebe Farbewerte, gesetzt nach Seite die oben liegt
++raincolor[row][3]; // Zähler für Reihe auf 1 setzen (Zählen ist füpr Zeitverzögerung zuständig)
}
}
strip.show();
}
void snake()
{
uint8_t nachbarPixel[4];
mem = 0;
for (uint8_t i = 0; i < 4; i++) // für alle 4 Nachbarpixel überprüfen
{
bool crash = false;
for (uint8_t k = 1; k < sizeof(viper); k++) // für alle Pixel die die Schlange belegt überprüfen
{
if (readNachbarPixel(viper[0], i) == viper[k]) // wenn das Nachbarpixel gleich eines Pixels der Schlange
{
crash = true;
}
}
if (!crash) // wenn das Nachbarpixel keine besetzte Position ist
{
nachbarPixel[mem] = readNachbarPixel(viper[0], i); // dann schiebe den PixelIndex über eventuelle mögliche Pixel
mem++; // Zähler für mögliche Pixel erhöhen
}
}
for (uint8_t j = sizeof(viper) - 1; j > 0; j--) // Über die Länge der Schlange
{
viper[j] = viper[j - 1]; // Übergib das gespeicherte Pixel im Viper Array eine Position Richtung Ende, das letzte fällt weg
strip.setPixelColor(viper[j], 255 - (j * 40), 0 + (j * 40), 0); // setze Farbewerte ändernd Richtung Schanzende (Von Rot Kopf, über gelb Richtung grün
}
viper[0] = nachbarPixel[random(0, mem)]; // übergibt dem Kopf, eine zufällige auswahl aus den möglichen Nachbarpixeln
strip.setPixelColor(viper[0], 255, 0, 0); // Farbwert Kopf
strip.show();
strip.clear();
}
void flash()
{
strip.clear();
strip.setPixelColor(random(ledAnzahl - 1), random(255), random(255), random(255));
strip.show();
delay(7);
strip.clear();
strip.show();
}
void rainbow()
{
if (red > 250 || green > 250 || blue > 250)
{
red = 250; blue = 0; green = 0;
}
uint8_t newred = red;
uint8_t newgreen = green;
uint8_t newblue = blue;
for (uint8_t i = 0; i < ledAnzahl; i++)
{
if (newred == 250 && newblue == 0 && newgreen < 250) newgreen += 10;
else if (newred > 0 && newblue == 0 && newgreen == 250) newred -= 10;
else if (newred == 0 && newblue < 250 && newgreen == 250) newblue += 10;
else if (newred == 0 && newblue == 250 && newgreen > 0) newgreen -= 10;
else if (newred < 250 && newblue == 250 && newgreen == 0) newred += 10;
else if (newred == 250 && newblue > 0 && newgreen == 0) newblue -= 10;
strip.setPixelColor(i, newred, newgreen, newblue);
}
strip.show();
if (red == 250 && blue == 0 && green < 250) green += 10;
else if (red > 0 && blue == 0 && green == 250) red -= 10;
else if (red == 0 && blue < 250 && green == 250) blue += 10;
else if (red == 0 && blue == 250 && green > 0) green -= 10;
else if (red < 250 && blue == 250 && green == 0) red += 10;
else if (red == 250 && blue > 0 && green == 0) blue -= 10;
else
{
red = 250; blue = 0; green = 0;
}
}
void disco()
{
for (uint8_t i = 0; i <= ledAnzahl; i++)
{
strip.setPixelColor(i, random(255), random(255), random(255));
}
strip.show();
}
void fadeonsite()
{
uint8_t newred = map(x, -280, 280, 0, 255);
uint8_t newgreen = map(y, -280, 280, 0, 255);
uint8_t newblue = map(z, -280, 280, 0, 255);
if (newred + 10 < red) red -= 2;
if (newred - 10 > red) red += 2;
if (newgreen + 10 < green) green -= 2;
if (newgreen - 10 > green) green += 2;
if (newblue + 10 < blue) blue -= 2;
if (newblue - 10 > blue) blue += 2;
for (uint8_t i = 0; i <= ledAnzahl; i++)
{
strip.setPixelColor(i, red, green, blue);
}
strip.show();
}
void dice()
{
if (bitRead(intdata, 6)) mem = 2; // Wenn Erschütterung erkannt
if (mem < 520) // Solange Zeitspanne unter 520 mS
{
cube(random(0, 6)); // Wähle eine zufällige Seite oben
delay(mem); // Warte die zwischengespeicherte Zeit
mem = (mem * random(10, 21)) / 10; // Erhöhe die wartezeit etwas im zufälligen Bereich (simuliert ein langsames auslaufen der Zeit
}
}
void cube(byte side)
{
uint64_t pgm = 0; // Zwischenspeicher für das aus dem PROGMEM geholten Bitmuster
memcpy_P(&pgm, &Sequenz[side], sizeof(pgm)); // memcpy_P holt aus dem PROGMEM Daten (Ziel, Quelle, Größe in Byte von Quelle und Ziel)
for (uint8_t index = 0; index < 54; index++)
{
if (bitRead(pgm, index)) strip.setPixelColor(index, red, green, blue);
else strip.setPixelColor(index, 0, 0, 0);
}
strip.show();
}
#else //neopixel library required 7.37MHz minimum clock speed; these and following lines are used to skip this sketch in internal testing. It is not needed in your sketches.
#warning "Neopixel control requires F_CPU > 7.37MHz"
void setup() {}
void loop() {}
#endif