На выходных неплохо посидел над кодом проекта, можно было и лучше но не так много времени было. На данный момент я решил проблему с заменой эффектов, и выстроил некоторую структуру кода готовую к большому количеству эффектов, также сделал автоматическую их смену через каждые 10 секунд. Дальше по коду:
#define clock 3 //синхро контакт
#define reset 4 // контакт сброса
#define data 2 // контакт данных
boolean matrix[8][8][8]; // массив который является внутренним
//представлением куба
byte i,j,k,x,y,z,iteration; // переменные для циклов
byte lastX, lastY, lastZ; // переменные для последней координаты
byte curEffect; // номер текущего эффекта
// Переменные для работы со временемlong pause; // задержка обновления эффекта
long lastEffectChangeTime; // время последней смены эффекта
long lastEffectCallTime; // время последней смены эффекта
void setup() // функция установки начальных праметров
{
// инициализируем переменные
curEffect = 0;
lastEffectChangeTime = 0;
lastEffectCallTime = 0;
pause = 0;
//переводим все контакты в режим вывода
pinMode(clock, OUTPUT);
pinMode(reset, OUTPUT);
pinMode(data, OUTPUT);
for(i = 0; i < 8; i++){
for(j = 0; j < 8; j++){
for(k = 0; k < 8; k++){
matrix[i][k][j] = false;
}
}
}
lastX = 0;
lastY = 0;
lastZ = 0;
}
void loop()
{/*обнаруживаем время смены эффекта
мросто берем время с момента запуска программы и
вычисляем временной промежуток с момента
последней смены эффекта, если прошло больше 10 секунд
меняем эффект на случайный
*/ if(millis() - lastEffectChangeTime >10000){
curEffect = random(0,4); //меняем эффект
lastEffectChangeTime = millis(); // запоминаем время
}/*
тоже самое и для обновления эффекта
как оказалось быстродействие ардуины больше
чем я думал, и если делать обновление эффекта
на каждой итерации то не будет плавности,
и так как каждому эффекту нужно све время
обновления(гдето больше, гдето меньше)
добавлена пауза для эффектов
*/
if(millis() - lastEffectCallTime > pause){
startEffect(); // если сделана достаточная выдержка
// то обновляем эффект
lastEffectCallTime = millis(); //запоминаем время
}
writeMatrix(); //выводим массив на куб
}
/*
самая простая функция которая по номеру запускает нужный эффект
*/void startEffect(){
switch(curEffect){
case 0: effectRandomeMagik(); break;
case 1: effectRain(); break;
case 2: effectStruya(); break;
case 3: effectCircleSpiral(); break;
default: effectCircleSpiral();
}
}/*
Эфект спирального целиндра, после долгих раздумий
решил сделать просто прописав 5 его состояний..
*/void effectCircleSpiral(){
pause = 70;
moveMassToDown(); // функция- утилита которая сдвигает массив вниз
switch(lastZ){
case 1: matrix[7][0][2] = true;
matrix[7][2][7] = true;
matrix[7][7][5] = true;
matrix[7][5][0] = true;
lastZ = 2;
break;
case 2: matrix[7][0][3] = true;
matrix[7][3][7] = true;
matrix[7][7][4] = true;
matrix[7][4][0] = true;
lastZ = 3;
break;
case 3: matrix[7][0][4] = true;
matrix[7][4][7] = true;
matrix[7][7][3] = true;
matrix[7][3][0] = true;
lastZ = 4;
break;
case 4: matrix[7][0][5] = true;
matrix[7][5][7] = true;
matrix[7][7][2] = true;
matrix[7][2][0] = true;
lastZ = 0;
break;
default: matrix[7][1][1] = true;
matrix[7][1][6] = true;
matrix[7][6][1] = true;
matrix[7][6][6] = true;
lastZ = 1;
}
}
/*
эффект хаоса
*/void effectRandomeMagik(){
pause = 10;
x = random(0,8) - 1;
y = random(0,8) - 1;
z = random(0,8) - 1;
matrix[z][x][y] = !matrix[z][x][y];
}/*
эффект похожий на дождь
*/
void effectRain(){
pause = 60;
moveMassToDown();
x = random(0,8);
y = random(0,8);
matrix[7][y][x] = true;
}
/*
эффект струи которая льется сверху вних
*/
void effectStruya(){
pause = 60;
moveMassToDown();
x = random(1,4) - 2 + lastX;
if(x > 7){
x = 0;
}
if(x < 0){
x = 7;
}
y = random(1,4) - 2 + lastY;
if(y > 7){
y = 0;
}
if(y < 0){
y = 7;
}
lastX = x;
lastY = y;
matrix[7][y][x] = true;
}
/*
функция утилита которая просто сдвигает
массив вниз.
*/
void moveMassToDown(){
for(i = 0; i < 8; i++){
for(j = 0; j < 8; j++){
for(k = 0; k < 8; k++){
if(matrix[i][j][k]){
matrix[i-1][j][k] = true;
matrix[i][j][k] = false;
}
}
}
}
}// функция которая отображает внутренний массив на кубе
void writeMatrix(){
digitalWrite(clock, LOW);
for(i = 0; i < 8; i++){ // цикл по этажам координата Z
digitalWrite(reset, LOW);
for(j = 0; j < 8; j++){ //цикл по рядам(координата Y)
// сбрасываю синхросигнал
// цикл по строкам(координата X)
for(k = 0; k < 8; k++){
// сбрасываю сигнал на выходе данных
digitalWrite(data, LOW);
//проверка на истину
if(matrix[i][k][j] == true){
// если истина то даю логическую 1 на выход
digitalWrite(data, HIGH);
}
if(matrix[i][k][j] == true){
}else{
}
digitalWrite(clock, HIGH);
digitalWrite(clock, LOW);
} //сбрасываю сигнал по координате Z
}
for(j = 0; j < 8; j++ ){
digitalWrite(data, LOW);
if(i == j){
digitalWrite(data, HIGH);
}
digitalWrite(clock, HIGH);
digitalWrite(clock, LOW);
}
digitalWrite(reset, HIGH); //зажигаю ряд(этаж)
digitalWrite(reset, LOW); //гашу ряд(этаж)
}
}
Небольшое видео с демонстрацией:
На видео "струя", "дождь", "спиральный цилиндр", и "хаос" поймал момент когда они шли один за другим без повторов.
#define clock 3 //синхро контакт
#define reset 4 // контакт сброса
#define data 2 // контакт данных
boolean matrix[8][8][8]; // массив который является внутренним
//представлением куба
byte i,j,k,x,y,z,iteration; // переменные для циклов
byte lastX, lastY, lastZ; // переменные для последней координаты
byte curEffect; // номер текущего эффекта
// Переменные для работы со временемlong pause; // задержка обновления эффекта
long lastEffectChangeTime; // время последней смены эффекта
long lastEffectCallTime; // время последней смены эффекта
void setup() // функция установки начальных праметров
{
// инициализируем переменные
curEffect = 0;
lastEffectChangeTime = 0;
lastEffectCallTime = 0;
pause = 0;
//переводим все контакты в режим вывода
pinMode(clock, OUTPUT);
pinMode(reset, OUTPUT);
pinMode(data, OUTPUT);
for(i = 0; i < 8; i++){
for(j = 0; j < 8; j++){
for(k = 0; k < 8; k++){
matrix[i][k][j] = false;
}
}
}
lastX = 0;
lastY = 0;
lastZ = 0;
}
void loop()
{/*обнаруживаем время смены эффекта
мросто берем время с момента запуска программы и
вычисляем временной промежуток с момента
последней смены эффекта, если прошло больше 10 секунд
меняем эффект на случайный
*/ if(millis() - lastEffectChangeTime >10000){
curEffect = random(0,4); //меняем эффект
lastEffectChangeTime = millis(); // запоминаем время
}/*
тоже самое и для обновления эффекта
как оказалось быстродействие ардуины больше
чем я думал, и если делать обновление эффекта
на каждой итерации то не будет плавности,
и так как каждому эффекту нужно све время
обновления(гдето больше, гдето меньше)
добавлена пауза для эффектов
*/
if(millis() - lastEffectCallTime > pause){
startEffect(); // если сделана достаточная выдержка
// то обновляем эффект
lastEffectCallTime = millis(); //запоминаем время
}
writeMatrix(); //выводим массив на куб
}
/*
самая простая функция которая по номеру запускает нужный эффект
*/void startEffect(){
switch(curEffect){
case 0: effectRandomeMagik(); break;
case 1: effectRain(); break;
case 2: effectStruya(); break;
case 3: effectCircleSpiral(); break;
default: effectCircleSpiral();
}
}/*
Эфект спирального целиндра, после долгих раздумий
решил сделать просто прописав 5 его состояний..
*/void effectCircleSpiral(){
pause = 70;
moveMassToDown(); // функция- утилита которая сдвигает массив вниз
switch(lastZ){
case 1: matrix[7][0][2] = true;
matrix[7][2][7] = true;
matrix[7][7][5] = true;
matrix[7][5][0] = true;
lastZ = 2;
break;
case 2: matrix[7][0][3] = true;
matrix[7][3][7] = true;
matrix[7][7][4] = true;
matrix[7][4][0] = true;
lastZ = 3;
break;
case 3: matrix[7][0][4] = true;
matrix[7][4][7] = true;
matrix[7][7][3] = true;
matrix[7][3][0] = true;
lastZ = 4;
break;
case 4: matrix[7][0][5] = true;
matrix[7][5][7] = true;
matrix[7][7][2] = true;
matrix[7][2][0] = true;
lastZ = 0;
break;
default: matrix[7][1][1] = true;
matrix[7][1][6] = true;
matrix[7][6][1] = true;
matrix[7][6][6] = true;
lastZ = 1;
}
}
/*
эффект хаоса
*/void effectRandomeMagik(){
pause = 10;
x = random(0,8) - 1;
y = random(0,8) - 1;
z = random(0,8) - 1;
matrix[z][x][y] = !matrix[z][x][y];
}/*
эффект похожий на дождь
*/
void effectRain(){
pause = 60;
moveMassToDown();
x = random(0,8);
y = random(0,8);
matrix[7][y][x] = true;
}
/*
эффект струи которая льется сверху вних
*/
void effectStruya(){
pause = 60;
moveMassToDown();
x = random(1,4) - 2 + lastX;
if(x > 7){
x = 0;
}
if(x < 0){
x = 7;
}
y = random(1,4) - 2 + lastY;
if(y > 7){
y = 0;
}
if(y < 0){
y = 7;
}
lastX = x;
lastY = y;
matrix[7][y][x] = true;
}
/*
функция утилита которая просто сдвигает
массив вниз.
*/
void moveMassToDown(){
for(i = 0; i < 8; i++){
for(j = 0; j < 8; j++){
for(k = 0; k < 8; k++){
if(matrix[i][j][k]){
matrix[i-1][j][k] = true;
matrix[i][j][k] = false;
}
}
}
}
}// функция которая отображает внутренний массив на кубе
void writeMatrix(){
digitalWrite(clock, LOW);
for(i = 0; i < 8; i++){ // цикл по этажам координата Z
digitalWrite(reset, LOW);
for(j = 0; j < 8; j++){ //цикл по рядам(координата Y)
// сбрасываю синхросигнал
// цикл по строкам(координата X)
for(k = 0; k < 8; k++){
// сбрасываю сигнал на выходе данных
digitalWrite(data, LOW);
//проверка на истину
if(matrix[i][k][j] == true){
// если истина то даю логическую 1 на выход
digitalWrite(data, HIGH);
}
if(matrix[i][k][j] == true){
}else{
}
digitalWrite(clock, HIGH);
digitalWrite(clock, LOW);
} //сбрасываю сигнал по координате Z
}
for(j = 0; j < 8; j++ ){
digitalWrite(data, LOW);
if(i == j){
digitalWrite(data, HIGH);
}
digitalWrite(clock, HIGH);
digitalWrite(clock, LOW);
}
digitalWrite(reset, HIGH); //зажигаю ряд(этаж)
digitalWrite(reset, LOW); //гашу ряд(этаж)
}
}
Небольшое видео с демонстрацией:
Комментариев нет:
Отправить комментарий