Супер! Сегодня вечером потестю :)
Вид для печати
А я вот смотрю сюда и думаю, а стоит ли изобретать велосипед ?
https://github.com/adafruit/Adalight.../LEDstream.pde
может воспользоваться этим скетчем ? тем более поддержка АДА в LightPack'e уже есть.... А в АДА есть поддержка WS2801....
Тоже хорошее решение.
Только по скетчу пока не пойму как они определяют границы, кадров.
Вроде вижу синхросигнал "Ada" от контроллера в компьютер - запрос получения данных для очередного кадра.
Но как определяется конец данных для кадра, пока не пойму.
Вроде похоже на таймаут ожидания получения порции данных, но пока не уверен на 100%.
Кстати они у себя на странице ссылаются на использование LightPack, как на утилитку с дружественным GUI и хорошей производительностью
http://learn.adafruit.com/adalight-d...ftware-options
Ну в коде вроде все описали...
После magic word (Ada) идет 16битное значение количества светодиодов(только количество начинается с 0, т.е. для 120 светодиодов прилетает 119).....Код:immediately following the magic word
// are three bytes: a 16-bit count of the number of LEDs (high byte
// first) followed by a simple checksum value (high byte XOR low byte
// XOR 0x55). LED data follows, 3 bytes per LED, in order R, G, B,
// where 0 = off and 255 = max brightness.
далее чексум по формуле (high byte XOR low byte XOR 0x55). ну а далее цвета.... кстати в коде(во втором скетче ) написано, что у WS2801 цвета перепутаны. Кстати может добавить опцию порядка цветов на уровне Host'а ?
Ну а если я не ошибаюсь, то где-то тут весь буфер уходит в SPI:
Код:case MODE_DATA:
while(spiFlag && !(SPSR & _BV(SPIF))); // Wait for prior byte
if(bytesRemaining > 0) {
if(bytesBuffered > 0) {
SPDR = buffer[indexOut++]; // Issue next byte
bytesBuffered--;
bytesRemaining--;
spiFlag = 1;
Не работает :(
Требует дополнительно к файлам из комплекта LightPack 5.8.6-1 библиотеку libstdc++-6.dll
После добавления ругается:
"Точка входа в процедуру _ZN6QMutex12lockInternalEv не найдена в библиотеке DLL QtCore4.dll"
Сама библиотека QtCore4.dll в каталоге с программой присутствует.
МАКС, во! У меня такая же была ошибка кода я пытался скомпилировать LightPack из свежих исходников
Для запуска тестовой версии, нужны файлы из архива с программой на 255 зон для ardulight
http://www.compcar.ru/forum/attachme...2&d=1344572460
MAKC, думал тут думал, а ведь все очень просто получается с кодом управления через SPI.. что то типа
на ошибки проверил, а вот как работает к сожалению пока не могу... так что тебе карты в руки... но по логике должно все работать....Код:#include <SPI.h>
unsigned long LastByteTime, t;
uint8_t data;
void setup()
{
Serial.begin(115200);
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV16); // 1 МГц
//DDRB |= _BV(PORTB5); // Enable output for LED
//PORTB &= ~_BV(PORTB5); // LED off
//PORTB |= _BV(PORTB5); // LED on
}//setup()
void loop()
{
// for(;;){
t= millis();
if ((data = Serial.read()) >= 0) {
LastByteTime = t;
//if (data == 255){delay(1);continue;} //подождем 1мс для след кадра
if (data == 255){delay(1);return;} //подождем 1мс для след кадра
else{
while(!(SPSR & _BV(SPIF)));
SPDR = data;
}
}else{
//гасим подсветку если нет потока более 10 сек
if((t - LastByteTime) > 10000) {
for(char i=0; i<255; i++) {
SPDR = 0;while(!(SPSR & _BV(SPIF)));
}
delay(1); // подождем 1мс
LastByteTime = t; // Reset counter
}
}
// }//for
}
Очередная итерация скетча для работы с WS2801.
1. проверена работа в паре с другой Ардуиной в режиме SPI приемника, соотвественно исправлены все ошибки.
2. заменены библиотеки COM порта на более легкие и быстрые.
3. произведена оптимизация в сторону максимального отказа от Ардуиновских библиотек.
4. После оптимизаций прошивка на порядок полегчала , с 3.16кб до 0,85кб. Думаю, так же улучшилась отзывчивость кода.
Сам скетч:
(некоторые комментарии оставил для понимания кода)
Если кому-нибудь нужно, могу дополнительно выложить Скетч для Ардуино, который переводит мегу в режим приемника SPI и посылает принятые данные из шины SPI на COM порт. Очень удобно для отладки...Код:#include <util/delay.h>
#include <smallUart.h>
//#include <SPI.h>
unsigned long LastByteTime, t;
uint8_t data,byte_count = 0;
void setup()
{
UART_Init(115200);
//Заменяем команду SPI.begin();
//SPI.begin();
DDRB |= (1<<MOSI) | (1<< SCK) | (1<<SS);
PORTB |= _BV(PORTB2);
PORTB &= ~((1<<PORTB3)|(1<<PORTB5));
//SPI.setBitOrder(MSBFIRST);
//SPI.setDataMode(SPI_MODE0);
//SPI.setClockDivider(SPI_CLOCK_DIV16); // 1 МГц
SPCR = 1; SPSR = 0; // 1 МГц; MSBFIRST; SPI_MODE0
//SPCR = 1; SPSR = 1; // 2 МГц; MSBFIRST; SPI_MODE0
//SPCR = 2; SPSR = 1; // 0.5 МГц; MSBFIRST; SPI_MODE0
}//setup()
void loop()
{
//for(;;){
t= millis();
if (UART_ReadByte(data)){
LastByteTime = t;
//if (data == 255){_delay_ms(1);continue;} //подождем 1мс для след кадра(for(;;))
if (data == 255){_delay_ms(1);return;} //подождем 1мс для след кадра(loop())
else{
// PORTB &= ~_BV(PORTB2); // для отладки: SS off, начинаем передачу
SPDR = data;while(!(SPSR & _BV(SPIF)));
//PORTB |= _BV(PORTB2); // для отладки: SS on, закончили передачу
}
}else{
//гасим подсветку если нет потока более 10 сек
if((t - LastByteTime) > 10000) {
for(int8_t i=0; i<255; i++) {
SPDR = 0;while(!(SPSR & _BV(SPIF)));
}
_delay_ms(1); // подождем 1мс
LastByteTime = t;
}
}
//}//for
}
PS: библиотеку SmallUart можно взять отсюда
Продолжение темы/Очередная доработка:
Отказался от библиотеки SmallUart, так что теперь нет необходимости скачивать библиотеку SmallUart. Основные функции перенес в скетч.
После очередной оптимизации программа снова "похудела" почти на 200 байтКод:#include <util/delay.h>
//#include <smallUart.h>
//#include <SPI.h>
unsigned long LastByteTime, t;
uint8_t data;
void setup()
{
//Инициализация UART
UBRR0L = 16;UBRR0H = 0; //115200
//UBRR0L = 34;UBRR0H = 0; //57600
UCSR0A = ( 1<<U2X0 ); //UART_DOUBLESPEED
UCSR0C=((1<<UCSZ01) | (1<<UCSZ00)); //Set Frame Format
UCSR0B = ((1<<TXEN0) | (1<<RXEN0)); //Enable The receiver and transmitter
//Инициализация SPI;
//SPI.begin();
DDRB |= (1<<MOSI) | (1<< SCK) | (1<<SS);
PORTB |= _BV(PORTB2);
PORTB &= ~((1<<PORTB3)|(1<<PORTB5));
//SPI.setBitOrder(MSBFIRST);
//SPI.setDataMode(SPI_MODE0);
//SPI.setClockDivider(SPI_CLOCK_DIV16); // 1 МГц
SPCR = 1; SPSR = 0; // 1 МГц; MSBFIRST; SPI_MODE0
//SPCR = 1; SPSR = 1; // 2 МГц; MSBFIRST; SPI_MODE0
//SPCR = 2; SPSR = 1; // 0.5 МГц; MSBFIRST; SPI_MODE0
}//setup()
bool Read_Next_Byte(uint8_t& data)
{
if (_SFR_MEM8(0xC0) & (1<<7)) //(UCRA & (1<<UART_RXREADY))
{
data = _SFR_MEM8(0xC6); //data = UDR;
return true;
}
else return false;
}
void loop()
{
//for(;;){
t= millis();
if (Read_Next_Byte(data)){
//if (true){
LastByteTime = t;
//if (data == 255){_delay_ms(1);continue;} //подождем 1мс для след кадра(for(;;))
if (data == 255){_delay_ms(1);return;} //подождем 1мс для след кадра(loop())
else{
// PORTB &= ~_BV(PORTB2); // для отладки: SS off, начинаем передачу
SPDR = data;while(!(SPSR & _BV(SPIF)));
//PORTB |= _BV(PORTB2); // для отладки: SS on, закончили передачу
}
}else{
//гасим подсветку если нет потока более 10 сек
if((t - LastByteTime) > 10000) {
for(int8_t i=0; i<255; i++) {
SPDR = 0;while(!(SPSR & _BV(SPIF)));
}
_delay_ms(1); // подождем 1мс
LastByteTime = t;
}
}
//}//for
}
Знаковое число получилось )))Цитата:
Размер скетча в двоичном коде: 666 байт