POV-бегущая строка. Нужна помощь новичку.

votodef
Offline
Зарегистрирован: 13.03.2012

Здравствуйте.

Помогите пожалуйста зеленому пользователю ардуино.
Делаю устройство для курсового проекта.

Тема звучит как "Динамичесое светодиодное табло с механической разверткой"

Хочу сделать нечто среднее между propeller clock и бегущей строкой.

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

Со схемным решением тоже более-менее все ясно и просто. Задействуются 8 пинов, на которые из памяти выводится сообщение "постолбцово". Сигнал обратной связи от оптопары. Может быть еще ИК-датчик для приема сигналов управления может быть даже bluetooth-модуль для управления и приема текста, хотя последнее это уже наверное слишком жирно...

Вот с программной частью у меня загвоздка. Может быть уважаемые форумчане помогут набросать скелет будущего скетча для реализации описанных функций?

Заранее спасибо.

 

 

step962
Offline
Зарегистрирован: 23.05.2011

 Вот такой гаджет, что-ли?

votodef
Offline
Зарегистрирован: 13.03.2012

Принцип отображения тот же.
Мое устройство будет чем-то средним между
http://www.youtube.com/watch?v=90ZovgKY91Y&feature=related
и
http://www.youtube.com/watch?v=_OJvh8eZCIk

 

Zapek@n
Offline
Зарегистрирован: 16.02.2012

Часы понравились на видео. Вероятно вторая ссылка должна вести на другое видео? У Вас две ссылки одинаковые.

votodef
Offline
Зарегистрирован: 13.03.2012

 сорри, исправился

whoim
Offline
Зарегистрирован: 03.11.2011

 Начните с таблицы символов в массиве, выводе "постолбцово" с задержкой какой нибудь.. Там видно будет.

Сигнал от оптопары - на прерывание, инициализирующее вывод.

Оптопара одна? Некий "стартовый" позишн? Задержки подбирать будете методом тыка? Или искать вариант отслеживать несколько положений и / или контрлировать скорость вращения?

votodef
Offline
Зарегистрирован: 13.03.2012

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

не хочется сильно усложнять устройство

whoim
Offline
Зарегистрирован: 03.11.2011

 ну вот, обыграйте цикл вывода из массива

переменная со строкой вывода => разбор и определение элементов массива, где хранятся "светодиоды которые горят", по каждому массиву цикл по "столбцам" и вывод из на пины, задержка.  Все)

votodef
Offline
Зарегистрирован: 13.03.2012

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

пока главный вопрос - как организовать ее движение?

whoim
Offline
Зарегистрирован: 03.11.2011

  по каждому массиву цикл по "столбцам" и вывод из на пины [каждого столбца по очереди], задержка

whoim
Offline
Зарегистрирован: 03.11.2011

 Предположим символ "А"

byte[1][0]=B00000000
byte[1][1]=B00011000
byte[1][2]=B00100100
byte[1][3]=B01000010
byte[1][4]=B11111111
byte[1][5]=B10000001
byte[1][6]=B10000001
byte[1][7]=B00000000

...разбор какой символ выводим

for (int y=7; y>=0; y--) {

   if (bitRead(byte[1][0], y)==HIGH) зажигаем светодиод (верхний)
   if (bitRead(byte[1][1], y)==HIGH) зажигаем светодиод (второй сверху)
  ...

}

 

step962
Offline
Зарегистрирован: 23.05.2011

votodef пишет:

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

пока главный вопрос - как организовать ее движение?

 

Ну, так, например:

code.google.com/p/povglobe/,

ytai-mer.blogspot.com/2010/08/pov-globe-part-ii-mechanics.html,

hackedgadgets.com/2010/05/03/rotating-led-globe/akikorhonen.org/projects.php,

www.eee.manchester.ac.uk/undergraduate/electronicsclub/POV/

или по-рюсськи:

easyelectronics.ru/3d-led-globus.html

Задайте в Google "pov led mechanic" и гребите идеи лопатой.

votodef
Offline
Зарегистрирован: 13.03.2012

 А если так?

 byte stroka[]={       //массив, в котором один байт (строка) соответствует одному столбцу отображаемого текста
 B11111100,
 B00010010,
 B00010001,
 B00010010,
 B11111100
 };
 
 for int y=0; y < 4; y++;                                            //перебираем массив по вертикали
  {                                                                  
  if (bitRead (stroka [y], 0) == HIGH) digitalWrite (pin0 = HIGH);   //перебираем байт по горизонтали
  if (bitRead (stroka [y], 1) == HIGH) digitalWrite (pin1 = HIGH);
  if (bitRead (stroka [y], 2) == HIGH) digitalWrite (pin2 = HIGH);
  if (bitRead (stroka [y], 3) == HIGH) digitalWrite (pin3 = HIGH);
  if (bitRead (stroka [y], 4) == HIGH) digitalWrite (pin4 = HIGH);
  if (bitRead (stroka [y], 5) == HIGH) digitalWrite (pin5 = HIGH);
  if (bitRead (stroka [y], 6) == HIGH) digitalWrite (pin6 = HIGH);
  if (bitRead (stroka [y], 7) == HIGH) digitalWrite (pin7 = HIGH);
  delay ()                                                         //время отображения одного столбца
  }

 

step962
Offline
Зарегистрирован: 23.05.2011

Тогда уж так (в предположении, что pin0...pin7 соответствуют выводам D0...D7, то есть тютелька в тютельку расположены в пределах одного порта микроконтроллера, а именно порта D):

byte stroka[]={       //массив, в котором один байт (строка) соответствует одному столбцу отображаемого текста
B11111100,
B00010010,
B00010001,
B00010010,
B11111100
};

for(int y=0; y < 4; y++) {                                            //перебираем массив по вертикали
 PORTD = stroka[y];
 delay ()                                                         //время отображения одного столбца
}

 или - если кровь из носа необходим UART (выводы D0-D1) - используем группы по 4 вывода в разных регистрах ввода вывода, например, младшую часть порта B и старшую часть порта D. Возможны и другие группировки, но эта - самая экономная по количеству необходимых дополнительных преобразований:

for(int y=0; y &lt; 4; y++) {                                            //перебираем массив по вертикали
// младших ниббл загоняем в выводы D8...D11 (PORTB[0:3])
 mask = stroka[y] & 0x0F;
 PORTB |= mask;
 PORTB &= ~mask;
// старший ниббл загоняем в выводы D4...D7 (PORTD[4:7])
 mask = stroka[y] & 0xF0;
 PORTD |= mask;
 PORTD &= ~mask;
 delay ()                                                         //время отображения одного столбца
}

Чего добъемся вышеприведенными извращениями?

Во-первых, код чуть-чуть компактнее (и не сложнее исходного в понимании, если иметь представление о портах ввода/вывода и логических опреациях).

Во-вторых, раз в десять быстрее, поскольку избавились от череды выделений отдельных битов и бесконечных вычислений соответствия между выводами в нумерации Arduino (D0...D13, A0...A5) и AVR-адресацией (PORTB.0, PORTC.5, PORTD7 и еще 17 другими подобными адресами).

votodef
Offline
Зарегистрирован: 13.03.2012

спасибо, первый вариант вообще красивый)) 

Подскажите еще плиз, а есть ли функция, которая возвращала бы размер массива?

whoim
Offline
Зарегистрирован: 03.11.2011

votodef пишет:

спасибо, первый вариант вообще красивый)) 

Подскажите еще плиз, а есть ли функция, которая возвращала бы размер массива?

а вы хотите создавать массив, неизвестного размера? мне не очень давно хороший человек обрисовал тупиковость этого пути в небольших МК. 

В общем, при работе с данными проще всего отслеживать конец "данных" наличием символа 0. Например, при чтении строки с ЕЕПРОМ. И это правильно.

step962
Offline
Зарегистрирован: 23.05.2011

votodef пишет:

Подскажите еще плиз, а есть ли функция, которая возвращала бы размер массива?

Если я правильно понимаю, вы не хотите ручками подсчитывать длину?

Разместите за массивом переменную. Разность адреса этой переменной и адреса первого элемента масива (т.е. элемента с индексом 0) - искомая длина. По крайней мере для массивов типа byte и char.

Пример. Выводим адреса и размеры переменных a, s, c:

byte a[]={1,2,3};
char s[]="Hello, world!";
char c='A',d='s';
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.print("a: "); Serial.print((int)&a,HEX); Serial.print(" "); Serial.print((int)&s-(int)&a,DEC); Serial.println(" .");
  Serial.print("s: "); Serial.print((int)&s,HEX); Serial.print(" "); Serial.print((int)&c-(int)&s,DEC); Serial.println(" .");
  Serial.print("c: "); Serial.print((int)&c,HEX); Serial.print(" "); Serial.print((int)&d-(int)&c,DEC); Serial.println(" .");
}

void loop() {
  // put your main code here, to run repeatedly: 
  
}

Получаем:

a: 111 3 .
s: 114 14 .
c: 122 1 .

Да, еще: при проверке выяснил, что установленная за переменной/строкой/массивом переменная тоже должна быть проинициализирована. Обычные переменные, похоже, сохраняются в отдельной секции и между проинициализированными и обычными переменными образуется разрыв в несколько байтов. 

votodef
Offline
Зарегистрирован: 13.03.2012

Простите, не совсем понял Ваш пример.

Зачем используется Serial?

Можете расписать применительно для моего случая?

byte stroka[]={       
 B11111100,
 B00010010,
 B00010001,
 B00010010,
 B11111100
 };

 

step962
Offline
Зарегистрирован: 23.05.2011

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

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

Ну а в вашем случае должно быть что-то вроде:

byte stroka[]={       
 B11111100,
 B00010010,
 B00010001,
 B00010010,
 B11111100
 },mark=0;
...
// где-нибудь в кодах:
unsigned int size = &mark-&stroka[0];

 

slogg
Offline
Зарегистрирован: 11.12.2015

votodef, столкнулся тоже с данной работой и у меня возникли некоторые проблемы по поводу реализации POV  бегущей строки. Если вы еще находитесь на этом форуме, то отпишите мне на mail: serious.downСАБАКАyandex.ru 

satelit
Offline
Зарегистрирован: 12.12.2015

подскажите зеленому . собираю pov надпись на колесо(на основе старого колпака-не суть важна, так для определения понятия)

диоды вертикально(подругому ни как)

итого 9 пикселей в вертикали

далее скетч

int led1 = 2; //задаем переменные для диодов пина светодиода   2 ПОТОМУЧТО ПИН1 RX TX
int led2 = 3; //переменная с номером пина светодиода
int led3 = 4; //переменная с номером пина светодиода
int led4 = 5; //переменная с номером пина светодиода
int led5 = 6; //переменная с номером пина светодиода
int led6 = 7; //переменная с номером пина светодиода
int led7 = 8; //переменная с номером пина светодиода
int led8 =9 ; //переменная с номером пина светодиода
int led9 = 10; //переменная с номером пина светодиода
 
 
int ldr = 0; //и фоторезистора ? ПОЧЕМУ пин 0 ВРОДЕ RX TX И МОЖНО ЛИ ПОМЕНЯТЬ НА ДРУГОЙ(ну если 0 это пин)
 
void setup() //процедура setup
 
{
 
pinMode(led1, OUTPUT); //указываем, что светодиод - выход
pinMode(led2, OUTPUT); //указываем, что светодиод - выход
pinMode(led3, OUTPUT); //указываем, что светодиод - выход
pinMode(led4, OUTPUT); //указываем, что светодиод - выход
pinMode(led5, OUTPUT); //указываем, что светодиод - выход
pinMode(led6, OUTPUT); //указываем, что светодиод - выход
pinMode(led7, OUTPUT); //указываем, что светодиод - выход
pinMode(led8, OUTPUT); //указываем, что светодиод - выход
pinMode(led9, OUTPUT); //указываем, что светодиод - выход
 
}
 
void loop() //процедура loop 
 
{
 
if (analogRead(ldr) < 800) digitalWrite(led, HIGH); //если показатель освещенности меньше 800(800 ЭТО БЫЛО В ИСТОЧНИКЕ, МНЕ ПРИДЕТСЯ ПОДБИРАТЬ), //ТОЛЬКО МНЕ НАДО БУДЕТ ВКЛЮЧАТЬ НЕКОТОРЫЕ СВЕТОДИОДЫ ПОТОМ ДЕЛАЙ И ДРУГУЮ ПАРТИЮ СВЕТОДИОДОВ И ОПЯТЬ ПОВТОРЯЮСЬ ПО ПРОСТОМУ ЧЕРЕЗ ДЕЛАЙ
 
Я ХОЧУ СОБРАТЬ КОЛПАК, НА КОТОРОМ БУДЕТ СВЕТИТЬСЯ СЛОВО NISSAN. НАМОГИТЕ С НАПРАВЛЕНИЕМ  В ЦИКЛЕ
 
P.S. ЗАГЛАВНЫМИ БУКВАМИ ПИСАЛ ТО, НА ЧТО У МЕНЯ ВОПРОСЫ