« AM2301BのCRC | トップページ | まさお君とボーちゃんの遠足 »

2022年7月27日 (水)

M5Atom LITE/M5Stamp PICOのフルカラーシリアルLEDをライブラリなしで制御する

M5Atom LITE / M5Stamp PICOに付いている フルカラーシリアルLEDをライブラリなしで操作できたので、その方法です。
フルカラーシリアルLEDの仕様は▼のようにHIGH/LOWシグナルの長さで1Bitを表現、GRB各8ビット(計24Bit)を送信すれば色をせってできます。
仕様は単純ですが、問題は0.3μ秒の短いタイミングをどうやって計るかです。
M5Stampのライブラリを覗くと、アセンブリコードのループでタイミングをとっていました。

 

ArduinoIDEではタイマの最小単位は1μ秒なので、普通にやったのでは0.3μ秒は計れません。
ライブラリでやっているように無駄にループを回してタイミングをとるしかないのですが
コンパイラが無駄に賢くて、ループ内で値が変化しない、変化がループ外に波及しないコードは省略されてしまい、タイミング取りには使えません。
なので、最適化出来ない処理をループしてタイミングをとる必要があります。

Led

ArduinoUNOではシリアルLEDをSPI-MOSIに接続して、クロックを調整してタイミングを取る方法を編み出した人がいましたが
M5Atom LITE / M5Stamp PICOのシリアルLEDはSPIピンにはつながっていないのでこの方法は使えません。
そこで、digitalRead()にかかる時間でタイミングを取ってみました。
幸いな事にM5Atom LITE / M5Stamp PICOには読み取るのに丁度よいデバイス(ボタン)が付いています。
1000回繰り返して300μ秒±150μ秒に収まるようにdigitalRead()の回数を調整ます。
1000回で300μ秒なら1回あたり0.3μ秒だねって理屈です。

▼ 調整に使用したスケッチ


#define RGBPIN 27
#define BTNPIN 39
#define LEDPIN 25
int BTN = LOW ;

void setup() {
  Serial.begin(115200);
  while (!Serial) { delay(1);}

  pinMode(RGBPIN,OUTPUT) ;
  pinMode(LEDPIN,OUTPUT) ;
  pinMode(BTNPIN,INPUT) ;

  digitalWrite(RGBPIN,LOW) ;
  delayMicroseconds(80) ;

  Serial.println("--- STRAT");
  digitalWrite(LEDPIN,HIGH) ;

  unsigned long stratTime = micros( ) ;
  // -----
  for (int N=0;N<1000;N++) {
    digitalWrite(LEDPIN,HIGH) ;
    for (int L=0;L<3;L++) {
      BTN = digitalRead(BTNPIN);
    }
  }
  // -----
  unsigned long endTime = micros( ) - stratTime ;
  Serial.print("--- BIT 1 :");
  Serial.println(endTime);

  stratTime = micros( ) ;
  // -----
  for (int N=0;N<1000;N++) {
    digitalWrite(LEDPIN,HIGH) ;
      for (int L=0;L<2;L++) {
        BTN = digitalRead(BTNPIN);
      }
    }
  // -----
  endTime = micros( ) - stratTime ;
  Serial.print("--- BIT 0 HIGH :");
  Serial.println(endTime);

  stratTime = micros( ) ;
  // -----
  for (int N=0;N<1000;N++) {
  digitalWrite(LEDPIN,HIGH) ;
    for (int L=0;L<5;L++) {
      BTN = digitalRead(BTNPIN);
    }
  }
  // -----
  endTime = micros( ) - stratTime ;
  Serial.print("--- BIT 0 LOW :");
  Serial.println(endTime);

  Serial.println("--- END");
  digitalWrite(LEDPIN,LOW) ;
}

void loop() {
}


ボタン状態の読み込み回数で1.5μ秒間隔単位くらいの調整ができるので、0Bit、1Bitの時間調整を行います。
±1.5μ秒の余裕があるので、近い値に寄せれば大丈夫です。 ※実際にはもうちょっと余裕があるっぽい。
で、digitalRead()でタイミングを取ってビットデータを送信するスケッチが▼


#define RGBPIN 27
#define BTNPIN 39
int BTN = LOW ;

void sendBitData(uint32_t bitData) {
  for (uint32_t sendBit = 0x00800000;sendBit!=0;sendBit>>=1) {
    if ((bitData & sendBit) == 0 ) {
      digitalWrite(RGBPIN,HIGH);
      for (int L=0;L<2;L++) {
        BTN = digitalRead(BTNPIN);
      }
      digitalWrite(RGBPIN,LOW);
      for (int L=0;L<5;L++) {
        BTN = digitalRead(BTNPIN);
      }
    } else {
      digitalWrite(RGBPIN,HIGH);
      for (int L=0;L<3;L++) {
        BTN = digitalRead(BTNPIN);
      }
      digitalWrite(RGBPIN,LOW);
      for (int L=0;L<3;L++) {
        BTN = digitalRead(BTNPIN);
      }
    }
  }
}

void setup() {
  pinMode(RGBPIN,OUTPUT) ;
  pinMode(BTNPIN,INPUT) ;
  digitalWrite(RGBPIN,LOW);
  delayMicroseconds(80) ;
}

void loop() {
  sendBitData(0x00FF0000) ;
  delay(500) ;
  sendBitData(0x0000FF00) ;
  delay(500) ;
  sendBitData(0x000000FF) ;
  delay(500) ;
}


PicoledAtomled

|

« AM2301BのCRC | トップページ | まさお君とボーちゃんの遠足 »

arduino」カテゴリの記事

コメント

この記事へのコメントは終了しました。