วันเสาร์ที่ 28 ตุลาคม พ.ศ. 2560

NodeMCU ESP8266 แสดงผลบน OLED LCD 128x64

   วันนี้ผมก็จะพาเล่น NodeMCU ESP8266 ทำให้มันแสดงผลออกจอภาพนะครับ เป็นจอแสดงผลแบบ OLED LCD สำหรับ Arduino หน้าจอ 128x64 ขนาด 0.96" เชื่อมต่อแบบ IIC ใช้ไฟได้ทั้ง 3.3V หรือ 5V ให้จอสว่างแสดงผลมองเห็นได้อย่างชัดเจน และประหยัดไฟ สามารถวาดภาพกราฟฟิกส์เป็นรูปต่าง ๆ หรือทำเป็นเมนูตามแบบที่ต้องการได้



     ESP8266 เป็นชื่อเรียกของชิฟของโมดูล ESP8266 สำหรับติดต่อสื่อสารบนมาตรฐาน WiFi ทำงานที่แรงดันไฟฟ้า 3.0-3.6V ทำงานใช้กระแสโดยเฉลี่ย 80mA รองรับคำสั่ง deep sleep ในการประหยัดพลังงาน ใช้กระแสน้อยกว่า 10 ไมโครแอมป์ สามารถ wake up กลับมาส่งข้อมูลใช้เวลาน้อยกกว่า 2 มิลลิวินาที ภายในมี Low power MCU 32bit ทำให้เราเขียนโปรแกรมสั่งงานได้ มีวงจร analog digital converter ทำให้สามารถอ่านค่าจาก analog ได้ความละเอียด 10bit ทำงานได้ที่อุณหภูมิ -40 ถึง 125 องศาเซลเซียส


 จอแสดงผลแบบ OLED (Organic Light Emitting Diodes) คือจอภาพที่มีลักษณะคล้ายแผ่นฟิล์ม ซึ่งมีส่วนประกอบเป็นสารอินทรีย์ที่สามารถเปล่งแสงเองได้เมื่อได้รับพลังงาน ไฟฟ้า เรียกว่ากระบวนการอิเล็คโทรลูมิเนเซนส์ (Electroluminescence) โดยที่ไม่ต้องพึ่งพาแสง Backlight และจะไม่มีการเปล่งแสดงในบริเวณที่เป็นภาพสีดำ ส่งผลให้สีดำนั้นดำสนิท อีกทั้งยังช่วยพลังงานอีกด้วย

 ก่อนอื่นเราก็มาต่อวงจรกันก่อนนะครับ
สาย VCC ของ OLED ต่อเข้า 3.3v. ของบอร์ด NodeMCU ESP8266
สาย GND ของ OLED ต่อเข้า GND ของบอร์ด NodeMCU ESP8266
สาย SCL ของ OLED ต่อเข้า D2 ของบอร์ด NodeMCU ESP8266
สาย SDA ของ OLED ต่อเข้า D1 ของบอร์ด NodeMCU ESP8266
ตามรูปด้านล่างนี้

ส่วนโค๊ดก็ก๊อปปีด้านล่างนี้เลยครับ


#include <Wire.h>
#include <Adafruit_GFX.h>
#include <ESP_Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2


#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH  16
static const unsigned char logo16_glcd_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup()   {             
  Serial.begin(9600);

  display.begin(SSD1306_SWITCHCAPVCC, 0x78>>1);

  display.display();
  delay(2000);

  display.clearDisplay();

  display.drawPixel(10, 10, WHITE);

  display.display();
  delay(2000);
  display.clearDisplay();

  testdrawline();
  display.display();
  delay(2000);
  display.clearDisplay();

  testdrawrect();
  display.display();
  delay(2000);
  display.clearDisplay();

  testfillrect();
  display.display();
  delay(2000);
  display.clearDisplay();

  testdrawcircle();
  display.display();
  delay(2000);
  display.clearDisplay();

  display.fillCircle(display.width()/2, display.height()/2, 10, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  testdrawroundrect();
  delay(2000);
  display.clearDisplay();

  testfillroundrect();
  delay(2000);
  display.clearDisplay();

  testdrawtriangle();
  delay(2000);
  display.clearDisplay();
 
  testfilltriangle();
  delay(2000);
  display.clearDisplay();

  testdrawchar();
  display.display();
  delay(2000);
  display.clearDisplay();

  testscrolltext();
  delay(2000);
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Hello, world!");
  display.setTextColor(BLACK, WHITE);
  display.println(3.141592);
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.print("0x"); display.println(0xDEADBEEF, HEX);
  display.display();
  delay(2000);

  display.clearDisplay();
  display.drawBitmap(30, 16,  logo16_glcd_bmp, 16, 16, 1);
  display.display();

  display.invertDisplay(true);
  delay(1000);
  display.invertDisplay(false);
  delay(1000);

  testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH);
}


void loop() {

}


void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  uint8_t icons[NUMFLAKES][3];

  // initialize
  for (uint8_t f=0; f< NUMFLAKES; f++) {
    icons[f][XPOS] = random(display.width());
    icons[f][YPOS] = 0;
    icons[f][DELTAY] = random(5) + 1;
 
    Serial.print("x: ");
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(" y: ");
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(" dy: ");
    Serial.println(icons[f][DELTAY], DEC);
  }

  while (1) {
    for (uint8_t f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo16_glcd_bmp, w, h, WHITE);
    }
    display.display();
    delay(200);

    for (uint8_t f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS],  logo16_glcd_bmp, w, h, BLACK);
      icons[f][YPOS] += icons[f][DELTAY];
      if (icons[f][YPOS] > display.height()) {
  icons[f][XPOS] = random(display.width());
  icons[f][YPOS] = 0;
  icons[f][DELTAY] = random(5) + 1;
      }
    }
   }
}


void testdrawchar(void) {
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);

  for (uint8_t i=0; i < 168; i++) {
    if (i == '\n') continue;
    display.write(i);
    if ((i > 0) && (i % 21 == 0))
      display.println();
  } 
  display.display();
}

void testdrawcircle(void) {
  for (int16_t i=0; i<display.height(); i+=2) {
    display.drawCircle(display.width()/2, display.height()/2, i, WHITE);
    display.display();
  }
}

void testfillrect(void) {
  uint8_t color = 1;
  for (int16_t i=0; i<display.height()/2; i+=3) {
    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, color%2);
    display.display();
    color++;
  }
}

void testdrawtriangle(void) {
  for (int16_t i=0; i<min(display.width(),display.height())/2; i+=5) {
    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, WHITE);
    display.display();
  }
}

void testfilltriangle(void) {
  uint8_t color = WHITE;
  for (int16_t i=min(display.width(),display.height())/2; i>0; i-=5) {
    display.fillTriangle(display.width()/2, display.height()/2-i,
                     display.width()/2-i, display.height()/2+i,
                     display.width()/2+i, display.height()/2+i, WHITE);
    if (color == WHITE) color = BLACK;
    else color = WHITE;
    display.display();
  }
}

void testdrawroundrect(void) {
  for (int16_t i=0; i<display.height()/2-2; i+=2) {
    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, WHITE);
    display.display();
  }
}

void testfillroundrect(void) {
  uint8_t color = WHITE;
  for (int16_t i=0; i<display.height()/2-2; i+=2) {
    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i, display.height()/4, color);
    if (color == WHITE) color = BLACK;
    else color = WHITE;
    display.display();
  }
}
 
void testdrawrect(void) {
  for (int16_t i=0; i<display.height()/2; i+=2) {
    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, WHITE);
    display.display();
  }
}

void testdrawline() {
  for (int16_t i=0; i<display.width(); i+=4) {
    display.drawLine(0, 0, i, display.height()-1, WHITE);
    display.display();
  }
  for (int16_t i=0; i<display.height(); i+=4) {
    display.drawLine(0, 0, display.width()-1, i, WHITE);
    display.display();
  }
  delay(250);

  display.clearDisplay();
  for (int16_t i=0; i<display.width(); i+=4) {
    display.drawLine(0, display.height()-1, i, 0, WHITE);
    display.display();
  }
  for (int16_t i=display.height()-1; i>=0; i-=4) {
    display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
    display.display();
  }
  delay(250);

  display.clearDisplay();
  for (int16_t i=display.width()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
    display.display();
  }
  for (int16_t i=display.height()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
    display.display();
  }
  delay(250);

  display.clearDisplay();
  for (int16_t i=0; i<display.height(); i+=4) {
    display.drawLine(display.width()-1, 0, 0, i, WHITE);
    display.display();
  }
  for (int16_t i=0; i<display.width(); i+=4) {
    display.drawLine(display.width()-1, 0, i, display.height()-1, WHITE);
    display.display();
  }
  delay(250);
}

void testscrolltext(void) {
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(10,0);
  display.clearDisplay();
  display.println("Poradech Surinta");
  display.display();

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

}
//==============================

<iframe allowfullscreen="" frameborder="0" height="270" src="https://www.youtube.com/embed/n-OfYbtyjQo" width="480"></iframe>


วันพฤหัสบดีที่ 26 ตุลาคม พ.ศ. 2560

Arduino Uno R3 ให้แสดงผลบนจอ OLED LCD 128x64

  วันนี้ผมก็จะพาเล่น Arduino Mega 2560 R3ให้แสดงผลออกจอภาพนะครับ เป็นจอแสดงผลแบบ OLED LCD สำหรับ Arduino หน้าจอ 128x64 ขนาด 0.96" เชื่อมต่อแบบ IIC ใช้ไฟได้ทั้ง 3.3V หรือ 5V ให้จอสว่างแสดงผลมองเห็นได้อย่างชัดเจน และประหยัดไฟ สามารถวาดภาพกราฟฟิกส์เป็นรูปต่าง ๆ หรือทำเป็นเมนูตามแบบที่ต้องการได้

 ส่วน  Arduino Mega 2560 R3 เป็นบอร์ด Arduino ที่ออกแบบมาสำหรับงานที่ต้องใช้ I/O มากเป็นพิเศษ เช่น งานที่ต้องการรับสัญญาณจาก Sensor หรือควบคุมมอเตอร์ Servo หลายๆ ตัว บอร์ด Mega 2560 R3 ยังมีความหน่วยความจำแบบ Flash มากกว่า Arduino Uno R3 ทำให้สามารถเขียนโค้ดโปรแกรมเข้าไปได้มากขึ้น



ข้อมูลจำเพาะ 

ชิปไอซีไมโครคอนโทรเลอร์ ATmega2560
ใช้แรงดันไฟฟ้า 5V
รองรับการจ่ายแรงดันไฟฟ้า (ที่แนะนำ) 7 – 12V
รองรับการจ่ายแรงดันไฟฟ้า (ที่จำกัด) 6 – 20V
พอร์ต Digital I/O 54 พอร์ต (มี 15 พอร์ต PWM output)
พอร์ต Analog Input 16 พอร์ต
กระแสไฟฟ้ารวมที่จ่ายได้ในทุกพอร์ต 40mA
กระแสไปที่จ่ายได้ในพอร์ต 3.3V 50mA
พื้นที่โปรแกรมภายใน 256KB แต่ 8KB ถูกใช้โดย Bootloader
พื้นที่แรม 8KB
พื้นที่หน่วยความจำถาวร (EEPROM) 4KB
ความถี่คริสตัล 16MHz


   ก่อนอื่นเราก็มาต่อวงจรกันก่อนนะครับ

สาย VCC ของ OLED ต่อเข้า 3.3v. ของบอร์ด Arduino Mega 2560 R3
สาย GND ของ OLED ต่อเข้า GND ของบอร์ด Arduino Mega 2560 R3
สาย SCL ของ OLED ต่อเข้า SCL ของบอร์ด Arduino Mega 2560 R3
สาย SDA ของ OLED ต่อเข้า SDA ของบอร์ด Arduino Mega 2560 R3
ตามรูปด้านล่างนี้


ส่วนโค๊ดก็ก๊อปปีด้านล่างนี้เลยครับ

#include <Wire.h>  //ดึงไฟล์ Wire.h เข้ามาใช้งาน
 #include <Adafruit_GFX.h>  //ดึงไฟล์ Adafruit_GFX.h เข้ามาใช้งาน
 #include <Adafruit_SSD1306.h> //ดึงไฟล์ Adafruit_SSD1306.h เข้ามาใช้งาน

 #define OLED_RESET 4 //ประกาศใช้ OLED_RESET เป็นขาที่ 4
 Adafruit_SSD1306 display(OLED_RESET); //เรียกใช้ ไลบรารี่ Adafruit_SSD1306
 display.begin(SSD1306_SWITCHCAPVCC, 0x3C);// ใส่ค่าเริ่มต้น  0x3C สำหรับจอ OLED ไฟ 3.3 V.


void setup()   {   //เซ็ตหน้าจอ และล้างหน้าจอ และล้าง buffer
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
}


void loop() {  //วนการทำงานไปเรื่อยๆ
  testscrolltext(); //เรียกใช้กระบวนงาน testscrolltext
  delay(2000); // หน่วงเวลา
  display.clearDisplay(); //ล้างหน้าจอ และล้าง buffer
}

//เริ่มสร้างกระบวนงาน testscrolltext
void testscrolltext(void) {
  display.setTextSize(1);  //ขนาดของฟ้อนที่ใช้แสดงผล
  display.setTextColor(WHITE); //สีของฟ้อนต์ที่ใช้แสดงผล
  display.setCursor(10,0);  //เซ็ตจุดเริ่มต้นเคอเซอร์
  display.clearDisplay();  //ล้างหน้าจอ และล้าง buffer
  display.println("Poradech Surinta");    //ข้อความที่จะให้แสดงผลแถวที่ 1
  display.println("");                                //ข้อความที่จะให้แสดงผลแถวที่ 2
  display.println(" My name is Mike");  //ข้อความที่จะให้แสดงผลแถวที่ 3
  display.display();  //กำหนดการแสดงผล
  delay(1);  // หน่วงเวลา
  
  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();
}


ใครชอบแบบไหนก็แก้ไขและประยุกต์ใช้ตามความต้องการได้เลยครับ