Помогите улучшить led cube 4x4x4

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Всех с наступившим!

Уважаемые, помогите идиоту, пожалуйста. Я только недавно начал ковыряться с Ардуино и ещё мало чего знаю и понимаю. Но у меня уже получилось собрать и запрограммировать свои 3х3х3 и 4х4х4 кубики. И захотелось мне большего: очень хочется к кубику х4 прикрутить микрофон (имеется), чтобы кубик светился в зависимости от громкости звука. Но возникла проблема: на моей Freaduino UNO v1.8.1 заняты все 20 портов под светодиоды и некуда приткнуть микрофон :(

Собственно, вопрос: можно ли как-то это решить?

Если что, у меня есть ещё один совсем китайский аналог UNO, у которого на корпусе написано DCcEle DCcduino UNO. Работает сие чудо аналогично фридуинке. Может как-то их вместе связать? Например, передать управление слоями китайцу, высвободив тем самым на фридуинке 4 порта под датчики? Только опять вопрос: как это сделать?

P.S.: поиском пользовался. Но либо я тупой, либо искать совсем не умею :) Если кому интересно, готов поделиться скетчем собственной разработки для х4 кубика.

Заранее спасибо за терпение и ответ.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013
Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Эту тему я видел, спасибо. Ваш ответ там тоже прочитал. 5940 и 7219 под рукой нет, зато в загашнике обнаружился 74HC595N. Вы упоминали его по ссылке. Не подскажете, как его прикрутить к х4 кубику? Я сейчас буду насиловать Гугл на эту тему, но мало ли тут быстрее подскажет кто :)

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Так, кажется я сам нашёл ответ :) http://arduino.ru/Tutorial/registr_74HC595

 Буд пробовать. jeka_tm, спасибо за наводку!

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Не, видимо я тупой :(

Подключил 74HC595 к своему кубику, освободив тем самым 1 вывод ардуинки. Но что-то я делаю не так... 4 контакта, отвечающих за слои кубика я подключил к 74HC595 (по http://arduino.ru/Tutorial/registr_74HC595). Попытался адаптировать свой скетч под новые условия и обломался по полной программе...

Вот такой код БЕЗ 74HC595 работает как надо:

// Initalize our LED columns (positive)
int LEDPin[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
// Initalize the LED layers (ground)
int LayerPin[] = {16,17,18,19};
int count = 0;

void setup(){
  // Set up LED columns as output
  for(int pin = 0; pin < 16 ; pin++ ){
    pinMode(LEDPin[pin],OUTPUT);
    digitalWrite(LEDPin[pin],LOW);
  }
  // Set up LED Layers as output
  for(int layer = 0; layer < 4; layer++){
    pinMode(LayerPin[layer], OUTPUT);
    digitalWrite(LayerPin[layer], HIGH);
  }
}

void loop(){ 
  // Set up LED columns as output
  for(int pin = 0; pin < 16 ; pin++ ){
    digitalWrite(LEDPin[pin],LOW);
  }
  // Set up LED Layers as output
  for(int layer = 0; layer < 4; layer++){
    digitalWrite(LayerPin[layer], HIGH);
  }  
  count = 1;
  while(count < 3){
  //One layer
  for(int pin = 0; pin < 16 ; pin++ ){
    digitalWrite(LEDPin[pin],HIGH);
  }
  for(int layer = 0; layer < 4; layer++){
  digitalWrite(LayerPin[layer],LOW);
  delay(50);

  digitalWrite(LayerPin[layer],HIGH);
  delay(10);
  }
  
  for(int layer = 2; layer >= 1; layer--){
  digitalWrite(LayerPin[layer],LOW);
  delay(50);

  digitalWrite(LayerPin[layer],HIGH);
  delay(10);
  }
  count++;
  }
    // Set up LED columns as output
  for(int pin = 0; pin < 16 ; pin++ ){
    digitalWrite(LEDPin[pin],LOW);
  }
  // Set up LED Layers as output
  for(int layer = 0; layer < 4; layer++){
    digitalWrite(LayerPin[layer], HIGH);
  } 
  
  //4 columns
  for(int layer = 0; layer < 4; layer++){
    digitalWrite(LayerPin[layer], LOW);
  } 
  count = 1;
  while(count < 3){
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(0+pin)],HIGH);
    digitalWrite(LEDPin[(4+pin)],HIGH);
    digitalWrite(LEDPin[(8+pin)],HIGH);
    digitalWrite(LEDPin[(12+pin)],HIGH);
    delay(50);
    digitalWrite(LEDPin[(0+pin)],LOW);
    digitalWrite(LEDPin[(4+pin)],LOW);
    digitalWrite(LEDPin[(8+pin)],LOW);
    digitalWrite(LEDPin[(12+pin)],LOW);
  }
  for(int pin = 3; pin >= 0 ; pin-- ){
    digitalWrite(LEDPin[(0+pin)],HIGH);
    digitalWrite(LEDPin[(4+pin)],HIGH);
    digitalWrite(LEDPin[(8+pin)],HIGH);
    digitalWrite(LEDPin[(12+pin)],HIGH);
    delay(50);
    digitalWrite(LEDPin[(0+pin)],LOW);
    digitalWrite(LEDPin[(4+pin)],LOW);
    digitalWrite(LEDPin[(8+pin)],LOW);
    digitalWrite(LEDPin[(12+pin)],LOW);
  }
  count++;
  }
  
  //1 columns
  for(int layer = 0; layer < 4; layer++){
    digitalWrite(LayerPin[layer], LOW);
  } 
  
   for(int pin = 0; pin < 16 ; pin++ ){
    digitalWrite(LEDPin[pin],HIGH);
    delay(50);
    digitalWrite(LEDPin[pin],LOW);
  }
  for(int pin = 14; pin >= 0 ; pin-- ){
    digitalWrite(LEDPin[pin],HIGH);
    delay(50);
    digitalWrite(LEDPin[pin],LOW);
  }
  
  //_aA
  count = 1;
  while(count < 5){
  digitalWrite(LayerPin[0],LOW);
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(4*pin)],HIGH);
  }
   delay(100);
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(4*pin)],LOW);
  }
  digitalWrite(LayerPin[1],LOW);
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(4*pin+1)],HIGH);
  }
   delay(100);
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(4*pin+1)],LOW);
  }
  digitalWrite(LayerPin[2],LOW);
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(4*pin+2)],HIGH);
  }
   delay(100);
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(4*pin+2)],LOW);
  }
  digitalWrite(LayerPin[3],LOW);
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(4*pin+3)],HIGH);
  }
   delay(100);
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(4*pin+3)],LOW);
  }
  digitalWrite(LayerPin[1],HIGH);
  digitalWrite(LayerPin[2],HIGH);
  digitalWrite(LayerPin[3],HIGH);
  
  //reverse (Aa_)
  digitalWrite(LayerPin[3],HIGH);
  digitalWrite(LayerPin[2],LOW);
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(4*pin+2)],HIGH);
  }
   delay(100);
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(4*pin+2)],LOW);
  }
  digitalWrite(LayerPin[1],HIGH);
  digitalWrite(LayerPin[2],HIGH);
  
  digitalWrite(LayerPin[0],LOW);
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(4*pin)],HIGH);
  }
   delay(100);
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(4*pin)],LOW);
  }
  digitalWrite(LayerPin[0],HIGH);
  count++;
  }
  
  //helicopter
  count = 1;
  while(count < 5){
  for(int layer = 0; layer < 4; layer++){
    digitalWrite(LayerPin[layer], LOW);
    digitalWrite(LEDPin[5],HIGH);
    digitalWrite(LEDPin[6],HIGH);
    digitalWrite(LEDPin[9],HIGH);
    digitalWrite(LEDPin[10],HIGH);
  
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[pin],HIGH);
    digitalWrite(LEDPin[(15-pin)],HIGH);
    delay(30);
    digitalWrite(LEDPin[pin],LOW);
    digitalWrite(LEDPin[(15-pin)],LOW);
  }
  for(int pin = 0; pin < 4 ; pin++ ){
    digitalWrite(LEDPin[(4*pin+3)],HIGH);
    digitalWrite(LEDPin[(12-4*pin)],HIGH);
    delay(30);
    digitalWrite(LEDPin[(4*pin+3)],LOW);
    digitalWrite(LEDPin[(12-4*pin)],LOW);
  }
  digitalWrite(LayerPin[layer], HIGH);
 }
  count++;
  }
}

С 74HC595 попробовал начать с простого:

// Initalize our LED columns (positive)
int LEDPin[] = {0,1,2,3,4,5,6,7,A2,9,10,A3,A4,13,A0,A1};
// Initalize the LED layers (ground)
//int LayerPin[] = {16,17,18,19};
int Laeyr[] = {1,2,3,4};

//Пин подключен к ST_CP входу 74HC595
int latchPin = 8;
//Пин подключен к SH_CP входу 74HC595
int clockPin = 12;
//Пин подключен к DS входу 74HC595
int dataPin = 11;

void setup(){
  // Set up LED columns as output
  for(int pin = 0; pin < 16 ; pin++ ){
    pinMode(LEDPin[pin],OUTPUT);
    digitalWrite(LEDPin[pin],LOW);
  }
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop(){
  int Layer = 0;
  digitalWrite(LEDPin[0],HIGH);
  digitalWrite(LEDPin[1],HIGH);
  digitalWrite(LEDPin[2],HIGH);
  digitalWrite(LEDPin[3],HIGH);
  
    // устанавливаем синхронизацию "защелки" на LOW
    digitalWrite(latchPin, LOW);
    // передаем последовательно на dataPin
    shiftOut(dataPin, clockPin, MSBFIRST, Layer); 
    //"защелкиваем" регистр, тем самым устанавливая значения на выходах
    digitalWrite(latchPin, HIGH);
    // пауза перед следующей итерацией
    delay(100);
  
}

В результате, при Layer = 0 горят все 4 слоя в первых 4 столбцах. Добавляя digitalWrite(LEDPin[X],HIGH) зажигаю выбранный столбец... Стоит написать Layer = 1, и начинаются чудеса: слои начинают загораться/гаснуть и постепенно все слои гаснут совсем. Возвращаю Layer = 0 и слои один за другим загораются снова, после чего опять горит первая плоскость...

Я не понимаю, что я делаю не так :( Помогите, пожалуйста, разобраться!

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

много кода читать. может стоит начать со схемы как было как стало

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Было так (несколько кривых фоток получившегося девайса):

  1. столбцы подключены к пинам 0-13, А0, А1 (всего 16 столбцов, 4х4)
  2. слои подключены к пинам А2-А5 (всего 4 слоя, по 16 светодиодов в каждом)

Вот по этому рисунку делал (сорри, картинка большевата для вставки).

Стало так:

  1. столбцы подключены к пинам 0-13, А0, А1 (всего 16 столбцов, 4х4)
  2. слои подключены к портам Q1-Q4 на 74HC595 (как 2-5 светодиоды в статье)
  3. 74HC595 подключён к Ардуинке как описано в статье из пункта 2. Единственное отличие - у меня нет сейчас под рукой конденсатора на 0,1 мкФ, поэтому подключал без него.

Схему из статьи собирать пробовал - всё заработало...

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

ну оформи ты нормально. нарисуй схемы

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Тогда подскажите, в чём вы красивые схемы рисуете? А то у меня только Paint/Photoshop да Visio есть. Но в них это будет долго и страшно.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

splan например

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Уфффффф. Блин, я схему рисовал дольше, чем паял этот кубик :) Получилось криво, простите, но, хочется верить, достаточно понятно: схема. Рисовал в sPlan 7.0.0.9, если что. Столбцы - это аноды светодиодов (к ним припаяны резисторы на 43 Ом, на схеме уже сил не было рисовать, простите), слои - катоды светодиодов. Светодиоды использованы вот такие.

Так лучше? Простите, но я схемы не рисовал никогда раньше (кроме как от руки) и у меня это плохо получается. Я бы лучше сайт с нуля поднял :(

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

вообще то в программе есть экспорт графики

но из этого я понял что каждый светодиод из слоя идет на свой пин, и например анод. и все аноды объеденены в столбце

а катоды объеденены у каждого слоя, чтобы включать нужные слои

для начала стоит сделать так. 2 74HC595 управляют одним слоем. катоды пока просто за земле (резисторы не показывал, надеюсь они у тебя есть или ты поигрался с питанием чтобы не попалить порты)

когда научишься управлять одним слоем добавляются остальные. каторы черзе полевики к земле. управлять ими лучше пинами ардуины чтобы не тормозило

контакты я просто указал. сделай как тебе удобнее. схему последовательного соеденения я думаю ты уже знаешь, так что ее тоже не рисовал

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Спасибо! Направление понял. Как раз сгонял в магазин и купил ещё несколько 74HC595, да прочей мелочи. Буду пробовать.

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Я вернулся с продолжением дурацкого вопроса :) После долгих мучений у меня получилось по совету jeka_tm подключить свой кубик с Ардуинке с использованием двух 74HC595. Я даже научился зажигать светодиоды в одном столбце. Только вот дальше снова затык из-за слабых знаний C/C++ и вообще слабых навыков программирования.

Вот такой код последовательно зажигает отдельные столбцы светодиодов:

// Пин подключен к ST_CP входу 74HC595
const int latchPin = 8;
// Пин подключен к SH_CP входу 74HC595
const int clockPin = 12;
// Пин подключен к DS входу 74HC595
const int dataPin = 11;
 
char inputString[2];

// указываем пины, к которым подключены слои
int layerPin1 = 4;
int layerPin2 = 5;
int layerPin3 = 6;
int layerPin4 = 7;
 
 
void setup() {
  // устанавливаем режим OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
    
  pinMode(layerPin1, OUTPUT);
  pinMode(layerPin2, OUTPUT);
  pinMode(layerPin3, OUTPUT);
  pinMode(layerPin4, OUTPUT);
}
 
void loop() {
  // зажигаем слои
  digitalWrite(layerPin1, HIGH);
  digitalWrite(layerPin2, HIGH);
  digitalWrite(layerPin3, HIGH);
  digitalWrite(layerPin4, HIGH);
  
 // проходим циклом по всем 16 выходам двух регистров
  for (int thisLed = 0; thisLed < 16; thisLed++) {
    // записываем сигнал в регистр для очередного светодиода
    registerWrite(thisLed, HIGH);
    delay(1000);   
    // если это не первый светодиод, то отключаем предыдущий
    if (thisLed > 0) {
      registerWrite(thisLed - 1, LOW);
    }
    // если это первый светодиод, то отключаем последний
    else {
      registerWrite(15, LOW);
    }
    // делаем паузу перед следующией итерацией
    delay(250);
  } 
}
 
// этот метод отсылает бит на сдвиговый регистр
 
void registerWrite(int whichPin, int whichState) {
  // для хранения 16 битов используем unsigned int
  unsigned int bitsToSend = 0;   
 
  // выключаем светодиоды на время передачи битов
  digitalWrite(latchPin, LOW);
 
  // устанавливаем HIGH в соответствующий бит
  bitWrite(bitsToSend, whichPin, whichState);
 
  // разбиваем наши 16 бит на два байта
  // для записи в первый и второй регистр
  byte registerOne = highByte(bitsToSend);
  byte registerTwo = lowByte(bitsToSend);
 
  // "проталкиваем" байты в регистры
  shiftOut(dataPin, clockPin, MSBFIRST, registerTwo);
  shiftOut(dataPin, clockPin, MSBFIRST, registerOne);
 
  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
}

Если вместо цикла

for (int thisLed = 0; thisLed < 16; thisLed++) {

для thisLed задавать конкретное значение от 0 до 15, то зажигается выбранный столбец. Но у меня никак не получается зажечь одновременно несколько столбцов! Если я пишу

registerWrite(0, HIGH);
registerWrite(3, HIGH);
registerWrite(12, HIGH);
registerWrite(15, HIGH);

то вместо зажигания угловых столбцов, получаю горящий последний столбец и мигающие остальные угловые. Причём, даже если я часть void loop оставляю вот такой:

void loop() {
  // зажигаем слои
  digitalWrite(layerPin1, HIGH);
  digitalWrite(layerPin2, HIGH);
  digitalWrite(layerPin3, HIGH);
  digitalWrite(layerPin4, HIGH);
  
 // проходим циклом по всем 16 выходам двух регистров
  for (int thisLed = 0; thisLed < 16; thisLed++) {
    // записываем сигнал в регистр для очередного светодиода
    registerWrite(thisLed, HIGH);
    delay(1000);   
  } 
}

то всё равно столбцы зажигаются последовательно по одному... Я уже весь моск себе свернул, пытаясь понять этот прикол.

Собственно, вопрос: подскажите, как зажечь несколько столбцов одновременно?

После этого начну думать, как бы зажигать эти столбцы через терминал ардуиновский... А потом, если не свихнусь, буду сюда же bluetooth прикручивать для управления кубиком с телефона. Но это пока совсем заоблачная мечта :(

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а если массив организовать 4 на 4 boolean

менять в нем значения и массив целиком отправлять. так и проще для понимания, и программировать

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

А можно с примером кода? Я же говорю, я почти полный ноль в программировании. Из школы остались смутные представления о Бейсике, в институте программирования практически не было, работая учителем пришлось чуть столкнуться с Паскалем, но... Мне как-то проще понять, разбирая конкретный код.

Если не трудно, покажите пример. Я-то сейчас пойду Гугл опять мучить на эту тему, но мало ли не найду нужного :)

Спасибо за помощь и терпение!

UPD: про сами массивы я почитал, но всё же не понял, как "организовать массив 4 на 4 boolean" :(

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

можно одномерный, можно двумерный. я например сделал одномерный, но для понимания оформил в виде 4х4

что то вроде этого должно получится

boolean mass[16] {
  0,0,0,0,
  0,0,0,0,
  0,0,0,0,
  0,0,0,0
}

byte registerOn = 0;
byte registerTwo = 0;

for(byte i=0;i<8;i++){
  registerOn = mass[i]<<i;
}
for(byte i=8;i<16;i++){
  registerTwo = mass[i]<<(i-8);
}

shiftOut(dataPin, clockPin, MSBFIRST, registerTwo);
shiftOut(dataPin, clockPin, MSBFIRST, registerOne);

 

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Чуть пришлось похимичить с кодом, а то ругалось на ошибки. В результате получилось вот так:

// Пин подключен к ST_CP входу 74HC595
const int latchPin = 8;
// Пин подключен к SH_CP входу 74HC595
const int clockPin = 12;
// Пин подключен к DS входу 74HC595
const int dataPin = 11;
 
char inputString[2];

// указываем пины, к которым подключены слои
int layerPin1 = 4;
int layerPin2 = 5;
int layerPin3 = 6;
int layerPin4 = 7;

boolean mass[16] = {
  0,0,0,0,
  0,0,0,1,
  0,0,0,0,
  0,0,0,1
};
 
 
void setup() {
  // устанавливаем режим OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
    
  pinMode(layerPin1, OUTPUT);
  pinMode(layerPin2, OUTPUT);
  pinMode(layerPin3, OUTPUT);
  pinMode(layerPin4, OUTPUT);
}
 
void loop() {
  // зажигаем слои
  digitalWrite(layerPin1, HIGH);
  digitalWrite(layerPin2, HIGH);
  digitalWrite(layerPin3, HIGH);
  digitalWrite(layerPin4, HIGH);

byte registerOne = 0;
byte registerTwo = 0;

for(byte i=0; i<8; i++){
  registerOne = mass[i]<<i;
}
for(byte i=8; i<16; i++){
  registerTwo = mass[i]<<(i-8);
}

  // выключаем светодиоды на время передачи битов
  digitalWrite(latchPin, LOW);
  
shiftOut(dataPin, clockPin, MSBFIRST, registerTwo);
shiftOut(dataPin, clockPin, MSBFIRST, registerOne);

  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
  delay(1000);
}

Беда в том, что нормально оно теперь реагирует только на 1 в указанных местах, зажигая при этом 8-й и 16-й столбцы (или один из них, если поставить одну 1). На единички в других местах не реагирует.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

хз че у меня ругается. попробуй у себя откомпилировать

#define latchPin  8
#define clockPin 12
#define dataPin  11

// указываем пины, к которым подключены слои
#define layerPin1  4
#define layerPin2  5
#define layerPin3  6
#define layerPin4  7

boolean mass[16] = {
  0,0,0,0,
  0,0,0,1,
  0,0,0,0,
  0,0,0,1
};


void setup() {
  // устанавливаем режим OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);

  pinMode(layerPin1, OUTPUT);
  pinMode(layerPin2, OUTPUT);
  pinMode(layerPin3, OUTPUT);
  pinMode(layerPin4, OUTPUT);
}

void loop() {
  // зажигаем слои
  digitalWrite(layerPin1, HIGH);
  digitalWrite(layerPin2, HIGH);
  digitalWrite(layerPin3, HIGH);
  digitalWrite(layerPin4, HIGH);

  unsigned int DATA = 0;

  for(byte i=0; i<16; i++){
    if(mass[i]==1) DATA |= 1<<i;
    else           DATA &= ~(1<<i);
  }

  // выключаем светодиоды на время передачи битов
  digitalWrite(latchPin, LOW);

  shiftOut(dataPin, clockPin, MSBFIRST, (DATA >> 8));
  shiftOut(dataPin, clockPin, MSBFIRST, DATA);

  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
  delay(1000);
}

 

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Вот в таком виде заработало:

// Пин подключен к ST_CP входу 74HC595
const int latchPin = 8;
// Пин подключен к SH_CP входу 74HC595
const int clockPin = 12;
// Пин подключен к DS входу 74HC595
const int dataPin = 11;
 
char inputString[2];

// указываем пины, к которым подключены слои
int layerPin1 = 4;
int layerPin2 = 5;
int layerPin3 = 6;
int layerPin4 = 7;

boolean mass[16] = {
  0,0,0,0, // слой 3
  0,0,0,0, // слой 4
  0,0,0,0, // слой 1
  0,0,0,1 // слой 2
};
 
 
void setup() {
  // устанавливаем режим OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
    
  pinMode(layerPin1, OUTPUT);
  pinMode(layerPin2, OUTPUT);
  pinMode(layerPin3, OUTPUT);
  pinMode(layerPin4, OUTPUT);
}
 
void loop() {
  // зажигаем слои
  digitalWrite(layerPin1, HIGH);
  digitalWrite(layerPin2, HIGH);
  digitalWrite(layerPin3, HIGH);
  digitalWrite(layerPin4, HIGH);

  unsigned int DATA = 0;

  for(byte i=0; i<16; i++){
    if(mass[i]==1) DATA |= 1<<i;
    else           DATA &= ~(1<<i);
  }

  // выключаем светодиоды на время передачи битов
  digitalWrite(latchPin, LOW);

  shiftOut(dataPin, clockPin, MSBFIRST, (DATA >> 8));
  shiftOut(dataPin, clockPin, MSBFIRST, DATA);

  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
  delay(1000);
}

Собственно, теперь получается зажигать нужные столбцы, супер! Не совсем понял, как именно оно работает, но буду разбираться дальше. Сейчас перепишу свои эффекты для кубика и буду пытаться присобачить сюда, например, микрофон. Чтобы от громкости звука срабатывали разные слои кубика.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

так что ему не нравилось? что пины не через const int объявлены? если да то странно

работает просто. есть массив из 16 битов. потом просто собирается в одну переменную int (2 байта = 16 бит)

затем отправляется. сначала первый байт из 2 байтов, потом второй

и в массиве не слои, а строки или столбцы. весь массив этой слой. хотя как сделаешь конечно

но если слои горизонтально расположены то массив это слой

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Стоит поменять объявление пинов на #define и его сразу начинает колбасить.

Так, я снова подвис. А как теперь динамически менять значение массива? Хотя... *ушёл пробовать*

UPD: да, там не слои. Я неудачно написал. Правильнее было бы написать так: строка 1 (ряды 1-4), строка 2 (ряды 5-8)...

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

тогда не так, а так

строка 1 (светодиоды 1-4), строка 2 (светодиоды 5-8)...

объяви это дело в функцию так. вроде так массив передается. может и не так

может надо объявлять массив byte и тогда будет работать. надо проверять

void Sloy(boolean *sloy_data){
  unsigned int DATA = 0;

  for(byte i=0; i<16; i++){
    if((sloy_data+i)==1) DATA |= 1<<i;
    else           DATA &= ~(1<<i);
  }

  // выключаем светодиоды на время передачи битов
  digitalWrite(latchPin, LOW);

  shiftOut(dataPin, clockPin, MSBFIRST, (DATA >> 8));
  shiftOut(dataPin, clockPin, MSBFIRST, DATA);

  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
}

а значение массива менять просто mass[1] = 1; и это дело в цикл

массив по большому счету тебе нужен в начале. если будет какой нибудь конвертер картинок то массив не нужен, а все данные можно хранить в int как DATA

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Я свихнусь с этим кубиком :(

Переткнул провода в схеме правильно и теперь массив нормально показывает зажигаемые светодиоды. Но появился новый вопрос:

// Пин подключен к ST_CP входу 74HC595
const int latchPin = 8;
// Пин подключен к SH_CP входу 74HC595
const int clockPin = 12;
// Пин подключен к DS входу 74HC595
const int dataPin = 11;

// указываем пины, к которым подключены слои
int LayerPin[] = {4,5,6,7};

boolean mass[16] = {
  0,0,0,0, // строка 1 (светодиоды 0-2)
  0,0,0,0, // строка 2 (светодиоды 3-7)
  0,0,0,0, // строка 3 (светодиоды 8-11)
  0,0,0,0 // строка 4 (светодиоды 12-15)
};
 
void setup() {
  Serial.begin(9600);
  // устанавливаем режим OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
    
  for(int layer = 0; layer < 4; layer++){
    pinMode(LayerPin[layer], OUTPUT);
  }
}
 
void loop() {
  // зажигаем слои
for(int layer = 0; layer < 4; layer++){
    pinMode(LayerPin[layer], OUTPUT);
    digitalWrite(LayerPin[layer], HIGH);
  }
  unsigned int DATA = 0;
  for(byte pin = 0; pin < 4; pin++) {
    mass[pin] = 1;
    mass[pin+4] = 1;
    mass[pin+8] = 1;
    mass[pin+12] = 1;  
    
  for(byte i=0; i<16; i++){
    if(mass[i]==1) DATA |= 1<> 8));
  shiftOut(dataPin, clockPin, MSBFIRST, DATA);

  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
  delay(1000);
    mass[pin] = 0;
    mass[pin+4] = 0;
    mass[pin+8] = 0;
    mass[pin+12] = 0;
  }
for(byte pin = 2; pin >= 0; pin--) {
    mass[pin] = 1;
    mass[pin+4] = 1;
    mass[pin+8] = 1;
    mass[pin+12] = 1;  
    
  for(byte i=0; i<16; i++){
    if(mass[i]==1) DATA |= 1<> 8));
  shiftOut(dataPin, clockPin, MSBFIRST, DATA);

  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
  delay(1000);
    mass[pin] = 0;
    mass[pin+4] = 0;
    mass[pin+8] = 0;
    mass[pin+12] = 0;
    }  
    for(int layer = 0; layer < 4; layer++){
    digitalWrite(LayerPin[layer], LOW);
    }
    
    for(int layer = 0; layer < 4; layer++){
    digitalWrite(LayerPin[layer], HIGH);
    for(byte pin = 0; pin < 4; pin++) {
    mass[pin] = 1;
    mass[15-pin] = 1;
    
  for(byte i=0; i<16; i++){
    if(mass[i]==1) DATA |= 1<> 8));
  shiftOut(dataPin, clockPin, MSBFIRST, DATA);

  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
  delay(100);
    mass[pin] = 0;
    mass[15-pin] = 0;
    }
  }
};>;>;>

Данный код последовательно зажигает вертикальный слой от одной стороны кубика к другой и обратно. После этого в монитор порта выводятся сплошные нули (и для массива, и для DATA). Вопрос: почему он не выполняет следующую часть программы и не повторяет потом программу заново? Пробовал всё это помещать в конструкцию

count = 1;
  while(count < 5){...
  count++;
}

как делал при прямом подключении кубика к ардуинке - нифига не меняется.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

хз. сам голову ломай. я с кубами не занимался. самое главное я тебе дал

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

:) Я не теряю надежду, что кто-нибудь ещё сюда заглянет и подскажет мысль дельную

jeka_tm, огромное спасибо за помощь!

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Всем привет!

Благодаря помощи jeka_tm и одного моего старого знакомого, удалось сделать вот такое: https://www.youtube.com/watch?v=lGUCWdvnb0s

В описании к видео есть ссылка на код программы, но, на всякий случай, приведу её и здесь:

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

const int latchPin = 8;        // Пин подключен к ST_CP входу 74HC595
const int clockPin = 12;       // Пин подключен к SH_CP входу 74HC595
const int dataPin = 11;        // Пин подключен к DS входу 74HC595
int LayerPin[] = {4,5,6,7};    // указываем пины, к которым подключены слои кубика
int ButPin = 2;               // подключаем кнопку к выходу 10

int layer = 0;                 // слой
int count = 0;                 // счётчик
int flag = 0;                  // флаг состояния
volatile int rejim = 0;        // Переключалка

int DATA1[] = {37929,16770,10260,37449,16770,10260}; //вертолёт от левого нижнего угла к правому верхнему и потов сверху вниз
//int DATA2[] = {36873,16770,10260};
//int DATA3[] = {1632,38505,1632,38505,38505,1632}; // центральный квадрат + угловые

unsigned int DATA = 0;
 
void setup() {
  Serial.begin(9600);
  
  lcd.init();
  lcd.backlight();
  lcd.print("Hello, world!");
  
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
  pinMode(ButPin, INPUT);
  
  // гасим все слои на всякий случай
  for(layer = 0; layer < 4; layer++){
    pinMode(LayerPin[layer], OUTPUT);
    digitalWrite(LayerPin[layer], LOW);
  }
  
  attachInterrupt(INT0, ChangeRejim, CHANGE);
}

// функция смены режима по кнопке
void ChangeRejim() {
  if(digitalRead(ButPin) == LOW && flag == 0)      
    {                                              
      rejim ++;
      flag = 1;
      if(rejim > 9)            // Если номер режима превышает количество эффектов,
        {  rejim = 0; }        // то отсчет начинается с нуля
    }
    if(digitalRead(ButPin) == HIGH && flag == 1)
    {
      flag = 0;
    } 
}

// функция передачи данных в сдвиговый регистр для зажигания светодиодов
void doMagicWithRegisters(int whatToPush) {
  digitalWrite(latchPin, LOW);
 
  shiftOut(dataPin, clockPin, MSBFIRST, (whatToPush>> 8));
  shiftOut(dataPin, clockPin, MSBFIRST, whatToPush);
 
  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
}

void LayersOff() { // функция для выключения всех слоёв
  for(layer = 0; layer < 4; layer++){
    digitalWrite(LayerPin[layer], LOW);
  }
}

void LayersOn() { // функция для включения всех слоёв
  for(int layer = 0; layer < 4; layer++){
    digitalWrite(LayerPin[layer], HIGH);
  }
}

// функция для работы с вертикальными слоями
// where = 1 - от нас, -1 - к нам
void vLayer(int where, unsigned int start, int mask, int time) {
  LayersOn();
   DATA = start;
   if (where > 0) {
   for (int n = 0; n < 4; n++) {
       DATA ^= mask<< (n*4);
       DATA ^= mask<< ((n-1)*4);
       doMagicWithRegisters(DATA);
   delay(time);
     }
   } else {
     for (int n = 2; n >= 0; n--) {
       DATA ^= mask<< ((n+1)*4);
       DATA ^= mask<< (n*4);
       doMagicWithRegisters(DATA);
   delay(time);
       }
   }
  LayersOff();
}

// функция для работы с горизонтальными слоями
// where = 1 - снизу вверх, -1 - сверху вниз, 0 - только указанный/все слои
// data - какие светодиоды горят, например: 1 - горит только первый, 15 - горят первых 4, 65535 - горят все
// time - сколько мс горят светодиоды
// NumLayer - какой слой горит (работает только при where = 0!), при 4 - все слои горят
void hLayer(int where, int data, int time, int NumLayer) {
  if (where > 0) {                          // снизу вверх
    for (layer = 0; layer < 4; layer++) {
      digitalWrite(LayerPin[layer], HIGH); 
      doMagicWithRegisters(data);
      delay(time);
      digitalWrite(LayerPin[layer], LOW); 
    }
  }
  else if (where < 0) {                      // сверху вниз
    for (layer = 2; layer >= 0; layer--) {
      digitalWrite(LayerPin[layer], HIGH); 
      doMagicWithRegisters(data);
      delay(time);
      digitalWrite(LayerPin[layer], LOW); 
    }
  }
  else {
   if (NumLayer == 4) {                    // все слои горят
      LayersOn();
        doMagicWithRegisters(data);
        delay(time);
      LayersOff();
        delay(time);
    }
  else {
      digitalWrite(LayerPin[NumLayer], HIGH); 
      doMagicWithRegisters(data);
      delay(time);
      digitalWrite(LayerPin[NumLayer], LOW); 
   }
  }
  LayersOff();
}

void LCDtext(char Rname[]) // функция вывода на LCD 16x2 экран
  {
    lcd.setCursor(0,0);
    lcd.print(Rname);     // выводится название режима
    lcd.setCursor(0,1);
    lcd.print("Rejim: ");
    lcd.setCursor(8,1);
    lcd.print(rejim);     // выводится номер режима
  }

void loop() {
  
    Serial.println(digitalRead(ButPin));
    if(rejim == 0)
    { 
      LayersOff();
      LCDtext("Press button!   ");
  }
    
    if(rejim == 1)
    {    
  //вертолёт от левого нижнего угла к правому верхнему и потов сверху вниз
  LCDtext("Helicopter  *..*");
  count = 0;
  while (count < 5) { // повторяем count раз
      layer = 0;
        for (int i = 0; i < 6; i++) {
          digitalWrite(LayerPin[layer], HIGH);
          doMagicWithRegisters(DATA1[i]);
          delay(150);
          digitalWrite(LayerPin[layer], LOW);
            if (i < 3) {
              layer++;
            }
            else {
              layer--;
            }
        }
     count++;
  }
  LayersOff();
    }
 
    if(rejim == 2)
    {
      LCDtext("hLayers+vLayers ");
      count = 0;
      while (count < 3) { // повторяем count раз  
          hLayer(1, 65535, 70, 4); // горизонтальные слои сверху вниз
          hLayer(-1, 65535, 70, 4); // горизонтальные слои снизу вверх
          vLayer(1, 15, 15, 70); // вертикальные слои от нас
          vLayer(-1, 61440, 15, 70); // вертикальные слои к нам
          count++;
       }
    }
    
    if(rejim == 3)
    {
      LCDtext("ALL IS UP!      ");
      count = 0;
      while (count < 3) { // повторяем count раз
          hLayer(0, 65535, 300, 4); // весь кубик
          count++;
       }
    }
    
    if(rejim == 4)
    {
      LCDtext("vLayers         ");
      count = 0;
      while (count < 3) { // повторяем count раз
          vLayer(1, 9, 9, 200); // угловые столбцы от нас
          vLayer(-1, 24576, 6, 200); // центральные столбцы к нам
          count++;
        }
    }
    
    if(rejim == 5)
    {
      LCDtext("hLayers 1       ");
      count = 0;
      while (count < 5) { // повторяем count раз 
          hLayer(0, 36873, 200, 0);
          hLayer(0, 1632, 200, 1);
          hLayer(0, 1632, 200, 2);
          hLayer(0, 36873, 200, 3);
          count++;
        } 
    }
    
    if(rejim == 6)
    {
      LCDtext("hLayers 2       ");
      count = 0;
      while (count < 5) { // повторяем count раз  
          hLayer(1, 38505, 100, 4);
          hLayer(-1, 38505, 100, 4);
          count++;
        }
    }
    
    if(rejim == 7)
    {
      LCDtext("hLayers 3       ");
      count = 0;
      while (count < 5) { // повторяем count раз
          hLayer(1, 28662, 100, 4);
          hLayer(-1, 28662, 100, 4);
          count++;
        }
    }
    
    if(rejim == 8)
    {    
      LCDtext("hLayers 4       ");
      count = 0;
      while (count < 5) { // повторяем count раз
          hLayer(1, 63903, 150, 4); // горизонтальные слои сверху вниз
          hLayer(-1, 1632, 150, 4); // горизонтальные слои снизу вверх
          count++;
      }
    }
    
    if(rejim == 9)
    {    
      LCDtext("hLayers 5       ");
      count = 0;
      while (count < 5) { // повторяем count раз
          hLayer(1, 1632, 150, 4); // горизонтальные слои сверху вниз
          hLayer(-1, 63903, 150, 4); // горизонтальные слои снизу вверх
          count++;
      }
    }
}

Постарался максимально прокомментировать код. Надеюсь, получилось нормально. Буду рад комментариям и замечаниям по данной программе!

Спасибо за внимание :)

UPD: забыл один момент. Пришлось подключить к ардуинке внешний БП от старого роутера, кажется, (12 В, 1 А). Связано это с тем, что, при питании от USB, когда загоралось много светодиодов, экран заметно терял яркость. С внешним БП такого не происходит. Если не ошибаюсь, USB всего 0,5 А выдаёт, чего явно было маловато моему чудовищу.

mkvmaks
Offline
Зарегистрирован: 07.07.2013

Здравствуйте, воспольщоалсявашим последнимкодом и есь проблема ((( почему-то не все светодиоды загораются, хотя замыканий нет. что может быь не так??

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

mkvmaks пишет:

Здравствуйте, воспольщоалсявашим последнимкодом и есь проблема ((( почему-то не все светодиоды загораются, хотя замыканий нет. что может быь не так??

Попробуйте проверить светодиоды просто подключая батарейку к контактам. Точно все горят?

maksmkv
Offline
Зарегистрирован: 07.04.2013

Как нистранно да (((

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Вот так светодиоды подключены у меня в итоговой версии кубика. Возможно, у вас они подключены как-то иначе или не к тем пинам?

Вот последняя рабочая версия кода:

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

const int latchPin = 8;        // Пин подключен к ST_CP входу 74HC595
const int clockPin = 12;       // Пин подключен к SH_CP входу 74HC595
const int dataPin = 11;        // Пин подключен к DS входу 74HC595
int LayerPin[] = {4,5,6,7};    // указываем пины, к которым подключены слои кубика
int ButPin = 2;               // подключаем кнопку к выходу 2

int layer = 0;                 // слой
int flag = 0;                  // флаг состояния
volatile int rejim = 0;        // Переключалка

int DATA1[] = {37929,16770,10260,37449,16770,10260}; //вертолёт от левого нижнего угла к правому верхнему и потов сверху вниз
int DATA2[] = {32,64,512,1024};
//int DATA3[] = {1632,38505,1632,38505,38505,1632}; // центральный квадрат + угловые

unsigned int DATA = 0;
 
void setup() {
  Serial.begin(9600);
  
  lcd.init();
  lcd.backlight();
  lcd.print("Hello, world!");
  
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
  pinMode(ButPin, INPUT);
  
  // гасим все слои на всякий случай
  for(layer = 0; layer < 4; layer++){
    pinMode(LayerPin[layer], OUTPUT);
    digitalWrite(LayerPin[layer], LOW);
  }
  
  attachInterrupt(INT0, ChangeRejim, CHANGE);
}

// функция смены режима по кнопке
void ChangeRejim() {
  if(digitalRead(ButPin) == LOW && flag == 0)      
    {                                              
      rejim ++;
      flag = 1;
      if(rejim > 10)            // Если номер режима превышает количество эффектов,
        {  rejim = 0; }        // то отсчет начинается с нуля
    }
    if(digitalRead(ButPin) == HIGH && flag == 1)
    {
      flag = 0;
    } 
}

// функция передачи данных в сдвиговый регистр для зажигания светодиодов
void doMagicWithRegisters(int whatToPush) {
  digitalWrite(latchPin, LOW);
 
  shiftOut(dataPin, clockPin, MSBFIRST, (whatToPush>> 8));
  shiftOut(dataPin, clockPin, MSBFIRST, whatToPush);
 
  // "защелкиваем" регистр, чтобы биты появились на выходах регистра
  digitalWrite(latchPin, HIGH);
}

void LayersOff() { // функция для выключения всех слоёв
  for(layer = 0; layer < 4; layer++){
    digitalWrite(LayerPin[layer], LOW);
  }
}

void LayersOn() { // функция для включения всех слоёв
  for(int layer = 0; layer < 4; layer++){
    digitalWrite(LayerPin[layer], HIGH);
  }
}

// функция для работы с вертикальными слоями
// where = 1 - от нас, -1 - к нам
void vLayer(int where, unsigned int start, int mask, int time) {
  LayersOn();
   DATA = start;
   if (where > 0) {
   for (int n = 0; n < 4; n++) {
       DATA ^= mask<< (n*4);
       DATA ^= mask<< ((n-1)*4);
       doMagicWithRegisters(DATA);
   delay(time);
     }
   } else {
     for (int n = 2; n >= 0; n--) {
       DATA ^= mask<< ((n+1)*4);
       DATA ^= mask<< (n*4);
       doMagicWithRegisters(DATA);
   delay(time);
       }
   }
  LayersOff();
}

// функция для работы с горизонтальными слоями
// where = 1 - снизу вверх, -1 - сверху вниз, 0 - только указанный/все слои
// data - какие светодиоды горят, например: 1 - горит только первый, 15 - горят первых 4, 65535 - горят все
// time - сколько мс горят светодиоды
// NumLayer - какой слой горит (работает только при where = 0!), при 4 - все слои горят
void hLayer(int where, int data, int time, int NumLayer) {
  if (where > 0) {                          // снизу вверх
    for (layer = 0; layer < 4; layer++) {
      digitalWrite(LayerPin[layer], HIGH); 
      doMagicWithRegisters(data);
      delay(time);
      digitalWrite(LayerPin[layer], LOW); 
    }
  }
  else if (where < 0) {                      // сверху вниз
    for (layer = 3; layer >= 0; layer--) {
      digitalWrite(LayerPin[layer], HIGH); 
      doMagicWithRegisters(data);
      delay(time);
      digitalWrite(LayerPin[layer], LOW); 
    }
  }
  else {
   if (NumLayer == 4) {                    // все слои горят
      LayersOn();
        doMagicWithRegisters(data);
        delay(time);
      LayersOff();
        delay(time);
    }
  else {
      digitalWrite(LayerPin[NumLayer], HIGH); 
      doMagicWithRegisters(data);
      delay(time);
      digitalWrite(LayerPin[NumLayer], LOW); 
   }
  }
  LayersOff();
}

void LCDtext(char Rname[]) // функция вывода на LCD 16x2 экран
  {
    lcd.setCursor(0,0);
    lcd.print(Rname);     // выводится название режима
    lcd.setCursor(0,1);
    lcd.print("Rejim: ");
    if (rejim < 10) {
      lcd.setCursor(8,1);
      lcd.print(rejim);     // выводится номер режима
      lcd.setCursor(9,1);
      lcd.print("  ");
    } else {
      lcd.setCursor(8,1);
      lcd.print(rejim);     // выводится номер режима
    }
  }

void loop() {
  
    Serial.println(digitalRead(ButPin));
    if(rejim == 0)
    { 
      LayersOff();
      LCDtext("Press button!   ");
  }
    if(rejim == 1)
    {    
  //вертолёт от левого нижнего угла к правому верхнему и потов сверху вниз
  LCDtext("Helicopter  *..*");
      layer = 0;
        for (int i = 0; i < 6; i++) {
          digitalWrite(LayerPin[layer], HIGH);
          doMagicWithRegisters(DATA1[i]);
          delay(100);
          digitalWrite(LayerPin[layer], LOW);
            if (i < 3) {
              layer++;
            }
            else {
              layer--;
            }
        }
  LayersOff();
    }
    
    if(rejim == 2)
    {
      LCDtext("Random LED      ");
        int randomLED = (pow(2, random(15)) + 1);
          hLayer(-1, randomLED, random(10, 100), 4);
          delay(100);
//          hLayer(-1, randomLED, 40, 4);
    }
 
    if(rejim == 3)
    {
      LCDtext("hLayers+vLayers ");
          hLayer(1, 65535, 70, 4); // горизонтальные слои сверху вниз
          hLayer(-1, 65535, 70, 4); // горизонтальные слои снизу вверх
          vLayer(1, 15, 15, 70); // вертикальные слои от нас
          vLayer(-1, 61440, 15, 70); // вертикальные слои к нам
    }
    
    if(rejim == 4)
    {
      LCDtext("ALL IS UP!      ");
        int TimeUP = 10;
          while (TimeUP <= 150) {
            hLayer(0, 65535, TimeUP, 4); // весь кубик
            TimeUP = TimeUP + 10;
          }
    }

    if(rejim == 5)
    {
      LCDtext("hLayers 1       ");
          hLayer(0, 36873, 200, 0);
          hLayer(0, 1632, 200, 1);
          hLayer(0, 1632, 200, 2);
          hLayer(0, 36873, 200, 3);
    }
    
    if(rejim == 6)
    {
      LCDtext("hLayers 2       ");
          hLayer(1, 38505, 100, 4);
          hLayer(-1, 38505, 100, 4);
    }
    
    if(rejim == 7)
    {
      LCDtext("hLayers 3       ");
          hLayer(1, 28662, 100, 4);
          hLayer(-1, 28662, 100, 4);
    }
    
    if(rejim == 8)
    {    
      LCDtext("hLayers 4       ");
          hLayer(1, 63903, 150, 4); // горизонтальные слои сверху вниз
          hLayer(-1, 1632, 150, 4); // горизонтальные слои снизу вверх
    }
    
    if(rejim == 9)
    {    
      LCDtext("hLayers 5       ");
          hLayer(1, 1632, 150, 4); // горизонтальные слои сверху вниз
          hLayer(-1, 63903, 150, 4); // горизонтальные слои снизу вверх
    }
    
    if(rejim == 10)
    { 
      LCDtext("Fireshow        ");
        for (int i = 0; i < 4; i++) {
          hLayer(1, DATA2[i], 120, 4);
          hLayer(-1, random(0,65535), 150, 4);
          delay(300);
        }
    }
}

Попробуйте так.

maksmkv
Offline
Зарегистрирован: 07.04.2013

Спасибо, попробую

mkvmaks
Offline
Зарегистрирован: 07.07.2013

Попробовал, ерунда какая-то, теперь лругие смветодиоды не работают (( - вы какой блок питания использовали??? У меня 5 v, 0,7 А

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Если у вас всё так же, как у меня (с экраном), но лучше стоит взять помощнее БП. Я взял на 12 В / 1 А (от старого роутера D-Link, кажется). При 5 В БП у меня экран "проседал", когда все светодиоды загорались и Ардуинка временами в ребут убегала.

Да, ещё момент: у вас к 74HC595 всё подключено как у меня? Может здесь что-то не туда подключили? У меня такое было с POV-палочкой. Перепутал порядок подключения светодиодов и половина рисующейся буквы была перевёрнута :)

maksmkv
Offline
Зарегистрирован: 07.04.2013

Не пробовали такой код переделывать как здесь http://www.instructables.com/id/The-4x4x4-LED-cube-Arduino/?ALLSTEPS ??? Ато здесь эффекты нравяться, а как сделать через сдвиговые регистры пока не знаю

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Видел эту статью и программу-генератор, но не пробовал. Пока не до этого сейчас :( Скорее всего, все издевательства дальнейшие над этим кубиком будут уже летом.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

выкладываю на всякий случай

 

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Спасибо!

Только я не совсем понял: там написано "RGB куб", это правильно? Я, видимо, туплю конкретно, но не могли бы вы более подробно про него написать или ссылочкой поделиться? А то я плату вижу, но не очень понимаю что куда подключается и как это потом программится :)

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

))) да ошибочка. обычный куб. ссылка

программа позже будет, хз когда. схема как здесь пины только другие. и управление слоями также через регистр+полевики

светодиоды 5мм. собирается так. делается пластина из чего нибудь. сверлятся отверстия под корпус светодиода, чтобы они туда вставали пластиковой частью. шаг 13мм, выбран изза длины выводов, чтобы доп. проводников было поменьше

сначала если держать так светодиод от себя "под корень" под углом 90 градусов согнуть. затем плюсовой загнуть обратно в месте пересечения плюса и края корпуса светодиода. в итоге если светодиод держать вертикально минусы будут горизонтально а плюсы вертикально. минусы спаиваются. плюсы для припаивания к следующему слою. для жесткости минусы пропаиваются поперек тремя проволочками

картинка вид светодиодов снизу. самый нижний слой впаивается в плату

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Спасибо!

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да смысл тебе собирать. у тебя уже все сделано и работает))

это я изобретаю велосипед

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Ну, вдруг я когда-нибудь решу другой кубик сделать :)

Правда, сначала надо бы разобраться с перепрошивкой ESP8266...

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

так у тебя уже вроде 2шт))) про перепрошивку не подскажу. знаю что через uart вроде прошивается

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Не совсем 2 :) Один 3*3*3 и один 4*4*4.

А ещё у меня вот такое появилось: http://habrahabr.ru/post/258955/

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да ты смотрю увлекся кубиками))

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Не только кубиками :) http://alninyo.ru/news/54/

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

ссылка не работает

а нет. блокирует)

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Не, это сервак упал :) Сервак домашний, под столом у друга в Москве стоит. Иногда падает :(

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

ну вот и мой куб заработал на 3шт 74HC595. используется 3 ноги ардуины

хардварный spi не стал делать, и так никаких морганий не увидел, а биты переставлять не хотелось, так как изза особенностей платы пришлось половину из двух байт разворачивать. да и еще управление слоями у меня 3 и 4 не по порядку, просто так спаять было удобнее

https://www.youtube.com/watch?v=TMSEihyWA2I

#define latch      8
#define clock     12
#define data      11

#define time_led   100

unsigned long time;
int length;
int N=0;

byte mass[] = {
  B0000,B0000,B0000,B0000   ,B0000,B0000,B0000,B0000   ,B0000,B0000,B0000,B0000   ,B0000,B0000,B0000,B0000   , 10,
  B0000,B0000,B0000,B0000   ,B0000,B0001,B0000,B0010   ,B0000,B0000,B0100,B0000   ,B0010,B0000,B0000,B0000   , 10,
  B0000,B0000,B0001,B0000   ,B0100,B0000,B0000,B0000   ,B0000,B0000,B0000,B0001   ,B0010,B0100,B0000,B1000   , 10,
  B0000,B0000,B0001,B0100   ,B0100,B0100,B0000,B0000   ,B0000,B0000,B0100,B0001   ,B1010,B0100,B0000,B1000   , 10,
  B0001,B0000,B1001,B0100   ,B0100,B0110,B0000,B1000   ,B0000,B0000,B0100,B0001   ,B1010,B0100,B0000,B1000   , 10,
  B0001,B0000,B1001,B0100   ,B0100,B0110,B0000,B1000   ,B0001,B1000,B0101,B0001   ,B1010,B0100,B0000,B1010   , 10,
  B1001,B0000,B1001,B0100   ,B0100,B0110,B0100,B1000   ,B0001,B1010,B0101,B0101   ,B1010,B0100,B0000,B1010   , 10,
  B1101,B1000,B1001,B0101   ,B0101,B0110,B0110,B1000   ,B0001,B1010,B0101,B0101   ,B1010,B0101,B1000,B1011   , 10,
  B1101,B1010,B1001,B0101   ,B0111,B0110,B1110,B1001   ,B0101,B1010,B0101,B1101   ,B1010,B0111,B1001,B1011   , 10,
  B1101,B1011,B1011,B0101   ,B0111,B0110,B1110,B1101   ,B1101,B1110,B0101,B1111   ,B1011,B0111,B1101,B1011   , 10,
  B1101,B1011,B1011,B1101   ,B1111,B1111,B1110,B1111   ,B1101,B1110,B0111,B1111   ,B1111,B0111,B1111,B1011   , 10,
  B1101,B1011,B1011,B0101   ,B0111,B0110,B1110,B1101   ,B1101,B1110,B0101,B1111   ,B1011,B0111,B1101,B1011   , 10,
  B1101,B1010,B1001,B0101   ,B0111,B0110,B1110,B1001   ,B0101,B1010,B0101,B1101   ,B1010,B0111,B1001,B1011   , 10,
  B1101,B1000,B1001,B0101   ,B0101,B0110,B0110,B1000   ,B0001,B1010,B0101,B0101   ,B1010,B0101,B1000,B1011   , 10,
  B1001,B0000,B1001,B0100   ,B0100,B0110,B0100,B1000   ,B0001,B1010,B0101,B0101   ,B1010,B0100,B0000,B1010   , 10,
  B0001,B0000,B1001,B0100   ,B0100,B0110,B0000,B1000   ,B0001,B1000,B0101,B0001   ,B1010,B0100,B0000,B1010   , 10,
  B0001,B0000,B1001,B0100   ,B0100,B0110,B0000,B1000   ,B0000,B0000,B0100,B0001   ,B1010,B0100,B0000,B1000   , 10,
  B0000,B0000,B0001,B0100   ,B0100,B0100,B0000,B0000   ,B0000,B0000,B0100,B0001   ,B1010,B0100,B0000,B1000   , 10,
  B0000,B0000,B0001,B0000   ,B0100,B0000,B0000,B0000   ,B0000,B0000,B0000,B0001   ,B0010,B0100,B0000,B1000   , 10,
  B0000,B0000,B0000,B0000   ,B0000,B0000,B0000,B0000   ,B0000,B0000,B0000,B0000   ,B0000,B0000,B0000,B0000   , 10,

  B0001,B0001,B0001,B0001   ,B0010,B0010,B0010,B0010   ,B0100,B0100,B0100,B0100   ,B1000,B1000,B1000,B1000   , 10,
  B0010,B0010,B0010,B0010   ,B0010,B0010,B0010,B0010   ,B0100,B0100,B0100,B0100   ,B0100,B0100,B0100,B0100   , 10,
  B0100,B0100,B0100,B0100   ,B0100,B0100,B0100,B0100   ,B0010,B0010,B0010,B0010   ,B0010,B0010,B0010,B0010   , 10,
  B1000,B1000,B1000,B1000   ,B0100,B0100,B0100,B0100   ,B0010,B0010,B0010,B0010   ,B0001,B0001,B0001,B0001   , 10,
  B0000,B0000,B0000,B0000   ,B1100,B1100,B1100,B1100   ,B0011,B0011,B0011,B0011   ,B0000,B0000,B0000,B0000   , 10,
  B0000,B0000,B0000,B0000   ,B0011,B0011,B0011,B0011   ,B1100,B1100,B1100,B1100   ,B0000,B0000,B0000,B0000   , 10,
  B0001,B0001,B0001,B0001   ,B0010,B0010,B0010,B0010   ,B0100,B0100,B0100,B0100   ,B1000,B1000,B1000,B1000   , 10,
  B0010,B0010,B0010,B0010   ,B0010,B0010,B0010,B0010   ,B0100,B0100,B0100,B0100   ,B0100,B0100,B0100,B0100   , 10,
  B0100,B0100,B0100,B0100   ,B0100,B0100,B0100,B0100   ,B0010,B0010,B0010,B0010   ,B0010,B0010,B0010,B0010   , 10,
  B1000,B1000,B1000,B1000   ,B0100,B0100,B0100,B0100   ,B0010,B0010,B0010,B0010   ,B0001,B0001,B0001,B0001   , 10,
  B0000,B0000,B0000,B0000   ,B1100,B1100,B1100,B1100   ,B0011,B0011,B0011,B0011   ,B0000,B0000,B0000,B0000   , 10,
  B0000,B0000,B0000,B0000   ,B0011,B0011,B0011,B0011   ,B1100,B1100,B1100,B1100   ,B0000,B0000,B0000,B0000   , 10,
  B0001,B0001,B0001,B0001   ,B0010,B0010,B0010,B0010   ,B0100,B0100,B0100,B0100   ,B1000,B1000,B1000,B1000   , 10,
  B0010,B0010,B0010,B0010   ,B0010,B0010,B0010,B0010   ,B0100,B0100,B0100,B0100   ,B0100,B0100,B0100,B0100   , 10,
  B0100,B0100,B0100,B0100   ,B0100,B0100,B0100,B0100   ,B0010,B0010,B0010,B0010   ,B0010,B0010,B0010,B0010   , 10,
  B1000,B1000,B1000,B1000   ,B0100,B0100,B0100,B0100   ,B0010,B0010,B0010,B0010   ,B0001,B0001,B0001,B0001   , 10,
  B0000,B0000,B0000,B0000   ,B1100,B1100,B1100,B1100   ,B0011,B0011,B0011,B0011   ,B0000,B0000,B0000,B0000   , 10,
  B0000,B0000,B0000,B0000   ,B0011,B0011,B0011,B0011   ,B1100,B1100,B1100,B1100   ,B0000,B0000,B0000,B0000   , 10,
  B0001,B0001,B0001,B0001   ,B0010,B0010,B0010,B0010   ,B0100,B0100,B0100,B0100   ,B1000,B1000,B1000,B1000   , 10,
  B0010,B0010,B0010,B0010   ,B0010,B0010,B0010,B0010   ,B0100,B0100,B0100,B0100   ,B0100,B0100,B0100,B0100   , 10,
  B0100,B0100,B0100,B0100   ,B0100,B0100,B0100,B0100   ,B0010,B0010,B0010,B0010   ,B0010,B0010,B0010,B0010   , 10,
  B1000,B1000,B1000,B1000   ,B0100,B0100,B0100,B0100   ,B0010,B0010,B0010,B0010   ,B0001,B0001,B0001,B0001   , 10,
  B0000,B0000,B0000,B0000   ,B1100,B1100,B1100,B1100   ,B0011,B0011,B0011,B0011   ,B0000,B0000,B0000,B0000   , 10,
  B0000,B0000,B0000,B0000   ,B0011,B0011,B0011,B0011   ,B1100,B1100,B1100,B1100   ,B0000,B0000,B0000,B0000   , 10,
};


void setup() {
  pinMode(latch, OUTPUT);
  pinMode(data,  OUTPUT); 
  pinMode(clock, OUTPUT);
  length = sizeof(mass)/17;
  time=millis();
}

void loop(){
  if((millis()-time)>time_led){
    N++;
    time=millis();
  }
  if(N==length) N=0;
  Cube_send(N);
}


//=======================================================Отрисовка куба  
void Cube_send(int numb){
  for(byte i=0;i<4;i++){
    dWrite(latch, LOW);

    Send_4_Bit_INV(mass[3-i+N*17]);
    Send_4_Bit_NOR(mass[7-i+N*17]);

    switch (i){
    case 0:  
      SendByte(0x01); 
      break;
    case 1:  
      SendByte(0x02); 
      break;
    case 2:  
      SendByte(0x08); 
      break;
    case 3:  
      SendByte(0x04); 
      break;
    }

    Send_4_Bit_INV(mass[11-i+N*17]);
    Send_4_Bit_NOR(mass[15-i+N*17]);

    dWrite(latch, HIGH);
  }
}

//==========================================Отправка 4 бит прямой порядок     
void Send_4_Bit_NOR(byte c){
  for(byte i=0;i<4;i++){
    dWrite(clock,0);
    (c & 0x08)? dWrite(data,1) : dWrite(data,0);
    dWrite(clock,1);
    c <<= 1;
  }
}

//========================================Отправка 4 бит обратный порядок    
void Send_4_Bit_INV(byte c){
  for(byte i=0;i<4;i++){
    dWrite(clock,0);
    (c & 0x01)? dWrite(data,1) : dWrite(data,0);
    dWrite(clock,1);
    c >>= 1;
  }
}

//=========================================================Отправка 8 байт    
void SendByte(byte c){
  for(byte i=0;i<8;i++){
    dWrite(clock,0);
    (c & 0x80)? dWrite(data,1) : dWrite(data,0);
    dWrite(clock,1);
    c <<= 1;
  }
}
//=======================================================Управление пинами  
void dWrite(byte pin, byte val){
  byte bit = digitalPinToBitMask(pin);
  volatile byte *out;
  out = portOutputRegister(digitalPinToPort(pin));
  (val)? *out |= bit : *out &=~bit;
}

рисовать в этой программе

https://yadi.sk/d/3Pupj8oxhHrrF

скопировать получившийся массив в код и он будет отображаться

есть математические способы построения различных эффектов, но врядли руки дойдут. вот код, может кто то захочет приделать

//void setvoxel(int x, int y, int z);
//void clrvoxel(int x, int y, int z);
//unsigned char getvoxel(int x, int y, int z);
//unsigned char inrange(int x, int y, int z);
//void flpvoxel(int x, int y, int z);
//void altervoxel(int x, int y, int z, int state);
//void setplane_z(int z);
//void clrplane_z(int z);
//void setplane_x(int x);
//void clrplane_x(int x);
//void setplane_y(int y);
//void clrplane_y(int y);
//void setplane(unsigned char plane, int i, int state);
//void setline_z(int x, int y, int z1, int z2);
//void setline_x(int z, int y, int x1, int x2);
//void setline_y(int z, int x, int y1, int y2);
//void clrline_z(int x, int y, int z1, int z2);
//void clrline_x(int z, int y, int x1, int x2);
//void clrline_y(int z, int x, int y1, int y2);
//void drawline_plane(int x2, int y2, int x1, int y1,unsigned char anchor);
//void fill (unsigned char pattern);
//void tmp2cube(void);
//void cube2tmp(void);


// Set a voxel in the cube buffer
void setvoxel(int x, int y, int z){ 
  if (inrange(x, y, z))  cube[z][y] |= (1 << x);
}

// Clear a voxel in the cube buffer
void clrvoxel(int x, int y, int z){
  if (inrange(x, y, z))  cube[z][y] &= ~(1 << x);
}

// Get the current status of a voxel
unsigned char getvoxel(int x, int y, int z){
  if (inrange(x, y, z)){
    if (cube[z][y] & (1 << x)){
      return 0x01;
    } 
    else{
      return 0x00;
    }
  }
}

// This function validates that we are drawing inside the cube.
unsigned char inrange(int x, int y, int z)
{
  if (x >= 0 && x < 4 && y >= 0 && y < 4 && z >= 0 && z < 4){
    return 0x01;
  } 
  else{
    // One of the coordinates was outside the cube.
    return 0x00;
  }
}

// Alter the state of  a voxel in the cube buffer
// This function was made in order to make set and clr versions
// of other functions without writing two almost identical functions
void altervoxel(int x, int y, int z, int state){
  if (state == 1){
    setvoxel(x,y,z);
  } 
  else
  {
    clrvoxel(x,y,z);
  }
}

// Flip the state of a voxel.
// If the voxel is 1, its turned into a 0, and vice versa.
void flpvoxel(int x, int y, int z){
  if (inrange(x, y, z))  cube[z][y] ^= (1 << x);
}

// Sets all the leds in the X and Y for a given Z
// i.e. draws a horizonal plane on a given level (z)
void setplane_z (int z){
  int i;
  // Loop the 4 rows on the given level and write 1 to the bits.
  for (i=0;i<4;i++) cube[z][i] = 0x0f;
}

// Clears all the leds on X and Y for a given Z
void clrplane_z (int z){
  int iy;
  for (iy=0;iy<4;iy++)  cube[z][iy] = 0x00;
}

// Sets all the leds on Y and Z for a given X
void setplane_x (int x){
  int z;
  int y;
  // Since coordinates along the X axis are
  // the actual bits in each row of each layer
  // We loop them all, and set the apropriate bit.
  for (z=0;z<4;z++){
    for (y=0;y<4;y++){
      // Set a bit, and shift it inwards to the right X
      cube[z][y] |= (0x01 << x);
    }
  }
}

// Clear all the leds on Y and Z for a given X
void clrplane_x (int x){
  int z;
  int y;
  for (z=0;z<4;z++){
    for (y=0;y<4;y++){
      cube[z][y] &= ~(0x01 << x);
    }
  }
}

// Sets all the leds on X and Z for a given Y
void setplane_y (int y){
  int iz;
  for (iz=0;iz<4;iz++)
    cube[iz][y] = 0x0f; 
}

// Sets all the leds on X and Z for a given Y
void clrplane_y (int y){
  int iz;
  for (iz=0;iz<4;iz++)  cube[iz][y] = 0x00; 
}

// Set a plane using the functions above
void setplane(unsigned char plane, int i, int state){
  if (plane == "x"){
    if (state > 0){
      setplane_x(i);
    } 
    else{
      clrplane_x(i);
    }
  }

  if (plane == "y"){
    if (state > 0){
      setplane_y(i);
    } 
    else{
      clrplane_y(i);
    }
  }

  if (plane == "z"){
    if (state > 0){
      setplane_z(i);
    } 
    else{
      clrplane_z(i);
    }
  }
}


// Draw a line along the Z axis
// state=0 clears a line of voxels,
// state=1 sets a line of voxels.
void line_z(int x, int y, int z1, int z2, int state){
  if (z1>z2){
    int tmp;
    tmp = z1;
    z1= z2;
    z2 = tmp;
  }
  int i;
  for (i=z1;i<=z2;i++){
    altervoxel(x,y,i,state);
  }
}

// Draw a line along the X axis
void line_x(int z, int y, int x1, int x2, int state){
  if (x1>x2){
    int tmp;
    tmp = x1;
    x1= x2;
    x2 = tmp;
  }
  int i;
  for (i=x1;i<=x2;i++){
    altervoxel(i,y,z,state);
  }
}

// Draw a line along the Y axis.
void line_y(int z, int x, int y1, int y2, int state){
  if (y1>y2){
    int tmp;
    tmp = y1;
    y1= y2;
    y2 = tmp;
  }
  int i;
  for (i=y1;i<=y2;i++){
    altervoxel(x,i,z,state);
  }
}

// Draws a plane on any diagonal angle
// unsigned char anchor is the plane that is constant. ("x","y", or "z")
void drawline_plane(int x2, int y2, int x1, int y1,unsigned char anchor){
  int deltax = abs(x2 - x1);        // The difference between the x's
  int deltay = abs(y2 - y1);        // The difference between the y's
  int x = x1;                       // Start x off at the first pixel
  int y = y1;                       // Start y off at the first pixel
  int xinc1;
  int xinc2;
  int yinc1;
  int yinc2;
  int den;
  int num;
  int numadd;
  int numpixels;

  if (x2 >= x1){                 // The x-values are increasing
    xinc1 = 1;
    xinc2 = 1;
  }
  else{                          // The x-values are decreasing
    xinc1 = -1;
    xinc2 = -1;
  }

  if (y2 >= y1){                 // The y-values are increasing
    yinc1 = 1;
    yinc2 = 1;
  }
  else{                          // The y-values are decreasing
    yinc1 = -1;
    yinc2 = -1;
  }

  if (deltax >= deltay){         // There is at least one x-value for every y-value
    xinc1 = 0;                  // Don't change the x when numerator >= denominator
    yinc2 = 0;                  // Don't change the y for every iteration
    den = deltax;
    num = deltax / 2;
    numadd = deltay;
    numpixels = deltax;         // There are more x-values than y-values
  }
  else{                          // There is at least one y-value for every x-value
    xinc2 = 0;                  // Don't change the x for every iteration
    yinc1 = 0;                  // Don't change the y when numerator >= denominator
    den = deltay;
    num = deltay / 2;
    numadd = deltax;
    numpixels = deltay;         // There are more y-values than x-values
  }
  int curpixel;
  for (curpixel = 0; curpixel <= numpixels; curpixel++){
    if (anchor == "z"){
      // Draw the current pixels
      setvoxel(x, y, 3);
      setvoxel(x, y, 2);
      setvoxel(x, y, 1);
      setvoxel(x, y, 0);
    }

    if (anchor == "x"){
      // Draw the current pixels
      setvoxel(x, 3, y);
      setvoxel(x, 2, y);
      setvoxel(x, 1, y);
      setvoxel(x, 0, y);
    }

    if (anchor == "y"){
      // Draw the current pixels
      setvoxel(3, y, x);
      setvoxel(2, y, x);
      setvoxel(1, y, x);
      setvoxel(0, y, x);
    }

    num += numadd;              // Increase the numerator by the top of the fraction
    if (num >= den){             // Check if numerator >= denominator
      num -= den;               // Calculate the new numerator value
      x += xinc1;               // Change the x as appropriate
      y += yinc1;               // Change the y as appropriate
    }
    x += xinc2;                 // Change the x as appropriate
    y += yinc2;                 // Change the y as appropriate
  }
}

// Copy the temp cube onto the real cube
void tmp2cube(void){
  int y, z;
  for (z=0;z<4;z++){
    for (y=0;y<4;y++){
      cube[z][y] = tmpcube[z][y];
    }
  }
}

// Copy the cube into the temp buffer
void cube2tmp(void){
  int y, z;
  for (z=0;z<4;z++){
    for (y=0;y<4;y++){
      tmpcube[z][y] = cube[z][y];
    }
  }
}

// Fill the cube with a given pattern.
// fill(0x00); clears the cube
// fill(0xff); lights all leds
void fill (unsigned char pattern){
  int z;
  int y;
  for (z=0;z<4;z++){
    for (y=0;y<4;y++){
      cube[z][y] = pattern;
    }
  }
}



//void effect_spiral(int direction, int iterations, int del);
//void effect_spinning_plane(int direction, int iterations, int del);
//void effect_rain (int iterations, int delay, int hold, int speed);
//void sendvoxel_z (unsigned char x, unsigned char y, unsigned char z, int del);
//void sendplane_rand_z (unsigned char z, int delay, int wait);
//void blinky(void);
//void flyplane (unsigned char plane,unsigned char direction, int del);
//void loadbar(int del);
//void random_1 (int iterations, int voxels, int del);
//void random_2 (void);
//void random_filler (int iterations, int pixels, int delay, int state);
//void random_filler2 (int delay, int state);
//void planeflip (unsigned char axis1, int pos1, unsigned char axis2, int pos2, int del);
//void flip_playback (int delay, unsigned char flip_x, unsigned char flip_y, unsigned char flip_z);
//void boingboing (uint16_t iterations, int delay, unsigned char mode, unsigned char drawmode);

// Shows an animation of a spinning spiral
void effect_spiral(int direction, int iterations, int del){
  int i;
  int z;		// cube level

  for (i=0;i<iterations;i++)  {
    // Loop cube levels
    for (z=0;z<4;z++)    {
      // Read the animation from program memory and put it in the cube buffer.
      // y=0 and y=2 is stored in the upper nibble of the byte, and must be bitshifted into place.
      cube[z][0] = (pgm_read_byte(&spinning_line[(i+z)%6][0]) >> 4);
      cube[z][1] = pgm_read_byte(&spinning_line[(i+z)%6][0]);
      cube[z][2] = (pgm_read_byte(&spinning_line[(i+z)%6][1]) >> 4);
      cube[z][3] = pgm_read_byte(&spinning_line[(i+z)%6][1]);
      // the +z makes the animation iterate one step for each plane
      // making it into a spiral
    }
    delay(del);
  }
}

// Shows an animation of a spinning plane.
void effect_spinning_plane(int direction, int iterations, int del){
  int i;
  int z;		// cube level

  for (i=0;i<iterations;i++)  {
    // Loop cube levels.
    for (z=0;z<4;z++)    {
      cube[z][0] = (pgm_read_byte(&spinning_line[(i)%6][0]) >> 4);
      cube[z][1] = pgm_read_byte(&spinning_line[(i)%6][0]);
      cube[z][2] = (pgm_read_byte(&spinning_line[(i)%6][1]) >> 4);
      cube[z][3] = pgm_read_byte(&spinning_line[(i)%6][1]);
    }
    delay(del);
  }
}

// Random voxels light up at the top layer and falls to the bottom layer.
void effect_rain (int iterations, int delay, int hold, int speed){
  int i;
  int p;		// Position of the raindrop on Z
  int z;		// cube layer
  int y;		// byte

  fill(0x00);

  for (i = 0; i < iterations; i++){
    // Start by setting a random pixel on layer 3.
    setvoxel(rand()%4,rand()%4,3);
    delay(hold);

    // The raindrop has to step down one layer 4 times
    // in order to travel from the top, and exit out the bottom.
    for (p=1;p<4;p++){
      // Shift all the layers one position down,
      for (z=0;z<3;z++){
        for (y=0;y<4;y++){
          cube[z][y] = cube[z+1][y];
        }
      }

      // and a blank image on the top layer.
      cube[3][0] = 0x00;
      cube[3][1] = 0x00;
      cube[3][2] = 0x00;
      cube[3][3] = 0x00;

      // Accelerate the raindrop as it falls.
      // (speed/p) will decrease as p increases.
      delay(speed+(speed/p));
    }

    fill(0x00);
    delay(del);
  }
}

// Send a voxel flying from one side of the cube to the other
// It its at the bottom, send it to the top..
void sendvoxel_z (unsigned char x, unsigned char y, unsigned char z, int del){
  int i, ii;
  for (i=0; i<4; i++){
    if (z == 3){
      ii = 3-i;
      clrvoxel(x,y,ii+1);
    } 
    else{
      ii = i;
      clrvoxel(x,y,ii-1);
    }
    setvoxel(x,y,ii);
    delay(del);
  }
}

// Send all the voxels from one side of the cube to the other
// Start at z and send to the opposite side.
// Sends in random order.
void sendplane_rand_z (unsigned char z, int delay, int wait){
  unsigned char loop = 16;
  unsigned char x, y;

  fill(0x00);

  setplane_z(z);

  // Send voxels at random untill all 16 have crossed the cube.
  while(loop){
    x = rand()%4;
    y = rand()%4;
    if (getvoxel(x,y,z)){
      // Send the voxel flying
      sendvoxel_z(x,y,z,del);
      delay(wait);
      loop--; // one down, loop-- to go. when this hits 0, the loop exits. 
    }
  }
}

// For each coordinate along X and Y, a voxel is set either at level 0 or at level 3
// for n iterations, a random voxel is sent to the opposite side of where it was.
void sendvoxels_rand_z (int iterations, int delay, int wait){
  unsigned char loop = 16;
  unsigned char x, y, last_x, last_y, i;

  fill(0x00);

  // Loop through all the X and Y coordinates
  for (x=0;x<4;x++){
    for (y=0;y<4;y++){
      // Then set a voxel either at the top or at the bottom
      if (rand()%2 == 0){
        setvoxel(x,y,0);
      } 
      else{
        setvoxel(x,y,3);
      }
    }
  }

  for (i=0;i<iterations;i++){
    // Pick a random x,y position
    x = rand()%4;
    y = rand()%4;
    // but not the sameone twice in a row
    if (y != last_y && x != last_x){
      // If the voxel at this x,y is at the bottom
      if (getvoxel(x,y,0)){
        // send it to the top
        sendvoxel_z(x,y,0,del);
      } 
      else{
        // if its at the top, send it to the bottom
        sendvoxel_z(x,y,3,del);
      }
      delay(wait);

      // Remember the last move
      last_y = y;
      last_x = x;
    }
  }
}

// Set n number of voxels at random positions
void random_1 (int iterations, int voxels, int del){
  int i;
  int v;
  for (i = 0; i < iterations; i++){
    for (v=0;v<=voxels;v++)
      setvoxel(rand()%4,rand()%4,rand()%4);

    delay(del);
    fill(0x00);
  }
}

// blink 1 random voxel, blink 2 random voxels..... blink 20 random voxels
// and back to 1 again.
void random_2 (void)
{
  int i;

  for (i=1;i<20;i++){
    random_1(5,i,500);
  }

  for (i=20;i>=1;i--){
    random_1(5,i,500);
  }
}

// Randomly fill or empty the cube with n voxels.
void random_filler (int iterations, int pixels, int delay, int state){
  int i;
  int p;
  for (i = 0; i < iterations; i++){
    for (p=0;p<=pixels;p++)
      altervoxel(rand()%4,rand()%4,rand()%4,state);

    delay(del);
  }
}

// Set or clear exactly 64 voxels in a random order.
void random_filler2 (int delay, int state){
  int x,y,z;
  int loop = 0;

  while (loop<63){
    x = rand()%4;
    y = rand()%4;
    z = rand()%4;

    if ((state == 0 && getvoxel(x,y,z) == 0x01) || (state == 1 && getvoxel(x,y,z) == 0x00)){
      altervoxel(x,y,z,state);
      delay(del);
      loop++;
    }	
  }
}

// ...to be continiued
void planeflip (unsigned char axis1, int pos1, unsigned char axis2, int pos2, int del)
{

}


// Light all leds layer by layer,
// then unset layer by layer
void loadbar(int del){
  fill(0x00);

  int z,y;

  for (z=0;z<4;z++){
    for (y=0;y<4;y++)
      cube[z][y] = 0xff;

    delay(del);
  }

  delay(delay*3);

  for (z=0;z<4;z++){
    for (y=0;y<4;y++)
      cube[z][y] = 0x00;

    delay(del);
  }
}

void flyplane (unsigned char plane,unsigned char direction, int del)
{
  int i,ii;

  fill(0x00);

  for (i=0;i<4;i++)
  {
    if (direction != 0)
    {
      ii = 3-i;
    } 
    else
    {
      ii = i;
    }

    setplane(plane,ii,1);
    delay(del);
    setplane(plane,ii,0);
  }

  for (i=2;i>=0;i--)
  {
    if (direction != 0)
    {
      ii = 3-i;
    } 
    else
    {
      ii = i;
    }

    setplane(plane,ii,1);
    delay(del);
    setplane(plane,ii,0);
  }
}

void blinky()
{
  int a;

  fill(0x00);
  delay(2000);

  for (a=0;a<3;a++)
  {
    fill(0xff);
    delay(50);
    fill(0x00);

    delay(1500);

    fill(0xff);
    delay(30);
    fill(0x00);

    delay(7000);
  }


}

void blinky2()
{
  int i,r;
  fill(0x00);

  for (r=0;r<5;r++)
  {
    i = 750;
    while (i>0)
    {
      fill(0x00);
      delay(i);

      fill(0xff);
      delay(100);

      i = i - (15+(1000/(i/10)));
    }

    delay(1000);

    i = 750;
    while (i>0)
    {
      fill(0x00);
      delay(751-i);

      fill(0xff);
      delay(100);

      i = i - (15+(1000/(i/10)));
    }
  }

}



// Big ugly function :p but it looks pretty
void boingboing(uint16_t iterations, int delay, unsigned char mode, unsigned char drawmode)
{
  fill(0x00);		// Blank the cube

  int x, y, z;		// Current coordinates for the point
  int dx, dy, dz;	// Direction of movement
  int lol, i;		// lol?
  unsigned char crash_x, crash_y, crash_z;

  // Coordinate array for the snake.
  int snake[8][3];
  for (i=0;i<8;i++)
  {
    snake[i][0] = 4;
    snake[i][1] = 4;
    snake[i][2] = 4;
  }

  y = rand()%4;
  x = rand()%4;
  z = rand()%4;

  dx = 1;
  dy = 1;
  dz = 1;

  while(iterations)
  {
    crash_x = 0;
    crash_y = 0;
    crash_z = 0;


    // Let's mix things up a little:
    if (rand()%3 == 0)
    {
      // Pick a random axis, and set the speed to a random number.
      lol = rand()%3;
      if (lol == 0)
        dx = rand()%3 - 1;

      if (lol == 1)
        dy = rand()%3 - 1;

      if (lol == 2)
        dz = rand()%3 - 1;
    }


    if (dx == -1 && x == 0)
    {
      crash_x = 0x01;
      if (rand()%3 == 1)
      {
        dx = 1;
      } 
      else
      {
        dx = 0;
      }
    }

    if (dy == -1 && y == 0)
    {
      crash_y = 0x01;
      if (rand()%3 == 1)
      {
        dy = 1;
      } 
      else
      {
        dy = 0;
      }
    }

    if (dz == -1 && z == 0)
    {
      crash_z = 0x01;
      if (rand()%3 == 1)
      {
        dz = 1;
      } 
      else
      {
        dz = 0;
      }
    }

    if (dx == 1 && x == 3)
    {
      crash_x = 0x01;
      if (rand()%3 == 1)
      {
        dx = -1;
      } 
      else
      {
        dx = 0;
      }
    }

    if (dy == 1 && y == 3)
    {
      crash_y = 0x01;
      if (rand()%3 == 1)
      {
        dy = -1;
      } 
      else
      {
        dy = 0;
      }
    }

    if (dz == 1 && z == 3)
    {
      crash_z = 0x01;
      if (rand()%3 == 1)
      {
        dz = -1;
      } 
      else
      {
        dz = 0;
      }
    }

    // mode bit 0 sets crash action enable
    if (mode | 0x01)
    {
      if (crash_x)
      {
        if (dy == 0)
        {
          if (y == 3)
          {
            dy = -1;
          } 
          else if (y == 0)
          {
            dy = +1;
          } 
          else
          {
            if (rand()%2 == 0)
            {
              dy = -1;
            } 
            else
            {
              dy = 1;
            }
          }
        }
        if (dz == 0)
        {
          if (z == 3)
          {
            dz = -1;
          } 
          else if (z == 0)
          {
            dz = 1;
          } 
          else
          {
            if (rand()%2 == 0)
            {
              dz = -1;
            } 
            else
            {
              dz = 1;
            }
          }	
        }
      }

      if (crash_y)
      {
        if (dx == 0)
        {
          if (x == 3)
          {
            dx = -1;
          } 
          else if (x == 0)
          {
            dx = 1;
          } 
          else
          {
            if (rand()%2 == 0)
            {
              dx = -1;
            } 
            else
            {
              dx = 1;
            }
          }
        }
        if (dz == 0)
        {
          if (z == 3)
          {
            dz = -1;
          } 
          else if (z == 0)
          {
            dz = 1;
          } 
          else
          {
            if (rand()%2 == 0)
            {
              dz = -1;
            } 
            else
            {
              dz = 1;
            }
          }	
        }
      }

      if (crash_z)
      {
        if (dy == 0)
        {
          if (y == 3)
          {
            dy = -1;
          } 
          else if (y == 0)
          {
            dy = 1;
          } 
          else
          {
            if (rand()%2 == 0)
            {
              dy = -1;
            } 
            else
            {
              dy = 1;
            }
          }	
        }
        if (dx == 0)
        {
          if (x == 3)
          {
            dx = -1;
          } 
          else if (x == 0)
          {
            dx = 1;
          } 
          else
          {
            if (rand()%2 == 0)
            {
              dx = -1;
            } 
            else
            {
              dx = 1;
            }
          }	
        }
      }
    }

    // mode bit 1 sets corner avoid enable
    if (mode | 0x02)
    {
      if (	// We are in one of 8 corner positions
      (x == 0 && y == 0 && z == 0) ||
        (x == 0 && y == 0 && z == 3) ||
        (x == 0 && y == 3 && z == 0) ||
        (x == 0 && y == 3 && z == 3) ||
        (x == 3 && y == 0 && z == 0) ||
        (x == 3 && y == 0 && z == 3) ||
        (x == 3 && y == 3 && z == 0) ||
        (x == 3 && y == 3 && z == 3) 				
        )
      {
        // At this point, the voxel would bounce
        // back and forth between this corner,
        // and the exact opposite corner
        // We don't want that!

        // So we alter the trajectory a bit,
        // to avoid corner stickyness
        lol = rand()%3;
        if (lol == 0)
          dx = 0;

        if (lol == 1)
          dy = 0;

        if (lol == 2)
          dz = 0;
      }
    }

    // Finally, move the voxel.
    x = x + dx;
    y = y + dy;
    z = z + dz;

    if (drawmode == 0x01) // show one voxel at time
    {
      setvoxel(x,y,z);
      delay(del);
      clrvoxel(x,y,z);	
    } 
    else if (drawmode == 0x02) // flip the voxel in question
    {
      flpvoxel(x,y,z);
      delay(del);
    } 
    if (drawmode == 0x03)
    {
      for (i=7;i>=0;i--)
      {
        snake[i][0] = snake[i-1][0];
        snake[i][1] = snake[i-1][1];
        snake[i][2] = snake[i-1][2];
      }
      snake[0][0] = x;
      snake[0][1] = y;
      snake[0][2] = z;

      for (i=0;i<8;i++)
      {
        setvoxel(snake[i][0],snake[i][1],snake[i][2]);
      }
      delay(del);
      for (i=0;i<8;i++)
      {
        clrvoxel(snake[i][0],snake[i][1],snake[i][2]);
      }
    }


    iterations--;
  }
}




































эффекты писал не я. где то скопировал

an4ous
Offline
Зарегистрирован: 21.09.2015

Al_Ninyo пишет:

Вот последняя рабочая версия кода:

Не могу понять как управлять диодами. А именно "int data" && "unsigned int start, int mask"

void hLayer(int where, int data, int time, int NumLayer) 
void vLayer(int where, unsigned int start, int mask, int time)

 как расчиать нужное число что бы горели нужные мне диоды? например 4 центральных, или по диагонали. и т.д вообще не понимаю с этими цифрами)

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

an4ous пишет:

 как расчиать нужное число что бы горели нужные мне диоды? например 4 центральных, или по диагонали. и т.д вообще не понимаю с этими цифрами)

Я делал так: слой светодиодов представляет из себя 16 точек. Получается 16-значное число в двоичной системе счисления, где каждой цифре 0 в записи числа соответствует погашенный светодиод, а каждой 1 - горящий. Например, нам надо зажечь только угловые светодиоды, вот так:

1 0 0 1
0 0 0 0
0 0 0 0
1 0 0 1

Записываем это состояние как число в двоичной системе (от 1 светодиода к 16-му): 1001000000001001. Переводим число в десятичную систему и получаем 36873. Это число и пишем как data.

UPD: только центральные - число 1632. Диагонали - число 38505.

Надо бы как-то это переделать в более человеческий вид. Только как-то не до того пока. Работает и ладно. Вот скоро сделаю кубик 5*5*5 (может быть), тогда и буду программить его как-то правильнее, что ли.