« アナデバの電力計用IC、arduinoで周波数(周期)を計る#2 | トップページ | 出窓に「跳ねるLED」 »

2021年1月21日 (木)

カラーLEDテープを手に入れた

出窓 の新アトラクションに
GitHub - KenKenMkIISR/Bouncing-LED: NeoPixel互換のLEDテープを利用したLEDが跳ねるアニメーション
はいかがかと(モータ駆動系のはうるさいんで)、カラーLEDテープを
手に入れてみました。

11_20210121101001
うまいこと光るもんですなぁ。

「シリアルLEDスティック」光らせてみた! ? スイッチサイエンス マガジン
   ※7年くらい前に遡れるようです。

制御ICの制御方法がなるほどです。
WS2812B の制御タイミングを見ますと、短パルスと長パルスで
データの0と1を表現。
RGBそれぞれ8ビットのデータをドバ~っとの連続送出。
そのタイミング、データシートにはけっこうキビシイ値が記されていますが、実際は・・・
といいますのが、この記事
NeoPixel(WS2812B)の制御: 猫にコ・ン・バ・ン・ワ (WS2812B)の制御をライブラリ無しで行ってみました。
NeoPixel(WS2812B)の制御 その2 SPIで

Adafruit_NeoPixelライブラリーを使わず、自前で出力ポートを直叩き。
そして、SPIでもってハード的にパルス列を出そうという試み。

自前で制御すれば、Arduinoから離れられます。
28ピンのATmega328Pを使わないでもっと小さいマイコンで制御できるわけ
です。
  ※表示用バッファにRAMが必要ですが、1メートル60LEDの
   ものだと、1LEDに3バイトで240バイトのバッファ。
   ATtiny85だと512バイトでなんとかなりそう。

ということで、制御波形を見てみました。

まず、これがAdafruit_NeoPixelライブラリーでの制御波形。
L002

これもI/O直叩きですが、Hパルス、Lパルスのパルス幅が仕様通りに
出ている感じです。

これが「猫にコ・ン・バ・ン・ワ」さんのI/O直叩き。
L001

Lレベル部分がずいぶん長くなっていますが、これでもちゃんと制御
されています。

そしてSPIでの制御。
SCKパルスといっしょに見ています。
L000

これもずいぶんLレベル部分が長い。

WS2812Bの制御、Hレベル部分の長短が重要でLレベル部が少々延びても
問題ないのかな?

昔のデータシートと新しいデータシートで値が変わっています。

W1
パルス列のデューティーで判断してるんじゃ「TH」のパルス幅で
0/1を見ているのかな?
T0L、T1Lとももっと長くしてもOKなようです。

※ATmega328pのSPIについて
SPIを使っての転送タイミングを見ていて・・・
 「送信後の待ちってこんなにかかるの?」
っと、疑問に思ったんでちょっとテストプログラムを
書いてみました。

まず、関連するI/Oポート

    PORTB = 0b00010011;     // data/pull up
DDRB = 0b00101100; // port in/out指定
// |||||+---- PB0 IO8 in -
// ||||+----- PB1 IO9 in -
// |||+------ PB2 IO10 out /SS (L)
// ||+------- PB3 IO11 out MOSI →★LED接続
// |+-------- PB4 IO12 in MISO (pull up)
// +--------- PB5 IO13 out SCK

そしてSPI回りのイニシャル。

    SPCR  = 0b01010100;
// ||||||++---- SPR fosc/2
// |||||+------ CPHA sck位相 SCH↑で出力確定
// ||||+------- CPOL sck極性 mode1
// |||+-------- MSTR 主装置で
// ||+--------- DODR MSBから出力
// |+---------- SPE SPI許可
// +----------- SPIE 割り込みなしで
SPSR = 0b00000001;
// || +---- SPI2X fosc/2で
// |+---------- WCOL
// +----------- SPIF SPI完了割り込みはなし

LEDデータバッファの転送ルーチン

void ledshow(void)
{
word i;
byte j;
byte d;
cli(); // 割り込み禁止
for(i = 0; i < (LED_N * 3); i++){ // LEDの数*G,R,B
d = led_bff[i];
for(j = 0; j < 8; j++){ // 8bit loop
if(d & 0x80) SPDR = LED_1; // H
else SPDR = LED_0; // L
d <<= 1; // MSBから出力
PD7_H; // (!!!)
while(!(SPSR & (1 << SPIF))); // SPI送信完了待ち
PD7_L; // (!!!)
}
}
sei(); // 割込許可
}

送信完了待ちのタイミング、D7ポートをH/Lして待ち時間を
見られるようにしています

その結果。
L004

SPI完了の待ち時間だけでなく8回loopの処理時間も
大きいようです。 (しかし、どうしようもない)
クロックパルスが8MHzですんで。
これが限界かな。
  ※D7ポートへのテストパルス、これのH/Lだけで
   2クロック+2クロック、0.25usかかっています。

「猫にコ・ン・バ・ン・ワ」さんのSPIでの描画ルーチンは
こんな具合。

void NeoUpdate() {
// ピクセル数x24ビット送信
for (uint8_t i = 0; i < PIXCELNUM*3; i++) {
for (uint8_t j = 0; j < 8; j++) {
SPDR = buf[i] & (0x80>>j) ? NEOSPI_1:NEOSPI_0; // SPIデータ送信
while(!(SPSR & (1 << SPIF))) ; // 送信完了待ち
}
}
}

8回ループ内にバッファメモリの読み出しと0x80のシフト操作が
入っています。
毎回これが実行されるので遅くなっているのでしょう。

自由にタイミングを作れる出力ポート直叩きのほうが
よさそうです。

|

« アナデバの電力計用IC、arduinoで周波数(周期)を計る#2 | トップページ | 出窓に「跳ねるLED」 »

出窓」カテゴリの記事

LED」カテゴリの記事

電子工作」カテゴリの記事

Arduino」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




« アナデバの電力計用IC、arduinoで周波数(周期)を計る#2 | トップページ | 出窓に「跳ねるLED」 »