酒と薔薇の日々(その2)

好きなことだけ求めて生きるアスペ気味のINTJ人

Aliex OLED SSD1306 128*32)のテスト

2023年10月20日 14時50分18秒 | マイコン(ESP32・Arduino等)

先日到着したAliExからのパッケージ中、OLEDをテスト 161円

0.91 inch OLED module 128*32 IIC通信版 青
ピンヘッダは最初からハンダ付けされていた。

I2C通信アドレスは「0x3C」だが「0x3D」に変更も可能(参考サイト2

制御が「SSD1306」というチップで成されているようで、このドライバをAdafruitから入手する。
動作電源は3.3Vで通信も3.3Vベース
なので本来はレベル変換が必要らしいのだが、ネット記事では直結してる・・・

ちなみに「adafruit」は「エイダフルーツ」で、由来は計算機の始祖「Ada」さんだそうです。

ライブラリを「SSD1306」で検索
①Adafruitの名前を冠したものをインストール
関連するライブラリを入れるか聞いてくるので②「全てをインストール」する。

サンプルから「Adafruit SSD1306」「ssd1306_128x32_i2c」を選ぶ。

配線は3.3V,GND、SDAはA4ピン、SCK(SCL)はA5ピンへ。
(SCLとSCKは同じ意味でクロック線を意味する。)

前回の128*64のOLEDは表示がバッグっていたが、今回は無問題です。
あっさりと動いてる。
前回のアズリ方を考えると、なんか拍子抜け。  

参考サイト(基本)    参考サイト2(文字表示詳細・ATOM例) 参考サイト3

本日朝からダルいし喉は痛いし、鼻血が出るし・・・ボラ休みます。

サンプル・ソースを読んでおまとめしてみた。
参考サイト2 display.drawFastHLine(x, y, 長さ, 色); で、水平垂直線が引けるそうです。

#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library. 
// On an arduino UNO:       A4(SDA), A5(SCL)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {

  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {   // デバイス確認
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  display.display();
  display.clearDisplay();

  display.drawPixel(10, 10, SSD1306_WHITE);  // 画面バッファに点を打つ
  display.display(); // 表示

  testdrawchar();      // 標準フォントで文字表示
     :
     :
}

void loop() {
}

===========各サブルーチンから抜粋==============
//  文字描画(標準フォント)
    display.setTextSize(1);      // Normal 1:1 pixel scale
    display.setTextColor(SSD1306_WHITE); // Draw white text
    display.setCursor(0, 0);     // Start at top-left corner
    display.cp437(true);         // Use full 256 char 'Code Page 437' font
    // 全てのキャラクタ表示
    for(int16_t i=0; i<256; i++) {
      if(i == '\n') display.write(' ');
      else   display.write(i);
  }
//  装飾文字表示
  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.setCursor(0,0);             // Start at top-left corner
  display.println(F("Hello, world!"));

  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // 文字反転
  display.println(3.141592);

  display.setTextSize(2);             // 2倍体
  display.setTextColor(SSD1306_WHITE);
  display.print(F("0x")); display.println(0xDEADBEEF, HEX);

// スクロール
  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 0);
  display.println(F("scroll"));

  display.startscrollright(0x00, 0x0F);         delay(2000);
  display.stopscroll();                                  delay(1000);
  display.startscrollleft(0x00, 0x0F);            delay(2000);
  display.stopscroll();                                   delay(1000);
  display.startscrolldiagright(0x00, 0x07);  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);    delay(2000);
  display.stopscroll();                                  delay(1000);

// 線を引く
    display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
    // display.width()

// 矩形(Fill)  
    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
    display.fillRect    (i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);

// 円(Fill)
    display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
    display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);

// 角丸矩形(Fill)
    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,display.height()/4, SSD1306_WHITE);
    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,display.height()/4, SSD1306_INVERSE);

// 三角形(Filll)
    display.drawTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
    display.fillTriangle(・・・);

// BitMap描画
  #define LOGO_HEIGHT   16
  #define LOGO_WIDTH    16
  static const unsigned char PROGMEM logo_bmp[] =
  { 0b00000000, 0b11000000,
    0b00000001, 0b11000000,
        : 
   0b00000000, 0b00110000 };
   ------
  display.clearDisplay();
  display.drawBitmap(
    (display.width()  - LOGO_WIDTH ) / 2,
    (display.height() - LOGO_HEIGHT) / 2,
    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.display();

// bitmapアニメーション
  icons[][]の二次元配列に位置情報を生成し、
  icons[][]に沿ってdrowbitmapし、
 1画面完成したらdisplay.display();している
  底づきしたら新たな場所を生成しているようです。

 


Aliex シリアルLED(WS2812B)のテスト

2023年10月20日 10時23分16秒 | マイコン(ESP32・Arduino等)

先日到着したAliExからのパッケージ中、シリアルLED8連を試験 (1本50円)

ポイント
 ソース内デバイス名の指定は NEO_GRB + NEO_KHZ800 を記述する。(WS2812Bの場合)
 明るさセット:pixels.setBrightness(x);  // 0..255 255を超えると0にリセットされるようです
 明るさ取得: Serial.println(pixels.getBrightness());
注意点:
 パネルにはデータが進む向きがあって、DI(DataIn)へarduinoのデータピンを繋ぎます。

 DO(DataOut)ではないよ。

パネルには直接Pinをハンダ付けした。
高さと水平整合性をちゃんと取ってからハンダ付けします。これ重要
パネルには予め予備ハンダされているのかすんなりハンダが乗る。

上記写真は電源ラインを別系統から取っています。
ArduinoからはGNDと信号線を与えます。GNDとは電源と共通にする。
8*8マトリックス全部を一斉に白点灯すると12.6mAが流れるそう。
今回の8個程度では3mA以下のはずなので無問題と思う。
電源や回路詳細は  マルツオンラインからの情報

流れるLEDのサンプルソースはこちらからいただきました。
かなり明るいので電流オーバーになりそうで怖かったけどそうでもないようだ。
このLEDは鮮やかで明るいですね。
delayが100ms入ってると流れるようだが、0にすると全白表示となる。
手持ちならバーサライタもできそうです。

本日夕方からボラなので持って行って見せたくなってきた。

取り敢えず動きましたが、ちょっとひと悶着あったのでした。
サンプルはページの最後に

GitHubにあった関数リファレンス

NeoPixcelsのGitHubから
ライブラリの機能一覧
Functions
    begin()
    updateLength()
    updateType()
    show()
    delay_ns()
    setPin()
    setPixelColor()
    fill()
    ColorHSV()
    getPixelColor()
    setBrightness()    0..255
    getBrightness()
    clear()
    gamma32()

----経過-----

実は昨晩ハンダ付けしたのだが頭と目が悪いので、DOutにデータ線を結んでしまっていた。
うんともすんとも言わない状態になってた。
あまりにもおかしいので、つまらんミスがあるんだと一晩寝ることにした。

やはり夜明けにデジタル神様が降臨し「これこれ、データを流す向きが間違ってないのか?」と。
昨晩参照したサイトの「結線した場所が一番最初に光るLED」という記述を誤解してたことに夢うつつで気がついた。
( °o°)ハッ
シリアル通信で1個ごとにデータを取り去り、次のLEDに伝えるには入と出があるはずだし、
LEDのチップ中のマイコンも、入力ラインをInputモードにして待ち続けるわけだから、
逆のDOutに接続してしまえば制御データを読めるはずもない。
ボードをよく見ると確かに「DO」「DI」の2種類の印刷が・・
馬鹿ですね。

実は昨晩からシリアルLEDを点ける前哨戦で、まずはArduino「Wokui」エミュでやってみた。
これは別記事で。

//--------赤1個だけ点灯----------------------

#include "Adafruit_NeoPixel.h"
const int DIN_PIN = 11; // D11
const int LED_COUNT = 8; // LEDの数

Adafruit_NeoPixel pixels(LED_COUNT, DIN_PIN, NEO_GRB + NEO_KHZ800);  // 赤文字は重要 このデバイス特有です。

void setup() {
  pixels.begin();
}

void loop() {
  pixels.clear();
  pixels.setPixelColor(0, pixels.Color(255, 0, 0)); // 0番目の色を赤に変える
  pixels.show();
}

=======流れる虹(走る火の玉)================

Arai様 パクらせていただきました。m(_ _)m

/*
  Created by Toshihiko Arai.
  https://101010.fun/iot/arduino-serial-led.html
*/

#include "Adafruit_NeoPixel.h"

const int DIN_PIN = 11; // D11
const int LED_COUNT = 8; // LEDの数

Adafruit_NeoPixel pixels(LED_COUNT, DIN_PIN, NEO_GRB + NEO_KHZ800);
/*
uint32_t red = pixels.Color(128, 0, 0);
uint32_t orange = pixels.Color(128, 82, 0);
uint32_t yellow = pixels.Color(128, 128, 0);
uint32_t green = pixels.Color(0, 128, 0);
uint32_t cyan = pixels.Color(0, 128, 128);
uint32_t blue = pixels.Color(0, 0, 128);
uint32_t purple = pixels.Color(128, 0, 128);
*/
uint32_t red       = pixels.Color(128,0,0);
uint32_t orange = pixels.Color( 64,0,0);
uint32_t yellow  = pixels.Color( 32,0,0);
uint32_t green   = pixels.Color(  0,0,0);
uint32_t cyan     = pixels.Color(  0,0,0);
uint32_t blue     = pixels.Color(  0,0,0);
uint32_t purple = pixels.Color(  0,0,0);

uint32_t rainbow_color[] = {red, orange, yellow, green, cyan, blue, purple};
int rainbow_index[] = {6, 5, 4, 3, 2, 1, 0};

void dsp_index(){
  for (int i=0;i<7; i++){
    Serial.print(rainbow_index[i]);Serial.write(' ');
  }
  Serial.println(' ');
  //delay(2000);
}

void clear_index(){
  for(int j = 0; j < 7; j++) {
      rainbow_index[j] = 0;
  }  
}

void setup() {
  pixels.begin();
  Serial.begin(9600);
  Serial.println("hello Neo Pixcel");
  pixels.setBrightness(20);
  delay(3000);
}

void loop() {
  for(int i = 0; i < LED_COUNT; i++) {    
    pixels.clear();    
    //Serial.println("-----start-----");
    for(int j = 0; j < 7; j++) {
      rainbow_index[j] = i + 6 - j;
      if(rainbow_index[j] >= LED_COUNT) rainbow_index[j] -= LED_COUNT;
      pixels.setPixelColor(rainbow_index[j], rainbow_color[j]);
      //dsp_index();
    }
    pixels.show();
    //Serial.println("result");
    //dsp_index();
    //clear_index();
    delay(50);
  }
}