2016-09-23 2 views
0

Я построил 10x10RGB (без WS2811 ..., нормальных). Светодиодная матрица с 5 сдвижными регистрами и 1 микросхема arduino.Оптимизация кода Arduino для мультиплексирования Светодиодная матрица

Моя проблема теперь в том, что мой код, похоже, замедляется или ардуино с его 16Mhz просто не справляется с приличной частотой кадров. На данный момент я получаю некоторое мерцание/отставание, когда я использую код ниже. Я думаю, что частота Гц около 60 Гц-100 Гц будет очень хорошей. Я уже изменил параметры компилятора Arduino IDE от -O до -O3, чтобы получить лучшую скорость (это действительно сработало).

Код имеет битовую модуляцию для регулировки яркости и мультиплексирования.

Так что мой вопрос: Стоит ли создать массив, где все возможные значения (10 значений, только Int < 10) предопределены, а затем использовать их в строке 312:

BitMapR1[intLayerSel/10] = _byte; 

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

setBitMaps(), где угол битой модуляция происходит myloop(), где мультиплексирование происходит

Код:http://pastebin.com/tkFZsVxS < - лучше посмотреть здесь

class FLED { 
private: 
bool b; 

public: 
FLED(); 
void show(); 
}; 

FLED::FLED() : b(false) { 

} 

void FLED::show() { 

} 


class LED { 
private: 
uint8_t LEDname; 
uint8_t R; 
uint8_t G; 
uint8_t B; 

public: 
LED(); 
uint8_t getR(); 
uint8_t getG(); 
uint8_t getB(); 
void setR(uint8_t _R); 
void setG(uint8_t _G); 
void setB(uint8_t _B); 
}; 

LED::LED() : R(0), G(0), B(0) { 

} 

uint8_t LED::getR() { 
return R; 
} 
uint8_t LED::getG() { 
return G; 
} 
uint8_t LED::getB() { 
return B; 
} 

void LED::setR(uint8_t _R) { 
R = _R; 
} 
void LED::setG(uint8_t _G) { 
G = _G; 
} 
void LED::setB(uint8_t _B) { 
B = _B; 
} 

LED leds[100]; 
FLED FastLED; 


void setup() { 
//set pins to output so you can control the shift register 
pinMode(2, OUTPUT); 
pinMode(4, OUTPUT); 
pinMode(3, OUTPUT); 
pinMode(5, OUTPUT); 
//Serial.begin(250000); 
//noInterrupts(); 

} 

unsigned long lngLast = 0; 


uint8_t BitMapR1[10] = { 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000 
}; 
uint8_t BitMapR2[10] = { 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000 
}; 
uint8_t BitMapR3[10] = { 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000 
}; 

uint8_t BitMapR4[10] = { 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000, 
B00000000 
}; 

LED CRGB(byte _R, byte _G, byte _B) { 
LED _LED = LED(); 
_LED.setR(constrain(_R/16, 0, 15)); 
_LED.setG(constrain(_G/16, 0, 15)); 
_LED.setB(constrain(_B/16, 0, 15)); 
return _LED; 
} 

void loop() { 


//Serial.print(micros()); Serial.println(" Start"); 

leds[0] = CRGB(36, 0, 0); 
leds[1] = CRGB(103, 0, 0); 
leds[2] = CRGB(170, 0, 0); 
leds[3] = CRGB(255, 0, 0); 
leds[4] = CRGB(255, 0, 0); 
leds[5] = CRGB(170, 0, 0); 
.......... 
leds[96] = CRGB(103, 0, 0); 
leds[97] = CRGB(36, 0, 0); 
leds[98] = CRGB(0, 0, 0); 
leds[99] = CRGB(0, 0, 0); 


//Serial.print(micros()); Serial.println(" Objekte"); 
BAM(); 

//Serial.print(micros()); Serial.println(" BAM"); 

} 

void BAM() { 
for (byte cycle = 1; cycle <= 15; cycle++) { 
//Serial.print(micros()); Serial.println(" bSetBitMaps"); 
setBitMaps(cycle, 1); 
//Serial.print(micros()); Serial.println(" aSetBitMaps"); 

lngLast = micros(); 
myloop(); 
delayMicroseconds(50); 
turnoff(); 





//Serial.print(micros()); Serial.println(" aMyloop"); 



} 



} 

void turnoff() { 
PORTD &= ~_BV(PORTD2); 

ShiftOut(B00000000); 
ShiftOut(B00000000); 
ShiftOut(B00000000); 
ShiftOut(B00000000); 
ShiftOut(B00000000); 

PORTD |= _BV(PORTD2);//LatchPin 
} 

void setBitMaps(byte cycle, byte pos) { 
//Register 1 
for (byte intLayerSel = 0; intLayerSel < 100; intLayerSel += 10){   

byte _byte = 0; 
for (byte i = intLayerSel; i < intLayerSel + 8; i++) { 
    if (cycle == 1 && (leds[i].getR() & (1 << pos - 1)) != 0) { 
    _byte = _byte << 1; 
    _byte = _byte + B00000001; 
    } 
    else if ((cycle == 2 || cycle == 3) && (leds[i].getR() & (1 << pos)) != 0) { 
    _byte = _byte << 1; 
    _byte = _byte + B00000001; 
    } 
    else if (cycle >= 4 && cycle <= 7 && (leds[i].getR() & (1 << pos + 1)) != 0) { 
    _byte = _byte << 1; 
    _byte = _byte + B00000001; 
    } 
    else if (cycle >= 8 && cycle <= 15 && (leds[i].getR() & (1 << pos + 2)) != 0) { 
    _byte = _byte << 1; 
    _byte = _byte + B00000001; 
    } 
    else { 
    _byte = _byte << 1; 
    _byte = _byte + B00000000; 
    } 
} 
BitMapR1[intLayerSel/10] = _byte; 
} 
for (byte intLayerSel = 0; intLayerSel < 100; intLayerSel += 10) { 

byte _byte = 0; 
for (byte i = intLayerSel + 8; i < intLayerSel + 10; i++) { 
    if (cycle == 1 && (leds[i].getR() & (1 << pos - 1)) != 0) { 
    _byte = _byte << 1; 
    _byte = _byte + B00000001; 
    } 
    else if ((cycle == 2 || cycle == 3) && (leds[i].getR() & (1 << pos)) != 0) { 
    _byte = _byte << 1; 
    _byte = _byte + B00000001; 
    } 
    else if (cycle >= 4 && cycle <= 7 && (leds[i].getR() & (1 << pos + 1)) != 0) { 
    _byte = _byte << 1; 
    _byte = _byte + B00000001; 
    } 
    else if (cycle >= 8 && cycle <= 15 && (leds[i].getR() & (1 << pos + 2)) != 0) { 
    _byte = _byte << 1; 
    _byte = _byte + B00000001; 
    } 
    else { 
    _byte = _byte << 1; 
    _byte = _byte + B00000000; 
    } 
} 
for (byte i = intLayerSel; i < intLayerSel + 6; i++) { 
    if (cycle == 1 && (leds[i].getG() & (1 << pos - 1)) != 0) { 
    _byte = _byte << 1; 
    _byte = _byte + B00000001; 
    } 
    else if ((cycle == 2 || cycle == 3) && (leds[i].getG() & (1 << pos)) != 0) { 
    _byte = _byte << 1; 
    _byte = _byte + B00000001; 
    } 
    else if (cycle >= 4 && cycle <= 7 && (leds[i].getG() & (1 << pos + 1)) != 0) { 
    _byte = _byte << 1; 
    _byte = _byte + B00000001; 
    } 
    else if (cycle >= 8 && cycle <= 15 && (leds[i].getG() & (1 << pos + 2)) != 0) { 
    _byte = _byte << 1; 
    _byte = _byte + B00000001; 
    } 
    else { 
    _byte = _byte << 1; 
    _byte = _byte + B00000000; 
    } 
} 
BitMapR2[intLayerSel/10] = _byte; 
} 
} 



void myloop() { 

byte bLayerA; 
byte bLayerB; 



for (byte bLayerTop = 1; bLayerTop <= 10; bLayerTop++) { 
//Serial.print(micros()); Serial.println(" startML"); 
bLayerA = B00000000; 
bLayerB = B00000000; 
switch (bLayerTop) { 
    case 1: 
    bLayerA = B10000000; 
    break; 
    case 2: 
    bLayerA = B01000000; 
    break; 
    case 3: 
    bLayerA = B00100000; 
    break; 
    case 4: 
    bLayerA = B00010000; 
    break; 
    case 5: 
    bLayerA = B00001000; 
    break; 
    case 6: 
    bLayerA = B00000100; 
    break; 
    case 7: 
    bLayerA = B00000010; 
    break; 
    case 8: 
    bLayerA = B00000001; 
    break; 
    case 9: 
    bLayerB = B00000010; 
    break; 
    case 10: 
    bLayerB = B00000001; 
    break; 

    } 
/* 
    if (bLayerTop == 1) { 
    bLayerA = B10000000; 
    } else if (bLayerTop == 2) { 
    bLayerA = B01000000; 
    } else if (bLayerTop == 3) { 
    bLayerA = B00100000; 
    } else if (bLayerTop == 4) { 
    bLayerA = B00010000; 
    } else if (bLayerTop == 5) { 
    bLayerA = B00001000; 
    } else if (bLayerTop == 6) { 
    bLayerA = B00000100; 
    } else if (bLayerTop == 7) { 
    bLayerA = B00000010; 
    } else if (bLayerTop == 8) { 
    bLayerA = B00000001; 
    } else if (bLayerTop == 9) { 
    bLayerB = B00000010; 
    } else if (bLayerTop == 10) { 
    bLayerB = B00000001; 
    } 
*/ 


//Serial.print(micros()); Serial.println(" bWait"); 
while (micros() - lngLast < 50) { 
    //Serial.println("call"); 
} 
//Serial.print(micros()); Serial.println(" aWait"); 
turnoff(); 

PORTD &= ~_BV(PORTD2); //Latch LOW 
//OutPut Enable = False 
PORTD |= _BV(PORTD5); 

byte bLayer = bLayerTop - 1; 
ShiftOut(bLayerA);      //Register 5 
ShiftOut(bLayerB + BitMapR4[bLayer]); //Register 4 
ShiftOut(BitMapR3[bLayer]);   //Register 3 
ShiftOut(BitMapR2[bLayer]);   //Register 2 
ShiftOut(BitMapR1[bLayer]);   //Register 1 

//take the latch pin high so the LEDs will light up: 

PORTD |= _BV(PORTD2);//Latch High 
//OutPut Enable = True 
PORTD &= ~_BV(PORTD5); 
// pause before next value: 

//delay(1); 
//delayMicroseconds(100); 
// Serial.print(micros()); Serial.println(" end"); 
lngLast = micros(); 

} 

} 

void ShiftOut(byte myDataOut) { 
// This shifts 8 bits out MSB first, 
//on the rising edge of the clock, 
//clock idles low 

//internal function setup 
byte i = 0; 

//clear everything out just in case to 
//prepare shift register for bit shifting 
PORTD &= ~_BV(PORTD3);//Data off 
PORTD &= ~_BV(PORTD4);//Clock off 

//for each bit in the byte myDataOutï 
//NOTICE THAT WE ARE COUNTING DOWN in our for loop 
//This means that %00000001 or "1" will go through such 
//that it will be pin Q0 that lights. 
for (i = 0; i <= 7; i++) { 
PORTD &= ~_BV(PORTD4);//Clock aus 

//if the value passed to myDataOut and a bitmask result 
// true then... so if we are at i=6 and our value is 
// %11010100 it would the code compares it to %01000000 
// and proceeds to set pinState to 1. 


/* 
    //00001010 - 00000010 = true 
    switch (myDataOut & (1 << i)) { 
     case 0: 
     Serial.println("0"); 
     PORTD &= ~_BV(PORTD3);//Data aus 
     break; 
     case 1: //case true 
     Serial.println("1"); 
     PORTD |= _BV(PORTD3);//Data an 

     break; 
    } 
*/ 

/* 
    digitalWrite(3, myDataOut & (1 << i)); 
*/ 


if (myDataOut & (1 << i)) { 
    PORTD |= _BV(PORTD3);//Data an 
} else { 
    PORTD &= ~_BV(PORTD3);//Data aus 
} 

//register shifts bits on upstroke of clock pin 
PORTD |= _BV(PORTD4);//Clock an 
//zero the data pin after shift to prevent bleed through 
PORTD &= ~_BV(PORTD3);//Data aus 
} 
} 

ответ

1

Есть много вопросов, например:

leds[0] = CRGB(36, 0, 0); 

Это значит:

  • параметры копирования в стек
  • вызов функции CRBG
  • создают местный светодиодный объект
  • Множество Л на этом локальном объекте с помощью вызова Constraint
  • SETG ...
  • SETB ...
  • возвращение экземпляра местного объекта
  • копировальный оператор-оператор на светодиодах [0]

Также использование переменных ширины 8b для цветов 12b немного избыточно. Так что для начала я бы рекомендовал что-то вроде этого:

class LED { 
    public: 
    uint16_t rgb; 

    LED(uint8_t r=0, uint8_t g=0, uint8_t b=0) { 
     setRGB(r,g,b); 
    } 

    void setRGB(uint8_t r=0, uint8_t g=0, uint8_t b=0) { 
     r = r >> 4; 
     g = g&0xF0; 
     rgb = b&0xF0; 
     rgb = (rgb<<4) | g | r; 
    } 

    bool getBit(uint16_t mask) { 
     return rgb & mask; 
    } 
}; 

LED leds[100]; 

void setup() { 
    pinMode(2, OUTPUT); 
    pinMode(4, OUTPUT); 
    pinMode(3, OUTPUT); 
    pinMode(5, OUTPUT); 
    Serial.begin(250000); 
} 

void loop() { 
    leds[0].setRGB(36, 0, 0); 
    leds[1].setRGB(103, 0, 0); 
    leds[2].setRGB(170, 0, 0); 
    leds[3].setRGB(255, 0, 0); 
    leds[4].setRGB(255, 0, 0); 
    leds[5].setRGB(170, 0, 0); 
    leds[6].setRGB(103, 0, 0); 
    leds[7].setRGB(36, 0, 0); 
    leds[8].setRGB(0, 0, 0); 
    leds[9].setRGB(0, 0, 0); 
    leds[10].setRGB(36, 0, 0); 
    leds[11].setRGB(103, 0, 0); 
    leds[12].setRGB(170, 0, 0); 
    leds[13].setRGB(255, 0, 0); 
    leds[14].setRGB(255, 0, 0); 
    leds[15].setRGB(170, 0, 0); 
    leds[16].setRGB(103, 0, 0); 
    leds[17].setRGB(36, 0, 0); 
    leds[18].setRGB(0, 0, 0); 
    leds[19].setRGB(0, 0, 0); 
    leds[20].setRGB(36, 0, 0); 
    leds[21].setRGB(103, 0, 0); 
    leds[22].setRGB(170, 0, 0); 
    leds[23].setRGB(255, 0, 0); 
    leds[24].setRGB(255, 0, 0); 
    leds[25].setRGB(170, 0, 0); 
    leds[26].setRGB(103, 0, 0); 
    leds[27].setRGB(36, 0, 0); 
    leds[28].setRGB(0, 0, 0); 
    leds[29].setRGB(0, 0, 0); 
    leds[30].setRGB(36, 0, 0); 
    leds[31].setRGB(103, 0, 0); 
    leds[32].setRGB(170, 0, 0); 
    leds[33].setRGB(255, 0, 0); 
    leds[34].setRGB(255, 0, 0); 
    leds[35].setRGB(170, 0, 0); 
    leds[36].setRGB(103, 0, 0); 
    leds[37].setRGB(36, 0, 0); 
    leds[38].setRGB(0, 0, 0); 
    leds[39].setRGB(0, 0, 0); 
    leds[40].setRGB(36, 0, 0); 
    leds[41].setRGB(103, 0, 0); 
    leds[42].setRGB(170, 0, 0); 
    leds[43].setRGB(255, 0, 0); 
    leds[44].setRGB(255, 0, 0); 
    leds[45].setRGB(170, 0, 0); 
    leds[46].setRGB(103, 0, 0); 
    leds[47].setRGB(36, 0, 0); 
    leds[48].setRGB(0, 0, 0); 
    leds[49].setRGB(0, 0, 0); 
    leds[50].setRGB(36, 0, 0); 
    leds[51].setRGB(103, 0, 0); 
    leds[52].setRGB(170, 0, 0); 
    leds[53].setRGB(255, 0, 0); 
    leds[54].setRGB(255, 0, 0); 
    leds[55].setRGB(170, 0, 0); 
    leds[56].setRGB(103, 0, 0); 
    leds[57].setRGB(36, 0, 0); 
    leds[58].setRGB(0, 0, 0); 
    leds[59].setRGB(0, 0, 0); 
    leds[60].setRGB(36, 0, 0); 
    leds[61].setRGB(103, 0, 0); 
    leds[62].setRGB(170, 0, 0); 
    leds[63].setRGB(255, 0, 0); 
    leds[64].setRGB(255, 0, 0); 
    leds[65].setRGB(170, 0, 0); 
    leds[66].setRGB(103, 0, 0); 
    leds[67].setRGB(36, 0, 0); 
    leds[68].setRGB(0, 0, 0); 
    leds[69].setRGB(0, 0, 0); 
    leds[70].setRGB(36, 0, 0); 
    leds[71].setRGB(103, 0, 0); 
    leds[72].setRGB(170, 0, 0); 
    leds[73].setRGB(255, 0, 0); 
    leds[74].setRGB(255, 0, 0); 
    leds[75].setRGB(170, 0, 0); 
    leds[76].setRGB(103, 0, 0); 
    leds[77].setRGB(36, 0, 0); 
    leds[78].setRGB(0, 0, 0); 
    leds[79].setRGB(0, 0, 0); 
    leds[80].setRGB(36, 0, 0); 
    leds[81].setRGB(103, 0, 0); 
    leds[82].setRGB(170, 0, 0); 
    leds[83].setRGB(255, 0, 0); 
    leds[84].setRGB(255, 0, 0); 
    leds[85].setRGB(170, 0, 0); 
    leds[86].setRGB(103, 0, 0); 
    leds[87].setRGB(36, 0, 0); 
    leds[88].setRGB(0, 0, 0); 
    leds[89].setRGB(0, 0, 0); 
    leds[90].setRGB(36, 0, 0); 
    leds[91].setRGB(103, 0, 0); 
    leds[92].setRGB(170, 0, 0); 
    leds[93].setRGB(255, 0, 0); 
    leds[94].setRGB(255, 0, 0); 
    leds[95].setRGB(170, 0, 0); 
    leds[96].setRGB(103, 0, 0); 
    leds[97].setRGB(36, 0, 0); 
    leds[98].setRGB(0, 0, 0); 
    leds[99].setRGB(255, 255, 255); 


// show context 
    for (uint16_t bitmask = 1U; bitmask < 0x400; bitmask <<= 1) { 
    for (LED & led : leds) { 
     Serial.print(led.getBit(bitmask), HEX); 
     Serial.print(" "); 
    } 
    Serial.println(); 
    } 

    do_cycle(); 
} 

void do_cycle() { 
    uint16_t bitmask_r = 0; 
    uint16_t bitmask_g = 0; 
    uint16_t bitmask_b = 0; 

    for (byte mag = 1; mag < 16; ++mag) { // magnitude 
    for (byte row = 0; row < 10; ++row) { // mistake #2 
     //uint32_t us = micros(); 

     if ((mag & (mag-1)) == 0) { // Is it power of two? Change bitmask 
     bitmask_r = mag; 
     bitmask_g = bitmask_r << 4; 
     bitmask_b = bitmask_g << 4; 
     } 

     // shift out init: 
     PORTD &= ~_BV(PD3); //Data aus 
     PORTD &= ~_BV(PD4); //Clock aus 

     for (int8_t cnt = 9; cnt >= 0; --cnt) { 
     //Serial.print(cnt==row?1:0); 
     shift1bit(cnt==row); // mistake #1 
     } 
     for (int8_t col = 9; col >= 0; --col) { 
     //Serial.print(leds[row*10+col].getBit(bitmask_b)); 
     shift1bit(leds[row*10+col].getBit(bitmask_b)); 
     } 
     for (int8_t col = 9; col >= 0; --col) { 
     //Serial.print(leds[row*10+col].getBit(bitmask_g)); 
     shift1bit(leds[row*10+col].getBit(bitmask_g)); 
     } 
     for (int8_t col = 9; col >= 0; --col) { 
     //Serial.print(leds[row*10+col].getBit(bitmask_r)); 
     shift1bit(leds[row*10+col].getBit(bitmask_r)); 
     } 
     PORTD |= _BV(PD2); // LatchPin 
     PORTD &= ~_BV(PD2); // disable LatchPin 

     //Serial.println(micros()-us); 
     delayMicroseconds(50); 
    } 
    } 
} 

inline void shift1bit (bool b) { 
    // set data: 
    if (b) { 
    PORTD |= _BV(PD3); 
    } else { 
    PORTD &= ~_BV(PD3); 
    } 
    // clock pulse: 
    PORTD |= _BV(PD4); 
    PORTD &= ~_BV(PD4); 
} 

И вы можете рассмотреть следующие вопросы:

  • Использование HW SPI
  • Используя /MR вход, чтобы очистить все регистры одного импульса (намного быстрее, чем shiftOut)
  • Использование счетчика Johnson (4017) для драйверов строк и сохранения один сдвиговый регистр (также буфер вписывается в один uint32_t).С предыдущим вы можете использовать Q7S выход и MSB, установленный в логическую 1 для обновления счетчика.
+0

Вы уверены, что цвет 12-бит не 24-бит? – putu

+0

@IPutuSusila Согласно _LED.setR ('constrain (_R/16, 0, 15)'); да, я уверен, – KIIV

+0

Я вижу, не замечал этого ( – putu

Смежные вопросы