Опять поморгал светодиодами

Joiner
Offline
Зарегистрирован: 04.09.2014

Делать было нечего, читал книжку по программированию Ардуино. Наткнулся на работу с битами. Чтобы проверить так ли я все понял, решил поморгать светодиодами. Подключил светики на D0-D13, все 14 штук, написал скетч

//Задаем массив, где обозначены огни. Единичка- светик горит.
unsigned long Template[47] = {0b10000000000001,
                              0b11000000000011,
                              0b01100000000110,
                              0b00110000001100,
                              0b00011000011000,
                              0b00001100110000,
                              0b00000011000000,
                              0b00001100110000,
                              0b00011000011000,
                              0b00110000001100,
                              0b01100000000110,
                              0b11000000000011,
                              0b10000000000001,
                              0b00000000000000,
                              0b10000000000000,
                              0b11000000000000,
                              0b11100000000000,
                              0b11110000000000,
                              0b01111000000000,
                              0b00111100000000,
                              0b00011110000000,
                              0b00001111000000,
                              0b00000111100000,
                              0b00000011110000,
                              0b00000001111000,
                              0b00000000111100,
                              0b00000000011110,
                              0b00000000001111,
                              0b00000000000111,
                              0b00000000000011,
                              0b00000000000001,
                              0b00000000000000,
                              0b00000000000001,
                              0b00000000000011,
                              0b00000000000111,
                              0b00000000001111,
                              0b00000000011111,
                              0b00000000111111,
                              0b00000001111111,
                              0b00000011111111,
                              0b00000111111111,
                              0b00001111111111,
                              0b00011111111111,
                              0b00111111111111,
                              0b01111111111111,
                              0b11111111111111,
                              0b00000000000000
                              };
int pause=100;//Задаем паузу для смены кадров.
void setup()
{
for (int i=0; i<=13; i++) {
  pinMode(i, OUTPUT);     //Задаем режим выводов 
    }
}

void loop()
{    
for (int i=0; i<=46; i++){//Отсчитываем кадры
   for (int k=0; k<=13; k++){
      digitalWrite(k,LOW); // Сначала гасим все нафик 
   }

    for (int j=0; j<=13; j++){ //Считываем кадр  
      digitalWrite(j,bitRead(Template[i], j));//и зажигаем светики       
      }
    delay(pause);//Немого тормозим между кадрами
    }
} 

Подскажите, правильно ли я сделал, в каких местах быдлокод.

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

про сдвиг почитай еще))

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Joiner, 2 стока -зачем лонг? У вас всего 14 бит, инта хватит. Сам  эффект если нельзя рассчитать математически, то лучше массив с ним записывать через прогмем во флэш . А вообще лучше без digitalWrite, битами подвигать..  я вот так делал .

Joiner
Offline
Зарегистрирован: 04.09.2014

jeka_tm пишет:

про сдвиг почитай еще))

А можно поподробней. Я что-то не понял.

Это что, огонек сдвигать вправо влево? Мне кажется возможных эффектов получится меньше.

Joiner
Offline
Зарегистрирован: 04.09.2014

dimax пишет:

Joiner, 2 стока -зачем лонг? У вас всего 14 бит, инта хватит. Сам  эффект если нельзя рассчитать математически, то лучше массив с ним записывать через прогмем во флэш . А вообще лучше без digitalWrite, битами подвигать..  я вот так делал .

dimax, спасибо! Ссылочку изучу.

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

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

нет. вместо функции 

bitRead

можно сделать сдвигом и функцией и

//=========================================================Отправка 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;
  }
}

вот например

Joiner
Offline
Зарегистрирован: 04.09.2014

jeka_tm пишет:

нет. вместо функции 

bitRead

можно сделать сдвигом и функцией и

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

Спасибо. Поизучаю, попробую со сдвигом.

Joiner
Offline
Зарегистрирован: 04.09.2014

jeka_tm пишет:

//=========================================================Отправка 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;
  }
}

вот например

Увидел много незнакомых букв :) Спасибо за пищу для размышления. Попробую разобраться.

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

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

или сравнил старший бит и сдвинул влево

Logik
Offline
Зарегистрирован: 05.08.2014

Бегущие огни и не на WS2812B! Раритет. Да, когдато такое делали..

Joiner
Offline
Зарегистрирован: 04.09.2014

Logik пишет:

 WS2812B!

Это что за зверь?

Joiner
Offline
Зарегистрирован: 04.09.2014

jeka_tm пишет:

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

или сравнил старший бит и сдвинул влево

Не совсем понял, вернее совсем не понял

Что с чем сравнил?

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

эталонное число, в моем примере 0x80, если в двоичной системе это же число станет понятнее

Joiner
Offline
Зарегистрирован: 04.09.2014

jeka_tm пишет:

эталонное число, в моем примере 0x80, если в двоичной системе это же число станет понятнее

Спасибо. Послезавтра попробую расшифровать.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Joiner пишет:

Подскажите, правильно ли я сделал, в каких местах быдлокод.

Константы 46 в строках 2 и 60 - он самый и есть.

Не дай Бог захочется добавить/удалить элемент массива Template - надо обязательно не забывать менять обе!

Решение №1 для девочек

Любой учебник выдаст Вам такое решение: нужно определить константу:

#define TOTAL_TEMPLATES 47

и строки 2 и 60 записать как

2: unsigned Template[TOTAL_TEMPLATES ] = ...
60: for (int i=0; i < TOTAL_TEMPLATES ; i++) {

но это решение для девочек. Здесь при изменении массива всё равно надо не забыватьт менять константу в #define. А зачем? Делаем по-мужски ...

Решение №2 - для мужиков

В строке 2 компилятор и без Вас посчитает сколько там элементов, потому пишем просто пустые скобки. Затем заставляем компилятор же посчитать сколько там элементов и определяем константу, которую потом используем в строке 60. Смотрите ...

2: unsigned Template[] = ...
...

(после стр. 49):#define TOTAL_TEMPLATES (sizeof(Template)/sizeof(Template[0]))
...
60: for (int i=0; i < TOTAL_TEMPLATES ; i++) {

Понятно?
 
Второе решение лучше первого тем, что Вы вообще нигде не указываете размер массива явно - компилятор сам считает (а при первом решении в одном месте таки указывалось - в define). При втором решении -  хотите добавить/удалить элемент массива Template - добавляйте и ни о чём не парьтесь, ничего нигде дополнительно менять не надо.
Joiner
Offline
Зарегистрирован: 04.09.2014

ЕвгенийП пишет:

Константы 46 в строках 2 и 60 - он самый и есть.

Не дай Бог захочется добавить/удалить элемент массива Template ........

Спасибо! Я даже кое что понял. Обязательно учту в будущем

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Не за что. 

Там в дефайне sizeof всего массива делится на sizeof одного элемента - получается размер массива. 

Logik
Offline
Зарегистрирован: 05.08.2014

Joiner пишет:

Logik пишет:

 WS2812B!

Это что за зверь?

 

Драйвер RGB светодиода. Индивидуальное управление цветом и яркостью каждого светодиода в ленте по последовательному однопроводному каналу. Есть и не на ленте, дискретно илии готовой гирляндой.

http://ru.aliexpress.com/item/1m-4m-5m-WS2812B-Smart-led-pixel-strip-Bla...

Joiner
Offline
Зарегистрирован: 04.09.2014

ЕвгенийП пишет:

Не за что. 

Там в дефайне sizeof всего массива делится на sizeof одного элемента - получается размер массива. 

Вчера попробовал Ваши рекомендации по массиву, все получилось, все понял. Спасибо.

А вот со сдвигом пока не понятно. Пока не разобрался. Буду скетч dimaxa и jeka_tm грызть.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Joiner пишет:

А вот со сдвигом пока не понятно. Пока не разобрался. Буду скетч dimaxa и jeka_tm грызть.

А чего со сдвигом? Вы лучше свой микроскетч напишите для эксперимента и всё мигом разрызётся.

Сдвиг просто сдвигает биты вправо (>>) или влево (<<) на указанное число позиций. 

При правом сдвиге самый правый(е) бит(ы) теряются, а слева дописывается нолик(и) (*)

При левом сдвиге самый левый(е) бит(ы) теряются, а справа дописывается нолик(и) .

Вот и всё. 

Вы умеете числа в двоичной системе записывать? Если умеете, то проблем у Вас нет. Например,

char unsigned a = 5; // двоичное 00000101
char unsigned b = a << 1; // b стало 00001010 - сдвинулось влево на 1 бит
Serial.println(b); //  должно быть 10
b = b >> 2; //  b стало 00000010 - сдвинулось вправо на 2 бита, крайние правые биты пропали
Serial.println(b); //  должно быть 2
b = b << 5; //  b стало 01000000 - сдвинулось влево на 5 битов
Serial.println(b); //  должно быть 64

Как видите, ничего страшного.

(*) В дописывании нулей слева есть тонкость. Это работает так, как я описал для беззнаковых чисел (unsigned). Для чисел со знаком там есть тонкость, но сначала разберитесь с unsigned, потом, если интересно, спросите - поговорим.

Joiner
Offline
Зарегистрирован: 04.09.2014

ЕвгенийП пишет:

 

А чего со сдвигом? Вы лучше свой микроскетч напишите для эксперимента и всё мигом разрызётся.

Сдвиг просто сдвигает биты вправо (>>) или влево (<<) на указанное число позиций. 

При правом сдвиге самый правый(е) бит(ы) теряются, а слева дописывается нолик(и) (*)

При левом сдвиге самый левый(е) бит(ы) теряются, а справа дописывается нолик(и) .

Вот и всё. .............

Пока не понял, засыпаю. Завтра попробую напишу "свой микроскетч". Но вот возник вопрос - смогу ли я со сдвигом написать сценарий эффектов как в массиве?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Joiner, если писать прямо в порты, то ваш loop несколько подсократится и ускорится :)

void loop()
{    
for (int i=0; i<=46; i++){//Отсчитываем кадры
    PORTD = Template[i]&0xff; // записать на пины 0..7
    PORTB = (Template[i]&0x3f00)>>8;  //записать на пины 8..13
    delay(pause);
    }
} 

И вот бегущий огонёк, работает на движении бит в переменной n. Бегает туда и обратно.

void loop()
{    
         static unsigned int n=0x2000;
         static boolean dir=1;
         if (dir) n==1? dir=0 : n>>=1 ; 
         else  n==0x2000? dir=1 : n<<=1;   
         PORTD = n&0xff;
         PORTB = (n&0x3f00)>>8;  
         delay(100);  
   }

 

Joiner
Offline
Зарегистрирован: 04.09.2014

dimax пишет:

Joiner, если писать прямо в порты......

dimax, спасибо! Познал кое-что новое для себя, но кое-что еще предстоит понять.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

dimax пишет:

Joiner, если писать прямо в порты, то ваш loop несколько подсократится и ускорится :)

    
    ...
    delay(pause);
    ...

Афигеть, насколько ускорилось.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

andriano, я подразумевал  ускорение вывода данных, просто не до конца сформулировал мысль.  В алгоритме Т.С. есть некоторые недостатки, например  светодиоды загораются по-очереди, а не одновременно.  2- даже если светодиоду нужно будет гореть, его всё равно в каждом цикле гасят. Этих проблем в моём варианте нет.

Joiner
Offline
Зарегистрирован: 04.09.2014

dimax пишет:

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

Вот и меня это немного напрягало. Большое спасибо за науку.

Всегда благодарен за советы бывалых.