'SSD1306'에 해당되는 글 8건

  1. 2018.11.23 Hardware | MAX30105 파티클 센서 - 1
  2. 2018.08.01 Hardware | ML8511 UV sensor 를 가지고 놀아보자
  3. 2018.07.24 Hardware | SSD1306 에 로고를 세겨보자
  4. 2017.11.22 Hardware | Safecast bGeigie Nano 를 조립해 보자 - 2
  5. 2017.09.19 Hardware | SSD1306 monochrome OLED 를 가지고 VU meter 를 만들어보자
  6. 2017.09.19 Hardware | Adafruit SSD1306 128x64 1.3" monochrome OLED 를 사용해보자
  7. 2017.09.14 Hardware | SSD1306 128x64 monochrome OLED 를 사용해보자
  8. 2017.09.07 Hardware | SSD1331 96x64 full color OLED 를 사용해보자

Hardware | MAX30105 파티클 센서 - 1

|

1. 파티클 센서


인터넷을 돌아다니다 particle sensor 라는 것을 알게 되었습니다.

이게 단순히 공기중의 입자를 확인하는것 뿐만아니라, 혈중 농도 및 심전도까지 확인할 수 있다고 합니다.


나중에 도플러 효과를 이용한 원격 심전도 확인 시스템을 만들 예정이라,

기초적인 지식을 습득하기 위해 일단 이런 류의 센서 사용법을 익혀 보기로 합니다.






2. 주문


물론 AliExpress 에서 주문했습니다.


* CFsunbird High Accuracy I2C MAX30105 Particle Optical Sensor Photodetectors Board Module 1.8V power supply

https://ko.aliexpress.com/item/CFsunbird-High-Accuracy-I2C-MAX30105-Particle-Optical-Sensor-Photodetectors-Board-Module-1-8V-power-supply/32819571918.html




여타 센서류보다 단일 부품으로는 꽤나 비싼편 입니다.

이는 다양한 기능이 들어가 있으며, 기본 소자 자체가 좀 있어 보입니다.


SparkFun 에서 팔고 있는 제품인데, AliExpress 에서 구입하다 보니, 조금 변형된 중국 제품입니다.

단, 소스는 완벽하게 호환됩니다.


* SparkFun Particle Sensor Breakout - MAX30105

https://learn.sparkfun.com/tutorials/max30105-particle-and-pulse-ox-sensor-hookup-guide


보통 정식 제품보다는 AliExpress 가 싼 편인데, 이 제품은 자비가 없군요.

AliExpress 에서 약 12 USD, SparkFun 제품은 13 USD 정도 합니다.





3. 도착


크게 무리없이 2주만에 도착.



납땜이 되지 않은 상태로 배달이 됩니다. 이제 AliExpress 에서 오는 것은 이게 당연한 거죠?



핵심이 되는 센서 부품을 클로즈 업 해봤습니다.



범상치 않아 보이는군요.





4. 연결


Arduino 와의 연결은 다음과 같습니다.


 MAX30105 | Arduino Nano
-------------------------
    VCC   |     3.3V
    GND   |     GND
    SDL   |     A5
    SDA   |     A4
-------------------------


실제 회로 구성은 다음과 같습니다.

Fritzing 에서 그려 보는데, 아쉽게도 아직 Fritzing 에서는 MAX30105 부품이 리스트에 존재하지 않습니다.

아직 아무도 만들지 않았나 봅니다.



Datasheet 입니다 - MAX30105_3.pdf





5. sketch - Red, IR, Green reading


이후 나오는 소스는 모두 아래 site 를 참고하였습니다.


* SparkFun Particle Sensor Breakout - MAX30105

https://learn.sparkfun.com/tutorials/max30105-particle-and-pulse-ox-sensor-hookup-guide


Library 를 인스톨 하고 가장 간단한 스케치를 로드하여 확인해 봅니다.

소스는 소자의 기본 동작인 빨간색, 적외선, 녹색을 감지하고 수치화 하는 스케치 입니다.


File > Examples > MAX3010x Pulse and Proximity Sensor > Example1_Basic_Readings



실제 소스를 여기에 옮겨 봅니다.


/*
  MAX30105 Breakout: Output all the raw Red/IR/Green readings
  By: Nathan Seidle @ SparkFun Electronics
  Date: October 2nd, 2016
  https://github.com/sparkfun/MAX30105_Breakout

  Outputs all Red/IR/Green values.

  Hardware Connections (Breakoutboard to Arduino):
  -5V = 5V (3.3V is allowed)
  -GND = GND
  -SDA = A4 (or SDA)
  -SCL = A5 (or SCL)
  -INT = Not connected

  The MAX30105 Breakout can handle 5V or 3.3V I2C logic. We recommend powering the board with 5V
  but it will also run at 3.3V.

  This code is released under the [MIT License](http://opensource.org/licenses/MIT).
*/

#include "Wire.h"
#include "MAX30105.h"

MAX30105 particleSensor;

#define debug Serial //Uncomment this line if you're using an Uno or ESP
//#define debug SerialUSB //Uncomment this line if you're using a SAMD21

void setup() {
  debug.begin(9600);
  debug.println("MAX30105 Basic Readings Example");

  // Initialize sensor
  if (particleSensor.begin() == false)
  {
    debug.println("MAX30105 was not found. Please check wiring/power. ");
    while (1);
  }

  particleSensor.setup(); //Configure sensor. Use 6.4mA for LED drive
}

void loop() {
  debug.print(" R[");
  debug.print(particleSensor.getRed());
  debug.print("] IR[");
  debug.print(particleSensor.getIR());
  debug.print("] G[");
  debug.print(particleSensor.getGreen());
  debug.print("]");

  debug.println();
}


우선 구동을 시작하면, 녹색과 빨간색 빛이 빠르게 점멸합니다.



저렇게 빛을 쏜 다음 반사되는 값을 읽는것이겠죠?



손가락을 센서 근처로 가져가면 값의 변동이 일어납니다.


센서의 불빛을 슬로우 모션으로 9초동안 찍어 봤습니다.

그랬더니 51초짜리 동영상이 되었네요.



얼마나 빨리 점멸을 하는지, 슬로모션으로 찍어도 실제로 보는것과 그리 차이나지 않습니다.





6. sketch - 물체 인식


IR 의 delta 값을 이용하여 물체가 일정 이상 안에 들어와 있는지 없는지를 판단합니다.

소스는 아래 path 에서 확인할 수 있습니다.


File > Examples > MAX3010x Pulse and Proximity Sensor > Example2_Presense_Sensing






7. sketch - 온도


SparkFun 사에서 제공되는 library 에서 "readTemperature()" 함수를 그대로 이용한 것 입니다.

그럼 위의 함수는 어떻게 되느냐 하면 아래와 같습니다.


// Die Temperature
// Returns temp in C
float MAX30105::readTemperature() {
  // Step 1: Config die temperature register to take 1 temperature sample
  writeRegister8(_i2caddr, MAX30105_DIETEMPCONFIG, 0x01);

  // Poll for bit to clear, reading is then complete
  // Timeout after 100ms
  unsigned long startTime = millis();
  while (millis() - startTime < 100)
  {
    uint8_t response = readRegister8(_i2caddr, MAX30105_DIETEMPCONFIG);
    if ((response & 0x01) == 0) break; //We're done!
    delay(1); //Let's not over burden the I2C bus
  }
  //TODO How do we want to fail? With what type of error?
  //? if(millis() - startTime >= 100) return(-999.0);

  // Step 2: Read die temperature register (integer)
  int8_t tempInt = readRegister8(_i2caddr, MAX30105_DIETEMPINT);
  uint8_t tempFrac = readRegister8(_i2caddr, MAX30105_DIETEMPFRAC);

  // Step 3: Calculate temperature (datasheet pg. 23)
  return (float)tempInt + ((float)tempFrac * 0.0625);


센서 내부에 register 값을 읽어와서 표현하는 것이군요.

구동 소스는 아래 path 에서 확인할 수 있습니다.


File > Examples > MAX3010x Pulse and Proximity Sensor > Example3_Temperature_Sense







8. sketch - 심전도


손가락을 센서에 대고 있으면 심전도를 그려주는 소스 입니다.


File > Examples > MAX3010x Pulse and Proximity Sensor > Example4_HeartBeat_Plotter


읽어들인 IR 값에 대한 변화를 plottor 을 이용해 그려주는 것이죠.
소스를 보면 setup 과 기준값 등을 정해주는 부분이 있을 뿐, 단순히 IR 값을 불러옵니다.

아래처럼 보려면, Tools > Serial Plotter 를 통해서 확인할 수 있습니다.


저의 심전도 모양입니다. 두근두근...





9. sketch - 심박수


대체로 심전도와 비슷한데, 이걸 1분에 몇분 정도 뛰는지를 확인해 주는 소스 입니다.

보통 병원이나 건강검진시 확인해 보는 심박수 겠죠?


구동 소스는 아래 path 에서 확인할 수 있습니다.


File > Examples > MAX3010x Pulse and Proximity Sensor > Example5_HeartRate







FIN


MAX30105 센서는 주로, 심박수 모니터링에 사용되는게 가장 적절해 보입니다.

인터넷에서 어느 분이, 이와 비슷한 센서를 이용하여 심박수를 OLED 에 표시해주는 것까지 해놓은 글이 아래 입니다.


* Heart beat Sensor and “ECG” Display

http://www.xtronical.com/basics/heart-beat-sensor-ecg-display/


저도 따라해 봤는데,

일단 센서에서 나오는 값 자체가 MAX30105 처럼 큰 값으로 나오지 않을 뿐더러,

값의 변화가 딱 OLED 크기만큼 잘 구현이 되어 있어서 잘 하신것 같은데, 도저히 따라해도 안되는군요.



겨우겨우 우겨 넣어서 OLED 에 보여주는 것 까지는 해 봤습니다.

이것 가지고는 만족스럽지 못하여, 못하는 코딩을 이용하여 한번 도전해 보겠습니다.


병원에서 보는 듯 한 모습으로 될 때까지 만들어서 공유해 볼께요.



And

Hardware | ML8511 UV sensor 를 가지고 놀아보자

|

1. 여름


유독 2018년의 여름은 예년보다 더욱 덥습니다.

지구 온실효과로 내년 뉴스에도, "올해도 최고 온도를 갱신했습니다!" 라는 멘트를 들을 수 있을것 같습니다.


오존층 파괴등으로 인하여 피부에 직사광선을 쬐는 것은 이제 위험한 시대입니다.

자외선 - Ultraviolet 인거죠.



위 표는 UV 세기에 따라 어떤식으로 몸을 보호해야 하는지 나타내주는 표 입니다.

더이상 선글라스는 패션이 아니군요.





2. ML8511 센서 구매


UV 를 측정해주는 아나로그 센서로는 ML8511 이 있습니다.

AliExpress 를 검색하니 아래가 가장 많이 팔렸던 제품입니다.


* GY-8511 ML8511 UVB Breakout Test Module Ray Sensor UV Detector Analog Output Module

https://www.aliexpress.com/item/GY-8511-ML8511-UVB-Breakout-Test-Module-Ray-Sensor-UV-Detector-Analog-Output-Module/32451073500.html



기능은... 280-390nm 를 가장 잘 측정해 준다 합니다.


The ML8511 breakout is an easy to use ultraviolet light sensor.

The MP8511 UV (ultraviolet) Sensor works by outputing an analog signal in relation to the amount of UV light that's detected.

This breakout can be very handy in creating devices that warn the user of sunburn or detect the UV index as it relates to weather conditions.


This sensor detects 280-390nm light most effectively.

This is categorized as part of the UVB (burning rays) spectrum and most of the UVA (tanning rays) spectrum.

It outputs a analog voltage that is linearly related to the measured UV intensity (mW/cm2).

If your microcontroller can do an analog to digital signal conversion then you can detect the level of UV!


이 구간은 피부를 가장 잘 타게 만드는 구간이라고 하네요.







3. ML8511 도착


뭐 특별히 이상한 점 없이 잘 도착 하였습니다.



이렇게 생겼습니다.



다리를 납땜해줍니다.



숫자가 적힌 부분은 마무리가 되지 않은 부분이므로, 니퍼로 제거해 줍니다.



센서를 확대해 봤습니다.

금으로 된 점퍼가 모든 단자에 연결되어 있지 않은 것을 보니, 가지고 있는 성능을 완전히 구현해 놓은 것은 아닌것 같군요.





4. Layout / Pinout


Pinout 은 다음과 같습니다.


   ML8511  | Arduino Micro
---------------------------
    3V3    |    A1 / 3.3V
    GND    |      GND
    OUT    |      A0
    EN     |    A1 / 3.3V
---------------------------


SparkFun 의 다음 link 가 도움이 됩니다.


* ML8511 UV Sensor Hookup Guide

https://learn.sparkfun.com/tutorials/ml8511-uv-sensor-hookup-guide


다만, 중국제는 pin 수가 하나 더 많아서 헷갈릴 수 있습니다.

결국 같은 pinout 이지만, 동일한 GY8511 을 사용한 다음 blogpost 가 더 도움이 되었습니다.


* GYM8511ML UV Sensor Connection To Arduino Nano

http://twenty5nov.blogspot.com/2016/02/gym8511ml-uv-sensor-connection-to.html



Layout 은 다음과 같습니다.






5. sketch


위의 SparkFun 사이트의 소스를 사용해 봅니다.


 /* 
 ML8511 UV Sensor Read Example
 By: Nathan Seidle
 SparkFun Electronics
 Date: January 15th, 2014
 License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).

 The ML8511 UV Sensor outputs an analog signal in relation to the amount of UV light it detects.

 Connect the following ML8511 breakout board to Arduino:
 3.3V = 3.3V
 OUT = A0
 GND = GND
 EN = 3.3V
 3.3V = A1
 These last two connections are a little different. Connect the EN pin on the breakout to 3.3V on the breakout.
 This will enable the output. Also connect the 3.3V pin of the breakout to Arduino pin 1.

 This example uses a neat trick. Analog to digital conversions rely completely on VCC. We assume
 this is 5V but if the board is powered from USB this may be as high as 5.25V or as low as 4.75V:
 http://en.wikipedia.org/wiki/USB#Power Because of this unknown window it makes the ADC fairly inaccurate
 in most cases. To fix this, we use the very accurate onboard 3.3V reference (accurate within 1%). So by doing an
 ADC on the 3.3V pin (A1) and then comparing this against the reading from the sensor we can extrapolate
 a true-to-life reading no matter what VIN is (as long as it's above 3.4V).

 Test your sensor by shining daylight or a UV LED: https://www.sparkfun.com/products/8662

 This sensor detects 280-390nm light most effectively. This is categorized as part of the UVB (burning rays)
 spectrum and most of the UVA (tanning rays) spectrum.

 There's lots of good UV radiation reading out there:
 http://www.ccohs.ca/oshanswers/phys_agents/ultravioletradiation.html
 https://www.iuva.org/uv-faqs

*/

//Hardware pin definitions
int UVOUT = A0; //Output from the sensor
int REF_3V3 = A1; //3.3V power on the Arduino board

void setup() {
	Serial.begin(9600);
	
	pinMode(UVOUT, INPUT);
	pinMode(REF_3V3, INPUT);
	
	Serial.println("ML8511 example");
}

void loop() {
	int uvLevel = averageAnalogRead(UVOUT);
	int refLevel = averageAnalogRead(REF_3V3);
	
	//Use the 3.3V power pin as a reference to get a very accurate output value from sensor
	float outputVoltage = 3.3 / refLevel * uvLevel;
	
	float uvIntensity = mapfloat(outputVoltage, 0.99, 2.8, 0.0, 15.0); //Convert the voltage to a UV intensity level
	
	Serial.print("output: ");
	Serial.print(refLevel);
	
	Serial.print("\tML8511 output: ");
	Serial.print(uvLevel);
	
	Serial.print("\tML8511 voltage: ");
	Serial.print(outputVoltage);
	
	Serial.print("\tUV Intensity (mW/cm^2): ");
	Serial.print(uvIntensity);
	
	Serial.println();
	
	delay(100);
}

//Takes an average of readings on a given pin
//Returns the average
int averageAnalogRead(int pinToRead) {
	byte numberOfReadings = 8;
	unsigned int runningValue = 0;
	
	for(int x = 0 ; x < numberOfReadings ; x++)
		runningValue += analogRead(pinToRead);
	runningValue /= numberOfReadings;
	
	return(runningValue);
}

//The Arduino Map function but for floats
//From: http://forum.arduino.cc/index.php?topic=3922.0
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
{
	return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}


Serial out 으로 보면 reLevel / uvLevel / outputVoltage / uvIntensity 를 아래와 같이 확인할 수 있습니다.



뭔가 와닿지 않죠?





6. OLED 로 UV Index 표시하기


Youtube 를 보니 UV Index 를 LCD 에 표현해 주는 분이 계셨습니다.


* Arduino UV Meter using the UV31A Ultraviolet Sensor

http://www.electronics-lab.com/project/arduino-uv-meter-using-uv30a-ultraviolet-sensor/



센서와 LCD 스크린도 다르지만 컨셉은 이해할 수 있었습니다.



따라하지 아니할 수가 없네요.

저는 SSD1306 과 ML8511 을 사용해서 소스를 converting 해 봅니다.


우선 처음 부팅시 보여주는 logo 를 만드는 작업을 하였습니다.

너무 길어지니 따로 포스팅 하였습니다.


* Hardware | SSD1306 에 로고를 세겨보자

http://chocoball.tistory.com/entry/Hardware-SSD1306-create-logo


표시해주는 UV Index 는 UV31A 센서가 기준이라, 가지고 있는 ML8511 로 하면 전혀 다른 숫자들이 나옵니다.


찾고 찾아보니, 중국에서 ML8511 을 가지고 UV Index 를 테이블화 하여 작성된 논문이 있었습니다.


* See UV on Your Skin: An Ultraviolet Sensing and Visualization System

BodyNets_2013_UV.pdf


논문 안에 기재된, 아래 테이블을 가지고 적용하면 되겠네요!



Vcc = 3.0V 이고, ML8511 은 3.3V 이지만, 소스에서 보정을 해주므로 그리 큰 문제는 되지 않을것 같습니다.


다음이 완성된 최종 sketch 입니다.

LOGO를 새기는 부분과 "else if" 를 이용한 UV Indexing 부분으로 나뉘어 있습니다.

나머지는 SparkFun 의 소스도 사용했구요. 한마디로 짜집기 버전입니다.


#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
  
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

static const unsigned char PROGMEM UVMeter[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x18, 0x03, 0x18, 0x01, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x18, 0x03, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x1C, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x07, 0xC0, 0x07, 0x00, 0x00, 0x1C, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC0, 0x0F, 0xC0, 0x0E, 0x00, 0x00, 0x1C, 0x03, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xE0, 0x0F, 0xE0, 0x3E, 0x00, 0x00, 0x1C, 0x03, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xF0, 0x0F, 0xF0, 0x7E, 0x00, 0x00, 0x1C, 0x03, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFC, 0x0F, 0xF8, 0xFE, 0x00, 0x00, 0x1C, 0x03, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xDF, 0xFD, 0xFE, 0x00, 0x00, 0x1C, 0x03, 0x07, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x1C, 0x03, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x1C, 0x03, 0x03, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x1C, 0x03, 0x03, 0x98, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x00, 0x1C, 0x07, 0x01, 0x98, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7F, 0x03, 0xE0, 0x7F, 0x00, 0x00, 0x0C, 0x06, 0x01, 0xB0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFC, 0x3F, 0xFE, 0x1F, 0x3F, 0xF0, 0x0E, 0x0E, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x06, 0x0F, 0xF8, 0xFF, 0xFF, 0x8F, 0xFF, 0xC0, 0x07, 0xFC, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x07, 0xFF, 0xF1, 0xFF, 0xFF, 0xC7, 0xFF, 0x80, 0x03, 0xF8, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00,
0x03, 0xFF, 0xE7, 0xFF, 0xFF, 0xF3, 0xFF, 0x00, 0x00, 0x00, 0x60, 0x18, 0x00, 0x00, 0x00, 0x00,
0x03, 0xFF, 0xCF, 0xFF, 0xFF, 0xF9, 0xFF, 0x00, 0x00, 0x00, 0x70, 0x38, 0x00, 0x20, 0x00, 0x00,
0x01, 0xFF, 0x9F, 0xFF, 0x7F, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x70, 0x38, 0x00, 0x20, 0x00, 0x00,
0x00, 0xFF, 0x9F, 0xF0, 0x07, 0xFC, 0xFE, 0x00, 0x00, 0x00, 0x58, 0x28, 0x38, 0x78, 0x38, 0x48,
0x00, 0x7F, 0x3F, 0xC0, 0x01, 0xFE, 0x7E, 0x00, 0x00, 0x00, 0x58, 0x68, 0x6E, 0x78, 0xCC, 0x7C,
0x00, 0x3E, 0x7F, 0x80, 0x00, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x48, 0x48, 0xC6, 0x20, 0x84, 0x60,
0x00, 0x1E, 0x7F, 0x00, 0x00, 0x7F, 0x3C, 0x00, 0x00, 0x00, 0x4C, 0xC8, 0xC2, 0x21, 0x86, 0x40,
0x00, 0x1E, 0x7E, 0x00, 0x00, 0x3F, 0x3C, 0x00, 0x00, 0x00, 0x4C, 0x88, 0xFE, 0x21, 0xFE, 0x40,
0x00, 0x3C, 0xFE, 0x00, 0x00, 0x3F, 0x9F, 0x00, 0x00, 0x00, 0x46, 0x88, 0x80, 0x21, 0x80, 0x40,
0x00, 0x7C, 0xFC, 0x00, 0x00, 0x1F, 0x9F, 0xF0, 0x00, 0x00, 0x47, 0x88, 0xC0, 0x21, 0x80, 0x40,
0x00, 0xFC, 0xFC, 0x00, 0x00, 0x1F, 0x9F, 0xFC, 0x00, 0x00, 0x43, 0x08, 0x42, 0x30, 0xC0, 0x40,
0x03, 0xFC, 0xFC, 0x00, 0x00, 0x1F, 0x9F, 0xFE, 0x00, 0x00, 0x43, 0x08, 0x7E, 0x1C, 0x7C, 0x40,
0x07, 0xFC, 0xFC, 0x00, 0x00, 0x1F, 0x9F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

String UV = "0"; 

//Hardware pin definitions
int UVOUT = A0; //Output from the sensor
int REF_3V3 = A1; //3.3V power on the Arduino board

void setup() {
	pinMode(UVOUT, INPUT);
	pinMode(REF_3V3, INPUT);
	
	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
	display.clearDisplay();
	display.drawBitmap(0, 0, UVMeter, 128, 32, WHITE);
	display.display();
	
	delay(3000);
}

 
void loop() {
	int stringLength = 0;
	UV = readSensor();
	
	display.clearDisplay();
	display.drawRect(0, 0, display.width(), display.height(), WHITE);
	display.drawFastHLine(0, 10, 128, WHITE);
	
	display.setTextSize(1);
	display.setTextColor(WHITE);
	display.setCursor(40, 2);
	display.print("UV INDEX");
	
	stringLength = UV.length();
	printUV(stringLength);
	display.display();
	
	delay(150);
}

void printUV(int length) {
	switch(length) {
		case 1:
			display.setTextSize(3);
			display.setTextColor(WHITE);
			display.setCursor(60, 10);
			display.print(UV); break;
		case 2:
			display.setTextSize(3);
			display.setTextColor(WHITE);
			display.setCursor(55, 10);
			display.print(UV); break;
		default: display.print(UV); break;
	}
}

String readSensor() {
	String UVIndex = "0";
	
	int uvLevel = averageAnalogRead(UVOUT);
	int refLevel = averageAnalogRead(REF_3V3);
	
	//Use the 3.3V power pin as a reference to get a very accurate output value from sensor
	float voltage = 3.3 / refLevel * uvLevel;
		
	if(voltage<=0.993) {
		UVIndex = "0";
	} else if (voltage>0.993 && voltage<=1.073) {
		UVIndex = "1";
	} else if (voltage>1.073 && voltage<=1.153) {
		UVIndex = "2";
	} else if (voltage>1.153 && voltage<=1.233) {
		UVIndex = "3";
	} else if (voltage>1.233 && voltage<=1.313) {
		UVIndex = "4";
	} else if (voltage>1.313 && voltage<=1.393) {
		UVIndex = "5";
	} else if (voltage>1.393 && voltage<=1.473) {
		UVIndex = "6";
	} else if (voltage>1.473 && voltage<=1.553) {
		UVIndex = "7";
	} else if (voltage>1.553 && voltage<=1.633) {
		UVIndex = "8";
	} else if (voltage>1.633 && voltage<=1.713) {
		UVIndex = "9";
	} else if (voltage>1.713 && voltage<=1.793) {
		UVIndex = "10";
	} else if (voltage>1.793 && voltage<=1.873) {
		UVIndex = "11";
	} else if (voltage>1.873 && voltage<=1.953) {
		UVIndex = "12";
	} else if (voltage>1.953 && voltage<=2.033) {
		UVIndex = "13";
	} else if (voltage>2.033 && voltage<=2.113) {
		UVIndex = "14";
	} else if (voltage>2.113 && voltage<=2.193) {
		UVIndex = "15";
	} else if (voltage>2.193 && voltage<=2.273) {
		UVIndex = "16";
	} else if (voltage>2.273 && voltage<=2.353) {
		UVIndex = "17";
	} else if (voltage>2.353 && voltage<=2.433) {
		UVIndex = "18";
	} else if (voltage>2.433 && voltage<=2.513) {
		UVIndex = "19";
	} else if (voltage>2.513 && voltage<=2.593) {
		UVIndex = "20";
	} else if (voltage>2.593) {
		UVIndex = "21";
	}
	
	return UVIndex;
}

//Takes an average of readings on a given pin
//Returns the average
int averageAnalogRead(int pinToRead) {
	byte numberOfReadings = 8;
    unsigned int runningValue = 0;
     
    for(int x = 0 ; x < numberOfReadings ; x++)
        runningValue += analogRead(pinToRead);
    runningValue /= numberOfReadings;
     
    return(runningValue);
}






7. 밖에 나가서 확인해 보자


저녁 6시가 되니, 해가 뉘엿뉘엿 지고 있습니다.

해떨어지기 전에 얼른 나가서 확인해 봅니다.



실내에서는 당연히 UV Index = 0 입니다.



저무는 해를 향해 조준합니다.



오옷!

3 ~ 4 정로를 보여주네요.



동영상 갑니다.


지역은 다르지만 New York 의 월별/시간대별 UV Index 그래프 입니다.

오후 4시만 되어도 3 이하로 떨어지는군요.


현재 한국은 한여름이고, 오후 6시라도 햇볕의 기운이 아직 남아 있으므로, "3 ~ 4" 는 적절하게 인식한것 같습니다.



집에 resin 을 굳히는 UV lamp 가 있다는걸 뒤늦게 생각해 내어,

UV lamp 로도 확인해 봅니다.



해지는 햇살과 비슷하게 3 ~ 4 정도를 나타내네요.





FIN


UV sensor 인 ML8511 을 가지고 알차게 실험해 봤네요.

이참에 OLED 에 로고 새기는 방법도 터득했구요.


해가 거듭될수록 자외선의 위험성이 강조되는 요즈음,

향후를 위해서라도 한번쯤은 확인해 보고 싶었던 센서 였습니다.


다른 분들도 참고가 되었으면 좋겠습니다.


And

Hardware | SSD1306 에 로고를 세겨보자

|

1. 이제 때가 되었군


그렇습니다.

OLED 를 사용하다 보면, 커스텀 로고 새기는 방법을 익혀야 하는 경우가 몇번 있었습니다만,

대세에 지장이 없어서 무시하고 왔습니다.


그러나 UV Meter 를 가지로 놀려고 아래 링크를 따라해 보니,

커스텀 로고를 새기는 방법을 익혀야 할 때가 된걸 느꼈습니다.


* Arduino UV Meter using the UV31A Ultraviolet Sensor

http://www.electronics-lab.com/project/arduino-uv-meter-using-uv30a-ultraviolet-sensor/


아래 그림처럼, 처음 시작을 커스텀 로고로 시작되는 것을 볼 수 있습니다.



또한, 예전에 VU Meter 를 만들 때, 제작자가 한번 언급한 경우도 있었습니다.

이때는 그냥 제작자 코드를 따라하기만 하면 되는거였죠.


* Hardware | SSD1306 monochrome OLED 를 가지고 VU meter 를 만들어보자

 - http://chocoball.tistory.com/entry/Hardware-VU-meter-using-SSD1306-monochrome-OLED


자 그럼, 한번 시작해 볼까요?





2. Arduino micro 의 I2C 연결


여기서 잠깐.

평소 사용하는 Arduino Nano 와는 다르게, 요즘 자주 사용하고 있는 Arduino Micro 의 I2C pinout 이 달라 조금 헤매었습니다.



OLED 의 SCL / SDA 연결을 위해서는 D3 / D2 pin 을 이용해야 합니다.


 SSD1306  | Arduino Micro
--------------------------
   VCC    |     3.3V
   GND    |     GND
   SDL    |     D3
   SDA    |     D2
--------------------------


연결은 다음과 같아요.






3. OLED 의 너비와 높이를 구해보자


우선 사용할 OLED 의 가로, 세로 pixel 수를 구해야 합니다.

이는 최종적으로 만들 그림의 크기를 정하기 위한거죠.


연결한 OLED 에 가로, 세로 pixel 수를 알아보기 위해 아래 code 를 사용합니다.


#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
 
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

void setup() {
	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
	display.clearDisplay();
	display.display();
}

void loop() {
	display.clearDisplay();
	
	display.setTextColor(WHITE);
	display.setCursor(0,0);
	display.setTextSize(2);
	display.println(display.width());
	display.print(display.height());
	
	display.display();
}


결과는 다음과 같습니다.



SSD1306 이지만 128x64 가 아닌, 128x32 군요.

높이가 일반적인 OLED 보다 반쪽이라서 그림을 신경써야 합니다.





4. 필요한 그림파일 찾기


UV Meter 를 위해서는, 우선 태양 그림이 필요합니다.

Googling 하여 태양 그림을 찾아 봅니다.

키워드는 "sun shining icon image" 로 검색했습니다.


주르륵 뜨는군요. 적당한 것을 하나 골라 봅니다.







5. 흑백 및 적당한 크기로


그림을 생성하기 위해 Paint.net 이라는 어플을 사용합니다.


* paint.net

https://www.getpaint.net/


우선 OLED 의 크기가 128x32 이므로, 그림 크기를 OLED 크기에 맞게 생성해 줍니다.



태양 그림 파일을 불러와서 크기를 줄여줍니다.

OLED 가 32 이므로, 32로 하면 그림이 다 들어가겠지만, 그렇게 되면 너무 작아 보여,

64x64 로 줄여줍니다.



또한 OLED 에 표시하기 위해서는 on/off, 0/1, white/black 으로 표시해야 합니다.

최대한 근접하게 우선 Brightness / Contrast 를 설정해 줍니다.



전체적으로 다음과 같이 꾸며 봅니다.


Contrast 를 최대로 높히면 Bitmap 생성시 완전한 흑백으로 근접하게 만들 수 있습니다.



마지막으로 Windows 에 기본으로 들어 있는,

mspaint ( %windir%\system32\mspaint.exe ) 를 사용하여,

최종적으로 Monochrome BMP 파일로 생성해 줍니다.


Save as Monochrome Bitmap 으로 하면서 완전히 white/black 으로 변경됩니다.






6. LCD Assistant


이제 C 코드용 bitmap 을 만들어주는 어플을 다운로드 받아서 실행합니다.


* LCD Assistant

http://en.radzio.dxp.pl/bitmap_converter/



실행한 후, 위에서 만든 파일을 load 합니다.



이제 "Save output" 으로 최종적으로 text 파일로 export 합니다.



Output 된 text 파일을 열어보면 아래와 같이 생성되어 있습니다.



Monochrome Bitmap 으로만 잘 만들면,

LCD Assistant 를 이용하여 C code map 을 만드는데 쉽게 진행됩니다.





7. OLED 에 커스텀 코드를 올려보자


C code map 을 array 로 올린 다음,

display.drawBitmap 을 이용하여 표현할 수 있는 준비가 되었습니다.


최종 코드는 다음과 같습니다.


#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
 
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

static const unsigned char PROGMEM UVMeter[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x18, 0x03, 0x18, 0x01, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x18, 0x03, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x1C, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x07, 0xC0, 0x07, 0x00, 0x00, 0x1C, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC0, 0x0F, 0xC0, 0x0E, 0x00, 0x00, 0x1C, 0x03, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xE0, 0x0F, 0xE0, 0x3E, 0x00, 0x00, 0x1C, 0x03, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xF0, 0x0F, 0xF0, 0x7E, 0x00, 0x00, 0x1C, 0x03, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFC, 0x0F, 0xF8, 0xFE, 0x00, 0x00, 0x1C, 0x03, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xDF, 0xFD, 0xFE, 0x00, 0x00, 0x1C, 0x03, 0x07, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x1C, 0x03, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x1C, 0x03, 0x03, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x1C, 0x03, 0x03, 0x98, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x00, 0x1C, 0x07, 0x01, 0x98, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7F, 0x03, 0xE0, 0x7F, 0x00, 0x00, 0x0C, 0x06, 0x01, 0xB0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFC, 0x3F, 0xFE, 0x1F, 0x3F, 0xF0, 0x0E, 0x0E, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x06, 0x0F, 0xF8, 0xFF, 0xFF, 0x8F, 0xFF, 0xC0, 0x07, 0xFC, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x07, 0xFF, 0xF1, 0xFF, 0xFF, 0xC7, 0xFF, 0x80, 0x03, 0xF8, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00,
0x03, 0xFF, 0xE7, 0xFF, 0xFF, 0xF3, 0xFF, 0x00, 0x00, 0x00, 0x60, 0x18, 0x00, 0x00, 0x00, 0x00,
0x03, 0xFF, 0xCF, 0xFF, 0xFF, 0xF9, 0xFF, 0x00, 0x00, 0x00, 0x70, 0x38, 0x00, 0x20, 0x00, 0x00,
0x01, 0xFF, 0x9F, 0xFF, 0x7F, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x70, 0x38, 0x00, 0x20, 0x00, 0x00,
0x00, 0xFF, 0x9F, 0xF0, 0x07, 0xFC, 0xFE, 0x00, 0x00, 0x00, 0x58, 0x28, 0x38, 0x78, 0x38, 0x48,
0x00, 0x7F, 0x3F, 0xC0, 0x01, 0xFE, 0x7E, 0x00, 0x00, 0x00, 0x58, 0x68, 0x6E, 0x78, 0xCC, 0x7C,
0x00, 0x3E, 0x7F, 0x80, 0x00, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x48, 0x48, 0xC6, 0x20, 0x84, 0x60,
0x00, 0x1E, 0x7F, 0x00, 0x00, 0x7F, 0x3C, 0x00, 0x00, 0x00, 0x4C, 0xC8, 0xC2, 0x21, 0x86, 0x40,
0x00, 0x1E, 0x7E, 0x00, 0x00, 0x3F, 0x3C, 0x00, 0x00, 0x00, 0x4C, 0x88, 0xFE, 0x21, 0xFE, 0x40,
0x00, 0x3C, 0xFE, 0x00, 0x00, 0x3F, 0x9F, 0x00, 0x00, 0x00, 0x46, 0x88, 0x80, 0x21, 0x80, 0x40,
0x00, 0x7C, 0xFC, 0x00, 0x00, 0x1F, 0x9F, 0xF0, 0x00, 0x00, 0x47, 0x88, 0xC0, 0x21, 0x80, 0x40,
0x00, 0xFC, 0xFC, 0x00, 0x00, 0x1F, 0x9F, 0xFC, 0x00, 0x00, 0x43, 0x08, 0x42, 0x30, 0xC0, 0x40,
0x03, 0xFC, 0xFC, 0x00, 0x00, 0x1F, 0x9F, 0xFE, 0x00, 0x00, 0x43, 0x08, 0x7E, 0x1C, 0x7C, 0x40,
0x07, 0xFC, 0xFC, 0x00, 0x00, 0x1F, 0x9F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};


void setup() {
	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
	display.clearDisplay();
	display.display();
}

void loop() {
	display.clearDisplay();
	
	display.drawBitmap(0, 0, UVMeter, 128, 32, WHITE);

	display.display();
}


짜잔~!!!

잘 나오는군요.






FIN


사실 이렇게까지 만드는데 거진 8시간정도 걸렸습니다.

Arduino micro 의 I2C pinout 이나, 순수한 Monochrome Bitmap 을 만드는 방법을 찾는데 많이 걸렸네요.

본 포스트가 다른 분들에게 많이 도움이 되었으면 합니다.


And

Hardware | Safecast bGeigie Nano 를 조립해 보자 - 2

|

이 글은 전편이 있습니다. 먼저 다음 link 를 꼭 읽고 오세요.


* Safecast bGeigie Nano 를 조립해 보자 - 1

http://chocoball.tistory.com/entry/Hardware-Safecast-bGeigie-Nano-1




1. Mainboard


bGeigie Nano 의 중추인 mainboard 입니다.



보드 버전은 1.1r5a 입니다.

조립 메뉴얼이 초기 버전을 기준으로 제작되어 있다 보니, 나름 최신 보드와 맞지 않는 부분들이 있습니다.

대략 예상하면서 메뉴얼을 따라가면 그리 큰 문제는 없습니다.



모든 실장 위치에 금도금이 되어 있어서 납이 잘 붙게 되어 있습니다.

잘 만들어진 보드라고 생각합니다.




2. 부품과 아크릴 지지대


부품은 따로 포장되어 있습니다.

제가 받은 제품의 고유 번호는 2981 되겠습니다.



기판을 보호하고 모양을 만들어주는 아크릴 지지대와 logging 을 위한 micro SD + adapater,

그리고 GM tube 를 보호해 주는 철망이 보입니다.






3. 저항 납땜하기


이제 본격적으로 작업을 시작합니다.

저항을 하나씩 검수해 가며 납땝합니다.

예전에 만들어 놓은 Transistor Tester 를 이용했습니다.


* Transistor Tester

http://chocoball.tistory.com/entry/Hardware-Transistor-Tester




10kΩ 짜리를 측정해 봅니다. 대략 오차범위 이내 입니다. 납땜해 줍니다.



1kΩ 짜리를 측정해 봅니다. 대략 오차범위 이내 입니다. 납땜해 줍니다.



4.5kΩ 짜리를 측정해 봅니다. 대략 오차범위 이내 입니다. 납땜해 줍니다.



겨우 4개 저항을 납땜했지만 뿌듯합니다. 기념샷 찍어줍니다.



계속 측정하고 땜질하고 반복합니다.



궁금해졌습니다. 왜 예전 방식인 "탄소 피막 저항" 일까?

온도변화에 약하며 정확도가 떨어지는 제품을 썼을까?


"메탈 피막 저항" 은 정확하며 온도변화에도 강한데 말입니다.


저항에 대해서는 아래 link 를 읽어보세요. 저도 처음에는 구분을 못했답니다.

http://chocoball.tistory.com/entry/Hardware-buying-resistors



집에 굴러다니는 메탈 피막 저항을 측정해 보는 것으로 궁금함은 더해가지만,

일단 접어두고 나중에 community 에 물어봐야겠습니다.





4. 콘덴서 납땜하기


저항 다음에는 콘덴서를 납땜해 줍니다.



총 3개가 있습니다. 100nF 이라고 합니다.



정말 소중하게 한땀한땀 납땜하였습니다.



뒷면의 리드로 모드 잘라주었습니다. 깔끔하게 잘 했다고 자화자찬을 해 봅니다.





5. 그 외 부품 납땜하기


저항과 콘덴서로 손이 어느정도 익었으니, 속도를 좀 내어 봅니다.

트랜지스터 1개와 스위치류, LED 등을 납땜해 갑니다.



C1815 라는 제품이지만 잘 모릅니다.



측정해 보면 NPN 트랜지스터 입니다. 납땜해 줍니다.



토클 스위치입니다. 일본에서 제조된 제품이네요.



사진으로는 크지만 앙증맞게 생겼습니다. 금속으로 된 스위치로 딸깍거리며 동작시키는 것이 은근 재미 있습니다.



무슨 용도의 스위치 인지는 모르겠습니다.

조이스틱처럼 누르기도 되고 상하좌우 움직일 수 있습니다. 메뉴 설정등에 사용될 듯 합니다.



밑면입니다.



스피커 입니다. 제품 마무리가 잘 되어 있습니다.



다이오드 입니다. 열에 약하니 최대한 짧게 열을 가하여 납땜합니다.



전원 스위치 입니다.

전류가 흐르는 곳이니 납을 많이 먹여 납땜합니다.



딥스위치 입니다. 납땜합니다.



Alerting 과 Counting 을 하는 LED 입니다.

제품 버전에 따라 빨간색 대신 파란색도 있었던것 같습니다.


조립하는 사람에 따라 빨간색을 counting 으로 사용하는 사람도 있고 여러가지 입니다.

저는 Alerting 에는 빨간색, Counting 에는 흰색을 선택해서 납땜하였습니다.



LED 는 이런 값을 보여주는군요.



Transistor Tester 로 측정시 불이 들어왔다 나갔다 하는 모습이 신기하여 동영상으로도 찍어 봤습니다.



아마도 측정시에 여러가지 패턴으로 전류/전압을 가해보고 결과를 도출하는 것 같습니다.



자잘한 부품을 모두 납땜한 모양입니다. 여기까지 하고 좀 쉬었습니다. 한 2주일.





6. OLED


가장 눈에 띄는 OLED 를 작업합니다.



뽁뽁이 포장지를 잘 뜯습니다.



저 위의 구멍에 납땜을 하면 됩니다.



제품 정식 명칭은 Adafruit 사의 SSD1306 1.3" 128x64 OLED 입니다.

집에 다른 OLED 두개를 더 가지고 있어서 잠깐 비교 놀이를 해봅니다.


* Adafruit SSD1306 128x64 1.3" monochrome OLED 를 사용해보자

http://chocoball.tistory.com/entry/Hardware-Adafruit-SSD1306-128x64-13inch-monochrome-OLED



기판 밑부분에 지지대를 납땜하고 볼트로 고정해 줍니다.



OLED 를 납땜한 소켓에 삽입하고 너트로 지지대 기둥에 고정해 줍니다.



설명서에는 휘지 않도록 너트를 위아래로 설치하라고 되어 있으나, 지지대 볼트 길이가 짧아서 절대 불가능 합니다.

그냥 위에만 너트로 고정해 줍니다. 너무 조이면 장력이 생기니 적당하게 조여줍니다.




7. GPS module


Adafruit 의 Ultimate GPS Breakout v3 제품입니다.



66개의 channel 을 받을 수 있다고 하네요. Wow!



뒷면은 GPS 정보를 저장하여 다시 reboot 될 때 GPS 를 빨리 연동되게 하기 위한 battery 고정부가 있습니다.



3.3V ~ 5V 까지 인가할 수 있습니다. 5V 도 견디지만 3.3V 로 동작시키면 좋겠죠?



이렇게 분리되어 있는 것을 아래와 같이 납땜해 주었습니다.



고정하는 부분이니 납을 많이 먹여 주었습니다.



GPS 가 올 자리는 여기가 되겠습니다.



지지대를 세우고 mainboard 와 연결되는 부분에 pin 을 납땜해 줍니다.



고정 기둥에 올려 놓고 너트로 조이면 이렇게 됩니다.

점점 모양을 갖춰 가네요.





8. OpenLog


측정한 data 를 micro SD 에 저장하는 부분입니다.



제품은 SparkFun 사의 OpenLog DEV-13712 입니다.



Arduino 와 친숙한 ATmega 칩이 달려 있습니다.



뒷면은 micro SD 를 삽입할 수 있게 되어 있습니다.

한번 넣으면 딸깍 하면서 고정이 되고, 다시한번 누르면 튀어나오는 방식입니다.



위치할 자리는 여기 입니다.

예전 버전에는 바로 아래 부분에 GM tube 와 연결하는 pin 납땜자리가 있어 쉴딩을 해줘야 했지만,

버전업이 되면서 GM tube 연결 땜 자리는, 그 밑으로 위치하는 레이아웃으로 바뀌었습니다.



이왕 본 김에 GM tube 와 연결되는 pin 을 납땜해 줍니다.





9. Arduino FIO


이제 두뇌에 해당하는 Arduino FIO 를 작업합니다.



DEV-10116 이라고 되어 있네요.



LED가 반짝반짝 하는 윗부분이 밑으로 가야 하는지라 좀 아쉽습니다.



밑부분이지만 위로 가는 부분입니다.



위치는 여기가 되겠네요.

납땜할 자리가 가장 많습니다.

일단 mainboard 에 모든 다리에 pin 을 넣고 납땜해야 하고, 그다음 male pin 들을 Arduino FIO 에 납땜하여 다리를 만들어 줘야 합니다.




향후 firmware upgrade 를 위해 FTDI 인터페이스에도 납땜을 해 줍니다.

실제로 이런 모양이라고 합니다.


* Using a L-shaped plug and soldered low-profile sockets to program a Fio

https://www.arduino.cc/en/Main/ArduinoBoardFioProgramming



나중에 software 가 version up 되면 도전해 보겠습니다.

마침 FTDI breakout 보드도 있네요 :-)


* FTDI Serial Adapter 를 사용해 보자

http://chocoball.tistory.com/entry/Hardware-FTDI-FT232RL-using



지금까지의 모든 부붐을 올려 봤습니다. 호오오오!





10. Bluetooth module


micro SD 카드에 logging 을 하지만,

스마트폰으로 실시간 측정치를 확인하거나, 로그를 인터넷으로 바로 보내고 싶으면 Bluetooth 모듈이 필요합니다.



제품은 seeed 사의 BLEBee v2 입니다.

https://www.seeedstudio.com/BLEBee-v2.0.0-p-2461.html


따로 사려면 34.5 USD 하는군요.

AliExpress 에서 파는 XBEE 의 bluetooth 모듈과 호환이 되는지 많이 궁금합니다.


https://ko.aliexpress.com/item/Free-shipping-bluetooth-wireless-module-bluetooth-slave-HC-06-red-for-arduino/2046081268.html


기회가 되면 한번 실험해 보겠습니다.



Bluegiga BLE113-A-M256K 라는 모듈을 이용해서 만들었다고 합니다.



오리지날은 MiKro Labs 라고 합니다.

하지만 이미 website 는 가동되지 않고 있네요. ( www.mikro-labs.com )



Arduino FIO 의 밑단 부분에 세모로 선이 그어있는 부분에 꽂습니다.






11. 시험 가동


GM tube 를 제외하고 모든 부품이 실장되었습니다.

GM tube 를 연결하기 전에 납땜이 정상인지를 확인하고,

추가 작업을 진행하기 전에 수정사항이 있는지를 보기 위해 battery 를 연결하고 시험 가동을 해 봅니다.


동봉된 battery 는 1200mAh Li-Ion Polymer 입니다.



두근두근....



한번에 성공입니다!!!

사실 실패하면 다른 방도는 없었습니다.


역시 납땜시는 열을 최대한 짧게 가하고 완료하는게 정말 중요하네요. 오로지 이거 하나만 지키면서 납땜하였습니다.

오랜 동안 납땜에 투자한 시간이 보상받는 순간입니다.





12. Geiger Mueller Tube


방사능 측정용 센서는 pancake 형태인 센서 입니다.


* LND 7317

http://www.lndinc.com/products/geiger-mueller-tubes/7317/


특장점으로는 엄청 예민하다는 것과, alpha / beta / gamma 모두를 잡아낼 수 있다는 것입니다.

일반적으로 한가지나 두가지만 잡아낼 수 있는 센서와는 격을 달리합니다.


그래서 낱개 구매는 130 ~ 200 USD 정도 한다고 합니다.

bGeigie Nano kit 가격의 1/3 에 해당합니다. 그만큼 조심해서 다뤄야 합니다.



GM tube 의 표면이 찟기지 않게 하기 위해 철망을 붙여줘야 합니다.

여성들의 메니큐어 코팅제로 붙이면 나중에 메니큐어 제거재로 쉽게 분리 가능하다 하니, 준비합니다.



살살 제품을 꺼냅니다. 아주 얇은 피막으로 되어 있다고 씌여 있습니다.



뒷면이 위로 오게 뒤집어져 있습니다. 앞쪽은 얇은 피막이니까요.

only USA 에서만 생산되고 있습니다.

들어보면 꽤 무겁습니다. 무식한 작은 후라이팬처럼 생겼습니다.



앞면입니다. 찟어지지 않도록 살살...



다른 작업으로 진행하기 전에 얼른 금속망을 앞면에 붙여줍니다.

1분 이상 지긋이 누르라고 설명서에 나와 있으니, 지긋하게 눌러서 고정되게 합니다.




13. GM tube 연결


GM tube 와 고전압 회로와 연결하는 보드를 조립합니다.



보드에 선을 납땜해야 하는데, 극성이 선의 배열과 다릅니다.

이쁘게 납땜할 수 있도록 핀을 이용하여 선을 동그랗게 말아줍니다.


미리 투명 수축 튜브도 끼워 넣어 줍니다.



납땜을 이쁘게 하고, 수축튜브를 잘 씌운 다음, 열을 가하여 수축, 고정되게 합니다.




14. Case 고무에 동그랗게 구멍 뚫기


Pelican 1010 case 의 안쪽 뒷면은 고무로 기기를 안정되게 고정될 수 있도록 쿠션이 있습니다.

여기를 GM tube 가 돌출될 수 있도록 구멍을 뚫어야 합니다.



보드에 LND 7317 과 연결하고 아크릴에 고정시켜 봅니다.

이제야 고지가 눈앞에 보이네요.



케이스 뒷면에 센서가 돌출될 수 있도록 동그랗게 구멍을 뚫어 줍니다.

신기하게도 250ml 주스캔 윗부분과 크기가 똑같습니다. 주스캔을 이용하여 그림을 그린 다음 커터로 잘라주면 됩니다.



짜잔~!





FIN


이로써 모든 조립 작업이 완료되었습니다.

계획하고 구입하고 조립하기 까지, 장장 6년(계획)하고 3개월(실조립) 이 걸렸습니다.


왜 구동 모습이 없냐구요?

실제 구동 모습은 따로 글을 만들어서 차근차근 기록하겠습니다.

여기까지만 해도 진이 다 빠졌습니다.


And

Hardware | SSD1306 monochrome OLED 를 가지고 VU meter 를 만들어보자

|

1. SSD1306 OLED


SSD1306 monochrome OLED 0.96" 를 가지고 신나게 놀았습니다.


http://chocoball.tistory.com/entry/Hardware-SSD1306-128x64-monochrome-OLED


그러던 와중에 VU meter 를 구현한 분의 link 를 찾게 됩니다.

여기에 나와있는 모든 내용은 Arduino Forum 에 올린 "stievenart" 라는 분의 글을 따라한 것임을 밝힙니다.


- https://forum.arduino.cc/index.php?topic=403234.0


VU meter 라는 것은 예전에 전축을 보면, 소리의 강도를 나타내는 아나로그 미터기 입니다.


https://en.wikipedia.org/wiki/VU_meter



이런 멋진걸 구현해 놓네요.




2. Layout


위의 링크 그대로 참조해서 연결합니다.


 128X64 OLED | Arduino Nano
----------------------------
     GND     |     GND
     VCC     |     3.3V
     SDA     |     A4
     SDL     |     A5
----------------------------
  TSSR Audio |
----------------------------
    SLEEVE   |     GND
     TIP     |     A0
----------------------------


Pin 연결 모습입니다.





3. Bitmap 만들기


방법은 Bitmap 파일을 128x64 pixel 로 만들고,

그것을 code 화 하면 됩니다.


모든것은 link 에서 설명되어 있습니다.


https://forum.arduino.cc/index.php?topic=403234.0


Bitmap 을 LCD 용의 데이터로 만들어 주는 것은 "Image2GLCD" 이라는 어플이라고 합니다.


http://www.ablab.in/image2glcd-software/


아래 bitmap 파일은 이 project 를 만든 사람이 직접 구성한 사진 입니다.



위의 bitmap 을 LCD용으로 데이터화 하면 아래와 같이 된다고 하네요.

// VU meter background mask image:
static const unsigned char PROGMEM VUMeter[] = { 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x04, 0x80, 0x21, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x01, 0x98, 0x08, 0x06, 0x03, 0x80, 0x21, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0xA4, 0x10, 0x09, 0x00, 0x80, 0x21, 0x20, 0x07, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0xA4, 0x10, 0x06, 0x03, 0x00, 0x20, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x71, 0x80, 0xA4, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x0A, 0x40, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3C, 0x00, 0x00,
  0x00, 0x00, 0x3A, 0x40, 0x00, 0x00, 0x02, 0x01, 0x00, 0x40, 0x80, 0x07, 0x00, 0x20, 0x00, 0x00,
  0x00, 0x00, 0x42, 0x40, 0x00, 0x08, 0x02, 0x01, 0x08, 0x40, 0x80, 0x00, 0x00, 0x38, 0x00, 0x00,
  0x00, 0x00, 0x79, 0x80, 0x04, 0x08, 0x02, 0x01, 0x08, 0x81, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x02, 0x01, 0x08, 0x81, 0x11, 0x04, 0x00, 0x38, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x02, 0x01, 0x08, 0x81, 0x21, 0x04, 0x00, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x00, 0x84, 0x02, 0x04, 0x0F, 0xFF, 0xFF, 0xC3, 0xE2, 0x04, 0x00, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x00, 0xC2, 0x01, 0x07, 0xF0, 0x00, 0x00, 0x3B, 0xFE, 0x08, 0x40, 0x40, 0x08, 0x00,
  0x00, 0xFE, 0x00, 0x62, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xE8, 0x40, 0x80, 0x7F, 0x00,
  0x00, 0x00, 0x00, 0x21, 0x1E, 0x00, 0x04, 0x00, 0x80, 0x00, 0x7F, 0xFE, 0x80, 0x80, 0x08, 0x00,
  0x00, 0x00, 0x03, 0x31, 0xE0, 0x00, 0x04, 0x00, 0x80, 0x04, 0x01, 0xFF, 0xC1, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x07, 0x1E, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1F, 0xFA, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x07, 0xF0, 0x00, 0x40, 0x3B, 0x07, 0x60, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x34, 0x81, 0x90, 0xCC, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x00,
  0x00, 0x00, 0x0C, 0x00, 0x03, 0x30, 0x0C, 0x82, 0x90, 0x53, 0x20, 0x00, 0x07, 0xF8, 0x00, 0x00,
  0x00, 0x00, 0x70, 0x40, 0x00, 0xC8, 0x3B, 0x02, 0x60, 0x53, 0x20, 0x00, 0x00, 0xFE, 0x00, 0x00,
  0x00, 0x01, 0x80, 0x20, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x4C, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00,
  0x00, 0x06, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00,
  0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00,
  0x00, 0x30, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00,
  0x00, 0x00, 0x40, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
  0x00, 0x00, 0xA0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x02, 0x02, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x06, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x8C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x70, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};




4. Sketch


제작자가 만든 sketch 입니다.

한가지 주의할 점은, 원 제작자는 "SH1106" 을 사용했으므로, "SSD1306" 으로 모두 바꿔줘야 합니다.

수정할 곳은 3군데 입니다.


Library 는 Adafruit 용을 사용했으므로, 동일하게 사용하면 됩니다.


모두 SSD1306 으로 수정한 sketch 입니다.


/* OLEDMeter was written to utilize any 128x64 display. I have only seen marginal attempts to * animate meters and I hope this one will set a standard. Please feel free to modify and share * this code for any 128x64 LCD or OLED. OLEDMeter sketch was written for use with I2C SH1106. * This code must be modified to work with other display devices. * * Working portion of code was taken from Adafruit Example Sound Level Sketch for the * Adafruit Microphone Amplifier * https://learn.adafruit.com/adafruit-microphone-amplifier-breakout/measuring-sound-levels * * Remaining code was written by Greg Stievenart with no claim to or any images or information * provided in this code. Freely published May 26, 2016. * * Software to convert background mask to 128x64 at: http://www.ablab.in/image2glcd-software/ * * IMPORTANT: Sound source must be grounded to the Arduino or other MCU's to work. Usually the * base sleeve contact on TRS or TRRS connector is the ground. */ #include "Wire.h" // requried to run I2C SH1106 #include "SPI.h" // requried to run I2C SH1106 #include "Adafruit_GFX.h" // https://github.com/adafruit/Adafruit-GFX-Library #include "Adafruit_SSD1306.h" // https://github.com/wonho-maker/Adafruit_SH1106 #define OLED_RESET 4 // reset required for SH1106 Adafruit_SSD1306 display(OLED_RESET); // reset required for SH1106 int analogInput = A0; // analog input for outside audio source int hMeter = 65; // horizontal center for needle animation int vMeter = 85; // vertical center for needle animation (outside of dislay limits) int rMeter = 80; // length of needle animation or arch of needle travel const int sampleWindow = 50; // sample window width in mS (50 mS = 20Hz) unsigned int sample; // VU meter background mask image: static const unsigned char PROGMEM VUMeter[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x04, 0x80, 0x21, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x98, 0x08, 0x06, 0x03, 0x80, 0x21, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x10, 0x09, 0x00, 0x80, 0x21, 0x20, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x10, 0x06, 0x03, 0x00, 0x20, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x80, 0xA4, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x40, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x3A, 0x40, 0x00, 0x00, 0x02, 0x01, 0x00, 0x40, 0x80, 0x07, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x42, 0x40, 0x00, 0x08, 0x02, 0x01, 0x08, 0x40, 0x80, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x79, 0x80, 0x04, 0x08, 0x02, 0x01, 0x08, 0x81, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x02, 0x01, 0x08, 0x81, 0x11, 0x04, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x02, 0x01, 0x08, 0x81, 0x21, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x84, 0x02, 0x04, 0x0F, 0xFF, 0xFF, 0xC3, 0xE2, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x01, 0x07, 0xF0, 0x00, 0x00, 0x3B, 0xFE, 0x08, 0x40, 0x40, 0x08, 0x00, 0x00, 0xFE, 0x00, 0x62, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xE8, 0x40, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x21, 0x1E, 0x00, 0x04, 0x00, 0x80, 0x00, 0x7F, 0xFE, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x03, 0x31, 0xE0, 0x00, 0x04, 0x00, 0x80, 0x04, 0x01, 0xFF, 0xC1, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x1E, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1F, 0xFA, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x40, 0x3B, 0x07, 0x60, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x34, 0x81, 0x90, 0xCC, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x03, 0x30, 0x0C, 0x82, 0x90, 0x53, 0x20, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x70, 0x40, 0x00, 0xC8, 0x3B, 0x02, 0x60, 0x53, 0x20, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x01, 0x80, 0x20, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x4C, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x30, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x40, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xA0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x02, 0x02, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x06, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x8C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x70, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; void setup(){ pinMode(analogInput, INPUT); // analog input for outside audio source display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // needed for SH1106 display display.clearDisplay(); // clears display from any library info displayed } void loop(){ /*********************************************************************** Start of code taken from Adafruit Example Sound Level Sketch for the Adafruit Microphone Amplifier ************************************************************************/ unsigned long startMillis = millis(); // start of sample window unsigned int PeaktoPeak = 0; // peak-to-peak level unsigned int SignalMax = 0; unsigned int SignalMin = 1024; while ( millis() - startMillis < sampleWindow ){ sample = analogRead(analogInput); if (sample < 1024) { if (sample > SignalMax){ SignalMax = sample; // saves just the max levels } else if (sample < SignalMin){ SignalMin = sample; // saves just the min levels } } } PeaktoPeak = SignalMax - SignalMin; // max - min = peak-peak amplitude float MeterValue = PeaktoPeak * 330 / 1024; // convert volts to arrow information /**************************************************** End of code taken from Adafruit Sound Level Sketch *****************************************************/ MeterValue = MeterValue - 34; // shifts needle to zero position display.clearDisplay(); // refresh display for next step display.drawBitmap(0, 0, VUMeter, 128, 64, WHITE); // draws background int a1 = (hMeter + (sin(MeterValue / 57.296) * rMeter)); // meter needle horizontal coordinate int a2 = (vMeter - (cos(MeterValue / 57.296) * rMeter)); // meter needle vertical coordinate display.drawLine(a1, a2, hMeter, vMeter, WHITE); // draws needle display.display(); }




5. 구동


아래는 실제로 구동한 사진 입니다.

iPhone 에서는 Youtube 로 동영상을 play 하였습니다.


곡 제목은 제가 좋아하는 피아니스트인 Valentina Lisitsa 가 연주한, 제가 좋아하는 "베토벤 월광 제3악장" 입니다.

(Beethoven "Moonlight" Sonata op 27 # 2 Mov 3)


https://www.youtube.com/watch?v=zucBfXpCA6s



신기하게 잘 동작하는군요.

선명하게 눈금이 잘 보입니다.



가리키는 바늘도 잘 동작합니다.



눈금이 잘 반응하는게 보이죠?



흠흠... 좋습니다.



아래는 동영상 입니다.





FIN


우선 "stievenart" 님의 글을 구동 부분만 빼고 인용했음을 밝힙니다.

OLED 로 놀 수 있는 방법은 무궁무진한 것 같습니다.

And

Hardware | Adafruit SSD1306 128x64 1.3" monochrome OLED 를 사용해보자

|

1. OLED display


지금가지 AliExpress 에서 쉽게 구할 수 있는 0.95 ~ 0.96 inch 짜리 OLED display 를 가지고 놀았습니다.


* SSD1306 128x64 0.96" monochrome OLED

http://chocoball.tistory.com/entry/Hardware-SSD1306-128x64-monochrome-OLED


* SSD1331 96x64 0.95" full color OLED

- http://chocoball.tistory.com/entry/Hardware-SSD1331-96x64-full-color-OLED


추가로 지금 만들고 있는, "Safecast bGeigie Nano" 의 구성품을 보니, 마침 "Adafruit SSD1306 128x64 1.3inch" 가 달려있네요?!


* Hardware | Safecast bGeigie Nano 를 조립해 보자 - 1

http://chocoball.tistory.com/entry/Hardware-Safecast-bGeigie-Nano-1



이왕 OLED 를 가지고 놀기 시작한거, 끝가지 해보자 하고 구동시켜 봅니다.

조립 전에 제품이 정상작동 하는지도 보고싶구요.


Adafruit 는 거의 레퍼런스급 제품이고, AliExpress 을 통한 짝퉁 중국산이 아닌 제품으로 구동시켜 보는 것은 거의 처음인것 같습니다.




2. 외형


1.3" 다 보니, 지금까지의 0.95" / 0.96" 보다 확실히 큰 것을 느낄 수 있습니다.



뒷면입니다.

프린팅 된것도 선명하고, I2C로 사용시에는 SJ1 / SJ2 를 쇼트시키라고 표현도 되어 있습니다.


"5V READY" 라고 하네요. 자체 레귤레이터가 달려 있습니다.

단, 저는 기기에 무리를 주기 싫기 때문에 무조건 "3.3V" 로 구동시켜 보겠습니다.



그간 테스트 했던 OLED 와의 비교샷 입니다.



화면도 클 뿐만 아니라, pin 갯수도 많습니다.

SPI 대응도 되고 I2C 대응도 모두 될 수 있게 만들어져 있기 때문인것 같아요.





3.Layout


Pin 배열은 아래 link 를 참고하였습니다. (Adafruit 제조사 사이트)


https://learn.adafruit.com/monochrome-oled-breakouts/wiring-1-dot-3-128x64


   Adafruit  |   Arduino
   SSD1306   |   Nano
----------------------------
     Data    |     D9
     Clk     |     D10
     SA0(DC) |     D11
     Rst     |     D13
     CS      |     D12
     3v3     |
     Vin     |     3.3V
     GND     |     GND
----------------------------




실제 배선 모양입니다.





4.Sketch


소스는 Arduino IDE 에서,

아래처럼 "File > Examples > Adafruit SDD1306 > ssd1306_128x64_spi" 를 선택하면 됩니다.



원본 소스는 다음과 같습니다.






5. 구동


실제 구동한 동영상 입니다.

소스 코드와 제품 자체가 모두 Adafruit 가 만든 것이니 당연 잘 됩니다.

거기에 Arduino 진영과 Adafruit 가 협력하여 만든 Arduino Micro 까지 구비하여 구동해 봤습니다. (완전체)



당연 잘 돌아 갑니다.


이제 3형제 다 모여서 구동시켜 봅니다.



확실히 Adafruit 제품의 구동 속도가 제일 빠릅니다.

소스 및 pin 배열을 Hardware SPI 로 변경하고 동작시키면 더 빠르겠지요?




FIN

이제 OLED는 거의 다 사용해 본것 같네.

And

Hardware | SSD1306 128x64 monochrome OLED 를 사용해보자

|

1. 상태 표시


Arduino 를 하다 보면, 표시창을 이용하여 상태를 알고 싶어 집니다.

PC로 말할것 같으면 모니터 같은 것이죠.

반짝반짝 빛나는 LED 도 좋지만, 쿨한 작은 모니터도 좋습니다.


AliExpress 에서 뒤져본 결과, 이런 적은 display 가 있네요!





2. 주문


AliExpress 는 무료 배송이 감사합니다.


https://ko.aliexpress.com/item/1pcs-0-96-blue-0-96-inch-OLED-module-New-128X64-OLED-LCD-LED-Display-Module/32643950109.html





3. 도착


재미 있는 것은, 전원 pin 이름이 보통 "VCC" 인데, "VDD" 로 써져 있으며, "SCL" 을 "SCK" 로 써 있는 부분입니다.

아루래도 라이센스 부분을 피해가기 위해서 그런게 아닐까 합니다만, 사용하는데 지장은 없습니다.



드라이버 칩은 뒤에 가려져서 보이지 않는것 같습니다.



Full color OLED 와의 비교샷 입니다.

Full color OLED 의 자세한 이야기는 아래 link 를 참고해 주세요.


http://chocoball.tistory.com/entry/Hardware-SSD1331-96x64-full-color-OLED


SSD1306 의 datasheet 입니다.


SSD1306.pdf



세로는 확실히 monochrome 이 짧은게 보입니다만, 가로는 같아 보입니다.

확실히 full color OLED 의 보드가 복잡합니다.






4. Layout


빵판에서 Arduino 와 연결은 다음과 같이 하면 됩니다.


    SSD1306  | Arduino Nano
----------------------------
     GND     |     GND
     VDD     |     3.3V
     SCK     |     A5
     SDA     |     A4
----------------------------



아래는 실제 회로 구성입니다.





5. I2C vs. SPI


항상 궁금했던 것은 arduino 와의 interface 에서 I2C 와 SPI 의 차이가 궁금했습니다.

특히 OLED 디바이스는 이 두가지로 극명하게 갈립니다.


SPI 는 비싼 편이고, pin 수가 많습니다.

바로 느낌이 SPI 아 좋아 보이죠? 속도면에서는 그렇습니다.

다만, 동시에 연결은 I2C 가 좋다고 하네요.



아래 link 들에서 참고하였습니다.


http://luma-oled.readthedocs.io/en/latest/hardware.html

https://www.youtube.com/watch?v=vECfvdBLHI0




6. I2C detect


본 OLED device 가 어떤 I2C 어드레스를 갖는지 궁금할 땐, "i2cdetect" 라는 sketch 를 사용하여 확인 가능합니다.


#include "Wire.h"
#include "i2cdetect.h"

void setup() {
	Wire.begin();
	Serial.begin(9600);
	Serial.println("i2cdetect example\n");
	Serial.print("Scanning address range 0x03-0x77\n\n");
}

void loop() {
	i2cdetect(); // default range from 0x03 to 0x77
	delay(2000);
}


결과는 "0x3c" 가 나옵니다.

향후, sketch 의 소스를 보고 해당 값들이 잘 들어갔는지 확인할 수 있습니다.





7. Adafruit Sketch


OLED 의 동작을 확인할 수 있는 sample sketch 는 여러개가 있습니다.

유명한 것은 Adafruit 와 U8g 입니다.


우선 Adafruit 를 이용해 봅니다.

아래 link 에서 library 등을 다운로드 받아 arduino 폴더에 설치합니다.


https://learn.adafruit.com/monochrome-oled-breakouts/arduino-library-and-examples


참고로 제품이 128x64 이므로, "ssd1306_128x64_i2c" 를 선택하면 동작하지 않습니다.

i2c 의 다른 셈플인 "ssd1306_128x32_i2c" 를 선택해야지만 정상으로 동작합니다.


제품 사이즈도 128x64 가 아니라 128x32 가 아닌가라는 생각도 해 봅니다.



Sketch source 는 다음과 같습니다.




아래는 동작 동영상 입니다.

화려한 내용을 보여줍니다. OLED 를 사용한다는 것이 실감납니다.





8. U8g Sketch


그 다음으로 유명한 U8g library 를 사용해 봅니다.

아래 link 를 참고하였습니다.


https://github.com/olikraus/u8glib/



주의할 점은, 범용 library 로 작성되어 있어서,

테스트할 device 의 정확한 방식을 정해줘야 합니다.


아래 스샷처럼 정확하게 선택해 줍니다.

다른 I2C 도 있지만, Fast I2C 를 선택하면 가장 빠른 퍼포먼스를 보여줍니다.



Sketch source 는 다음과 같습니다.


/*

  GraphicsTest.pde
  
  >>> Before compiling: Please remove comment from the constructor of the 
  >>> connected graphics display (see below).
  
  Universal 8bit Graphics Library, https://github.com/olikraus/u8glib/
  
  Copyright (c) 2012, olikraus@gmail.com
  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification, 
  are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this list 
    of conditions and the following disclaimer.
    
  * Redistributions in binary form must reproduce the above copyright notice, this 
    list of conditions and the following disclaimer in the documentation and/or other 
    materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  


*/


#include "U8glib.h"

// setup u8g object, please remove comment from one of the following constructor calls
// IMPORTANT NOTE: The following list is incomplete. The complete list of supported 
// devices with all constructor calls is here: https://github.com/olikraus/u8glib/wiki/device
//U8GLIB_NHD27OLED_BW u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD27OLED_2X_BW u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD27OLED_GR u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD27OLED_2X_GR u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD31OLED_BW u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD31OLED_2X_BW u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD31OLED_GR u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD31OLED_2X_GR u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGS102 u8g(13, 11, 10, 9, 8);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGM132 u8g(13, 11, 10, 9);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGM128 u8g(13, 11, 10, 9);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGM128_2X u8g(13, 11, 10, 9);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_ST7920_128X64_1X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_128X64_4X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_128X64_1X u8g(18, 16, 17);	// SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_128X64_4X u8g(18, 16, 17);	// SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_192X32_1X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_192X32_4X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_192X32_1X u8g(18, 16, 17);	// SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_192X32_4X u8g(18, 16, 17);	// SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_192X32_1X u8g(13, 11, 10);	// SPI Com: SCK = en = 13, MOSI = rw = 11, CS = di = 10
//U8GLIB_ST7920_192X32_4X u8g(10);		// SPI Com: SCK = en = 13, MOSI = rw = 11, CS = di = 10, HW SPI
//U8GLIB_ST7920_202X32_1X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_202X32_4X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_202X32_1X u8g(18, 16, 17);	// SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_202X32_4X u8g(18, 16, 17);	// SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_LM6059 u8g(13, 11, 10, 9);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_LM6063 u8g(13, 11, 10, 9);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGXL160_BW u8g(10, 9);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGXL160_GR u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGXL160_2X_BW u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGXL160_2X_GR u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8
//U8GLIB_PCF8812 u8g(13, 11, 10, 9, 8);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8
//U8GLIB_KS0108_128 u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 14, 15, 17, 16); 		// 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs1=14, cs2=15,di=17,rw=16
//U8GLIB_LC7981_160X80 u8g(8, 9, 10, 11, 4, 5, 6, 7,  18, 14, 15, 17, 16); 	// 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs=14 ,di=15,rw=17, reset = 16
//U8GLIB_LC7981_240X64 u8g(8, 9, 10, 11, 4, 5, 6, 7,  18, 14, 15, 17, 16); 	// 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs=14 ,di=15,rw=17, reset = 16
//U8GLIB_LC7981_240X128 u8g(8, 9, 10, 11, 4, 5, 6, 7,  18, 14, 15, 17, 16); 	// 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs=14 ,di=15,rw=17, reset = 16
//U8GLIB_ILI9325D_320x240 u8g(18,17,19,U8G_PIN_NONE,16 );  			// 8Bit Com: D0..D7: 0,1,2,3,4,5,6,7 en=wr=18, cs=17, rs=19, rd=U8G_PIN_NONE, reset = 16
//U8GLIB_SBN1661_122X32 u8g(8,9,10,11,4,5,6,7,14,15, 17, U8G_PIN_NONE, 16); 	// 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 cs1=14, cs2=15,di=17,rw=16,reset = 16
//U8GLIB_SSD1306_128X64 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1306_128X64 u8g(4, 5, 6, 7);	// SW SPI Com: SCK = 4, MOSI = 5, CS = 6, A0 = 7 (new white HalTec OLED)
//U8GLIB_SSD1306_128X64 u8g(10, 9);		// HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);	// I2C / TWI 
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST);	// Fast I2C / TWI 
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK);	// Display which does not send AC
//U8GLIB_SSD1306_ADAFRUIT_128X64 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1306_ADAFRUIT_128X64 u8g(10, 9);		// HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_SSD1306_128X32 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1306_128X32 u8g(10, 9);             // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE);	// I2C / TWI 
//U8GLIB_SSD1306_64X48 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1306_64X48 u8g(10, 9);             // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_SSD1306_64X48 u8g(U8G_I2C_OPT_NONE);	// I2C / TWI 
//U8GLIB_SH1106_128X64 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SH1106_128X64 u8g(4, 5, 6, 7);	// SW SPI Com: SCK = 4, MOSI = 5, CS = 6, A0 = 7 (new blue HalTec OLED)
//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE);	// I2C / TWI 
//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST);	// Dev 0, Fast I2C / TWI
//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NO_ACK);	// Display which does not send ACK
//U8GLIB_SSD1309_128X64 u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1327_96X96_GR u8g(U8G_I2C_OPT_NONE);	// I2C
//U8GLIB_SSD1327_96X96_2X_GR u8g(U8G_I2C_OPT_NONE);	// I2C
//U8GLIB_UC1611_DOGM240 u8g(U8G_I2C_OPT_NONE);	// I2C
//U8GLIB_UC1611_DOGM240 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_UC1611_DOGM240 u8g(10, 9);		// HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_UC1611_DOGM240 u8g(10, 9);		// HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_UC1611_DOGM240 u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 3, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs=3, di/a0=17,rw=16
//U8GLIB_UC1611_DOGXL240 u8g(U8G_I2C_OPT_NONE);	// I2C
//U8GLIB_UC1611_DOGXL240 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_UC1611_DOGXL240 u8g(10, 9);		// HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_UC1611_DOGXL240 u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 3, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs=3, di/a0=17,rw=16
//U8GLIB_NHD_C12864 u8g(13, 11, 10, 9, 8);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_NHD_C12832 u8g(13, 11, 10, 9, 8);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_LD7032_60x32 u8g(13, 11, 10, 9, 8);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_LD7032_60x32 u8g(11, 12, 9, 10, 8);	// SPI Com: SCK = 11, MOSI = 12, CS = 9, A0 = 10, RST = 8  (SW SPI Nano Board)
//U8GLIB_UC1608_240X64 u8g(13, 11, 10, 9, 8);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64_2X u8g(13, 11, 10, 9, 8);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64 u8g(10, 9, 8);	// HW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64_2X u8g(10, 9, 8);	// HW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X u8g(13, 11, 10, 9, 8);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64_2X u8g(13, 11, 10, 9, 8);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64 u8g(10, 9, 8);	// HW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64_2X u8g(10, 9, 8);	// HW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_T6963_240X128 u8g(8, 9, 10, 11, 4, 5, 6, 7, 14, 15, 17, 18, 16); // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7, cs=14, a0=15, wr=17, rd=18, reset=16
//U8GLIB_T6963_128X128 u8g(8, 9, 10, 11, 4, 5, 6, 7, 14, 15, 17, 18, 16); // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7, cs=14, a0=15, wr=17, rd=18, reset=16
//U8GLIB_T6963_240X64 u8g(8, 9, 10, 11, 4, 5, 6, 7, 14, 15, 17, 18, 16); // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7, cs=14, a0=15, wr=17, rd=18, reset=16
//U8GLIB_T6963_128X64 u8g(8, 9, 10, 11, 4, 5, 6, 7, 14, 15, 17, 18, 16); // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7, cs=14, a0=15, wr=17, rd=18, reset=16
//U8GLIB_HT1632_24X16 u8g(3, 2, 4);		// WR = 3, DATA = 2, CS = 4
//U8GLIB_SSD1351_128X128_332 u8g(13, 11, 8, 9, 7); // Arduino UNO: SW SPI Com: SCK = 13, MOSI = 11, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128_332 u8g(76, 75, 8, 9, 7); // Arduino DUE: SW SPI Com: SCK = 13, MOSI = 11, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128_332 u8g(8, 9, 7); // Arduino: HW SPI Com: SCK = 13, MOSI = 11, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128_HICOLOR u8g(76, 75, 8, 9, 7); // Arduino DUE, SW SPI Com: SCK = 76, MOSI = 75, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128_HICOLOR u8g(8, 9, 7); // Arduino, HW SPI Com: SCK = 76, MOSI = 75, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128GH_332 u8g(8, 9, 7); // Arduino, HW SPI Com: SCK = 76, MOSI = 75, CS = 8, A0 = 9, RESET = 7 (Freetronics OLED)
//U8GLIB_SSD1351_128X128GH_HICOLOR u8g(8, 9, 7); // Arduino, HW SPI Com: SCK = 76, MOSI = 75, CS = 8, A0 = 9, RESET = 7 (Freetronics OLED)

void u8g_prepare(void) {
  u8g.setFont(u8g_font_6x10);
  u8g.setFontRefHeightExtendedText();
  u8g.setDefaultForegroundColor();
  u8g.setFontPosTop();
}

void u8g_box_frame(uint8_t a) {
  u8g.drawStr( 0, 0, "drawBox");
  u8g.drawBox(5,10,20,10);
  u8g.drawBox(10+a,15,30,7);
  u8g.drawStr( 0, 30, "drawFrame");
  u8g.drawFrame(5,10+30,20,10);
  u8g.drawFrame(10+a,15+30,30,7);
}

void u8g_disc_circle(uint8_t a) {
  u8g.drawStr( 0, 0, "drawDisc");
  u8g.drawDisc(10,18,9);
  u8g.drawDisc(24+a,16,7);
  u8g.drawStr( 0, 30, "drawCircle");
  u8g.drawCircle(10,18+30,9);
  u8g.drawCircle(24+a,16+30,7);
}

void u8g_r_frame(uint8_t a) {
  u8g.drawStr( 0, 0, "drawRFrame/Box");
  u8g.drawRFrame(5, 10,40,30, a+1);
  u8g.drawRBox(50, 10,25,40, a+1);
}

void u8g_string(uint8_t a) {
  u8g.drawStr(30+a,31, " 0");
  u8g.drawStr90(30,31+a, " 90");
  u8g.drawStr180(30-a,31, " 180");
  u8g.drawStr270(30,31-a, " 270");
}

void u8g_line(uint8_t a) {
  u8g.drawStr( 0, 0, "drawLine");
  u8g.drawLine(7+a, 10, 40, 55);
  u8g.drawLine(7+a*2, 10, 60, 55);
  u8g.drawLine(7+a*3, 10, 80, 55);
  u8g.drawLine(7+a*4, 10, 100, 55);
}

void u8g_triangle(uint8_t a) {
  uint16_t offset = a;
  u8g.drawStr( 0, 0, "drawTriangle");
  u8g.drawTriangle(14,7, 45,30, 10,40);
  u8g.drawTriangle(14+offset,7-offset, 45+offset,30-offset, 57+offset,10-offset);
  u8g.drawTriangle(57+offset*2,10, 45+offset*2,30, 86+offset*2,53);
  u8g.drawTriangle(10+offset,40+offset, 45+offset,30+offset, 86+offset,53+offset);
}

void u8g_ascii_1() {
  char s[2] = " ";
  uint8_t x, y;
  u8g.drawStr( 0, 0, "ASCII page 1");
  for( y = 0; y < 6; y++ ) {
    for( x = 0; x < 16; x++ ) {
      s[0] = y*16 + x + 32;
      u8g.drawStr(x*7, y*10+10, s);
    }
  }
}

void u8g_ascii_2() {
  char s[2] = " ";
  uint8_t x, y;
  u8g.drawStr( 0, 0, "ASCII page 2");
  for( y = 0; y < 6; y++ ) {
    for( x = 0; x < 16; x++ ) {
      s[0] = y*16 + x + 160;
      u8g.drawStr(x*7, y*10+10, s);
    }
  }
}

void u8g_extra_page(uint8_t a)
{
  if ( u8g.getMode() == U8G_MODE_HICOLOR || u8g.getMode() == U8G_MODE_R3G3B2) {
    /* draw background (area is 128x128) */
    u8g_uint_t r, g, b;
    b = a << 5;
    for( g = 0; g < 64; g++ )
    {
      for( r = 0; r < 64; r++ )
      {
	u8g.setRGB(r<<2, g<<2, b );
	u8g.drawPixel(g, r);
      }
    }
    u8g.setRGB(255,255,255);
    u8g.drawStr( 66, 0, "Color Page");
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT )
  {
    u8g.drawStr( 66, 0, "Gray Level");
    u8g.setColorIndex(1);
    u8g.drawBox(0, 4, 64, 32);    
    u8g.drawBox(70, 20, 4, 12);
    u8g.setColorIndex(2);
    u8g.drawBox(0+1*a, 4+1*a, 64-2*a, 32-2*a);
    u8g.drawBox(74, 20, 4, 12);
    u8g.setColorIndex(3);
    u8g.drawBox(0+2*a, 4+2*a, 64-4*a, 32-4*a);
    u8g.drawBox(78, 20, 4, 12);
  }
  else
  {
    u8g.drawStr( 0, 12, "setScale2x2");
    u8g.setScale2x2();
    u8g.drawStr( 0, 6+a, "setScale2x2");
    u8g.undoScale();
  }
}


uint8_t draw_state = 0;

void draw(void) {
  u8g_prepare();
  switch(draw_state >> 3) {
    case 0: u8g_box_frame(draw_state&7); break;
    case 1: u8g_disc_circle(draw_state&7); break;
    case 2: u8g_r_frame(draw_state&7); break;
    case 3: u8g_string(draw_state&7); break;
    case 4: u8g_line(draw_state&7); break;
    case 5: u8g_triangle(draw_state&7); break;
    case 6: u8g_ascii_1(); break;
    case 7: u8g_ascii_2(); break;
    case 8: u8g_extra_page(draw_state&7); break;
  }
}

void setup(void) {

  // flip screen, if required
  //u8g.setRot180();

#if defined(ARDUINO)
  pinMode(13, OUTPUT);           
  digitalWrite(13, HIGH);  
#endif
}

void loop(void) {
  
  // picture loop  
  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );
  
  // increase the state
  draw_state++;
  if ( draw_state >= 9*8 )
    draw_state = 0;
  
  // rebuild the picture after some delay
  //delay(150);

}


가장 빠르지만, 아래처럼 arduino 의 빨간 led 가 미친듯이 점멸합니다.

아마 process 를 많이 사용하는 듯 합니다.



U8g library 에 "Rotation" 셈플도 있어서 확인해 봤습니다.

글씨도 세로로 바로 회전할 수 있는게 신기합니다.


Sketch 는 다음과 같습니다.


/*

  Rotation.pde
  
  Example code for RotXXX functions.
  
  >>> Before compiling: Please remove comment from the constructor of the 
  >>> connected graphics display (see below).
  
  Universal 8bit Graphics Library, https://github.com/olikraus/u8glib/
  
  Copyright (c) 2012, olikraus@gmail.com
  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification, 
  are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this list 
    of conditions and the following disclaimer.
    
  * Redistributions in binary form must reproduce the above copyright notice, this 
    list of conditions and the following disclaimer in the documentation and/or other 
    materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
  
*/


#include "U8glib.h"

// setup u8g object, please remove comment from one of the following constructor calls
// IMPORTANT NOTE: The following list is incomplete. The complete list of supported 
// devices with all constructor calls is here: https://github.com/olikraus/u8glib/wiki/device
//U8GLIB_NHD27OLED_BW u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD27OLED_2X_BW u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD27OLED_GR u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD27OLED_2X_GR u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD31OLED_BW u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD31OLED_2X_BW u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD31OLED_GR u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_NHD31OLED_2X_GR u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGS102 u8g(13, 11, 10, 9, 8);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGM132 u8g(13, 11, 10, 9);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGM128 u8g(13, 11, 10, 9);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGM128_2X u8g(13, 11, 10, 9);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_ST7920_128X64_1X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_128X64_4X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_128X64_1X u8g(18, 16, 17);	// SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_128X64_4X u8g(18, 16, 17);	// SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_192X32_1X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_192X32_4X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_192X32_1X u8g(18, 16, 17);	// SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_192X32_4X u8g(18, 16, 17);	// SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_192X32_1X u8g(13, 11, 10);	// SPI Com: SCK = en = 13, MOSI = rw = 11, CS = di = 10
//U8GLIB_ST7920_192X32_4X u8g(10);		// SPI Com: SCK = en = 13, MOSI = rw = 11, CS = di = 10, HW SPI
//U8GLIB_ST7920_202X32_1X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_202X32_4X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16
//U8GLIB_ST7920_202X32_1X u8g(18, 16, 17);	// SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_202X32_4X u8g(18, 16, 17);	// SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_LM6059 u8g(13, 11, 10, 9);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_LM6063 u8g(13, 11, 10, 9);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGXL160_BW u8g(10, 9);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGXL160_GR u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGXL160_2X_BW u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_DOGXL160_2X_GR u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8
//U8GLIB_PCF8812 u8g(13, 11, 10, 9, 8);		// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8
//U8GLIB_KS0108_128 u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 14, 15, 17, 16); 		// 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs1=14, cs2=15,di=17,rw=16
//U8GLIB_LC7981_160X80 u8g(8, 9, 10, 11, 4, 5, 6, 7,  18, 14, 15, 17, 16); 	// 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs=14 ,di=15,rw=17, reset = 16
//U8GLIB_LC7981_240X64 u8g(8, 9, 10, 11, 4, 5, 6, 7,  18, 14, 15, 17, 16); 	// 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs=14 ,di=15,rw=17, reset = 16
//U8GLIB_LC7981_240X128 u8g(8, 9, 10, 11, 4, 5, 6, 7,  18, 14, 15, 17, 16); 	// 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs=14 ,di=15,rw=17, reset = 16
//U8GLIB_ILI9325D_320x240 u8g(18,17,19,U8G_PIN_NONE,16 );  			// 8Bit Com: D0..D7: 0,1,2,3,4,5,6,7 en=wr=18, cs=17, rs=19, rd=U8G_PIN_NONE, reset = 16
//U8GLIB_SBN1661_122X32 u8g(8,9,10,11,4,5,6,7,14,15, 17, U8G_PIN_NONE, 16); 	// 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 cs1=14, cs2=15,di=17,rw=16,reset = 16
//U8GLIB_SSD1306_128X64 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1306_128X64 u8g(4, 5, 6, 7);	// SW SPI Com: SCK = 4, MOSI = 5, CS = 6, A0 = 7 (new white HalTec OLED)
//U8GLIB_SSD1306_128X64 u8g(10, 9);		// HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);	// I2C / TWI 
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST);	// Fast I2C / TWI 
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK);	// Display which does not send AC
//U8GLIB_SSD1306_ADAFRUIT_128X64 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1306_ADAFRUIT_128X64 u8g(10, 9);		// HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_SSD1306_128X32 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1306_128X32 u8g(10, 9);             // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE);	// I2C / TWI 
//U8GLIB_SSD1306_64X48 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1306_64X48 u8g(10, 9);             // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_SSD1306_64X48 u8g(U8G_I2C_OPT_NONE);	// I2C / TWI 
//U8GLIB_SH1106_128X64 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SH1106_128X64 u8g(4, 5, 6, 7);	// SW SPI Com: SCK = 4, MOSI = 5, CS = 6, A0 = 7 (new blue HalTec OLED)
//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE);	// I2C / TWI 
//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST);	// Dev 0, Fast I2C / TWI
//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NO_ACK);	// Display which does not send ACK
//U8GLIB_SSD1309_128X64 u8g(13, 11, 10, 9);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1327_96X96_GR u8g(U8G_I2C_OPT_NONE);	// I2C
//U8GLIB_SSD1327_96X96_2X_GR u8g(U8G_I2C_OPT_NONE);	// I2C
//U8GLIB_UC1611_DOGM240 u8g(U8G_I2C_OPT_NONE);	// I2C
//U8GLIB_UC1611_DOGM240 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_UC1611_DOGM240 u8g(10, 9);		// HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_UC1611_DOGM240 u8g(10, 9);		// HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_UC1611_DOGM240 u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 3, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs=3, di/a0=17,rw=16
//U8GLIB_UC1611_DOGXL240 u8g(U8G_I2C_OPT_NONE);	// I2C
//U8GLIB_UC1611_DOGXL240 u8g(13, 11, 10, 9);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_UC1611_DOGXL240 u8g(10, 9);		// HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)
//U8GLIB_UC1611_DOGXL240 u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 3, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs=3, di/a0=17,rw=16
//U8GLIB_NHD_C12864 u8g(13, 11, 10, 9, 8);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_NHD_C12832 u8g(13, 11, 10, 9, 8);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_LD7032_60x32 u8g(13, 11, 10, 9, 8);	// SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_LD7032_60x32 u8g(11, 12, 9, 10, 8);	// SPI Com: SCK = 11, MOSI = 12, CS = 9, A0 = 10, RST = 8  (SW SPI Nano Board)
//U8GLIB_UC1608_240X64 u8g(13, 11, 10, 9, 8);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64_2X u8g(13, 11, 10, 9, 8);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64 u8g(10, 9, 8);	// HW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64_2X u8g(10, 9, 8);	// HW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X u8g(13, 11, 10, 9, 8);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64_2X u8g(13, 11, 10, 9, 8);	// SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64 u8g(10, 9, 8);	// HW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_UC1608_240X64_2X u8g(10, 9, 8);	// HW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, RST = 8
//U8GLIB_T6963_240X128 u8g(8, 9, 10, 11, 4, 5, 6, 7, 14, 15, 17, 18, 16); // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7, cs=14, a0=15, wr=17, rd=18, reset=16
//U8GLIB_T6963_128X128 u8g(8, 9, 10, 11, 4, 5, 6, 7, 14, 15, 17, 18, 16); // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7, cs=14, a0=15, wr=17, rd=18, reset=16
//U8GLIB_T6963_240X64 u8g(8, 9, 10, 11, 4, 5, 6, 7, 14, 15, 17, 18, 16); // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7, cs=14, a0=15, wr=17, rd=18, reset=16
//U8GLIB_T6963_128X64 u8g(8, 9, 10, 11, 4, 5, 6, 7, 14, 15, 17, 18, 16); // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7, cs=14, a0=15, wr=17, rd=18, reset=16
//U8GLIB_HT1632_24X16 u8g(3, 2, 4);		// WR = 3, DATA = 2, CS = 4
//U8GLIB_SSD1351_128X128_332 u8g(13, 11, 8, 9, 7); // Arduino UNO: SW SPI Com: SCK = 13, MOSI = 11, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128_332 u8g(76, 75, 8, 9, 7); // Arduino DUE: SW SPI Com: SCK = 13, MOSI = 11, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128_332 u8g(8, 9, 7); // Arduino: HW SPI Com: SCK = 13, MOSI = 11, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128_HICOLOR u8g(76, 75, 8, 9, 7); // Arduino DUE, SW SPI Com: SCK = 76, MOSI = 75, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128_HICOLOR u8g(8, 9, 7); // Arduino, HW SPI Com: SCK = 76, MOSI = 75, CS = 8, A0 = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)
//U8GLIB_SSD1351_128X128GH_332 u8g(8, 9, 7); // Arduino, HW SPI Com: SCK = 76, MOSI = 75, CS = 8, A0 = 9, RESET = 7 (Freetronics OLED)
//U8GLIB_SSD1351_128X128GH_HICOLOR u8g(8, 9, 7); // Arduino, HW SPI Com: SCK = 76, MOSI = 75, CS = 8, A0 = 9, RESET = 7 (Freetronics OLED)

uint8_t offset = 0;

void draw(void) {
  // graphic commands to redraw the complete screen should be placed here  
  u8g.setFont(u8g_font_unifont);
  u8g.drawStr( 0+0, 20+0, "Hello!");
  u8g.drawStr( 0+2, 20+16, "Hello!");
  
  u8g.drawBox(0, 0, 3, 3);
  u8g.drawBox(u8g.getWidth()-6, 0, 6, 6);
  u8g.drawBox(u8g.getWidth()-9, u8g.getHeight()-9, 9, 9);
  u8g.drawBox(0, u8g.getHeight()-12, 12, 12);  
}

void setup(void) {
}


void rotate(void) {
  static  uint8_t dir = 0;
  static  unsigned long next_rotation = 0;
  
  if ( next_rotation < millis() )
  {
    switch(dir) {
      case 0: u8g.undoRotation(); break;
      case 1: u8g.setRot90(); break;
      case 2: u8g.setRot180(); break;
      case 3: u8g.setRot270(); offset = ( offset + 1 ) & 0x0f; break;
    }
    
    dir++;
    dir &= 3;
    next_rotation = millis();
    next_rotation += 1000;
  }
}

void loop(void) {
  // screen rotation 
  rotate();
  
  // picture loop
  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );
  
  // rebuild the picture after some delay
  delay(100);
}

동작 동영상은 다음과 같습니다.





9. U8g2 Sketch


U8g 를 작성하신 분이, 더이상 U8g를 업그래이드 하지 않고 U8g2 를 개발하셨습니다.


https://github.com/olikraus/u8g2/



여기서도 마찬가지로,

보유하고 있는 device 를 로딩할 수 있도록 찾고 comment out 해줍니다.



Sketch 는 다음과 같습니다.


/*

  GraphicsTest.ino

  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)

  Copyright (c) 2016, olikraus@gmail.com
  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification, 
  are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this list 
    of conditions and the following disclaimer.
    
  * Redistributions in binary form must reproduce the above copyright notice, this 
    list of conditions and the following disclaimer in the documentation and/or other 
    materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  

*/

#include "Arduino.h"
#include "U8g2lib.h"

#ifdef U8X8_HAVE_HW_SPI
#include "SPI.h"
#endif
#ifdef U8X8_HAVE_HW_I2C
#include "Wire.h"
#endif


/*
  U8glib Example Overview:
    Frame Buffer Examples: clearBuffer/sendBuffer. Fast, but may not work with all Arduino boards because of RAM consumption
    Page Buffer Examples: firstPage/nextPage. Less RAM usage, should work with all Arduino boards.
    U8x8 Text Only Example: No RAM usage, direct communication with display controller. No graphics, 8x8 Text only.
    
*/

// Please UNCOMMENT one of the contructor lines below
// U8g2 Contructor List (Frame Buffer)
// The complete list is available here: https://github.com/olikraus/u8g2/wiki/u8g2setupcpp
// Please update the pin numbers according to your setup. Use U8X8_PIN_NONE if the reset pin is not connected
//U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 12, /* dc=*/ 4, /* reset=*/ 6);	// Arduboy (Production, Kickstarter Edition)
//U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_F_3W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* reset=*/ 8);
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);   // All Boards without Reset of the Display
//U8G2_SSD1306_128X64_NONAME_F_6800 u8g2(U8G2_R0, 13, 11, 2, 3, 4, 5, 6, A4, /*enable=*/ 7, /*cs=*/ 10, /*dc=*/ 9, /*reset=*/ 8);
//U8G2_SSD1306_128X64_NONAME_F_8080 u8g2(U8G2_R0, 13, 11, 2, 3, 4, 5, 6, A4, /*enable=*/ 7, /*cs=*/ 10, /*dc=*/ 9, /*reset=*/ 8);
//U8G2_SSD1306_128X64_VCOMH0_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);	// same as the NONAME variant, but maximizes setContrast() range
//U8G2_SH1106_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//U8G2_SH1106_128X64_VCOMH0_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);		// same as the NONAME variant, but maximizes setContrast() range
//U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 21, /* data=*/ 20, /* reset=*/ U8X8_PIN_NONE);   // Adafruit Feather M0 Basic Proto + FeatherWing OLED
//U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);   // Adafruit Feather ESP8266/32u4 Boards + FeatherWing OLED
//U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);  // Adafruit ESP8266/32u4/ARM Boards + FeatherWing OLED
//U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ SCL, /* data=*/ SDA);   // pin remapping with ESP8266 HW I2C
//U8G2_SSD1306_64X48_ER_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);   // EastRising 0.66" OLED breakout board, Uno: A4=SDA, A5=SCL, 5V powered
//U8G2_SSD1306_64X32_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); 
//U8G2_SSD1306_96X16_ER_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);   // EastRising 0.69" OLED
//U8G2_SSD1322_NHD_256X64_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);	// Enable U8G2_16BIT in u8g2.h
//U8G2_SSD1322_NHD_256X64_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);	// Enable U8G2_16BIT in u8g2.h
//U8G2_SSD1325_NHD_128X64_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); 
//U8G2_SSD1325_NHD_128X64_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);	
//U8G2_SSD1327_SEEED_96X96_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);	// Seeedstudio Grove OLED 96x96
//U8G2_SSD1327_SEEED_96X96_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);	// Seeedstudio Grove OLED 96x96
//U8G2_SSD1329_128X96_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SSD1329_128X96_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SSD1305_128X32_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SSD1305_128X32_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_SSD1309_128X64_NONAME0_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);  
//U8G2_SSD1309_128X64_NONAME0_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);  
//U8G2_SSD1309_128X64_NONAME2_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);  
//U8G2_SSD1309_128X64_NONAME2_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);  
//U8G2_LD7032_60X32_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 11, /* data=*/ 12, /* cs=*/ 9, /* dc=*/ 10, /* reset=*/ 8);	// SW SPI Nano Board
//U8G2_LD7032_60X32_F_4W_SW_I2C u8g2(U8G2_R0, /* clock=*/ 11, /* data=*/ 12, /* reset=*/ U8X8_PIN_NONE);	// NOT TESTED!
//U8G2_UC1701_EA_DOGS102_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_UC1701_EA_DOGS102_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_PCD8544_84X48_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);  // Nokia 5110 Display
//U8G2_PCD8544_84X48_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); 		// Nokia 5110 Display
//U8G2_PCF8812_96X65_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);	// Could be also PCF8814
//U8G2_PCF8812_96X65_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);						// Could be also PCF8814
//U8G2_KS0108_128X64_F u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 18, /*dc=*/ 17, /*cs0=*/ 14, /*cs1=*/ 15, /*cs2=*/ U8X8_PIN_NONE, /* reset=*/  U8X8_PIN_NONE); 	// Set R/W to low!
//U8G2_KS0108_ERM19264_F u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 18, /*dc=*/ 17, /*cs0=*/ 14, /*cs1=*/ 15, /*cs2=*/ 16, /* reset=*/  U8X8_PIN_NONE); 	// Set R/W to low!
//U8G2_ST7920_192X32_F_8080 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 18, /*cs=*/ U8X8_PIN_NONE, /*dc=*/ 17, /*reset=*/ U8X8_PIN_NONE);
//U8G2_ST7920_192X32_F_SW_SPI u8g2(U8G2_R0, /* clock=*/ 18 /* A4 */ , /* data=*/ 16 /* A2 */, /* CS=*/ 17 /* A3 */, /* reset=*/ U8X8_PIN_NONE);
//U8G2_ST7920_128X64_F_8080 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 18 /* A4 */, /*cs=*/ U8X8_PIN_NONE, /*dc/rs=*/ 17 /* A3 */, /*reset=*/ 15 /* A1 */);	// Remember to set R/W to 0 
//U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /* clock=*/ 18 /* A4 */ , /* data=*/ 16 /* A2 */, /* CS=*/ 17 /* A3 */, /* reset=*/ U8X8_PIN_NONE);
//U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* CS=*/ 10, /* reset=*/ 8);
//U8G2_ST7920_128X64_F_HW_SPI u8g2(U8G2_R0, /* CS=*/ 10, /* reset=*/ 8);
//U8G2_ST7565_EA_DOGM128_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_ST7565_EA_DOGM128_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_ST7565_64128N_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_ST7565_64128N_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_ST7565_EA_DOGM132_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ U8X8_PIN_NONE);	// DOGM132 Shield
//U8G2_ST7565_EA_DOGM132_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ U8X8_PIN_NONE);	// DOGM132 Shield
//U8G2_ST7565_ZOLEN_128X64_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_ST7565_ZOLEN_128X64_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_ST7565_LM6059_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);		// Adafruit ST7565 GLCD
//U8G2_ST7565_LM6059_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);		// Adafruit ST7565 GLCD
//U8G2_ST7565_ERC12864_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_ST7565_ERC12864_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_ST7565_NHD_C12832_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_ST7565_NHD_C12832_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_ST7565_NHD_C12864_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_ST7565_NHD_C12864_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_ST7567_PI_132X64_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 7, /* dc=*/ 9, /* reset=*/ 8);  // Pax Instruments Shield, LCD_BL=6
//U8G2_ST7567_PI_132X64_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 7, /* dc=*/ 9, /* reset=*/ 8);  // Pax Instruments Shield, LCD_BL=6
//U8G2_NT7534_TG12864R_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);  
//U8G2_NT7534_TG12864R_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);  
//U8G2_ST7588_JLX12864_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ 5);  
//U8G2_ST7588_JLX12864_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ 5);
//U8G2_IST3020_ERC19264_F_6800 u8g2(U8G2_R0, 44, 43, 42, 41, 40, 39, 38, 37,  /*enable=*/ 28, /*cs=*/ 32, /*dc=*/ 30, /*reset=*/ 31); // Connect WR pin with GND
//U8G2_IST3020_ERC19264_F_8080 u8g2(U8G2_R0, 44, 43, 42, 41, 40, 39, 38, 37,  /*enable=*/ 29, /*cs=*/ 32, /*dc=*/ 30, /*reset=*/ 31); // Connect RD pin with 3.3V
//U8G2_IST3020_ERC19264_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
//U8G2_LC7981_160X80_F_6800 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 18, /*cs=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // Connect RW with GND
//U8G2_LC7981_160X160_F_6800 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 18, /*cs=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // Connect RW with GND
//U8G2_LC7981_240X128_F_6800 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 18, /*cs=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // Connect RW with GND
//U8G2_SED1520_122X32_F u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*dc=*/ A0, /*e1=*/ A3, /*e2=*/ A2, /* reset=*/  A4); 	// Set R/W to low!
//U8G2_T6963_240X128_F_8080 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 17, /*cs=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // Connect RD with +5V, FS0 and FS1 with GND
//U8G2_T6963_256X64_F_8080 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 17, /*cs=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // Connect RD with +5V, FS0 and FS1 with GND
//U8G2_SED1330_240X128_F_8080 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 17, /*cs=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // Connect RD with +5V, FG with GND
//U8G2_SED1330_240X128_F_6800 u8g2(U8G2_R0, 13, 11, 2, 3, 4, 5, 6, A4, /*enable=*/ 7, /*cs=*/ 10, /*dc=*/ 9, /*reset=*/ 8); // A0 is dc pin!
//U8G2_RA8835_NHD_240X128_F_8080 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 17, /*cs=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // Connect /RD = E with +5V, enable is /WR = RW, FG with GND, 14=Uno Pin A0
//U8G2_RA8835_NHD_240X128_F_6800 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7,  /*enable=*/ 17, /*cs=*/ 14, /*dc=*/ 15, /*reset=*/ 16); // A0 is dc pin, /WR = RW = GND, enable is /RD = E
//U8G2_UC1604_JLX19264_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); 
//U8G2_UC1604_JLX19264_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);  
//U8G2_UC1608_ERC24064_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);  // SW SPI, Due ERC24064-1 Test Setup
//U8G2_UC1608_ERC240120_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); 
//U8G2_UC1608_240X128_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);  // SW SPI, Due ERC24064-1 Test Setup
//U8G2_UC1610_EA_DOGXL160_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/  U8X8_PIN_NONE);
//U8G2_UC1610_EA_DOGXL160_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/  U8X8_PIN_NONE);
//U8G2_UC1611_EA_DOGM240_F_2ND_HW_I2C u8g2(U8G2_R0, /* reset=*/ 8);	// Due, 2nd I2C, DOGM240 Test Board
//U8G2_UC1611_EA_DOGM240_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);   // Due, SW SPI, DOGXL240 Test Board
//U8G2_UC1611_EA_DOGXL240_F_2ND_HW_I2C u8g2(U8G2_R0, /* reset=*/ 8);	// Due, 2nd I2C, DOGXL240 Test Board
//U8G2_UC1611_EA_DOGXL240_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);   // Due, SW SPI, DOGXL240 Test Board
//U8G2_SSD1606_172X72_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);		// eInk/ePaper Display
//U8G2_SSD1607_200X200_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);	// eInk/ePaper Display
//U8G2_IL3820_296X128_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);	// WaveShare 2.9 inch eInk/ePaper Display, enable 16 bit mode for this display!

// End of constructor list


void u8g2_prepare(void) {
  u8g2.setFont(u8g2_font_6x10_tf);
  u8g2.setFontRefHeightExtendedText();
  u8g2.setDrawColor(1);
  u8g2.setFontPosTop();
  u8g2.setFontDirection(0);
}

void u8g2_box_frame(uint8_t a) {
  u8g2.drawStr( 0, 0, "drawBox");
  u8g2.drawBox(5,10,20,10);
  u8g2.drawBox(10+a,15,30,7);
  u8g2.drawStr( 0, 30, "drawFrame");
  u8g2.drawFrame(5,10+30,20,10);
  u8g2.drawFrame(10+a,15+30,30,7);
}

void u8g2_disc_circle(uint8_t a) {
  u8g2.drawStr( 0, 0, "drawDisc");
  u8g2.drawDisc(10,18,9);
  u8g2.drawDisc(24+a,16,7);
  u8g2.drawStr( 0, 30, "drawCircle");
  u8g2.drawCircle(10,18+30,9);
  u8g2.drawCircle(24+a,16+30,7);
}

void u8g2_r_frame(uint8_t a) {
  u8g2.drawStr( 0, 0, "drawRFrame/Box");
  u8g2.drawRFrame(5, 10,40,30, a+1);
  u8g2.drawRBox(50, 10,25,40, a+1);
}

void u8g2_string(uint8_t a) {
  u8g2.setFontDirection(0);
  u8g2.drawStr(30+a,31, " 0");
  u8g2.setFontDirection(1);
  u8g2.drawStr(30,31+a, " 90");
  u8g2.setFontDirection(2);
  u8g2.drawStr(30-a,31, " 180");
  u8g2.setFontDirection(3);
  u8g2.drawStr(30,31-a, " 270");
}

void u8g2_line(uint8_t a) {
  u8g2.drawStr( 0, 0, "drawLine");
  u8g2.drawLine(7+a, 10, 40, 55);
  u8g2.drawLine(7+a*2, 10, 60, 55);
  u8g2.drawLine(7+a*3, 10, 80, 55);
  u8g2.drawLine(7+a*4, 10, 100, 55);
}

void u8g2_triangle(uint8_t a) {
  uint16_t offset = a;
  u8g2.drawStr( 0, 0, "drawTriangle");
  u8g2.drawTriangle(14,7, 45,30, 10,40);
  u8g2.drawTriangle(14+offset,7-offset, 45+offset,30-offset, 57+offset,10-offset);
  u8g2.drawTriangle(57+offset*2,10, 45+offset*2,30, 86+offset*2,53);
  u8g2.drawTriangle(10+offset,40+offset, 45+offset,30+offset, 86+offset,53+offset);
}

void u8g2_ascii_1() {
  char s[2] = " ";
  uint8_t x, y;
  u8g2.drawStr( 0, 0, "ASCII page 1");
  for( y = 0; y < 6; y++ ) {
    for( x = 0; x < 16; x++ ) {
      s[0] = y*16 + x + 32;
      u8g2.drawStr(x*7, y*10+10, s);
    }
  }
}

void u8g2_ascii_2() {
  char s[2] = " ";
  uint8_t x, y;
  u8g2.drawStr( 0, 0, "ASCII page 2");
  for( y = 0; y < 6; y++ ) {
    for( x = 0; x < 16; x++ ) {
      s[0] = y*16 + x + 160;
      u8g2.drawStr(x*7, y*10+10, s);
    }
  }
}

void u8g2_extra_page(uint8_t a)
{
  u8g2.drawStr( 0, 0, "Unicode");
  u8g2.setFont(u8g2_font_unifont_t_symbols);
  u8g2.setFontPosTop();
  u8g2.drawUTF8(0, 24, "☀ ☁");
  switch(a) {
    case 0:
    case 1:
    case 2:
    case 3:
      u8g2.drawUTF8(a*3, 36, "☂");
      break;
    case 4:
    case 5:
    case 6:
    case 7:
      u8g2.drawUTF8(a*3, 36, "☔");
      break;
  }
}

#define cross_width 24
#define cross_height 24
static const unsigned char cross_bits[] U8X8_PROGMEM  = {
  0x00, 0x18, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x42, 0x00, 
  0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x81, 0x00, 0x00, 0x81, 0x00, 
  0xC0, 0x00, 0x03, 0x38, 0x3C, 0x1C, 0x06, 0x42, 0x60, 0x01, 0x42, 0x80, 
  0x01, 0x42, 0x80, 0x06, 0x42, 0x60, 0x38, 0x3C, 0x1C, 0xC0, 0x00, 0x03, 
  0x00, 0x81, 0x00, 0x00, 0x81, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 
  0x00, 0x42, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x18, 0x00, };

#define cross_fill_width 24
#define cross_fill_height 24
static const unsigned char cross_fill_bits[] U8X8_PROGMEM  = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x64, 0x00, 0x26, 
  0x84, 0x00, 0x21, 0x08, 0x81, 0x10, 0x08, 0x42, 0x10, 0x10, 0x3C, 0x08, 
  0x20, 0x00, 0x04, 0x40, 0x00, 0x02, 0x80, 0x00, 0x01, 0x80, 0x18, 0x01, 
  0x80, 0x18, 0x01, 0x80, 0x00, 0x01, 0x40, 0x00, 0x02, 0x20, 0x00, 0x04, 
  0x10, 0x3C, 0x08, 0x08, 0x42, 0x10, 0x08, 0x81, 0x10, 0x84, 0x00, 0x21, 
  0x64, 0x00, 0x26, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };

#define cross_block_width 14
#define cross_block_height 14
static const unsigned char cross_block_bits[] U8X8_PROGMEM  = {
  0xFF, 0x3F, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20, 
  0xC1, 0x20, 0xC1, 0x20, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20, 0x01, 0x20, 
  0x01, 0x20, 0xFF, 0x3F, };

void u8g2_bitmap_overlay(uint8_t a) {
  uint8_t frame_size = 28;

  u8g2.drawStr(0, 0, "Bitmap overlay");

  u8g2.drawStr(0, frame_size + 12, "Solid / transparent");
  u8g2.setBitmapMode(false /* solid */);
  u8g2.drawFrame(0, 10, frame_size, frame_size);
  u8g2.drawXBMP(2, 12, cross_width, cross_height, cross_bits);
  if(a & 4)
    u8g2.drawXBMP(7, 17, cross_block_width, cross_block_height, cross_block_bits);

  u8g2.setBitmapMode(true /* transparent*/);
  u8g2.drawFrame(frame_size + 5, 10, frame_size, frame_size);
  u8g2.drawXBMP(frame_size + 7, 12, cross_width, cross_height, cross_bits);
  if(a & 4)
    u8g2.drawXBMP(frame_size + 12, 17, cross_block_width, cross_block_height, cross_block_bits);
}

void u8g2_bitmap_modes(uint8_t transparent) {
  const uint8_t frame_size = 24;

  u8g2.drawBox(0, frame_size * 0.5, frame_size * 5, frame_size);
  u8g2.drawStr(frame_size * 0.5, 50, "Black");
  u8g2.drawStr(frame_size * 2, 50, "White");
  u8g2.drawStr(frame_size * 3.5, 50, "XOR");
  
  if(!transparent) {
    u8g2.setBitmapMode(false /* solid */);
    u8g2.drawStr(0, 0, "Solid bitmap");
  } else {
    u8g2.setBitmapMode(true /* transparent*/);
    u8g2.drawStr(0, 0, "Transparent bitmap");
  }
  u8g2.setDrawColor(0);// Black
  u8g2.drawXBMP(frame_size * 0.5, 24, cross_width, cross_height, cross_bits);
  u8g2.setDrawColor(1); // White
  u8g2.drawXBMP(frame_size * 2, 24, cross_width, cross_height, cross_bits);
  u8g2.setDrawColor(2); // XOR
  u8g2.drawXBMP(frame_size * 3.5, 24, cross_width, cross_height, cross_bits);
}

uint8_t draw_state = 0;

void draw(void) {
  u8g2_prepare();
  switch(draw_state >> 3) {
    case 0: u8g2_box_frame(draw_state&7); break;
    case 1: u8g2_disc_circle(draw_state&7); break;
    case 2: u8g2_r_frame(draw_state&7); break;
    case 3: u8g2_string(draw_state&7); break;
    case 4: u8g2_line(draw_state&7); break;
    case 5: u8g2_triangle(draw_state&7); break;
    case 6: u8g2_ascii_1(); break;
    case 7: u8g2_ascii_2(); break;
    case 8: u8g2_extra_page(draw_state&7); break;
    case 9: u8g2_bitmap_modes(0); break;
    case 10: u8g2_bitmap_modes(1); break;
    case 11: u8g2_bitmap_overlay(draw_state&7); break;
  }
}


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

void loop(void) {
  // picture loop  
  u8g2.clearBuffer();
  draw();
  u8g2.sendBuffer();
  
  // increase the state
  draw_state++;
  if ( draw_state >= 12*8 )
    draw_state = 0;

  // deley between each page
  delay(100);

}

속도는 U8g 의 Fast I2C 정도는 아니지만,

그리 느린 속도는 아니면서 arduino 의 led 는 점멸하지 않습니다.





10. Reference


위에서 열거되지 않은 부분은, 주로 아래 link 들을 참고하였습니다.


https://forum.arduino.cc/index.php?topic=403234.0

https://github.com/squix78/esp8266-oled-ssd1306

http://www.instructables.com/id/Monochrome-096-i2c-OLED-display-with-arduino-SSD13/




FIN

역시 사람은 오감으로 느껴야지만 이해가 갑니다.

And

Hardware | SSD1331 96x64 full color OLED 를 사용해보자

|

1. Full Color OLED


Arduino 에 연결하여 표현해 주는 OLED 가 있습니다.

센서값을 보여주는 모니터링용으로는 괜찮아 보입니다.


Monochrome 제품은 이미 테스트 해봤습니다.


http://chocoball.tistory.com/entry/Hardware-SSD1306-128x64-monochrome-OLED


0.95 크기를 가지는 OLED 는 대략 세가지가 있는것 같습니다.


하나는 위의 Monochrome 이고,

두번째는 윗쪽이 노란색이고 밑에가 파란색인 제품.




마지막은 full color 제품 입니다.



AliExpress 에서 찾아보니 6.84 USD 로 판매되고 있습니다.


https://ko.aliexpress.com/item/0-95-Inch-SPI-Full-Color-OLED-Display-DIY-Module-96x64-LCD-For-Arduino-SSD1306-Driver/32790785282.html



재미있는 것은, 제품이 SSD1306 드라이버라고 사이트에 올라와 있는데,

SSD1306 은 Monochrome 제품용이고, full color 는 SSD1331 드라이버 입니다.

결국 사이트에 잘못 올린거지요.


SSD1331 용 full color OLED 는 10 USD 정도 인데, SSD1306 으로 검색되는 full color OLED 는 7 USD 정도 이니,

검색은 SSD1306 으로 되는 full color OLED 를 구매하면 이득입니다.


이번 글에서도 "SSD1331" 드라이버에 맞는 sketch 를 이용했습니다.




2. 도착


도착샷은 다음과 같습니다.



창이 달린 모니터 있다 보니, 뽁뽁이로 잘 쌓여서 왔습니다.



오호이. 상태는 좋아 보입니다.



제품의 줌샷 입니다.



뒷면입니다.


SSD1331 datasheet 는 다음과 같습니다.


SSD1331_1.2.pdf


아래 link 를 많이 참조 했습니다.


http://educ8s.tv/arduino-color-oled-display-tutorial/




3. Pinout


Arduino 와 pin 연결 정보 입니다.


    SSD1331  | Arduino Nano
----------------------------
     GND     |     GND
     VCC     |     3.3V
     SCL     |     D13
     SDA     |     D11
     RES     |     D9
     DC      |     D8
     CS      |     D10
----------------------------


Layout 은 다음과 같습니다.



참조 Youtube 동영상에서 캡춰한 내용이 가장 잘 맞는것 같네요.






3. Library


아래 GitHub 에서 SSD1331 라이브러리를 다운로드 받습니다.


https://github.com/adafruit/Adafruit-SSD1331-OLED-Driver-Library-for-Arduino


"/Arduino/Library/" 폴더에 다운로드 받은 파일을 넣어도 좋고,

아래처럼 Arduino IDE 에서 검색해서 install 할 수도 있습니다.


"Sketch > Include Library > Manage Libraries..." 에서 "gfx" 와 "SSD1331" 을 검색하면 install 되어 있으면 OK.

없으면 install 하면 됩니다.



"gfx" 를 검색하니, Adafruit GFX 가 이미 깔려 있네요.



"SSD1331" 을 검색하니, Adafruit SSD1331 OLED Driver Library for Arduino 도 이미 깔려 있습니다.





4. Sketch


"File > Examples > Adafruit SSD1331 OLED Driver Library for Arduino > test" 의 소스 입니다.


/*************************************************** 
  This is a example sketch demonstrating the graphics
  capabilities of the SSD1331 library  for the 0.96" 
  16-bit Color OLED with SSD1331 driver chip

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/684

  These displays use SPI to communicate, 4 or 5 pins are required to  
  interface
  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/


// You can use any (4 or) 5 pins 
#define sclk 13
#define mosi 11
#define cs   10
#define rst  9
#define dc   8


// Color definitions
#define	BLACK           0x0000
#define	BLUE            0x001F
#define	RED             0xF800
#define	GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0  
#define WHITE           0xFFFF

#include "Adafruit_GFX.h"
#include "Adafruit_SSD1331.h"
#include "SPI.h"

// Option 1: use any pins but a little slower
Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, mosi, sclk, rst);  

// Option 2: must use the hardware SPI pins 
// (for UNO thats sclk = 13 and sid = 11) and pin 10 must be 
// an output. This is much faster - also required if you want
// to use the microSD card (see the image drawing example)
//Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, rst);

float p = 3.1415926;

void setup(void) {
  Serial.begin(9600);
  Serial.print("hello!");
  display.begin();

  Serial.println("init");
  uint16_t time = millis();
  display.fillScreen(BLACK);
  time = millis() - time;
  
  Serial.println(time, DEC);
  delay(500);
   
  lcdTestPattern();
  delay(1000);
  
  display.fillScreen(BLACK);
  display.setCursor(0,0);
  display.print("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa");
  delay(1000);

  // tft print function!
  tftPrintTest();
  delay(2000);
  
  //a single pixel
  display.drawPixel(display.width()/2, display.height()/2, GREEN);
  delay(500);
  
  // line draw test
  testlines(YELLOW);
  delay(500);    
  
  // optimized lines
  testfastlines(RED, BLUE);
  delay(500);    
 
  testdrawrects(GREEN);
  delay(1000);

  testfillrects(YELLOW, MAGENTA);
  delay(1000);

  display.fillScreen(BLACK);
  testfillcircles(10, BLUE);
  testdrawcircles(10, WHITE);
  delay(1000);

  testroundrects();
  delay(500);
  
  testtriangles();
  delay(500);
  
  Serial.println("done");
  delay(1000);
}

void loop() {
}

void testlines(uint16_t color) {
   display.fillScreen(BLACK);
   for (int16_t x=0; x < display.width()-1; x+=6) {
     display.drawLine(0, 0, x, display.height()-1, color);
   }
   for (int16_t y=0; y < display.height()-1; y+=6) {
     display.drawLine(0, 0, display.width()-1, y, color);
   }
   
   display.fillScreen(BLACK);
   for (int16_t x=0; x < display.width()-1; x+=6) {
     display.drawLine(display.width()-1, 0, x, display.height()-1, color);
   }
   for (int16_t y=0; y < display.height()-1; y+=6) {
     display.drawLine(display.width()-1, 0, 0, y, color);
   }
   
   display.fillScreen(BLACK);
   for (int16_t x=0; x < display.width()-1; x+=6) {
     display.drawLine(0, display.height()-1, x, 0, color);
   }
   for (int16_t y=0; y < display.height()-1; y+=6) {
     display.drawLine(0, display.height()-1, display.width()-1, y, color);
   }

   display.fillScreen(BLACK);
   for (int16_t x=0; x < display.width()-1; x+=6) {
     display.drawLine(display.width()-1, display.height()-1, x, 0, color);
   }
   for (int16_t y=0; y < display.height()-1; y+=6) {
     display.drawLine(display.width()-1, display.height()-1, 0, y, color);
   }
   
}

void testdrawtext(char *text, uint16_t color) {
  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();
  }    
}

void testfastlines(uint16_t color1, uint16_t color2) {
   display.fillScreen(BLACK);
   for (int16_t y=0; y < display.height()-1; y+=5) {
     display.drawFastHLine(0, y, display.width()-1, color1);
   }
   for (int16_t x=0; x < display.width()-1; x+=5) {
     display.drawFastVLine(x, 0, display.height()-1, color2);
   }
}

void testdrawrects(uint16_t color) {
 display.fillScreen(BLACK);
 for (int16_t x=0; x < display.height()-1; x+=6) {
   display.drawRect((display.width()-1)/2 -x/2, (display.height()-1)/2 -x/2 , x, x, color);
 }
}

void testfillrects(uint16_t color1, uint16_t color2) {
 display.fillScreen(BLACK);
 for (int16_t x=display.height()-1; x > 6; x-=6) {
   display.fillRect((display.width()-1)/2 -x/2, (display.height()-1)/2 -x/2 , x, x, color1);
   display.drawRect((display.width()-1)/2 -x/2, (display.height()-1)/2 -x/2 , x, x, color2);
 }
}

void testfillcircles(uint8_t radius, uint16_t color) {
  for (uint8_t x=radius; x < display.width()-1; x+=radius*2) {
    for (uint8_t y=radius; y < display.height()-1; y+=radius*2) {
      display.fillCircle(x, y, radius, color);
    }
  }  
}

void testdrawcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=0; x < display.width()-1+radius; x+=radius*2) {
    for (int16_t y=0; y < display.height()-1+radius; y+=radius*2) {
      display.drawCircle(x, y, radius, color);
    }
  }  
}

void testtriangles() {
  display.fillScreen(BLACK);
  int color = 0xF800;
  int t;
  int w = display.width()/2;
  int x = display.height();
  int y = 0;
  int z = display.width();
  for(t = 0 ; t <= 15; t+=1) {
    display.drawTriangle(w, y, y, x, z, x, color);
    x-=4;
    y+=4;
    z-=4;
    color+=100;
  }
}

void testroundrects() {
  display.fillScreen(BLACK);
  int color = 100;
  int i;
  int t;
  for(t = 0 ; t <= 4; t+=1) {
  int x = 0;
  int y = 0;
  int w = display.width();
  int h = display.height();
    for(i = 0 ; i <= 24; i+=1) {
    display.drawRoundRect(x, y, w, h, 5, color);
    x+=2;
    y+=3;
    w-=4;
    h-=6;
    color+=1100;
  }
  color+=100;
  }
}

void tftPrintTest() {
  display.fillScreen(BLACK);
  display.setCursor(0, 5);
  display.setTextColor(RED);  
  display.setTextSize(1);
  display.println("Hello World!");
  display.setTextColor(YELLOW, GREEN);
  display.setTextSize(2);
  display.print("Hello Wo");
  display.setTextColor(BLUE);
  display.setTextSize(3);
  display.print(1234.567);
  delay(1500);
  display.setCursor(0, 5);
  display.fillScreen(BLACK);
  display.setTextColor(WHITE);
  display.setTextSize(0);
  display.println("Hello World!");
  display.setTextSize(1);
  display.setTextColor(GREEN);
  display.print(p, 5);
  display.println(" Want pi?");
  display.print(8675309, HEX); // print 8,675,309 out in HEX!
  display.print(" Print HEX");
  display.setTextColor(WHITE);
  display.println("Sketch has been");
  display.println("running for: ");
  display.setTextColor(MAGENTA);
  display.print(millis() / 1000);
  display.setTextColor(WHITE);
  display.print(" seconds.");
}

void mediabuttons() {
 // play
  display.fillScreen(BLACK);
  display.fillRoundRect(25, 10, 78, 60, 8, WHITE);
  display.fillTriangle(42, 20, 42, 60, 90, 40, RED);
  delay(500);
  // pause
  display.fillRoundRect(25, 90, 78, 60, 8, WHITE);
  display.fillRoundRect(39, 98, 20, 45, 5, GREEN);
  display.fillRoundRect(69, 98, 20, 45, 5, GREEN);
  delay(500);
  // play color
  display.fillTriangle(42, 20, 42, 60, 90, 40, BLUE);
  delay(50);
  // pause color
  display.fillRoundRect(39, 98, 20, 45, 5, RED);
  display.fillRoundRect(69, 98, 20, 45, 5, RED);
  // play color
  display.fillTriangle(42, 20, 42, 60, 90, 40, GREEN);
}

/**************************************************************************/
/*! 
    @brief  Renders a simple test pattern on the LCD
*/
/**************************************************************************/
void lcdTestPattern(void)
{
  uint32_t i,j;
  display.goTo(0, 0);
  
  for(i=0;i<64;i++)
  {
    for(j=0;j<96;j++)
    {
      if(i>55){display.writeData(WHITE>>8);display.writeData(WHITE);}
      else if(i>47){display.writeData(BLUE>>8);display.writeData(BLUE);}
      else if(i>39){display.writeData(GREEN>>8);display.writeData(GREEN);}
      else if(i>31){display.writeData(CYAN>>8);display.writeData(CYAN);}
      else if(i>23){display.writeData(RED>>8);display.writeData(RED);}
      else if(i>15){display.writeData(MAGENTA>>8);display.writeData(MAGENTA);}
      else if(i>7){display.writeData(YELLOW>>8);display.writeData(YELLOW);}
      else {display.writeData(BLACK>>8);display.writeData(BLACK);}
    }
  }
}




5. 동작


위의 sketch 를 업로드 하고 pin 을 잘 연결하면, 아래와 같은 동작을 보여줍니다.



글씨, 배경색, 크기 등 여러가지를 확인해 볼 수 있습니다.



그림들도 잘 표현이 됩니다. 물론 컬러로.



SPI 프로토콜이라서 그런지, Monochorme 의 I2C 인터페이스보다는 확실히 빠른 성늘을 보여주네요.

다음은 동영상 입니다.





FIN


화면의 상하단의 색이 다른 OLED 는 SSD1306 을 사용한지라,

부분 컬러이긴 하지만, 더이상 OLED 는 구매하지 않아도 될 듯 해요.

And
prev | 1 | next