Например TDA7294

РадиоКот >Схемы >Цифровые устройства >Игрушки >

Мир в пикселях или 3D LED глобус

Автор: Саша Леськив, sasha_leskiv@mail.ru
Опубликовано 14.05.2014.
Создано при помощи КотоРед.

Всем привет!

Как видно из названия, сегодня мы поговорим о таком устройстве, как LED глобус. А точнее, о конструкции, прицпипе его работы, схеме, прошивке, исходниках на языке Си.

Не будем томить, посмотрим же, как оно выглядит и работает:

 На видео картинка мерцает. Но это всего лишь глюк камеры. В живую, работа устройства выглядит так:

Если есть желание собрать себе такую же штуковину, читайте далее :)

Итак, первым делом поговорим о конструкции. Глобус состоит из двух частей: из самой схемы с микроконтроллером ATtiny2313A и основы.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Если их соединить, получится что-то типа этого:

Плата

Основная плата девайса включает в себя микроконтроллер, светодиоды, здвиговые регистры, диодный мост, мини блок питания и прочее. Все это собрано на одном кусочке фигурно вырезаного текстолита. Все это дело стоит перпендикулярно к ротору компьютерного кулера и крепиться к нему двумя уголками. У ротора обрезаны "крылья" и вместо них намотана катушка (детальнее о ней далее).

Основа

Основа представляет собой квадратный кусок дерева, в центре которого стоит кулер. По периметру располагаются трансформатор, диодные мосты, блоки питания, стабилизаторы, генераторы, ик светодиод. Детальнее об этом тоже поговорим далее.

Схема

Ну а теперь рассмотрим схему: 

Основное пространство на рисунке занимает схема основной платы. Слева внизу я выделил схему основы. Думаю, здесь все понятно. Здесь генератор выдает прямоугольные импульсы с частотой примерно в несколько десятков, а то и сотен, килогерц со скважностю ~50%. Все это дело усиливается irf540 (на схеме - buz11), и подается на первичную обмотку. Его схема вот (питанее на катушке L1 нужно повысить из 13.8 до 24 вольт, но на таймере оставляем 12(можно 9) вольт):

Напряжение

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

Подробнее о катушках Для изготовление воздушного трансформатора, вам понадобится взять достаточно мощный кулер (рассчитывайте, что он должен будет крутить со скоростью примерно в 5-10 оборотов в секунду некую конструкцию весом грамм в 150-200), изолированный медный (намотачный, в общем) провод, диаметром не меньше 0.5мм (ведь для 40-ка с лишним светодиодов нужно где-то полампера, не меньше), густрой клей или мебельный лак и просто супер (быстосохнущий) клей.

1) Сначала нужно из кулера вытянуть ротор с лопастями. Последние отламать и все это дело зачистить напильником и наждачкой. Тоесть, делаем такой себе магнитный кружок;

2) Дальше берем супер клей и с самого верха ротора горизонтально приклеиваем край медного провода. Наматывать можно как по часовой, так и против. Главное, чтобы у вас потом направление сошлось с направлением на первичке. Всего витков нужно намотать немало. Это немало расчитываем по формуле - W=U*50/S. Формулу площади круга вы должны были выучить еще в школе, в восьмом класе, во втором семестре - S=3.14*r^2 :D;
В общем транс у нас должен выйти понижающим. Тоесть, на входе первички, естественно, 24 вольта, на выходе - примерно 10-15, которые дальше сбрасываются до 5. Почему 10-15? Почитайте даташит на l7805. Чтобы вышло 5 вольт при токе до 1 ампера, на входе должно быть примерно так. Проверял лично, что по-другому не катит :));

3) Естественно, все витки (а лично у меня их под сто) вы в один слой ну никак не впихнете, даже не пытайтесь. Поэтому, делаем несколько слоев, каждый пропитываем жидким клеем или лаком, просушиваем.

4) Далее мы все это дело с вторичкой берем и замеряем диаметр. Добавляем туда 1-2 миллимиетра и приступаем к изготовлении первичной обмотки;

5) Находим широкий круглый предмет искомого диаметра (например, какой-то балончик с краской, советский мотор и т.д.). Обматываем скользкой бумагой или малярым скотчем или чем-то ещё (чтобы потом  снималось легче). И наматываем первичку. Особых советов по намотке нету...единственное что - ширина должна примерно быть равна ширине вторичной обмотки.

Основа

Ну, теперь можно все это монтировать. Отризаем кусок дерева/пластика. В общем, все равно. Главное - крепкость, и, желательно, достаточно тяжелое (чтобы стояло стабильно). Размер зависит от кулера. Последний ставим по ее центру. Где то-то там крепим трансформатор. Желательно, чтобы он был с несколькими обмотками. Напряжений там несколько: 24 вольта идет на первичку и, лично у меня, на кулер; 9-12 вольт идет на генератор; 3-5 вольт идет на ик-светодиод.

Плата

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

Для балансировки на плате есть два отверстия по вертикальной оси. Протягиваем между ними ниточку, подвешиваем. По мере надобности прикручиваем винтики, гайки. Если кто хочет, может для точной балансировки наносить припой на специальные дорожки-квадратики.  Ну вот и все, готово.

Принцип работы

Рубрика "Как это работает". Прицпип, надеюсь, будет ясен и понятен. Все делается так: между ножкой INT0 (6 вывод) микроконтроллера и землей у нас располагается инфракрасный фотодиод. Работает так: есть ик-свет - замкнут, нету ик-света - ток не течет. Вывод этот, шестой, через внутренний резистор подтянут до плюса питания. После начальной заставки мк ждет того момента, когда на INT0 появится низкий логический уровень. Это будет означать, что на диод воздействует ик свет. Свет этот, как вы догадались, береться от ик-светодиода, находящегося на основе. Тоесть, земля на 6 выводе есть тогда и только тогда, когда плата находиться строго в одном положении пространства (примерно, естественно). Так вот, после появления ик-света, включается таймер. Он тикает, отсчитывает...через некоторое время, на выводе снова плюс. А таймер все считает. Плата двигаеться, крутиться - таймер работает. Как только на шестом выводе появиться ноль, это будет означать, что плата совершила один оборот. Значение счетчика запоминаеться и делиться на 70. Именно 70 столбцов имеет моя картинка карты Земли (высота - 40). Далее идет бесконечный цикл, в котором: 1) Обнуляется, запускается таймер; 2) Выводиться 40-битное значение одного стобца (в общем, зажигаются светодиоды в нужном порядке); 3) Выжыдаеться, пока таймер не отсчитает ту семидясятую часть времени одного оборота. Так, по очереди, один за другим, столбцы картинки выводятся на 40 светодиодов. С моим кулером это происходит меньше, чем за шестую часть секунды. Глаз этого не замечает и складыветься ощущение, что мы выдим трёхмерную картинку Земли. Методом того, что мы умножаем изначальное значение счетчика на 0.99, картинка начинает крутится по часовой стрелке. Каждые 250 оборотов, глобус перезаписывает значение времени одного оборота, тоесть - калибруется. Ну, в общем, как-то так.

Кулер и частота кварца

 Тут у вас нет ограничений. Выбирайте любой размер, мощность, скорость оборотов. Как пожелаете. Единственное НО: к сожалению, память у микроконтроллера не резиновая и счетчик в ATtiny2313 может досчитывать только 65535 (2^16 включая 0). Частота кварца по умолчанию -  (тоесть у меня) 24,576 Мгц. Предделитель таймера - 64. Делаем вывод, что за одну секунду на таймер поступает 384000 импульсов. После переполнения таймера (достижения значения 65536), мы вместо 65536 получим снова ноль. Следовательно, один круг должен сделаться не более, чем за ~0,17 секунды. Значит, скорость оборотов - приблизительно более 6 за секунду. Учитывайте, что среднестатистический кулер делает 2500-3000 об/мин БЕЗ НАГРУЗКИ. Учитывайте это. В принципе, вы можете изменять менять частоту кварца, но это повлияет на скорость всех временных задержек, в том числе заставки, что может сделать ее в разы медленнее и печальнее...

Посколько проект абсолютно универсальный, я даю сразу несколько *.hex файлов, где в имени указана частота кварца, на которую они рассчитаны (в папке DEBUG). Опираясь на скорость вашего кулера, рассчитывайте по аналогичному алгоритму (только тут уже начинать с конца нужно будет) частоту кварца.

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

Прошивка

Ну вот мы и подходим к концу. На плате есть стандартный разъем, avr isp 10, с помощью которого заливаем в микроконтроллер нужную прошивку. Фьюзы выставляем так:

EXTENDED = 0xFF;
HIGH = 0xDF;
LOW = 0xFF.

Тоесть у нас во всех регистрах, кроме SPIEN стоит единичка. Для PonyProg2000 и AvrSTUDIO это означает то, что галочек нигде нету, кроме квадратика SPIEN.

Кому нужно визуально, так сказать, это увидеть, зайдите в любой калькулятор фьюзов (под PonyProg2000 или аналогичные этой программы).

Ну что же..на этом, радиолюбители, не знающие языка Си, могут закончить чтение статьи. От себя, желаю удачи. Если есть вопросы - все на почту - sasha_leskiv@mail.ru.
   

Исходники

О принципе работы мы уже говорили, но теперь еще раз рассмотри это в исходнике NewGlobe. New - следствие того, что изначально писал в CodeVisonAvr..

Итак, что же здесь к чему. В проект входит два главных файла: 1) Файл map0.c, расположенный в корневом каталоге диска C; 2) NewGlobe.c

1) Первый файл (map0.c) представляет собой кусок кода, состоящий всего из одного оператора - объявление довольно большого массива во флеш памяти:

__flash const unsigned char bind1 [column*5] =

{0b00001100,0b00000000,0b00010101,0b00000000,0b00000001,//1
0b00011100,0b00000000,0b00010010,0b00000000,0b00000001,
0b00011110,0b00000000,0b00000000,0b00000000,0b00000011,
0b00011100,0b00000000,0b00011111,0b00000000,0b00000011
...
...
...
0b00011100,0b00000000,0b00011111,0b00110000,0b00000011,
0b00011000,0b00000000,0b00010101,0b00100000,0b00000001,
0b00001000,0b00000000,0b00000000,0b00000000,0b00000001,
0b00001000,0b00000000,0b00001001,0b00000000,0b00000001}; //70

 

Именно с этого массива вытаскиваются значения для светодиодов. Конечно, можно было его расположить и в NewGlobe.c, но мне кажется, что так порядком удобней.

column - это константа, которая объявляется в главном файле прошивки - NewGlobe.c. 

По умолчанию, колон 70, поэтому массив должен иметь не более 350 байтов (по 5 штук на каждую)

Старший бит первого байта - верхний левый угол картинки (1 столбец, 1-ый светодиод сверху). Старший бит второго байта - 1 столбец, 9-ый светодиод сверху и так далее..

Ну что ж, здесь больше ничего интересного нет..

2) Ну и основной файл исходника глобуса, как я уже говорил, NewGlobe.c.

Сокращать ничего не буду, изложу, как есть: 

/*
* NewGlobe.c
*
* Created: 18.04.2014 11:22:21
* Author: Sasha
*/

#define F_CPU 24576000
#define column 70
#include <avr/io.h>
#include <util/delay.h>
#include <C:/map0.c>


unsigned char count;
unsigned int start;
unsigned char temp;
unsigned int time;
unsigned char reset;
unsigned char i;

 

unsigned char button (void)

{
unsigned char var;
PORTD=0b00001100;
var=PIND;
var>>=2;
var&= 0b00000001;
return var;
}

 

unsigned int set_time (void)

{
unsigned int var;
TCCR1B=0x00;
TCNT1=0;
if (button()==0) {while (button()==0) {}}
while (button()==1) {}
TCCR1B=0b00000011;
while (button()==0) {}
while (button()==1) {}
TCCR1B=0x00;
var=TCNT1;
PORTD=0b00000100;
return var;
}

 

 

int main (void)
{

//INIT

DDRA=0x00;
PORTA=0x00;

DDRB =0b00000111;
PORTB=0b00000111;

DDRD =0b0001000;
PORTD=0b0001100;

TCCR0A=0x00;
TCCR0B=0x00;

TCCR1A=0b00000000;
TCCR1B=0b00000000;
TCCR1C=0x00;

PORTD=0b00000100;

PORTB&=~(1<<2);
for (temp=0; temp<40; temp++)
{ PORTB&=~(1<<0);
PORTB|= (1<<0);
PORTB&=~(1<<0); }
PORTB&=~(1<<1);
PORTB|= (1<<1);
PORTB&=~(1<<1);

_delay_ms(1500);

 


//start

count=1;

for (temp=0; temp<10; temp++)
{count++;

for (i=0; i<count; i++)
{
PORTB|= (1<<2);
PORTB&=~(1<<0); PORTB|= (1<<0); PORTB&=~(1<<0);
PORTB&=~(1<<1); PORTB|= (1<<1); PORTB&∓∓=~(1<<1);
_delay_ms(50);
}

for (i=0; i<count; i++)
{
PORTB&=~(1<<2);
PORTB&=~(1<<0); PORTB|= (1<<0); PORTB&=~(1<<0);
PORTB&=~(1<<1); PORTB|= (1<<1); PORTB&=~(1<<1);
_delay_ms(50);
}
}

PORTB&=~(1<<2);
for (count=0; count<40; count++)
{ PORTB&=~(1<<0);
PORTB|= (1<<0);
PORTB&=~(1<<0);
PORTB&=~(1<<1);
PORTB|= (1<<1);
PORTB&=~(1<<1);
_delay_ms(50);
}



reset=250;

while (1)
{

reset++;
if (reset>250)
{
reset=0;
time=set_time();
time/=column;
time*=0.98;
start=0x00;
}

for (i=0; i<column; i++)
{
TCCR1B=0x00;
TCNT1=0;
TCCR1B=0b00000011;

for (count=0; count<5; count++)
{
temp=bind1[count+start]; temp&=0b10000000; if (temp==0b10000000) {PORTB|=(1<<2);} else {PORTB&=~(1<<2);} PORTB&=0b11111110; PORTB|=1; PORTB&=0b11111110;
temp=bind1[count+start]; temp&=0b01000000; if (temp==0b01000000) {PORTB|=(1<<2);} else {PORTB&=~(1<<2);} PORTB&=0b11111110; PORTB|=1; PORTB&=0b11111110;
temp=bind1[count+start]; temp&=0b00100000; if (temp==0b00100000) {PORTB|=(1<<2);} else {PORTB&=~(1<<2);} PORTB&=0b11111110; PORTB|=1; PORTB&=0b11111110;
temp=bind1[count+start]; temp&=0b00010000; if (temp==0b00010000) {PORTB|=(1<<2);} else {PORTB&=~(1<<2);} PORTB&=0b11111110; PORTB|=1; PORTB&=0b11111110;
temp=bind1[count+start]; temp&=0b00001000; if (temp==0b00001000) {PORTB|=(1<<2);} else {PORTB&=~(1<<2);} PORTB&=0b11111110; PORTB|=1; PORTB&=0b11111110;
temp=bind1[count+start]; temp&=0b00000100; if (temp==0b00000100) {PORTB|=(1<<2);} else {PORTB&=~(1<<2);} PORTB&=0b11111110; PORTB|=1; PORTB&=0b11111110;
temp=bind1[count+start]; temp&=0b00000010; if (temp==0b00000010) {PORTB|=(1<<2);} else {PORTB&=~(1<<2);} PORTB&=0b11111110; PORTB|=1; PORTB&=0b11111110;
temp=bind1[count+start]; temp&=0b00000001; if (temp==0b00000001) {PORTB|=(1<<2);} else {PORTB&=~(1<<2);} PORTB&=0b11111110; PORTB|=1; PORTB&=0b11111110;
}

start=start+5;
if (start==column*5) {start=0;}

PORTB&=0b11111101; PORTB|= 0b00000010; PORTB&=0b11111101;

while (TCNT1!=time) {}

}

}


}

 

Ну что ж, все по порядку.

  • определяем частоту кварца
  • определяем количество столбцов
  • подключаем в проект нужные файлы
  • объявляем переменные
  • функция чтения фотодиода. Если нету ик-света, возращается 1, в ином случае - 0
  • функция замерки времени оборота
  • начало main функции
  • инициализация портов ввода-вывода
  • начальная заставка
  • "reset=250;" означает, что глобус не скинут
  • Проверка надобности пересчитать значение времени на оборот
  • Начало цикла, которые проганяеться по умолчанию 70 раз, как вы понимаете. В нем останавливается таймер, обнуляеться значение, запускается таймер
  • Выводим значение первых пяти байтов на светодиоды
  • Цикл из пяти прогонов, в котором последовательно выводиться 5 байтов на светодиоды. Start - переменная, которая хранит номер байта, с которого будет начинаться следующая строка
  • Ожидаем, пока таймер будет отсчитывать семидесятую (или иную) часть оборота

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

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

Удачи!!!!


Файлы:
Все нужное


Все вопросы в Форум.


Как вам эта статья?

Заработало ли это устройство у вас?

43 8 7
1 0 0