Ви не увійшли.
Сторінки 1
Filaka пише:по одному резистору номіналом 100Ом.
Якого кольору ваші світлодіоди? При 100 омах втікаючий в катодні піни струм перевищуватиме допустимий, коли світитиметься весь шар. Також загальний струм через сам контроллер вже може бути завеликий. По-хорошому, таку кількість світлодіодів потрібно комутувати через буферні каскади. Або обмежити струм збільшенням резисторів, хоча б до 470 Ом.
Колір фіолетовий - 3,1V. Я думаю спробувати поставити на анод по мосфету та окремо подавати живлення, що скажете?
Звісно, середній струм через діоди, і як наслідок, яскравість, зменшаться в 4 рази. Щоб яскравість була така ж як зараз, без динамічної індикації, потрібно буде зменшити номінал резисторів в 4 рази. У вас же, сподіваюсь, по резистору на кожний стовпчик, а не на секцію?
Щоби порадити щось детальніше, потрібно хоча би побачити схему.Як запрацює динамічна індикація, тоді можна думати і про різні варіанти ефектів.
Так, після послідовного вмикання світлодіодів, яскравість поступово падає. Спробую окремо подавати живлення.
Резистори стоять на шари(4шт. анод), по одному резистору номіналом 100Ом. Катод на стовпчики(16шт. без резистора)
Filaka пише:Але поки що не зрозумів як це все реалізувати у своєму проєкт Куба. Куб повинен повністю заповнитись.
Якщо здогадки про вашу схему підключення вірні, то ось така наївна реалізація може запрацювати:
// Абстрактний клас періодичної задачі template <unsigned int Period> class task { protected: unsigned long last; virtual void process() = 0; public: task() : last { -Period } // дозволимо перший виклик одразу, без очікування {} void loop(unsigned long now) { if (now - last >= Period) { last = now; process(); } } }; // Клас динамічної індикації template <byte Segments, byte Layers, byte FPS = 60> class matrix: public task<1000/FPS/Layers> { const byte *segment_pins; const byte *layer_pins; static constexpr auto seg_size = (Segments+7)/8; // Кожний біт в масиві визначає стан окремого світлодіода byte leds[Layers][seg_size]; byte active_layer; void process() override { // Вимикаємо поточний шар digitalWrite(layer_pins[active_layer], LOW); // Беремо наступний шар за активний if (++active_layer == Layers) { active_layer = 0; } // Оновлюємо стан світлодіодів. // Перемикання світлодіодів по одному дуже повільне, але керування // декількома пінами одночасно ставить певні вимоги до схемотехніки // та не буде крос-платформенним. const byte *pin = segment_pins; const uint8_t *bits = leds[active_layer]; byte mask = 1; for (byte i = Segments;;) { digitalWrite(*pin++, (*bits & mask) ? LOW : HIGH); if (!--i) { break; } if ((mask <<= 1) == 0) { mask = 1; bits++; } } // Вмикаємо поточний шар digitalWrite(layer_pins[active_layer], HIGH); } public: matrix(const byte *segment_pins_, const byte *layer_pins_) : segment_pins(segment_pins_), layer_pins(layer_pins_), active_layer( Layers-1 ) {} void begin() { // початковий стан: все вимкнено for (const byte *pin = layer_pins; pin < layer_pins + Layers; pin++) { pinMode(*pin, OUTPUT); digitalWrite(*pin, LOW); } for (const byte *pin = segment_pins; pin < segment_pins + Segments; pin++) { pinMode(*pin, OUTPUT); } } void set(byte segment, byte layer, bool on) { byte mask = 1 << (segment % 8); byte *addr = &leds[layer][segment / 8]; if (on) { *addr |= mask; } else { *addr &= ~mask; } } void clear() { memset(leds, 0, sizeof(leds)); } void fill() { memset(leds, 0xff, sizeof(leds)); } }; // для номера піна достатньо байта const byte column[16]= { 13,12,11,10,9,8,7,6,5,4,3,2,1,0,A5,A4 }; const byte layer[4]= { A3,A2,A1,A0 }; #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) matrix<ARRAY_SIZE(column), ARRAY_SIZE(layer)> cube(column, layer); /* Клас анімації */ template <byte Cols, byte Height> class animation: public task<100> // квант 1/10 секунди { byte cols[Cols]; byte col_idx; byte col_state; unsigned int pause; bool wait; unsigned int update(void) { if (wait) { wait = false; cube.clear(); return 20; // пауза після очищення куба } cube.set(cols[col_idx], col_state, true); if (++col_state < Height) { // ще не заповнили стовпчик? return 2; // пауза після проміжного світлодіода в стопчику } col_state = 0; // вибираєм наступний стовпчик if (++col_idx < Cols) { // ще не заповнили всі ? return 6; // пауза після останнього світлодіода в стопчику } shuffle(); col_idx = 0; wait = true; return 20; // пауза після заповнення всього куба } void process() override { for (;;) { // дециматор if (pause) { --pause; return; } pause = update(); } } void shuffle() { for (size_t i = 0; i < Cols-1; i++) { size_t j = random(i, Cols); auto tmp = cols[i]; cols[i] = cols[j]; cols[j] = tmp; } } public: void begin() { for (size_t i = 0; i < Cols; i++) { cols[i] = i; } shuffle(); col_idx = 0; col_state = 0; pause = 0; wait = false; } }; animation<ARRAY_SIZE(column), ARRAY_SIZE(layer)> anim; void setup() { // Набираєм ентропію для генерації випадкових чисел // до того як перемкнули пін 10 в output { const byte rnd_pin = 10; pinMode(rnd_pin, INPUT); unsigned long seed = 0; for (size_t i = 0; i < sizeof(seed)*8; i++) { seed <<= 1; seed |= analogRead(rnd_pin) & 1; } randomSeed(seed ? seed : 1); } cube.begin(); anim.begin(); } void loop() { auto now = millis(); cube.loop(now); anim.loop(now); }
Не перевіряв, бо світлодіодного куба не маю. Так що на свій страх і ризик.
Дуже дякую! Все саме так як і хотів. Зараз буду розбиратись у самому коді
Добрий вечір! Другий день намагаюсь написати повідомлення і не виходить. Пишу через "Цитувати", едине що то це додаю посилання на файл. Якщо зайти у "Цитувати" або "Відповісти", то там вже два моїх повідомлення, а у темі їх немає. Чому так?
Filaka пише:Чи можете Ви допомогти та зробити приклад?
Оголошуєм константу з розміром масиву та сам масив:
const size_t N = 16; uint8_t cols[N];
Набираєм ентропію для генерації випадкових чисел. Достатньо один раз на початку, десь в setup():
unsigned long seed = 0; for (size_t i = 0; i < sizeof(seed)*8; i++) { seed <<= 1; seed |= analogRead(10) & 1; } randomSeed(seed ? seed : 1);
Заповнюємо масив послідовними значеннями:
for (size_t i = 0; i < N; i++) { cols[i] = i; }
і перемішуємо:
for (size_t i = 0; i < N-1; i++) { size_t j = random(i, N); auto tmp = cols[i]; cols[i] = cols[j]; cols[j] = tmp; }
Далі можете послідовно вибирати значення з масиву і робити з ними, що вам там потрібно. Наприклад, вивод в послідовний порт:
Serial.println(); for (auto i : cols) { Serial.print("X: "); Serial.print(i % 4); Serial.print(", Y: "); Serial.print(i / 4); Serial.println(); }
Якщо потрібна ще одна випадкова перестановка, можна не заповнювати послідовними значеннями заново, а лише перемішати існуючу.
Дуже дякую за допомогу та пояснення! Але мені ще поки що складно було розібратись в коді та синтаксису Інтернет моцна штука, допоміг! Спробував виводити у Монітор Порта Arduino, щоб зрозуміти що тут відбувається. Але поки що не зрозумів як це все реалізувати у своєму проєкт Куба. Та поєднати з :
digitalWrite (column[i] , 1);
digitalWrite (layer[j] , 0);
Можливо я не так пояснив свій задум, ось посилання на приклад. Куб повинен повністю заповнитись.
drive.google.com/file/d/1bFwaPjvazLKD6y … drive_link
Filaka пише:Чи можете Ви допомогти та зробити приклад?
Оголошуєм константу з розміром масиву та сам масив:
const size_t N = 16; uint8_t cols[N];
Набираєм ентропію для генерації випадкових чисел. Достатньо один раз на початку, десь в setup():
unsigned long seed = 0; for (size_t i = 0; i < sizeof(seed)*8; i++) { seed <<= 1; seed |= analogRead(10) & 1; } randomSeed(seed ? seed : 1);
Заповнюємо масив послідовними значеннями:
for (size_t i = 0; i < N; i++) { cols[i] = i; }
і перемішуємо:
for (size_t i = 0; i < N-1; i++) { size_t j = random(i, N); auto tmp = cols[i]; cols[i] = cols[j]; cols[j] = tmp; }
Далі можете послідовно вибирати значення з масиву і робити з ними, що вам там потрібно. Наприклад, вивод в послідовний порт:
Serial.println(); for (auto i : cols) { Serial.print("X: "); Serial.print(i % 4); Serial.print(", Y: "); Serial.print(i / 4); Serial.println(); }
Якщо потрібна ще одна випадкова перестановка, можна не заповнювати послідовними значеннями заново, а лише перемішати існуючу.
Дуже дякую за допомогу та пояснення! Але мені ще поки що складно було розібратись в коді та синтаксису Інтернет моцна штука, допоміг! Спробував виводити у Монітор Порта Arduino, щоб зрозуміти що тут відбувається. Але поки що не зрозумів як це все реалізувати у своєму проєкт Куба. Та поєднати з :
digitalWrite (column[i] , 1);
digitalWrite (layer[j] , 0);
Можливо я не так пояснив свій задум, ось посилання на приклад. Куб повинен повністю заповнитись.
https://drive.google.com/file/d/1bFwaPj … drive_link
Зробіь масив int random_index[16]; спочатку заповніть його числами від 0 до 15, а потім їх перетасуйте (google: shuffle), з масиву послідовно берете індекс і заповнюєте цей стовпчик
Дякую! Але моїх знань ще замало щоб це все зрозуміти та зробити) Чи можете Ви допомогти та зробити приклад? Дуже вдячний за допомогу та розуміння
Honey пише:Вилазите за межі масива
i=4 замінити на i=3
i<=4 замінити на i<4Дякую! Працює )))
Підкажіть будь ласка ще, як реалізувати поступове заповнення всього куба по одному стовпчику. Так як в прикладах вище, але щоб поступово рандомно кожен стовпчик заповнився з верху до низу і так у весь куб
Вилазите за межі масива
i=4 замінити на i=3
i<=4 замінити на i<4
Дякую! Працює )))
Всім доброго дня та з Новим Роком! Допоможіть розібратись з кодом. Зробили з сином Led Cub 4*4*4. Куб працює, все добре. Програму взяли з GitHub, також все працює добре. Але хочемо створювати свої ефекти. По маленьку щось виходить, разом вчимо програмування ))). Стикнулись з таким. Два ефекти. Один (randomRain_v2) - рандомне заповнення одного стовпчика з низу до верху, Другий (randomRain_v3) навпаки - рандомне заповнення одного стовпчика з верху до низу. У першому випадку все добре, у другому сам ефект працюе, але чомусь спрацьовує ще один стовпчик. Буду дуже вдячний за допомогу та роз'яснення.
#include <avr/wdt.h>
//initializing and declaring led rows
int column[16]={13,12,11,10,9,8,7,6,5,4,3,2,1,0,A5,A4};
//initializing and declaring led layers
int layer[4]={A3,A2,A1,A0};
void setup() {
//настройка колонок для вывода
for(int i = 0; i<16; i++)
{
pinMode(column[i], OUTPUT);
}
//настройка слоев для вывода
for(int i = 0; i<4; i++)
{
pinMode(layer[i], OUTPUT);
}
//seeding random for random pattern
randomSeed(analogRead(10));
}
void loop() {
//randomRain_v2();
randomRain_v3();
//onCube();
//reboot();
}
void reboot() { // перезагрузка платы
wdt_disable();
wdt_enable(WDTO_1S);
while (1) {}
};
void offCube() { // выключение куба
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 4; j++) {
digitalWrite (column[i] , 1);
digitalWrite (layer[j] , 0);
}
}
}
void onCube() { // включение куба
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 4; j++) {
digitalWrite (column[i] , 0);
digitalWrite (layer[j] , 1);
}
}
}
void randomRain_v2(){
offCube();
for(int i = 0; i!=60; i+=2)
{
int randomColumn = random(0,16);
digitalWrite(column[randomColumn], 0);
for(int i = 4; i >= 0; i--) {
digitalWrite(layer[i], 1);
delay(50);
}
delay(300);
for(int j = 0; j <= 4; j++) {
digitalWrite(layer[j], 0);
delay(300);
}
digitalWrite(column[randomColumn], 1);
}
}
void randomRain_v3(){
offCube();
for(int i = 0; i!=60; i+=2)
{
int randomColumn = random(0,16);
digitalWrite(column[randomColumn], 0);
for(int i = 0; i <= 4; i++) {
digitalWrite(layer[i], 1);
delay(100);
}
delay(300);
for(int i = 4; i >= 0; i--) {
digitalWrite(layer[i], 0);
delay(100);
}
digitalWrite(column[randomColumn], 1);
}
}
Сторінки 1