Arduino и POV массив
- Войдите на сайт для отправки комментариев
Пнд, 12/09/2016 - 15:54
Здравствуйте !
Нужна помощь программеров чтоб натолкнуть на правильный путь.
Имеем собранное , исправно работающее устройство http://sebastian.setz.name/arduino/my-projekts/light-print/ .
Имеем массив типа
int columns[] = {
7230,25353,16702,34944,35007,34949,16698,25344,15935,25377,16670,34944,40127,34976,16703,25344,7231,128,1983,140,63,1920,286,1953,30};в котром каждый элемент массива является одним столбцом изображения. С этим разобрался.
Вопрос первый - как реализовать свою библиотеку символов.
Вопрос второй, главный - как создать массив и вывести изображение из bmp (черно белую) файла вот в таком виде http://www.toxel.com/wp-content/uploads/2009/07/monkeylectric04.jpg .
Уж очень сынишка просит на велосипед картинку папе электронщику тяжело даются уроки программирования .
Спасибо !
Продолжу беседу с умным человеком ))
Как правильно вывести на 16 светодиодов картинку, размером 16х16 пикселей , преобразованную битмап конвертером из этой темы http://arduino.ru/forum/programmirovanie/biblioteka-dlya-lcd-nokia-1100?page=7#comment-212906 в массив ?
Пример картинки
Код картинки "шахматная доска"
Продолжим косилиум ))
Почему горят не все светодиоды? Ведь 177777 это 1111 1111 1111 1111 ?
Светодиоды подключены к пинам 2,3,4,5,6,7,8,9,10,11,12,13,A0,A1,A2,A3
Проверил в скетче blink - все работают.
Почему горят не все светодиоды? Ведь 177777 это 1111 1111 1111 1111 ?
это кто вам такое сказал?
Пользуйтесь моей добротой =) стандартный калькулятор в винде, в режиме "программист"
а нужное вам число 0xFFFF = 65535 = 0177777 = 1111 1111 1111 1111
в вашей записи нехватат нолика перед числом чтоб его в виде восьмиричного записать
Да , тупанул . Заменил 177777 на 65535.
Не горят светодиоды на ногах A2,A3. Подскажите почему ?
Напомню -светодиоды подключены к пинам 2,3,4,5,6,7,8,9,10,11,12,13,A0,A1,A2,A3
Делать POV -эффекты с помощью Digitalwrite не получится, скорость выполнения очень низкая. Нужно пользоваться прямым управлением светодиодами через порты Дуни. Например
PORTB = B10101000;// устанавливает HIGH на цифровых выводах 7,5,3Не горят светодиоды на ногах A2,A3. Подскажите почему ?
Это элементарно. Потому что вы на них ничего не выводите. Зато выводите на ноги 0 и 1. Делайте циклы начиная с 2, как в сетапе. Телько и в сетапе ошибка, проверяйте количество проходов цикла.
Делать POV -эффекты с помощью Digitalwrite не получится, скорость выполнения очень низкая. Нужно пользоваться прямым управлением светодиодами через порты Дуни. Например
PORTB = B10101000;// устанавливает HIGH на цифровых выводах 7,5,3Все у нас получится ))
Не горят светодиоды на ногах A2,A3. Подскажите почему ?
Это элементарно. Потому что вы на них ничего не выводите. Зато выводите на ноги 0 и 1. Делайте циклы начиная с 2, как в сетапе. Телько и в сетапе ошибка, проверяйте количество проходов цикла.
Да увидел , спасибо большое !
Поправил. Теперь работает
Вот код
Теперь к самому началу. Как "загнать" восьмибитную шахматную доску ,выложеную несколькими постами выше ? Или как сделать 16 битную картинку ?
Уважаемые программисты !Не ругайтесь сильно . Я только учусь ))
Зато могу помочь по электронике (работа у меня с паяльником и тестером)
Для начала надо синхронизировать работу проги с вращением. Чтоб момент начала отсчета был. Затем вывод 0x5555, пауза, вывод 0xaaaa, пауза и т.д. И шахматная доска, но круглая, готова.
Для начала надо синхронизировать работу проги с вращением. Чтоб момент начала отсчета был. Затем вывод 0x5555, пауза, вывод 0xaaaa, пауза и т.д. И шахматная доска, но круглая, готова.
По поводу синхронизации и начала отсчета в курсе но решил оставить это в последнюю очередь - когда все остальное будет отточено. Сейчас пересобираю этот код с нуля так как многое непонятно (поторюсь - я начинающий). В процессе и обучаюсь. Тяжело дается , медленно но интересно и сын подстегивает )).
Logik, Покажите плиз в коде .
Посмотрите пожалуйста , я правильно мыслю по структуре BMP ?
К посту ниже ...
Пока для синхронизации регулирую обороты вентилятора - есть ЛБП(Лабораторный Блок Питания)
Ну ход мысли правильный. Но без синхронизации даже имея верное формирование сигнала просто ниче не увидете. Все будет мерцать и крутится.
Нет вы мыслите не правильно и не в том направлении.
Во первых у вас картинка и матрица не 8\16 битные а всгего 1 битные =)
Битность картинки - кол-во бит кодирующих цвет 1 пиксела =)
смотрите картинку =)
Вот что получилось ....
const int columnTime = 2; //15 Время [мс] работы каждого отдельного столбца const int spacer = 10; // 10Это значение, умноженное на columnTime , пауза между содержанием всего массива long columns[] = { //*******массив 16x16 шахматная доска //0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, //0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC // **************************** //*************** массив 16x16 стрелка 0x00, 0xC0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00 //*********************************** //*************** массив 16x16 сердце //0x00, 0x00, 0xFC, 0x02, 0x01, 0x01, 0x06, 0x18, 0x06, 0x01, 0x01, 0x02, 0xFC, 0x00, 0x00, 0x00, //0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x80, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00 //*********************************** }; int columnCount = (sizeof(columns) / sizeof(columns[0])); //Подсчет количества столбцов int p1=0; int p2=p1+8; void setup(){ for (int i=2;i<18;i++){ // массив пинов для светодиодов pinMode(i,OUTPUT); digitalWrite(i,HIGH); delay(columnTime); digitalWrite(i,LOW); } } void loop(){ for (int p0=0;p0<columnCount/2;p0++){ //преебираем все элементы массива //*******читаем все биты первого числа (первые 8 бит) for (int p1=0;p1<=7;p1++){ digitalWrite(p1+2,bitRead(columns[p0],p1));//..включаем первые 8 светодиодов } //******************************** //*******читаем все биты второго числа (вторые 8 бит) for (int p2=0;p2<=7;p2++){ digitalWrite(p2+10,bitRead(columns[p0+16],p2));//..включаем вторые 8 светодиодов } //******************************** delay(columnTime); // пауза между столбцами //********гасим все светодиоды for (int i=2;i<18;i++){ digitalWrite(i,LOW); } //*************************** } delay(spacer*columnTime);// пауза между всем массивом }Теперь думаю с чего бы "содрать" датчик холла.
Теперь пинайте ))
Получилось красиво =) датчик холла можно выдрать из любой расскладущки(я про старые мобилы) или из ноута, или вообще взять из карбюраторного движка( у меня стоит например на ваз 2109)....
но один момент который освящен в моем предыдущем посте, вы таки не учли, вы выводите попиксельно, и в случае с шахмотной доской это очень заметно.... чтобы клетки были ровные(квадраты и одинаковые) надо чуть больше математики =)
http://arduino.ru/Tutorial/Upravlenie_portami_cherez_registry
Получилось красиво =) датчик холла можно выдрать из любой расскладущки(я про старые мобилы) или из ноута, или вообще взять из карбюраторного движка( у меня стоит например на ваз 2109)....
но один момент который освящен в моем предыдущем посте, вы таки не учли, вы выводите попиксельно, и в случае с шахмотной доской это очень заметно.... чтобы клетки были ровные(квадраты и одинаковые) надо чуть больше математики =)
Спасибо! Теперь я это вижу.
Пока нет датчика холла дальше писать смысла нет.
quote=qwone]
http://arduino.ru/Tutorial/Upravlenie_portami_cherez_registry
[/quote]
Рано мне еще . Я этот код еле осилил.
Датчик Хола живёт в любом компьютерном вентиляторе. Даже в том который у вас крутится. Я из из старых, заклинивших, достаю.
Прикольно. Успех не должен останавливать. Переходите к 3Д. Матрицу вращать например. Или вот еще интересная тема - линейка светодиодов+датчик ускорения. При резком взмахе, обнаруженому по датчику, отрисовываем картинку разово. Должен быть занятный эффект. После взмаха в воздухе остается изображение на мгновение.
Прикрутил датчик холла от кулера . Заодно почитал про прерывания. Можно обойтись без attachInterrupt ?
Дело в том что посадить прерывание на 2 или 3 ногу в моем проэкте теперь проблематично так как на них повешены светодиоды , а чтоб сдвинуть все на один выше нужно перепаивать все , что не очень хочется.
Например так .
int pin = 19; unsigned long duration; void setup() { Serial.begin (9600); pinMode(pin, INPUT); } void loop() { duration = pulseIn(pin, HIGH); Serial.println(duration); }Датчик работает - миллисекунды , при поднесении магнита считает.
Только никак не соображу как это воткнуть в мою программу.
Можна и без прерывания. Ждем срабатывания датчика, как сработало - выводим картинку. Затем снова ждем срабатывания и т.д. Если вывод картинки успевает за 1 оборот - все ок. Иначе проблемы. И эти проблемы с прерыванием проще решать. Но если заведомо за 1 оборот успеваем то проще без прерывания.
Можна и без прерывания. Ждем срабатывания датчика, как сработало - выводим картинку. Затем снова ждем срабатывания и т.д. Если вывод картинки успевает за 1 оборот - все ок. Иначе проблемы. И эти проблемы с прерыванием проще решать. Но если заведомо за 1 оборот успеваем то проще без прерывания.
У меня две новости. Начну с хорошей ))
Датчик холла от кулера меня шокировал (вернее его эффект). Все четко отрабатывает .Теперь не стыдно и видео показать , плюс добавил мигалку во время простоя.
Плохое. Где то в коде я накосячил что вчера 2 часа "ковыряний " и анализа загнали меня в тупик.
Суть такова - если массив 16х16 то все работает прекрасно . Но если массив в ширину больше 16 пикселей начинается то что на видео. На втором видео код с двумя стрелками подряд т.е. 16 пикс. в высоту и 32 в ширину.
Смотрите и выручайте ))
1. Здесь все нормально
https://www.youtube.com/watch?v=nSl68jKeD8s&feature=youtu.be
2. Проблемы
https://youtu.be/VbSZxkht80Q
3. Код
const int columnTime = 2; //15 Время [мс] работы каждого отдельного столбца const int spacer = 10; // 10Это значение, умноженное на columnTime , пауза между содержанием всего массива unsigned long duration; long columns[] = { // *******массив 16x16 шахматная доска //0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, //0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC // **************************** // *************** массив 16x16 стрелка 0x00, 0xC0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00, //*********************************** // *************** массив 16x16 стрелка 0x00, 0xC0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00 // *********************************** // *************** массив 16x32 черный прямоугольник //0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // // *********************************** // *************** массив 16x16 сердце //0x00, 0x00, 0xFC, 0x02, 0x01, 0x01, 0x06, 0x18, 0x06, 0x01, 0x01, 0x02, 0xFC, 0x00, 0x00, 0x00, //0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x80, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00 // *********************************** // *************** массив 16x16 черный квадрат //0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF // *********************************** //0xFF, 0x01, 0x01, 0x01, 0x81, 0x41, 0x21, 0x19, 0x05, 0x19, 0x21, 0x41, 0x81, 0x01, 0x01, 0xFF, //0xFF, 0x80, 0x80, 0x80, 0x81, 0x82, 0x84, 0x98, 0xA0, 0x98, 0x84, 0x82, 0x81, 0x80, 0x80, 0xFF }; int columnCount = (sizeof(columns) / sizeof(columns[0])); //Подсчет количества столбцов int p1=0; int p2=p1+8; int pin = 19; //пин для подключения датчика холла void setup(){ for (int i=2;i<18;i++){ // массив пинов для светодиодов pinMode(i,OUTPUT); digitalWrite(i,HIGH); delay(columnTime); digitalWrite(i,LOW); Serial.begin(9600); } } void loop(){ duration = pulseIn(pin, HIGH); // ********гасим все светодиоды for (int i=2;i<18;i++){ digitalWrite(i,LOW); } // *************************** ///* // ***************пока стоим - красиво мигаем )) while (duration==0){ duration = pulseIn(pin, HIGH); for (int kk=2;kk<18;kk++){ digitalWrite(kk,HIGH); delay(20); digitalWrite(kk,LOW); } for (int kk=16;kk>2;kk--){ digitalWrite(kk,HIGH); delay(20); digitalWrite(kk,LOW); } } // ******************************************* if (duration>0){ // ***если сработал датчик холла то.... for (int p0=0;p0<columnCount/2;p0++){ //преебираем все элементы массива // *******читаем все биты первого числа (первые 8 бит) for (int p1=0;p1<=7;p1++){ digitalWrite(p1+2,bitRead(columns[p0],p1));//..включаем первые 8 светодиодов } // ******************************** // *******читаем все биты второго числа (вторые 8 бит) for (int p2=0;p2<=7;p2++){ digitalWrite(p2+10,bitRead(columns[p0+16],p2));//..включаем вторые 8 светодиодов } // ******************************** delay(columnTime); // пауза между столбцами } } //delay(spacer*columnTime);// пауза между всем массивом }Исправьте строку 90 на следующую
for (int p0=0; p0<ColumnCount-16; p0++, p0=((p0%16)==0)?p0+16:p0) {
должно помочь.
Проблема тут запущенная. Надо начинать с того, почему columns[] имеет тип long, верно ли считает columnCount и чего в строке 104 явно прописано 16.
Ну, в принципе, если нам не жалко памяти, то можно и long, на работы не влияет, все равно используются 8 младших разрядов.
Количество элементов массива columnCount считает верно, и даже правильно.
А 16 - количество строк в подмассиве, так что можно и так.
А насчет запущенности - Вы правы, я предложил минимально возможную правку.
Количество элементов массива columnCount считает верно, и даже правильно.
сколько?
А 16 - количество строк в подмассиве, так что можно и так.
Нельзя. код будет выводить пары значений с индексами 0,16;1,17;...15,31; 16,32; 17,32..... Это даже по картинке видно.
Автор просто должен сам разобратся в своем коде. Как раз тот момент, когда заработало - наилучший. Код сохраняется на всяк случай;) и делается рефакторинг, исправляется все искаженное при отладке, оптимизируется, актуализируются имена переменных (очевидно что columnCount сейчас совсем не columnCount ), коментарии и пр. При этом выявляются и исправляются второстепенные ошибки. Вы конечно можете сделать это за автора ;)
Исправьте строку 90 на следующую
for (int p0=0; p0<ColumnCount-16; p0++, p0=((p0%16)==0)?p0+16:p0) {
должно помочь.
Помогло ! За что СПАСИБО ! Но есть еще НО.
И про запущенность ... Тут не соглашусь . Это не запущенность , а незнание. Ненвижу TC ))
С НО разбираюсь, завтра отпишусь о результатах.
Это не запущенность , а незнание.
Ниразу нет. Это естественный ход процесса разработки. Когда по ходу приходится вносить правки, менять представление о назначении переменных, функций и т.д. И менять цели разработки тоже. Так всегда. Ну можно дополнит что всегда при отсутствии четкого планирования, но то скорей илюзия о наличии идеального планирования. Но проще это воспринимать как необходимость уборки в доме. Иногда надо, и даже старайся не сорить, хоть усрись, а всеравно прийдется убирать. Так и код, надо иногда "причесывать".
Это не запущенность , а незнание.
Так и код, надо иногда "причесывать".
Это если уметь пользоваться расческой )) У меня же пока получается только лохматить ))
Об обещанном "НО". Выявился глюк - конвертированные bmp размером больше 16x6 выводятся коряво. Удалось выяснить что это не глюк прошивки а конвертер конвертит "не в моем формате ". вот так.
Получается мои представления о структуре BMP , изложеные в посте 11 в корне неверны ?
Не то чтоб совсем. Просто термин BMP он как бы имеет 2 смысла: общий - представление картинки в несжатом виде при котором каждому пикселю отводится некоторое количество бит и конкретный - стандарт файла в котором реализован первый смысл. Совместимость и переносимость обеспечивает стандарт. Но Вы и автор того конвертора имеют в виду общий смысл. Потому у вас обоих BMP, но они не совместимы. Ваш способ хранения картинки мне показалось несколько не логичным и неудобным. Думаю нужно подстроится под конвертор.
Получается мои представления о структуре BMP , изложеные в посте 11 в корне неверны ?
Угу.
Точнее так: я совекршенно не понял, как именно Вы себе представляете сруктуру BMP, но все-таки понял достаточно, чтобы сказать, что Вы ее себе представляете неверно.
1. Структура BMP начинается с заголовка.
2. Изображение хранится по строкам, а не по столбцам.
Причесал ."Впихиваются " любые (сделанные конвертером в начале топика )монохромные BMP высотой 16 и шириной , ограниченой диаметром.
Пинайте ))
const int columnTime = 2; //15 Время [мс] работы каждого отдельного столбца const int spacer = 10; // 10Это значение, умноженное на columnTime , пауза между содержанием всего массива unsigned long duration; long columns[] = { // *******массив 16x43 BMW )) 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x18, 0xEC, 0x2C, 0x6C, 0xCC, 0x0C, 0x2C, 0xEC, 0xEC, 0x8C, 0xEC, 0xEC, 0x0C, 0xEC, 0x8C, 0x0C, 0xCC, 0xCC, 0x0C, 0x0C, 0xEC, 0x7C, 0xE0, 0xC0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3E, 0x33, 0x33, 0x30, 0x70, 0xD8, 0x8F, 0x8D, 0xFD, 0x7F, 0x26, 0x20, 0x27, 0x20, 0x21, 0x20, 0x27, 0x20, 0x20, 0x23, 0x26, 0x27, 0x21, 0x27, 0x67, 0xE1, 0xD8, 0x98, 0xF0, 0x60, 0x20, 0x21, 0x3F, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // **************************** // *******массив 16x16 шахматная доска //0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, //0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC // **************************** // *************** массив 16x16 стрелка //0x00, 0xC0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x00, //0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00, //*********************************** // *************** массив 16x16 сердце //0x00, 0x00, 0xFC, 0x02, 0x01, 0x01, 0x06, 0x18, 0x06, 0x01, 0x01, 0x02, 0xFC, 0x00, 0x00, 0x00, //0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x80, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00 // *********************************** }; int columnCount = (sizeof(columns) / 4); //Подсчет количества 8 битных столбцов int p1=0; int p2=p1+8; int pin = 19; //пин для подключения датчика холла void setup(){ for (int i=2;i<18;i++){ // массив пинов для светодиодов pinMode(i,OUTPUT); digitalWrite(i,HIGH); delay(columnTime); digitalWrite(i,LOW); } } void loop(){ duration = pulseIn(pin, HIGH); // ***************пока стоим - красиво мигаем )) while (duration==0){ duration = pulseIn(pin, HIGH); for (int kk=2;kk<18;kk++){ digitalWrite(kk,HIGH); delay(20); digitalWrite(kk,LOW); } for (int kk=16;kk>2;kk--){ digitalWrite(kk,HIGH); delay(20); digitalWrite(kk,LOW); } } // ******************************************* if (duration>0){ // ***если сработал датчик холла то.... for (int p0=0; p0<columnCount/2; p0++ ){ // *******читаем все биты первого числа (первые 8 бит) for (int p1=0;p1<8;p1++){ digitalWrite(p1+2,bitRead(columns[p0],p1));//..включаем первые 8 светодиодов } // ******************************** // *******читаем все биты второго числа (вторые 8 бит) for (int p2=0;p2<8;p2++){ digitalWrite(p2+10,bitRead(columns[columnCount/2+p0],p2));//..включаем вторые 8 светодиодов } // ******************************** delay(columnTime); // пауза между столбцами } // ********гасим все светодиоды for (int i=2;i<18;i++){ digitalWrite(i,LOW); } // *************************** } delay(spacer*columnTime);// пауза между всем массивом }А
columnsпо прежнему long. Зачем? ИintcolumnCount ...//Подсчет количества 8 битных столбцов. Ну какие еще 8 битные столбцы, если у Вас четко аппаратно 16 бит в столбце. Дак так и считайте, ведь далее везде columnCount используется деленым на 2. Ну и посчитайте его так сразу. Зачем эти штаны через голову одевать?А
columnsпо прежнему long. Зачем? ИintcolumnCount ...//Подсчет количества 8 битных столбцов. Ну какие еще 8 битные столбцы, если у Вас четко аппаратно 16 бит в столбце. Дак так и считайте, ведь далее везде columnCount используется деленым на 2. Ну и посчитайте его так сразу. Зачем эти штаны через голову одевать?Не ругайтесь. Я разрешал только пинать))
Это моя вторая самостоятельная работа. Первая (измеритель емкости LI ION акб) обошлась без помощи. А тут намного сложнее. По поводу ваших замечаний - я не совсем понимаю зачем это нужно. Если не трудно объясните "на пальцах" и в коде. По 8 битным столбцам - я имел в виду половину из 16 светодиодов.
Сорри за оффтоп,похвастаюсь ))
И снова здравствуйте !
Выкладываю "причесаную" версию (я так думаю).
Код значительно переработан.
Размер изображения не зависит от оборотов(почти).
Освободил 2 пин для прерывания но пока не использовал для этого. Как считаете стоит его использовать ? Будет лучше ?
И еще .... Подскажите редактор для преобразования картинки в полярную систему координат. Или есть другие мысли по этому поводу ?
int duration; //..толщина столбца //****************Пременные пинов светодиодов int l1 = 18; int l2 = 3; int l3 = 4; int l4 = 5; int l5 = 6; int l6 = 7; int l7 = 8; int l8 = 9; int l9 = 10; int l10 = 11; int l11 = 12; int l12 = 13; int l13 = 14; int l14 = 15; int l15 = 16; int l16 = 17; //************************** int lp[] = {l1, l2, l3, l4, l5, l6, l7, l8,l9, l10, l11, l12, l13, l14, l15, l16}; // массив пинов светодиодов byte columns[] = { // *******массив 16x43 BMW )) //0x00, 0x80, 0xE0, 0x98, 0x06, 0x01, 0x06, 0x98, 0xE0, 0x80, 0x00, 0x00, 0xFF, 0x81, 0x81, 0x81, //0x81, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xFF, 0x00, 0x00, 0xC0, //0x3C, 0x03, 0x3C, 0xC0, 0x00, 0x00, 0xFF, 0x1C, 0x60, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, //0xFF, 0x80, 0x80, 0x80, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0x06, 0x18, 0x60, //0x80, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x80, 0x80, 0x80, 0xFF, 0xC0, 0x3C, 0x03, 0x00, 0x00, 0x00, //0x03, 0x3C, 0xC0, 0xFF, 0x00, 0x00, 0x03, 0x1C, 0x60, 0xFF // **************************** // *******массив 16x16 шахматная доска //0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, //0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC // **************************** // *************** 16x41 большая стрелка //0x80, 0x80, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF8, 0xF8, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, //0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, //0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x07, //0x0F, 0x0F, 0x0F, 0x1F, 0x1F, 0x1F, 0x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, //0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, //0x0F, 0x0F, //********************************** // *************** массив 16x16 стрелка //0x00, 0xC0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x00, //0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00, //*********************************** // *************** массив 16x16 сердце //0x00, 0x00, 0xFC, 0x02, 0x01, 0x01, 0x06, 0x18, 0x06, 0x01, 0x01, 0x02, 0xFC, 0x00, 0x00, 0x00, //0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x80, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00 // *********************************** // *************** массив 16x86 arduino.ru 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0xCE, 0x31, 0x11, 0x11, 0x11, 0x11, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x82, 0x01, 0x01, 0x01, 0x01, 0x82, 0x7C, 0x00, 0x00, 0xFF, 0x80, 0x60, 0x10, 0x0C, 0x02, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x7C, 0x82, 0x01, 0x01, 0x01, 0x01, 0xFF, 0x00, 0x00, 0xCE, 0x31, 0x11, 0x11, 0x11, 0x11, 0xFF, 0x00, 0x80, 0x60, 0x38, 0x26, 0x21, 0x26, 0x38, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 // *********************************** }; int columnCount = (sizeof(columns)); //Подсчет количества байтов в массиве int pin = 2; //пин для подключения датчика холла void setup(){ for (int i = 0; i < 16; i++) { pinMode(lp[i], OUTPUT); digitalWrite(lp[i], LOW); } } void loop(){ duration = pulseIn(pin, HIGH); // ***************пока стоим - красиво мигаем )) while (duration==0){ duration = pulseIn(pin, HIGH); for (int kk=2;kk<18;kk++){ digitalWrite(kk,HIGH); delay(20); digitalWrite(kk,LOW); } for (int kk=16;kk>2;kk--){ digitalWrite(kk,HIGH); delay(20); digitalWrite(kk,LOW); } } // ****************************************** * if (duration>0){ // ***если сработал датчик холла то.... for (int p0=0; p0<columnCount/2; p0++ ){ // *******читаем все биты первого числа (первые 8 бит) for (int p1=0;p1<8;p1++){ digitalWrite(lp[p1],bitRead(columns[p0],p1));//..включаем первые 8 светодиодов } // ******************************** // *******читаем все биты второго числа (вторые 8 бит) for (int p2=0;p2<8;p2++){ digitalWrite(lp[p2+8],bitRead(columns[columnCount/2+p0],p2));//..включаем вторые 8 светодиодов } // ******************************** delayMicroseconds(duration/3); } // ********гасим все светодиоды for (int i=0;i<16;i++){ digitalWrite(lp[i],LOW); } // *************************** } }Видео работы https://youtu.be/0llRyQKpjqc
Пинайте !
Получилось достаточно интересно. В 2002 году делал таким образом часы на PIC контроллере. Теперь увидев эту тему и посмотрев Ютуб кусаю локти, что ограничился тогда часами. :)
Заказал уже на Али упаковку миниатюрных трехцветных светодиодов, попробую многоцветный рисунок влспроизвести.
Растянуть рисунок на 64 светодиода можно к примеру с помощью max7219. Но это будет в одном цвете. Пока что-то никак не соображу как три цвета организовать.
А вы спросите у гугла про WS2812 - будете приятно удивлены ))
Размер изображения не зависит от оборотов(почти).
Очень красиво получилось. И на видео, и реализация в коде красиво - просто и коротко.
Освободил 2 пин для прерывания но пока не использовал для этого. Как считаете стоит его использовать ? Будет лучше ?
По развитию проекта:
1. Убрать columns из ОЗУ. Совсем не сложно, ищите по слову PROGMEM, на форуме часто встречается. Цель - возможность хранить в флеше и выводить десяток полноформатных картинок, анимация.
2. Работа с портами напрямую. Цель - ускорение вывода, снижение нагрузки на процессор. На данный момент может и не актуально, но экономия не повредит, да и изучить вопрос полезно.
3. Ну и традиционно - формат хранения. Если найдется редактор для преобразования картинки - подстроится под него. Если нет и п.2 не делаете - переработать тот формат, что есть. Цель - сокращение и упрощение кода, заменив два цикла на один.
4. Подумать о ИК управлении. Это при реализации п.1 даст возможность переключать картинки и передавать изображениие во время работы. Получится целый дисплей )))
Честно говоря, удивлен, что картинка не зависит от скорости вращения - должна зависеть или я чего то сильно недопонимаю.
У Вас датчик Холла отмечает одно место на колесе ? Или срабатывает несколько раз за оборот?
Вроде по коду одно, но почему тогда картинка на сжимается при малых скоростях, я не понимаю.
Честно говоря, удивлен, что картинка не зависит от скорости вращения - должна зависеть или я чего то сильно недопонимаю.
ага. Вот этого - delayMicroseconds(duration/3); ))) Я ж говорю, красиво проблема решена. Длительность вывода пикселя привязана к длительности импульса с датчика.
PS. Теперь понял, я просто старый код смотрел с фиксированными длительностями свечения, а Вы в новом привязали ее к длительности предыдущего импульса, красиво получилось, своего рода ФАПЧ, единственное, что надо бы исправить - у Вас может быть один рабочий оборот и один пустой для измерения - скважность ухудшится, надо бы объединить. Ну и мерять не длительность импульса, а паузы между ними и делить на количество выводимых строк, но идея хороша.
Спасибо всем за отзывы !
Приятно читать . Сам не ожидал. Думаю оставить все как есть . Пусть это будет это версией 1.0 . Планы на версию 2.0 - вывести картинку в горизольталой плоскости, добавить анимацию. Скорее это будет уже другой проект. Ведь программа поменяется кардинально.
Еще бы "подтянуть" знания в программированиии. Тяжело начинать делать в 45 то что никогда не делал. Прорвемся ))
у Вас может быть один рабочий оборот и один пустой для измерения - скважность ухудшится, надо бы объединить.
Господа Программисты !
Тут http://mysku.ru/blog/ebay/30604.html есть описание редактора а тут https://yadi.sk/d/VreNSLjivqP5F сам редактор. Это вроде питоновский скрипт. Установил питон но запустить скрипт не удалось. Подскажите плиз по шагам как его запусть или перекомпилируйте пожалуйста в EXEшник .
Mobistrike, спасибо за подсказку, наконец-таки мне пришла лента WS8212b. На скорую руку соорудил макет.
Синхронизация по датчику холла. Светодиоды загораются на 40 мс, потом гаснут и так до следующего оборота.
Правильно ли я понимаю, что разрывы в свечении из-за импульсного питания светодиодов. Можно ли это исправить увеличив яркость светодиодов (strip.setBrightness(255), я использую библиотеку adafruit_neopixel)?
kasper007 , вы бы для начала скетч выложили. Второе - с WS2812b я не работал , но уверен найдутся знающие люди и подскажут, третье - не совсем понимаю что вы имеете ввиду под "импульсным питанием светодиодов".
Скетча нет под рукой, дома на компьюетере. Но в нем нет ничего неординарного. Настроено прерывание на int.0. По прерыванию загорается все линейка. Дальше счетчик на 40 мс, после чего гасим светодиоды.
"Надеюсь с знакомы с алгоритмом работы POV дисплея ?" Да, конечно же, прекрасно осведомлен. Вчера задача стояла завести агрегат физически, а что он будет потом отображать, это уже творческий процесс и "капелька ума" для реализации идеи в коде.
"что вы имеете ввиду под "импульсным питанием светодиодов".". Для регулировки яркости светодиодов повсеместно используется импульсное питание. Изменяя скважность импульсов мы изменяем яркость свечения. Когда светодиод неподвижен мы не замечаем это моргание, а когда мы раскручиваем светодиод, то уже можно заметить периоды когда питание на светодиод подается, а когда нет. Вроде так.
Скетча нет под рукой, дома на компьюетере. Но в нем нет ничего неординарного. Настроено прерывание на int.0. По прерыванию загорается все линейка. Дальше счетчик на 40 мс, после чего гасим светодиоды.
"Надеюсь с знакомы с алгоритмом работы POV дисплея ?" Да, конечно же, прекрасно осведомлен. Вчера задача стояла завести агрегат физически, а что он будет потом отображать, это уже творческий процесс и "капелька ума" для реализации идеи в коде.
"что вы имеете ввиду под "импульсным питанием светодиодов".". Для регулировки яркости светодиодов повсеместно используется импульсное питание. И изменяя скважность импульсов и изменяем яркость. Когда светодиод неподвижен мы не замечаем это моргание, а когда мы раскручиваем светодиод, то уже можно заметить периоды когда питание на светодиод подается, а когда нет. Вроде так.
Теперь понятно . Тогда стоит проверить на максимальной яркости .
Действительно, при максимальной яркости разрывов никаких нет.
Скелет кода получился примерно такой:
#include <Adafruit_NeoPixel.h> #define PIN 5 // лента на 5ом порту #define count_led 9 // количество светодиодов #define eff_int 50 // длина эффекта в точках Adafruit_NeoPixel strip = Adafruit_NeoPixel(count_led, PIN, NEO_GRB + NEO_KHZ800); volatile byte hall_detect; // флаг срабатывания датчика холла byte i; // переменная для номера текущей точки эффекта (не должна быть больше eff_int) unsigned long time_old; // время срабатывание датчика холла unsigned long time_int; // длительность оборота float time_eff; // длительность одной точки эффекта = длительность оборота/длина эффекта в точках boolean ind_on; void setup() { Serial.begin(115200); strip.begin(); strip.show(); attachInterrupt(0, magnet_detect, RISING); hall_detect = 1; i = 1; ind_on = true; time_old = millis(); } void loop() { if (hall_detect == 0) { if ((millis()-time_old) > 2000) { //если оборот более чем за 2 сек, выключаем индикацию light_off(); strip.show(); } if ((millis()-time_old) > (time_eff*i)) { i++; ind_on = true; strip.show(); //длительность записи в ленту 30*count_led мкс } else { if (ind_on) { eff_1(); ind_on = false; } } } if (hall_detect == 1) { time_int = millis()-time_old; time_old = millis(); hall_detect = 0; i = 1; time_eff = (float)time_int/eff_int; } } void magnet_detect() { hall_detect = 1; } void light_off () { for (byte ii=0; ii<count_led; ii++) { strip.setPixelColor(ii, 0,0,0);} } void eff_1 () { for (byte ii=0; ii<count_led; ii++) { if ((i > 1) & (i < 16)) { strip.setPixelColor(ii, 100, 0, 0);} if ((i > 17) & (i < 32)) { strip.setPixelColor(ii, 0, 100, 0);} if ((i > 33) & (i < 49)) { strip.setPixelColor(ii, 0, 0, 100);} } }В функцию eff_1 уже нужно вставлять то, что мы хотим индицировать на крутящейся полосе и что должно развернутся в рисунок.
Пока ради эксперимента и наглядности сделал три сегмента разных цветов.
https://www.youtube.com/watch?v=flEm-wQpx90
Доброе ввремя. mobistrike, в этом видео https://youtu.be/0llRyQKpjqc красные цифры я так понимаю скорость вращения? В чем она выражена и при какой минимальной скорости просмотривается строчка полностью?