0

5つのシフトレジスタと1つのarduinoマイクロを備えた10x10RGB(WS2811なし...、通常のもの)LEDマトリックスを構築しました。

私の問題は、私のコードが遅いように見えるか、16Mhz の arduino が適切な Hz レートを処理できないことです。現時点では、以下のコードを使用すると、ちらつきや遅延が発生します。約 60Hz-100Hz の Hz レートが非常に良いと思います。Arduino IDE Compiler の設定を -Os から -O3 に変更して速度を向上させました (実際に機能しました)。

このコードには、輝度制御用のビット角度変調と多重化機能があります。

私の質問:すべての可能な値 (10 個の値、int < 10 のみ) が事前定義されている配列を作成し、312 行目でそれらを使用する価値はありますか?

BitMapR1[intLayerSel / 10] = _byte;

インターネットを検索したところ、arduino(またはマイクロコントローラ)の除算が非常に遅いという記事がいくつか見つかりました。

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
}
}
4

1 に答える 1

1

次のような多くの問題があります。

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

これの意味は:

  • パラメータをスタックにコピーする
  • CRBG 関数を呼び出す
  • ローカル LED オブジェクトを作成する
  • 制約を呼び出してそのローカル オブジェクトに setR
  • セットG ...
  • セットB ...
  • ローカル オブジェクトのコピーを返す
  • led[0] のコピー代入演算子

また、12b カラーに 8b 幅の変数を使用するのは少し冗長です。したがって、最初は次のようなものをお勧めします。

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);
}

そして、あなたは考えることができます:

  • ハードウェアの使用SPI
  • 入力を使用/MRして、すべてのレジスタを 1 パルスでクリアします (shiftOut よりもはるかに高速です)。
  • 行ドライバーにジョンソン カウンター ( 4017) を使用し、シフト レジスタを 1 つ節約します (バッファーも 1 つに収まりますuint32_t)。前の例ではQ7S、論理 1 に設定された出力と MSB を使用してカウンタを更新できます。
于 2016-09-23T16:23:05.033 に答える