LED экран, передача данных по COM порту
- Войдите на сайт для отправки комментариев
Здравствуйте.
Делаю себе что-то вроде светодиодного экрана разрешением 32x16 (на основе max7219).
Начало пока более или менее удачное, Arduino самостоятелно уже рисует картинки на этом экране (в черновом варианте). Но у меня в планах управлять этим экраном с компьютера, и вот на этом у меня возникли затруднения, т.к. я пока ещё начинающий в этом деле.
На данный момент что бы прорисовать весь экран нужно 64 байта данных, каждый байт это 1/2 столбца экрана (8 светодиодов)
Эти байты я предоставил в виде массива чисел (0..255)
Вопрос: Как правильно принять эти 64 байта (или массив из 64 цифр) с компьютера, и как правильно их отправит на ардуино желателно при помощи Processing...?
Вот код автономной работы:
#include <SPI.h> int ic = 8; // количество микросхем int IC_SELECT = 8; int icbytes= ic*2; byte spidata[16]; byte status[64]; // #define OP_DECODEMODE 9 #define OP_INTENSITY 10 #define OP_SCANLIMIT 11 #define OP_SHUTDOWN 12 #define OP_DISPLAYTEST 15 void setup() { SPI.begin(); SPI.setClockDivider(SPI_CLOCK_DIV4); pinMode(IC_SELECT, OUTPUT); digitalWrite(IC_SELECT, HIGH); // Palitra(); for(int chip = 0; chip < ic; chip++) // выбор номера микросхемы { IcOff(chip, false); // включение микросхем Yarkost(chip, 15); // яркость } } void loop() { int shim = 15; for(int i = 0; i < 16; i++) { int mass[64] = {143,0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,60,199,128,128,0,0,0,128,128,128,128,0,0,0,128,128,128,128,0,0,0,128,128,128,128,0,0,0,128,128,128,128,30}; kadr(shim, mass); // передача данных в генератор кадра delay(70); int mass0[64] = {60,0,1,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,143,30,128,128,128,128,0,0,0,128,128,128,128,0,0,0,128,128,128,128,0,0,0,128,128,128,128,0,0,0,128,128,199}; kadr(shim, mass0); delay(70); int mass1[64] = {241,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,127,120,0,0,128,128,128,128,0,0,0,128,128,128,128,0,0,0,128,128,128,128,0,0,0,128,128,128,128,0,0,0,241}; kadr(shim, mass1); delay(70); int mass2[64] = {199,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,120,227,128,0,0,0,128,128,128,128,0,0,0,128,128,128,128,0,0,0,128,128,128,128,0,0,0,128,128,128,128,0,60}; kadr(shim, mass2); delay(70); //shim=shim--; } } // ------------ Генератор кадра ----------------------------------- void kadr(int shim, byte byt[64]) { int data = 0; int offset; for(uint8_t chip = 0; chip < ic; chip++) // выбор номера микросхемы { offset = chip*8; for(uint8_t kol = 0; kol < 8; kol++) // выбор номера столбца { status[offset+kol]=byt[data]; // Yarkost(chip, shim); //яркость // SPI_Data(chip, OP_INTENSITY,shim); //яркость напрямую SPI_Data(chip, kol+1,status[offset+kol]); data=data++; } } } // ----------- Подготовительный этап ---------------------------- void Palitra() { digitalWrite(IC_SELECT, LOW); for(int i=0;i<64;i++) status[i]=0x00; for(int i=0;i<ic;i++) { SPI_Data(i,OP_DISPLAYTEST,0); //максимальное колличество столбцов в сегменте SPI_Data(i,OP_SCANLIMIT,7); // SPI_Data(i,OP_DECODEMODE,0); clDisplay(i); //Выключение микросхем IcOff(i,true); } digitalWrite(IC_SELECT, HIGH); } //-------------- Включение и выключение микросхемы -------------- void IcOff(int addr, bool b) { if(addr<0 || addr>=ic) return; if(b) SPI_Data(addr, OP_SHUTDOWN,0); else SPI_Data(addr, OP_SHUTDOWN,1); } //------------ Яркость (ШИМ)------------------------------------ void Yarkost(int addr, int shim) { if(addr<0 || addr>=ic) return; if(shim>=0 || shim<16) SPI_Data(addr, OP_INTENSITY,shim); } //-------------- Очистка микросхемы ------------------------------ void clDisplay(int addr) { int offset; if(addr<0 || addr>=ic) return; offset=addr*8; for(int i=0;i<8;i++) { status[offset+i]=0; SPI_Data(addr, i+1,status[offset+i]); } } //------------- Передача данных в микросхему --------------------- void SPI_Data(int addr, volatile byte opcode, volatile byte data) { // Создание массива int offset=addr*2; for(int i=0;i<icbytes;i++) spidata[i]=(byte)0; // spidata[offset+1]=opcode; spidata[offset]=data; // Разрешение записи digitalWrite(IC_SELECT, LOW); // в микр. for(int i=icbytes;i>0;i--) SPI.transfer(spidata[i-1]); // Запрет записи digitalWrite(IC_SELECT, HIGH); }
А это я пытался принемать данные с терминала, картинка рисуется но не корректно:
... void setup() { Serial.begin(115200); SPI.begin(); SPI.setClockDivider(SPI_CLOCK_DIV4); pinMode(IC_SELECT, OUTPUT); digitalWrite(IC_SELECT, HIGH); // Palitra(); for(int chip = 0; chip < ic; chip++) // выбор номера микросхемы { IcOff(chip, false); // включение дисплея Yarkost(chip, 15); // 15 = яркость } } int mass[64]; void loop() { if ( Serial.available() > 0 ) // проверяем, есть ли, что читать { for(int i = 0; i < 64; i++) mass[i] = Serial.read(); } Serial.flush(); kadr(10, mass); } ...
Во- первых для экономии ОЗУ нужно обьявлять массивы типа byte, а не int (строки 35, 38, 41, 44) иначе у вас в памяти выделяется 128 байт, а вы используете только 64.
Во-вторых вы читаете из буфера UART данные, которые еще не пришли, то есть читаете мусор. Для того, что бы решить эту проблему, лучше всего дождаться пока все данные окажутся в буфере и после чего разом их считать оттуда
но для этого нужно увеличить размер буфера, здесь где-то недавно обсуждалось как это сделать.
Или можно поставить задержку при чтении данных
maksim, спасибо, у меня уже изменены масивы на тип byte и еще все for циклы имеют uint8_t
переменную.
благодорю за коррекию кода... буду искать как увеличить буфер, я по возможности не хочу применять задержки типа delay ...
uint8_t и byte это одно и тоже.
Спасибо за информацию, я примерно так и предпологал, то что uint8_t вроде занимает байт в памяти так же как и Byte. как то раз стал применять uint8_t так до сих пор и пишу так, теперь вы развеили мои сомнения, буду прописывать Byte , так легче и короче...
Сейчас проверил применить задержку при чтении с порта вроде бы корректно воспринемает данные.
В Processing-е на компьютере пока прописал так:
эти байты символов теперь корректно прочитал, до этого картинка могла прорисовыватся с беспорядочно любого места...
Прошу снова помощи и совета.
Пока я "творил" себе программу для управлением этого экрана с ПК, я решил что мне вовсе не нужна эта программа. Зачем мне тратить такое огромное количество ресурсов и электро энергии от ПК?, когда можно к ардуино подключить флешку и читать от туда нужные мне байты.
И следом у меня возник вопрос, хватит ли достаточно производительности микроконтролёру (и флешки) если одновременно к SPI будет подключено и экран и флешка с учетом обновления экрана примерно с периодом 100 милисекунд?
на флешке планирую разместить текстовый файл, а его содержимое будет из большого колличества строк из цифр разделённые запятыми или пробелами, каждая цифра это десятичное представление байта (0-255).
и возможно ли будет читать этот файл по строчно, к примеру прочитал строку - занес её в массив - после этот массив в экран и так по кругу, или нужно будет обязательно прочесть весь файл (на сколько хватит ОЗУ)?
Построчно и надо. Скорости шины хватитю
Правильно я реализовал построчное чтение или можно зделать как-то проще и еффективней? (пока строки вывожу в монитор com порта)
подключена библиотека SD...
Вот что у меня получилось.
Может конечно многое у меня и не правильно сделано, но моя цель уже реализованна на 99%.
С флешки все читает, экран кадры показывает (даже намного быстрей обновляется чем я расчитывал) да и еще впридачу данные о кадре на COM порт отпровляет.
Еще постараюсь что-нибудь оптимизировать, если соображу.
Спасибо огромное данному сайту и участникам форума за помощь в реализации моего проекта.
Если у кого есть желание покритиковать данный код, с удовольствием послушаю, и приму во внимание на будущее, хоть я и не программист, но есть желание хоть что-то освоить...
Здравствуйте! Пытаюсь сделать что-то наподобие того что написано в этой теме, и пробую разобрать в коде последнего поста, вроде коекак понял что чего делает, вот только не понятно что происходит в строчке:
spidata[i]=(byte)0; почему и зачем перед нулём в скобках byte ?
spidata[i]=(byte)0; почему и зачем перед нулём в скобках byte ?
Явно указан тип.
Это как правило хорошего тона.
Можно в данном случае и просто писать spidata[i] = 0;
Спасибо. Вчера пол ночи спаивал микросхемы, только у меня их 4, а у автора помоему 8 штук, будет ли корректно работать данный код в таком случае? У меня после прошивки ардуинки данным скетчем на первом модуле max7219 ничего нет на в тором и третьем написано "SD" (только эти буквы у меня получились лёжа на спине, наверное придётся светодиоды перепаивать) и с определённой переодичностью меняется яркость.
И ещё мне не совсем понятно что именно нужно писать в текстовом файле?
Спасибо. Вчера пол ночи спаивал микросхемы, только у меня их 4, а у автора помоему 8 штук, будет ли корректно работать данный код в таком случае? У меня после прошивки ардуинки данным скетчем на первом модуле max7219 ничего нет на в тором и третьем написано "SD" (только эти буквы у меня получились лёжа на спине, наверное придётся светодиоды перепаивать) и с определённой переодичностью меняется яркость.
И ещё мне не совсем понятно что именно нужно писать в текстовом файле?
Работать на 4 микросхемах будет, но без незначительной корректировки кода не совсем правильно... То, что на экране написано SD - это часть текста (SD init... и SD error) просто на 4 модулях весь текст не умещается. А если у Вас SD постоянно на экране видно значит, есть какие-то проблемы с флэш картой. В текстовом файле нужно прописать строки такого формата: 0,128,256,...,1 - в вашем случае 32 цифры (в моём 64) разделённой запятой, одна строка = один кадр. Каждая цифра это байт данных в десятичном виде на один столбец светодиодов. Писать их в ручную это очень муторное дело, для создания файла эффектов у меня отдельно написана программа под Windows. После написания мною здесь последнего сообщения код программы уже не раз редактировался и добавлялось много дополнительных функций, мог бы разместить его здесь но увы, не смог найти у себя его, может уже и нет, т.к. данный проект у меня уже не на основе Arduino...
Спасибо большое
Долго мучался с текствым файлом, а оказывается у меня была не правильно подключена флешка, теперь всё получилось, перепаял светодиоды. Теперь подумываю докупить ещё 4 микросхемы - драйвера, на 4х както мало чего нарисуешь.