'아두이노'에 해당되는 글 91건

  1. 2017.12.28 Hardware | HY-SRF05 초음파 거리 측정기를 사용해 보자
  2. 2017.12.14 Hardware | Heating Gun 을 만들어 보자 - 1
  3. 2017.12.11 Hardware | LED bar graph 를 컨트롤 해보자 - 2
  4. 2017.12.01 Hardware | LED bar graph 를 컨트롤 해보자 - 1
  5. 2017.12.01 Hardware | 74HC595 shift register 를 사용해 보자
  6. 2017.10.12 Hardware | VL53L0X 레이저 거리 측정 센서 사용해 보기 8
  7. 2017.10.01 Hardware | Rotary Encoder 를 사용해 보자
  8. 2017.09.19 Hardware | TSSR 3.5mm audio jack 구매하기
  9. 2017.09.19 Hardware | Adafruit SSD1306 128x64 1.3" monochrome OLED 를 사용해보자
  10. 2017.09.14 Hardware | SSD1306 128x64 monochrome OLED 를 사용해보자

Hardware | HY-SRF05 초음파 거리 측정기를 사용해 보자

|

1. 거리 측정기


거리를 측정하는 방법에는 여러가지가 있습니다.

일전에 laser 모듈을 이용하여 측정하는 방법을 구현해 봤습니다.


* Hardware | VL53L0X 레이저 거리 측정 센서 사용해 보기

http://chocoball.tistory.com/entry/Hardware-VL53L0X-laser-ranging-sensor


다만, 두개의 눈같이 생긴 센서가 자꾸 눈에 들어 옵니다.

로보트를 만든 사람들은 누구나 사용하는 센서인 듯 보이고, Arduino Starter Kit 에도 꼭 포함되어 있는 센서 입니다.


사용해 보지 않을 이유가 없습니다.

궂이 필요성은 없지만 서도...


AliExpress 에서 검색하니 그냥 나옵니다. 흠흠.


* 5Pin HY-SRF05 SRF05 Ultrasonic Distance Sensor Module For Arduino Replace SR04 Electronic Brick Compatible Interface DC 5V


https://ko.aliexpress.com/item/MAX6675-Module-K-Type-Thermocouple-Thermocouple-Sensor-for-Arduino-AL/32247186623.html



지금까지 구입하지 않고 오래 지났으니, 이제 구입할 시기라고 정당화 하면서 바로 구입합니다.




2. 도착


그리 오래 걸리지 않고 도착했습니다.

한 2주 정도?



뽁뽁이로 잘 쌓여 있고요.



아니 이게... WTF.

왜 너는 pin 들이 죄다 구부러져 있니?

너무 이쁘게 구부러져 있어서 원래 그런거라고 자답 위안을 삼아 봅니다.




3. 외형


앞모습 입니다. 두개의 눈처럼 생겼습니다.



뒷모습.



HC-SR04 버전과 비교해 보면, 조금 더 component 들이 더 많이 있음을 알 수 있습니다.




또한, SRF04 의 업그레이드 버전인 SRF08 도 있습니다.


SRF04 > SRF05 (좀더 정확해짐) > SRF08 (거리가 늘어나고 낮은 ampere)


http://www.f15ijp.com/2012/09/arduino-ultrasonic-sensor-hc-sr04-or-hy-srf05/

http://www.junun.org/MarkIII/Info.jsp?item=32


SRF08 은 photoresistor 까지 달려 있네요.




사실은 Ultrasonic 거리 측정기는 제품 넘버링 만큼 많이 있습니다.

https://www.robot-r-us.com/vmchk/sensor-ultrasonic.html






4. Layout


Pin 연결들은 다음과 같습니다.


  HY-SRF05  | Arduino Nano
---------------------------
    Vcc     |     5V
    Trig    |     D13
    Echo    |     D12
    OUT     |     
    GND     |     GND
---------------------------


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


회로도는 다음과 같습니다.



짜잔~ 전체 사진입니다.






5. Sketch


소스는 아래 link 를 참조하였습니다.


* Distance Measurement with an Ultrasonic Sensor HY-SRF05

- https://create.arduino.cc/projecthub/Nicholas_N/distance-measurement-with-an-ultrasonic-sensor-hy-srf05-64554e


#include "Adafruit_SSD1306.h"
Adafruit_SSD1306 display = Adafruit_SSD1306();

const unsigned int TRIG_PIN=13;
const unsigned int ECHO_PIN=12;
const unsigned int BAUD_RATE=9600;

void setup() {
	pinMode(TRIG_PIN, OUTPUT);
	pinMode(ECHO_PIN, INPUT);
	Serial.begin(BAUD_RATE);
	
	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
	// init done
	display.display();
	display.setTextSize(2);
	display.setTextColor(WHITE);
}

void loop() {
	digitalWrite(TRIG_PIN, LOW);
	delayMicroseconds(2);
	digitalWrite(TRIG_PIN, HIGH);
	delayMicroseconds(10);
	digitalWrite(TRIG_PIN, LOW);
	
	const unsigned long duration= pulseIn(ECHO_PIN, HIGH);
	int distance= duration/29/2;
	
	if(duration==0) {
		Serial.println("Warning: no pulse from sensor");
	} else {
		display.clearDisplay();
		display.setCursor(0,0);
		display.print(distance);
		display.print(" Cm");
		
		display.display();
	}
	
	delay(500);
}


수정한 부분은 output 을 Serical Monitor 가 아닌, OLED 로 표시하는 부분 뿐입니다.




6. 측정


구성을 하고 몇가지 측정해 봤습니다.



오차가 좀 있지만, 조정만 하면 정확한 계측용으로 사용이 가능할 것 같습니다.

20Cm 정도 떨어트린 곳에서 측정해보면 20Cm 정도 나오는 장면입니다.


동영상으로도 찍어 봤습니다.

40Cm > 30Cm > 20Cm > 10Cm > 0 순으로 해봤습니다.



센서 바로 앞은 논리적으로 0Cm 이지만 이상한 값을 뿌려줍니다.

이는 Ultrasonic 을 보내고 받을 수 있는 공간이 나오지 않아서 그런것 같아요.




7. 추가


뜬금없이 사용 전류량을 알고 싶어졌습니다.

전류 측정은 직렬로 연결해야 알 수 있으므로, sensor 의 ground 부분을 멀티미터 +/- 를 통하게 만들어서 측정해 봤습니다.



대략 5.36 mA 가 나오네요.

스펙상으로는 2mA 이하라고 나오는데, 어느쪽이 잘못된건지 모르겠습니다.


측정할 수 있는 최대 거리를 보고자 10m 정도 앞을 비추었더니, 아래와 같이 38m 값이 나옵니다.

유효한 거리는 대략 4m 정도로 보입니다. (스펙에도 4.5 m 로 표기되어 있슴)



오실로스코프를 이용하여 Ultrasonic sound 와 반사파를 측정하는 동영상이 있습니다.


* #40 Ultrasonic Distance Sensors Arduino Tutorial and Comparison for HC-SR04, HY-SRF05, US-015

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



거리에 따라 Response 값이 변하는 것을 알 수 있습니다.



그치만, 저의 DIY 오실로스코프는 측정하지 못합니다.

DC 에 200 us 이 필요한데, 제가 만든 DIY 오실로스코프는 10us 가 최대치 입니다.


* Hardware | DSO150 Oscilloscope

http://chocoball.tistory.com/entry/HardwareDSO150Oscilloscope


처음으로 좀더 좋은 Oscilloscope 를 갖고싶다는 생각을 했습니다.




FIN


로보트 등에 많이 사용되는 센서인데, 구동이나 사용법은 간단한것 같습니다.

Ultrasonic 이라서, 귀에 들리지 않는다는 것이 좀 아쉽고 궁금하군요.

(아니 당연한 것을...)


And

Hardware | Heating Gun 을 만들어 보자 - 1

|

1. 고장


예전에 설치하여 밤낮없이 돌아가 주던 Stick PC - MeeGoPad T07 4GB 가

어느때부터인가 Windows 10 기동이 되지 않았습니다.


* Hardware | MeeGoPad T07 4G RAM

http://chocoball.tistory.com/entry/Hardware-MeeGoPad-T07-4G-RAM


이 Stick PC 는 원활한 운용을 위해 heat sink 도 신경써서 버전업을 시켜준 상태였습니다.


* Hardware | MeeGoPad 히트싱크 업그레이드 하기

http://chocoball.tistory.com/entry/Hardware-MeeGoPad-heatsink-upgrade


* Hardware | MeeGoPad 히트싱크 업그레이드 하기 - 2

http://chocoball.tistory.com/entry/Hardware-MeeGoPad-heatsink-upgrade-2


그러던 와중에 무한 부팅에 빠지게 되었습니다.



아무래도 24시간용으로 운용하기에는 너무 빈약한 heat sink 와 내구성으로 버텨주지를 못했나 싶습니다.





2. 히팅건


특히 열이 많이 발산되는 부품들은 납땜이 제대로 되어 있지 않을 경우,

냉납이라는 현상으로 정상 작동이 되었다 안되었다 하는 불안한 현상을 보인다고 하였습니다.


무한 부팅이 일어나면서 고쳐지지 않는 것은 필시 냉납이라고 결론을 내리고 열풍기 - heating gun 을 물색합니다.


아래 제품을 구입하고 싶었으나, 세계적인 브렌드인 만큼 가격도 거의 10만원대 입니다.



구글링 하던 중, 비싼 히팅건 대용품은 2가지가 있었습니다.


1. 오븐에 굽기

a. 납이 녹는 200도 이상 올라가는 오븐을 구해야 함

b. 납은 유해 물질이므로, 전자제품 굽는것 전용으로만 활용해야 함

c. 온도 확인을 위해서 오븐 온도계가 추가로 필요함 (추가 구입)




2. 휴대용 토치

a. 대략 1.5 ~ 2만원의 가격대

b. 가스만 있으면 사용 가능

c. 불꽃을 직접 쐬므로, 부품이 녹을 수 있슴



일단 추가로 비용이 들어야 하는게 마음에 들지 않습니다. 흠...





3. 시거젝


그러다가 Youtube 에서 시거젝을 이용한 열풍기 제조기가 있다는 것을 발견했습니다.



뭔가 아주 저렴해 보이면서, 그렇게 어렵지 않게 생겼습니다.

거기다, 시거젝에서 나오는 열이 엄청날 것 같습니다. 효과는 동영상에서 검증이 되었네요.


여러가지 종류가 있습니다.

제대로 만들면 정말 물건이 되겠군요.


* 시거젝을 이용한 열풍기

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


* 스위치까지 장착된 시거젝 열풍기

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


* thermocouple 온도계를 이용하여 모니터링 하면서 작업하는 열풍기

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


* 가장 간단하게 만든 동영상

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


* PC power 를 이용하여, 가장 빠른 방법

- https://www.youtube.com/watch?v=7vgKGkxcm_c


* 더 간단한 방법

https://www.youtube.com/watch?v=7QB3ZQ1OU0w





4. 구입


필요한 것은 시거젝! 바로 알리에서 확인해 봅니다.

후훗, 역시 있군요. 개당 1.28 USD !!!



https://ko.aliexpress.com/item/12V-Auto-Car-Power-Plug-Socket-Output-20mm-Automatic-Cigarette-Lighter-Ignition-2016-New/32656607243.html


여분을 생각해서 2개를 주문합니다.




5. 도착


알리스럽게 도착하였습니다.



구조가 간단하니 파손의 위험은 없어 보입니다.



12V 20MM 규격이라 합니다.



조그만 해서 귀엽습니다.



스프링을 제껴 주면 가장 핵심부품이 보입니다.

워낙 뜨거워지니, 중간에 세라믹 (도자기) 구조물이 있습니다.





6. 전원


시거젝에 연결하는 전원은 12V 입니다.

마침 PC 의 PATA 케이블 - 주로 예전 HDD 연결하는 케이블 - 에 5V / 12V 가 출력되게 되어 있습니다.


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




12V 를 뽑기 위해서 집에 굴러다니는 ATX power 를 꺼내옵니다.

ATX 24pin power connector 에서 16, 17번 pin 을 이용하여 on/off 를 할 수 있다는걸 알게 됩니다.



끝단에 on/off 스위치를 연결하고 jump 선으로 연결해 줍니다.



문제 없이 12V 가 나오는지 확인해 봅니다.



오오오, 잘 나옵니다.




7. 시거젝 분해하기


이제 전원이 준비 되었으니, 시거젝을 12V pin 에 연결해 보도록 합니다.


우선 시거젝을 분리하여 전원선을 연결해 줘야 합니다.

먼저 시거젝을 분리합니다.



손잡이를 돌리면 분리가 됩니다.



꼭지에 있는 너트를 돌려서 분리하면 완전 분리가 됩니다.



바깥 커버를 정위치 시켜주는 스프링도 있습니다.

우리 작업에는 필요 없습니다.



완전 분리가 되었습니다.

바깥 케이스 및 스프링은 필요가 없습니다.





8. 전선 연결


많은 전류가 흐르므로 두꺼운 전원선이 필요합니다.

마침, 멀티탭 수리기 챙겨놨던 전원 케이블에서 적출합니다.


* Hardware | 멀티탭 수리기

http://chocoball.tistory.com/entry/Hardware-fix-power-strip



두꺼워서 좋습니다.

또한, 화재 예방을 위해서 전원 피복이 잘 안타는 재질입니다.



전원선 끝단을 펴 줍니다. 너트 부분에 연결할 부분은 짧게 잘라 줍니다.



요렇게요.

주의할 점은, 밑에 끼워 놓은 금속이 중심 심에 닿지 않도록 합니다. 닿게 되면 회로적으로 short 가 되니 power 가 고장날 수 있습니다.



뚜껑을 돌려서 다시 씌워 줍니다.



전선 다른 한쪽을 피복을 벗겨서 PATA pin 에 연결할 수 있도록 합니다.



연결 완료 !!!

자주 사용할 것이라면, isolation 을 확실하게 해야 하나, 이번에는 잠깐 사용할 것이므로 그냥 이대로 사용합니다.




9. 테스트


잘 동작하는지 전원을 인가해 봅니다.



오오오오!!! 잘 되네요.


마침 멀티미터에 thermocouple 센서를 통하여 200도 이상의 온도도 측정할 수 있는 기능이 있습니다.

측정해 봅니다.



납이 녹는 온도인 200도까지는 정말 쉽게 올라갑니다.

전원을 계속 인가하면 300도 이상까지도 문제 없이 올라갈 기세 입니다.





10. 작업


오늘의 수술 대상인 고장난 MeeGoPad T07 입니다.



Raspberry Pi 용 통구리 heat sink 도 붙여주고, 메모리에도 알루미늄 heat sink 도 붙여줬지만,

결국 열로 인하여 망가진 듯한 Stick PC 입니다.


붙어있던 heat sink 를 모두 벗겨내고, 캡톤 테이프를 둘러 쌓아서, 열에 약한 부품을 보호해 줍니다.



옆에 thermocouple 온도계로 측정하면서, 시간도 측정하면서 하나하나 작업합니다.

Memory 4개, CPU 1개, Storage chip 1개, Video chip 1 개 등, 모두 작업해 줍니다.



모든 작업을 완료하고, 성능이 더 좋은, 아껴 두웠던 BMR-C1 heatsink 를 붙여 줍니다.


* Hardware | BMR-C1 heatsink

http://chocoball.tistory.com/entry/HardwareBMRC1heatsink





11. 결과


결과는 망했습니다.

전원을 넣으면 기판이 엄청 뜨거워지기만 하고 전혀 video 출력으로 나오지 않습니다.


아....





FIN


오래 계획해서 실행에 옮겼지만, 결국 고치지 못했을 뿐 아니라 더 망가뜨려 버렸습니다.


이유로 생각할 수 있는 것은,

------------------------------------------------

1. 충분히 가열한답시고 너무 오래 열을 가했다.

2. 계속 온도가 올라가므로, 동일한 거리를 유지하고 지진다 한들 시간에 비례하여 전달되는 열은 엄청 많다.

3. 납볼이 촘촘히 박혀있는 경우는, 너무 높은 온도로 인하여 근접한 납들과 붙어버렸을 가능성이 있다.

4. 캡톤 테이프를 붙이긴 했지만, chip 근처의 작은 부품들이 손상되었을 수도 있다.



Upgrade 버전을 만들어보고 싶습니다.

아래 내용을 감안하여 다시 재도전 하고 싶습니다.

------------------------------------------------

1. IR infrared 센서를 이용하여 non contact 온도계를 같이 연동시킨다.

2. 설정한, 일정한 온도에 도달하면 전류를 차단하여 일정 온도 이상 올라가지 않게 한다.

3. 기성품과 기슷하게, 비접촉 온도계는 laster pointer 를 달아서 target 을 쉽게 인식할 수 있게 한다.

4. 손잡이를 더 편하게 만드며, 절연을 철저하게 해 놓는다.

5. OLED 를 이용한 설정창과 모니터링을 위해 Arduino 를 활용한다.


그런데, 열풍기 upgrade 한들, 이제 MeeGoPad T07 은 이제 없네?!!! (눈물)

And

Hardware | LED bar graph 를 컨트롤 해보자 - 2

|

1. 12 segments


LED bargraph 를 컨트롤시에 shift register 를 사용하면, arduino의 3가지 선으로 LED 들을 조정할 수 있습니다.

다만, shift register 의 사용 가능한 pin 갯수가 8개라서 shift register 로 컨트롤 할 수 있는 LED 갯수가 8개로 한정됩니다.


지금 가지고 있는 LED bargraph 가 12 segments, 즉 12개짜리인 관계로 4개를 사용하지 못하고 있었습니다.


* Hardware | LED bar graph 를 컨트롤 해보자 - 1

     - http://chocoball.tistory.com/entry/Hardware-LED-bar-graph-controlling-1



* Hardware | 74HC595 shift register 를 사용해 보자

http://chocoball.tistory.com/entry/Hardware-74HC595-shift-register


그럼 shift register 2개를 사용하여 12 segments 전부를 사용해 보고자 합니다.





2. Pinout


12개의 LED 를 조작하기 위한 선과 shift register 끼리 연결하는 Pin, GND, Power 선 등 연결은 간단하지만,

jumper 갯수 자체는 1개의 shift register 를 사용했을 때 보다 2배 이상 많아집니다.


  LED       | Shift Register | Shift Register | Arduino
  Bargraph  | SN74HC595N (1) | SN74HC595N (2) |  Nano
--------------------------------------------------------
  anode 7   | Q1 (pin 1)     |                |
  anode 8   | Q2 (pin 2)     |                |
  anode 9   | Q3 (pin 3)     |                |
  anode 10  | Q4 (pin 4)     |                |
  anode 11  | Q5 (pin 5)     |                |
            | Q6 (pin 6)     |                |
            | Q7 (pin 7)     |                |
            | GND (pin 8)    |                |  GND
            | Vcc (pin 16)   |                |  3.3V
  anode 6   | Q0 (pin 15)    |                |
            | DS (pin 14)    |                |  D11     --> dataPin
            | OE (pin 13)    |                |  GND
            | ST_CP (pin 12) | ST_CP (pin 12) |  D8      --> latchPin
            | SH_CP (pin 11) | SH_CP (pin 11) |  D12     --> clockPin
            | MR (pin 10)    |                |  3.3V
            | Q7' (pin 9)    | DS (pin 14)    |
  anode 1   |                | Q1 (pin 1)     |
  anode 2   |                | Q2 (pin 2)     |
  anode 3   |                | Q3 (pin 3)     |
  anode 4   |                | Q4 (pin 4)     |
  anode 5   |                | Q5 (pin 5)     |
            |                | Q6 (pin 6)     |
            |                | Q7 (pin 7)     |
            |                | GND (pin 8)    |  GND
            |                | Vcc (pin 16)   |  3.3V
  anode 0   |                | Q0 (pin 15)    |
            |                | DS (pin 14)    |
            |                | OE (pin 13)    |  GND
            |                | MR (pin 10)    |  3.3V
            |                | Q7' (pin 9)    |
--------------------------------------------------------


포인트는 serial data output 을 다음 shift register 의 serial data input 으로 해주고,

latch 와 clock 은 동기를 위해 동일한 pin ( 12 / 11 ) 에 연결하는 것입니다.


그 외 LED 와 연결하는 parallel data output 은 LED 에 각각 연결하면 됩니다.





3. Layout


선을 연결해 보면 아래와 같이 됩니다.


선이 복잡하므로 10개짜리 LED bargraph 를 사용해서 그려봤습니다.
2배로 선이 많아지죠?

그나마 resistor network 을 이용해서 실제 배선이 많이 간결해 졌습니다.
Resistor Network 에 대해서는 아래 link 글을 참조해 주세요.

* Hardware | Resistor Network 을 사용해보자


제대로 연결하면 잘 움직입니다.

아래 소스를 토대로 참조한 사이트의 핀 배열을 조금 바꾸었습니다.

(원래 사이트에서는 8 + 8 = 16 개 기준으로 만들어 졌슴)





4. Source code


아래는 참조한 사이트 입니다.


http://www.instructables.com/id/Arduino-16-LEDs-using-two-74HC595-shift-registers-/


실제 코드는 아래 github 링크에 있습니다.


- https://github.com/janisrove/Arduino-74HC595-shift-registers/blob/master/ArduinoLEDsWithShiftRegisters/ArduinoLEDsWithShiftRegisters.ino


int latchPin = 8;
int clockPin = 12;
int dataPin = 11;

int numOfRegisters = 2;
byte* registerState;

long effectId = 0;
long prevEffect = 0;
long effectRepeat = 0;
long effectSpeed = 30;

void setup() {
	//Initialize array
	registerState = new byte[numOfRegisters];
	for (size_t i = 0; i < numOfRegisters; i++) {
		registerState[i] = 0;
	}
	
	//set pins to output so you can control the shift register
	pinMode(latchPin, OUTPUT);
	pinMode(clockPin, OUTPUT);
	pinMode(dataPin, OUTPUT);
}

void loop() {
	do {
		effectId = random(6);
	} while (effectId == prevEffect);
	prevEffect = effectId;
	
	switch (effectId) {
		case 0:
			effectRepeat = random(1, 2);
			break;
		case 1:
			effectRepeat = random(1, 2);
			break;
		case 3:
			effectRepeat = random(1, 5);
			break;
		case 4:
			effectRepeat = random(1, 2);
			break;
		case 5:
			effectRepeat = random(1, 2);
			break;
	}
	
	for (int i = 0; i < effectRepeat; i++) {
		effectSpeed = random(10, 90);
		
		switch (effectId) {
			case 0:
				effectA(effectSpeed);
				break;
			case 1:
				effectB(effectSpeed);
				break;
			case 3:
				effectC(effectSpeed);
				break;
			case 4:
				effectD(effectSpeed);
				break;
			case 6:
				effectE(effectSpeed);
				break;
		}
	}
}

void effectA(int speed) {
	for (int i = 0; i < 12; i++) {
		for (int k = i; k < 12; k++) {
			regWrite(k, HIGH);
			delay(speed);
			regWrite(k, LOW);
		}
		
		regWrite(i, HIGH);
	}
}

void effectB(int speed) {
	for (int i = 11; i >= 0; i--) {
		for (int k = 0; k < i; k++) {
			regWrite(k, HIGH);
			delay(speed);
			regWrite(k, LOW);
		}
		
		regWrite(i, HIGH);
	}
}

void effectC(int speed) {
	int prevI = 0;
	for (int i = 0; i < 12; i++) {
		regWrite(prevI, LOW);
		regWrite(i, HIGH);
		prevI = i;
		
		delay(speed);
	}
	
	for (int i = 11; i >= 0; i--) {
		regWrite(prevI, LOW);
		regWrite(i, HIGH);
		prevI = i;
		
		delay(speed);
	}
}

void effectD(int speed) {
	for (int i = 0; i < 6; i++) {
		for (int k = i; k < 6; k++) {
			regWrite(k, HIGH);
			regWrite(11 - k, HIGH);
			delay(speed);
			regWrite(k, LOW);
			regWrite(11 - k, LOW);
		}
		
		regWrite(i, HIGH);
		regWrite(11 - i, HIGH);
	}
}

void effectE(int speed) {
	for (int i = 5; i >= 0; i--) {
		for (int k = 0; k <= i; k++) {
			regWrite(k, HIGH);
			regWrite(11 - k, HIGH);
			delay(speed);
			regWrite(k, LOW);
			regWrite(11 - k, LOW);
		}
		
		regWrite(i, HIGH);
		regWrite(11 - i, HIGH);
	}
}

void regWrite(int pin, bool state) {
	//Determines register
	int reg = pin / 6;
	//Determines pin for actual register
	int actualPin = pin - (6 * reg);
	
	//Begin session
	digitalWrite(latchPin, LOW);
	
	for (int i = 0; i < numOfRegisters; i++) {
		//Get actual states for register
		byte* states = ®isterState[i];
		
		//Update state
		if (i == reg) {
			bitWrite(*states, actualPin, state);
		}
	
	//Write
	shiftOut(dataPin, clockPin, MSBFIRST, *states);
	}
	
	//End session
	digitalWrite(latchPin, HIGH);
}


소스를 잘 보면 16, 15, 8, 7 등의 숫자가 나옵니다.

이를 토대로 12, 11, 6, 5 등으로 12개에 맞춰서 숫자만 바꾸어 주면 됩니다.


따로 변수를 빼놓고, 자동으로 계산해서 사용될 수 있도록 하면, LED 갯수가 바뀌더라도 편할것 같습니다.

참조 사이트 말대로 "Unlimited Pins" 구조가 되겠네요.





5. 구동


아래는 멋지게 구동되는 모습입니다.



Fully! 12개의 LED 들을 모두 사용하는 모습입니다.



거참 source code 잘 짰네요.

수학적인 컨트롤 이므로, 다양한 모양으로 컨트롤이 가능할 듯 합니다.





FIN


이제 몇개의 LED 가 되었든, shift register 를 daisy chain 으로 엮으면 못할게 없겠습니다.


And

Hardware | LED bar graph 를 컨트롤 해보자 - 1

|

1. Arduino 와 LED bar graph


이미 LED bar graph 를 사용해 봤습니다.

아래 글들은 본 포스팅과 관련 있는 글 들입니다.


* Hardware | LED bar graph 를 이용해 보자

http://chocoball.tistory.com/entry/Hardware-LED-bar-graph


* Hardware | Resistor Network 을 사용해보자

http://chocoball.tistory.com/entry/Hardware-Resistor-Network-using


* Hardware | 74HC595 shift register 를 사용해 보자

http://chocoball.tistory.com/entry/Hardware-74HC595-shift-register


우선 arduino 와 direct 연결과 shift register 1개를 이용해서 연결을 해보기로 합니다.





2. Digital Pin 으로 직접 컨트롤


LED bar graph 의 anode 쪽을 arduino 의 digital Pin 에 직접 연결하여 전원을 공급함과 동시에 LED 를 on/off 하는 방법입니다.



Source code 는 쉽지만, arduino 와 직접 연결되는 선이 많아집니다.

또한, D13 pin 까지 쓰면 더이상 연결할 수가 없습니다.


   LED       |   Arduino
   Bargraph  |   Nano
----------------------------
   anode 2   |     D2
   anode 3   |     D3
   anode 4   |     D4
   anode 5   |     D5
   anode 6   |     D6
   anode 7   |     D7
   anode 8   |     D8
   anode 9   |     D9
   anode 10  |     D10
   anode 11  |     D11
   anode 12  |     D12
   anode 13  |     D13
     GND     |     GND
----------------------------


참고한 사이트는 아래와 같습니다.

http://www.4tronix.co.uk/arduino/ArduinoLearning.pdf


int timer = 50; // The higher the number, the slower the timing. int pins[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }; // an array of pin numbers int num_pins = 12; // the number of pins (i.e. the length of the array) void setup() { int i; for (i = 0; i < num_pins; i++) // the array elements are numbered from 0 to num pins - 1 pinMode(pins[i], OUTPUT); // set each pin as an output } void loop() { int i; for (i = 0; i < num_pins; i++) { // loop through each pin... digitalWrite(pins[i], HIGH); // turning it on, delay(timer); // pausing, digitalWrite(pins[i], LOW); // and turning it off. } for (i = num_pins - 1; i >= 0; i--) { digitalWrite(pins[i], HIGH); delay(timer); digitalWrite(pins[i], LOW); } }

Source code 는 참고한 사이트것을 그대로 사용하빈다.

단순히 digitalWrite 를 이용한 컨트롤 되겠습니다.



연결 사진 입니다.



구동 동영상 입니다.





3. Shift Register 를 이용하는 방법


Shift Register 를 이용하면 data / latch / clock 핀인 3개의 digital pin 만으로 컨트롤이 가능합니다.

여러 sensor 를 사용할 때에는 이 방법이 최선으로 보입니다.


이미 shift register 를 이용하여 확인해 봤습니다만, 이 글에서 한번 더 해봅니다.


* Hardware | 74HC595 shift register 를 사용해 보자

http://chocoball.tistory.com/entry/Hardware-74HC595-shift-register


우선 74HC595 pin 정보 입니다.



원본 data sheet 는 다음과 같습니다.


595datasheet.pdf


참고한 link 는 다음과 같습니다.


https://www.sqlskills.com/blogs/paulselec/category/shift-registers.aspx


Pin 들의 연결은 다음과 같습니다.


  LED       | Shift Register | Arduino
  Bargraph  |   SN74HC595N   |  Nano
---------------------------------------
  anode 1   | Q1 (pin 1)     |
  anode 2   | Q2 (pin 2)     |
  anode 3   | Q3 (pin 3)     |
  anode 4   | Q4 (pin 4)     |
  anode 5   | Q5 (pin 5)     |
  anode 6   | Q6 (pin 6)     |
  anode 7   | Q7 (pin 7)     |
            | GND (pin 8)    |  GND
            | Vcc (pin 16)   |  3.3V
  anode 0   | Q0 (pin 15)    |
            | DS (pin 14)    |  D11     --> dataPin
            | OE (pin 13)    |  GND
            | ST_CP (pin 12) |  D8      --> latchPin
            | SH_CP (pin 11) |  D12     --> clockPin
            | MR (pin 10)    |  3.3V
----------------------------------------


Layout 입니다.

Arduino 에서는 컨트롤 위한 선이 3개만 사용된 것을 보실 수 있을껍니다.



연결된 모습니다.



Source code 입니다.


shiftOut 이라는 명령어를 쓰면 쉽게 동작시킬 수 있으나,

참고한 사이트의 제작자는 오로지 공부를 위해 digitalWrite 명령어를 사용했습니다.


/*
  Driving a 74HC595 shift register
  01/27/2010
*/

// This pin gets sets low when I want the 595 to listen
const int pinCommLatch = 8;

// This pin is used by ShiftOut to toggle to say there's another bit to shift
const int pinClock = 12;

// This pin is used to pass the next bit
const int pinData = 11;

void setup() {
	pinMode (pinCommLatch, OUTPUT);
	pinMode (pinClock, OUTPUT);
	pinMode (pinData, OUTPUT);
	//Serial.begin (56600);
} // setup

// Using my own method with as few instructions as possible
// Gotta love C/C++ for bit-twiddling!
void sendSerialData2 (byte  value) {
	// Signal to the 595 to listen for data
	digitalWrite (pinCommLatch, LOW);
	
	for (byte bitMask = 128; bitMask > 0; bitMask >>= 1) {
		digitalWrite (pinClock, LOW);
		digitalWrite (pinData, value & bitMask ? HIGH : LOW);
		digitalWrite (pinClock, HIGH);
	}
	
	// Signal to the 595 that I'm done sending
	digitalWrite (pinCommLatch, HIGH);
}  // sendSerialData2
  
void loop() {
	for (int counter = 1; counter < 256; counter++) {
		sendSerialData2 (counter);
		delay (75);
	}
} // loop


구동시킨 동영상 입니다.





4. 더 간단하게 사용해 보기


위와 같은 동작을 시키는 좀더 간단한 tutorial 이 있습니다.


https://www.arduino.cc/en/Tutorial/ShiftOut


shiftOut 이라는 명령어로 쉽게 구현되었습니다.

https://www.arduino.cc/reference/en/language/functions/advanced-io/shiftout/


//**************************************************************//
//  Name    : shiftOutCode, Hello World                                
//  Author  : Carlyn Maw,Tom Igoe, David A. Mellis 
//  Date    : 25 Oct, 2006    
//  Modified: 23 Mar 2010                                 
//  Version : 2.0                                             
//  Notes   : Code for using a 74HC595 Shift Register           //
//          : to count from 0 to 255                           
//****************************************************************

//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;



void setup() {
	//set pins to output so you can control the shift register
	pinMode(latchPin, OUTPUT);
	pinMode(clockPin, OUTPUT);
	pinMode(dataPin, OUTPUT);
}

void loop() {
	// count from 0 to 255 and display the number 
	// on the LEDs
	
	for (int numberToDisplay = 0; numberToDisplay < 256; numberToDisplay++) {
		// take the latchPin low so 
		// the LEDs don't change while you're sending in bits:
		digitalWrite(latchPin, LOW);
		// shift out the bits:
		shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay);  
		
		//take the latch pin high so the LEDs will light up:
		digitalWrite(latchPin, HIGH);
		// pause before next value:
		delay(50);
	}
}


위의 soruce 는 위의 동영상과 완벽하게 동일한 동작을 합니다.

comment out 라인만 빼면 정말 간단하게 구현되어 있다는 것을 알 수 있죠?


/*
  Shift Register Example
  Turning on the outputs of a 74HC595 using an array

  Hardware:
  * 74HC595 shift register 
  * LEDs attached to each of the outputs of the shift register
 */

//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;

//holders for infromation you're going to pass to shifting function
byte data;
byte dataArray[10];

void setup() {
	//set pins to output because they are addressed in the main loop
	pinMode(latchPin, OUTPUT);
	Serial.begin(9600);
	
	//Binary notation as comment
	dataArray[0] = 0xFF; //0b11111111
	dataArray[1] = 0xFE; //0b11111110
	dataArray[2] = 0xFC; //0b11111100
	dataArray[3] = 0xF8; //0b11111000
	dataArray[4] = 0xF0; //0b11110000
	dataArray[5] = 0xE0; //0b11100000
	dataArray[6] = 0xC0; //0b11000000
	dataArray[7] = 0x80; //0b10000000
	dataArray[8] = 0x00; //0b00000000
	dataArray[9] = 0xE0; //0b11100000
	
	//function that blinks all the LEDs
	//gets passed the number of blinks and the pause time
	blinkAll_2Bytes(2,500); 
}

void loop() {
	for (int j = 0; j < 10; j++) {
		//load the light sequence you want from array
		data = dataArray[j];
		//ground latchPin and hold low for as long as you are transmitting
		digitalWrite(latchPin, 0);
		//move 'em out
		shiftOut(dataPin, clockPin, data);
		//return the latch pin high to signal chip that it 
		//no longer needs to listen for information
		digitalWrite(latchPin, 1);
		delay(300);
	}
}


// the heart of the program
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
	// This shifts 8 bits out MSB first, 
	//on the rising edge of the clock,
	//clock idles low
	
	//internal function setup
	int i=0;
	int pinState;
	pinMode(myClockPin, OUTPUT);
	pinMode(myDataPin, OUTPUT);
	
	//clear everything out just in case to
	//prepare shift register for bit shifting
	digitalWrite(myDataPin, 0);
	digitalWrite(myClockPin, 0);
	
	//for each bit in the byte myDataOut
	//NOTICE THAT WE ARE COUNTING DOWN in our for loop
	//This means that %00000001 or "1" will go through such
	//that it will be pin Q0 that lights.
	for (i=7; i>=0; i--) {
		digitalWrite(myClockPin, 0);
		
		//if the value passed to myDataOut and a bitmask result 
		// true then... so if we are at i=6 and our value is
		// %11010100 it would the code compares it to %01000000 
		// and proceeds to set pinState to 1.
		
		if ( myDataOut & (1 << i) ) {
			pinState= 1;
		} else {
			pinState= 0;
		}
	//Sets the pin to HIGH or LOW depending on pinState
	digitalWrite(myDataPin, pinState);
	//register shifts bits on upstroke of clock pin  
	digitalWrite(myClockPin, 1);
	//zero the data pin after shift to prevent bleed through
	digitalWrite(myDataPin, 0);
	}
	
	//stop shifting
	digitalWrite(myClockPin, 0);
}


//blinks the whole register based on the number of times you want to 
//blink "n" and the pause between them "d"
//starts with a moment of darkness to make sure the first blink
//has its full visual effect.
void blinkAll_2Bytes(int n, int d) {
	digitalWrite(latchPin, 0);
	shiftOut(dataPin, clockPin, 0);
	shiftOut(dataPin, clockPin, 0);
	digitalWrite(latchPin, 1);
	delay(200);
	
	for (int x = 0; x < n; x++) {
		digitalWrite(latchPin, 0);
		shiftOut(dataPin, clockPin, 255);
		shiftOut(dataPin, clockPin, 255);
		digitalWrite(latchPin, 1);
		delay(d);
		digitalWrite(latchPin, 0);
		shiftOut(dataPin, clockPin, 0);
		shiftOut(dataPin, clockPin, 0);
		digitalWrite(latchPin, 1);
		delay(d);
	}
}


위 소스는 segment 의 모양을 dataArray 를 사용하여 표현하는 soruce 입니다.



위의 소스를 구동시킨 동영상 입니다.




FIN


12 segments LED bar graph 를 한개만 써서 하는 것은 확인해 봤습니다.


1 개의 shift register 만 사용하면 8개까지만 사용이 가능하니, 12 segments 을 모두 활용하지 못했습니다.

Shift register 를 daisy chain 으로 추가 엮어 주면 가능하다고 합니다.


따로 글을 작성해 보겠습니다.


And

Hardware | 74HC595 shift register 를 사용해 보자

|

1. Shift Register


LED bar graph 를 컨트롤 하려면 shift register 가 필요 합니다.


Arduino 의 digital pin 에 직접 연결하면 LED bar graph 를 컨트롤 할 수 있습니다만,

D2 ~ D13 에서, 총 12개의 LED 만 동시에 컨트롤을 할 수가 있습니다.


LED bar graph 에 대해서는 다음 글을 참고해 주세요.


* Hardware | LED bar graph 를 이용해 보자

http://chocoball.tistory.com/entry/Hardware-LED-bar-graph


이제 Shift Register 를 구입해 보고자 합니다.




2. 구입


AliExpress 에서 검색해 봅니다.

10개에 1천원도 하지 않는 가격!!! 거기에 무료 배송이라니.

오히려 제가 업자 걱정을 하게 되는 가격입니다.


https://ko.aliexpress.com/item/10pcs-free-shipping-SN74HC595N-SN74HC595-74HC595N-74HC595-DIP-16-Counter-Shift-Registers-Tri-State-8-Bit/32429190104.html





3. 도착


포장은 DIP 다리가 잘 보호되도록 플라스틱 릴에 넣어서 왔습니다.



제가 개인적으로 좋아하는 Texas Instruments 사에서 제조된 chip 입니다.



대학교 실험과목에서 많이 썼었는데...

그땐 공부가 너무 싫어 놀기에만 정신이 팔려 자세히 알지도 못했습니다.


이제는 공부의 개념이 아니라 취미의 개념으로 접근하니 즐겁기만 합니다.




4. Specification


스펙은 제조사에서 공유하고 있습니다.


sn74hc595.pdf


아마 이 문서만 빠삭하게 알고 있으면 활용도 100% 일 듯 합니다.

온갓 온도 / 전압 특성과 패키징에 대해서 자세히 나와 있습니다.


Chip 개발에 있어, 간단한 것이라도 이렇게 많은 내용을 포함해야 한다니 대단한 작업인것 같습니다.



회로 구성에 있어서 보통 5V 로 구동한다고 하지만,

Texas Instruments 에서 생산한 SN74HC959 는 3.3V 에서도 잘 동작하도록 제조된것 같습니다.

사양서에도 2V ~ 6V 사이에 구동된다고 합니다.



Clock 에 따라서 각각의 pin state 를 컨트롤 하고 있다는 것을 알 수 있습니다.




Function table 을 가지고 chip 의 기능을 모두 설명해 놨습니다.
위의 두개의 표만으로 이 chip 의 구동에 대해서 설명이 됩니다.




5. Layout


Shift Register 를 이용하여 arduino 와 연결하면 다음과 같은 구성이 됩니다.


  LED       | Shift Register | Arduino
  Bargraph  |   SN74HC595N   |  Nano
---------------------------------------
  anode 1   | Q1 (pin 1)     |
  anode 2   | Q2 (pin 2)     |
  anode 3   | Q3 (pin 3)     |
  anode 4   | Q4 (pin 4)     |
  anode 5   | Q5 (pin 5)     |
  anode 6   | Q6 (pin 6)     |
  anode 7   | Q7 (pin 7)     |
            | GND (pin 8)    |  GND
            | Vcc (pin 16)   |  3.3V
  anode 0   | Q0 (pin 15)    |
            | DS (pin 14)    |  D11     --> dataPin
            | OE (pin 13)    |  GND
            | ST_CP (pin 12) |  D8      --> latchPin
            | SH_CP (pin 11) |  D12     --> clockPin
            | MR (pin 10)    |  3.3V
----------------------------------------


회로도는 다음과 같습니다.



회로도에서도 알 수 있듯이, arduino 와의 연결선은 단 3개로 단축됩니다.



모든 연결은 shift register 가 담당하니, 선의 복잡도는 그대로일 수 밖에 없습니다.

다만, 복잡한 연결은 shitf register 가 담당하고 arduino 는 추가 기기들을 연결하는 controller 역할을 더 수행할 수 있게 됩니다.





6. Source


구동 source code 입니다.


int latchPin = 12;
int clockPin = 11;
int dataPin = 13;
byte leds = 0;
int currentLED = 0;

void setup() {
	pinMode(latchPin, OUTPUT);
	pinMode(dataPin, OUTPUT);
	pinMode(clockPin, OUTPUT);
	
	leds = 0;
}

void loop() {
	leds = 0;
	
	if (currentLED == 7) {
		currentLED = 0;
	} else 	{
		currentLED++;
	}
	
	bitSet(leds, currentLED);
	
	digitalWrite(latchPin, LOW);
	shiftOut(dataPin, clockPin, LSBFIRST, leds);
	digitalWrite(latchPin, HIGH);
	
	delay(250);
}




7. 확인


실제 연결 사진입니다.



스파게티~~~.





8. 번외


Shift register 는 clock 과 전압 high/low 를 통하여 컨트롤 하게 됩니다.


예전에 AliExpress 에서 부품을 조립하여 사용하는 Oscilloscope 인 DSO 150 를 만들어 놨으니,

파형을 확인해 보고 싶어졌습니다.


* Hardware | DSO150 Oscilloscope

http://chocoball.tistory.com/entry/HardwareDSO150Oscilloscope


Arduino 의 D12 에서 clock 을 발생하므로 확인해 봅니다.



흠흠, 정말 사각형 클럭이 보이네요.


D11 인 data 통신을 확인해 봅니다.



필요한 값을 shift register 에게 보내고 있다는 것을 알 수 있습니다.


LED 측의 값을 확인해 봅니다.



LED 점등은 shift register 를 통하여 High/Low 로 확인이 됩니다.




FIN


Shift register 는 정말 clock 으로 동작하는 것을 확인할 수 있었습니다.

이제 LED bar graph 두개 이상을 한번 연결해 보고싶네요.

And

Hardware | VL53L0X 레이저 거리 측정 센서 사용해 보기

|

1. 드론


드론 제작시 필요한 sensor 중에 하나는 거리 측정기 라고 합니다.

이는 호버링이나 일정한 높이를 유지하면서 이동시, 항상 지상의 높이를 측정하여 자기의 위치를 알아야 하니까요.


또한 충돌 방지등에도 필요할 것 같습니다.



드론이 보는 시각은 향후 이렇게 되겠죠?





2. 주문


항상 그렇듯 AliExpress 에서 검색하여 주문하였습니다.


정식 명칭은,

"VL53L0X,Time-of-Flight (ToF) Laser Ranging Sensor Breakout 940nm GY-VL53L0XV2 Laser Distance Module I2C IIC" 입니다.


https://ko.aliexpress.com/item/VL53L0X-Time-of-Flight-ToF-Laser-Ranging-Sensor-Breakout-940nm-GY-VL53L0XV2-Laser-Distance-Module-I2C/32773306734.html



여러가지 breakout 보드가 존재하지만, 이 제품이 고정홀이 2개이고 가장 저렴해서 선택했습니다.




3. 도착


도착샷들 입니다.

AliExpress 제품답게 포장되어 왔습니다. Gift 표시가 빠지면 섭섭하지요.



레이저를 쏘는 소자 부분입니다.



뒷면은 신호처리에 필요한 회로로 구성되어 있습니다.





4. Layout


Pin 연결 정보 입니다.


  VL53L0X | Arduino Nano
-------------------------
    VIN   |     3.3V
    GND   |     GND
    SCL   |     A5
    SDA   |     A4
-------------------------



I2C를 사용하는지라, SSD1306 연결과 완벽하게 동일합니다.


  SSD1306 | Arduino Nano
-------------------------
    VCC   |     3.3V
    GND   |     GND
    SDC   |     A5
    SDA   |     A4
-------------------------


구성도는 다음과 같습니다.





5. VL53L0X sketch


Adafruit 용 VL53L0X library 를 다운로드 받아 libraries 폴더에 카피합니다.


* Adafruit VL53L0X library

https://github.com/adafruit/Adafruit_VL53L0X


#include "Adafruit_VL53L0X.h"

Adafruit_VL53L0X lox = Adafruit_VL53L0X();

void setup() {
	Serial.begin(115200);
	
	// wait until serial port opens for native USB devices
	while (! Serial) {
	delay(1);
	}
	
	Serial.println("Adafruit VL53L0X test");
	if (!lox.begin()) {
	Serial.println(F("Failed to boot VL53L0X"));
	while(1);
	}
	// power 
	Serial.println(F("VL53L0X API Simple Ranging example\n\n")); 
}


void loop() {
	VL53L0X_RangingMeasurementData_t measure;
	
	Serial.print("Reading a measurement... ");
	lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!
	
	if (measure.RangeStatus != 4) {  // phase failures have incorrect data
	Serial.print("Distance (mm): "); Serial.println(measure.RangeMilliMeter);
	} else {
	Serial.println(" out of range ");
	}
	
	delay(100);
}


I2C detector 로 확인해 보면 VL53L0X 의 기본 address 인 "0x29" 이라는 것을 확인할 수 있습니다.


#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);
}




6. VL53L0X + OLED


SSD1306 OLED sample sketch 도 있어서 실행하면 에러를 냅니다.

원인은 library source 가 다른것.



특이하게도 Adafruit sample 에 vl53l0x_oled 라고 되어 있음에도 불구하고,

pololu 제작자가 만든 library 를 다운로드 받아서사용해야 합니다.


* VL53L0X library

https://github.com/pololu/vl53l0x-arduino


/* This example shows how to use continuous mode to take
range measurements with the VL53L0X. It is based on
vl53l0x_ContinuousRanging_Example.c from the VL53L0X API.

The range readings are in units of mm. */

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

Adafruit_SSD1306 display = Adafruit_SSD1306();

VL53L0X sensor;

void setup()
{
	Serial.begin(9600);
	
	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
	// init done
	display.display();
	delay(1000);
	
	
	Wire.begin();
	
	sensor.init();
	sensor.setTimeout(500);
	
	// Start continuous back-to-back mode (take readings as
	// fast as possible).  To use continuous timed mode
	// instead, provide a desired inter-measurement period in
	// ms (e.g. sensor.startContinuous(100)).
	sensor.startContinuous();
	
	// text display big!
	display.setTextSize(4);
	display.setTextColor(WHITE);
}

void loop()
{
	uint16_t reading = sensor.readRangeContinuousMillimeters();
	
	if (reading > 8000) {
		display.display();
		display.clearDisplay();
		return;
	}
	
	Serial.print(sensor.readRangeContinuousMillimeters());
	if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); }
	
	display.clearDisplay();
	display.setCursor(0,0);
	display.print(reading);
	display.print("mm");
	display.display();
	Serial.println();
	delay(50);
}


이번에는 OLED 를 추가하였으므로, I2C detector 로 확인해 보면 아래와 같이 "0x3c" 가 추가적으로 검출된 것을 알 수 있습니다.

속도는 좀 느릴지 모르지만, address 를 따로 가지고 있어서 동시에 같은 pin 연결을 할 수 있는 I2C 의 강점인것 같습니다.


* 참고 글

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





7. 결과


VL53L0X 센서만 부착하여 "Serial Monitor" 로 확인한 내용입니다.



아래는 OLED 를 부착하여 측정한 내용입니다.

15Cm 자를 쟀는데, 20Cm 언저리가 나오네요. 뭔가 칼리브레이션이 필요한 듯 보입니다.



왔다갔다 하면서 측정해 봤습니다.

역시 5Cm 정도가 이미 + 가 되어 있네요. 조정이 초기에는 필요한것 같습니다.



센서부를 찍어봤습니다.

맨눈으로는 보이지 않지만, 감도가 좋은 스마트폰 카메라에는 센서에서 나오는 불빛이 보입니다.

아마도 레이저겠죠?





FIN


잘만 사용하면 요긴하게 쓰일 수 있을것 같습니다.

애들 키 재는 용도로도 쉽게 만들 수 있을것 같네요.

And

Hardware | Rotary Encoder 를 사용해 보자

|

1. Rotary Encoder


예전 전자 기기들의 볼륨 조절은, 최저/최고값이 표시되어 있고, 그 안에서만 움직이는 방식이었습니다.


요즘 나오는 자동차의 음성 조절이나 iPod 같은 전자기기의 볼륨도,

min/max 가 정해져 있지 않은 볼륨 조절 장치로 되어 있어요.


이를 Rotary Encoder 라고 부른다고 합니다.


제가 arduio 및 전자 취미시 처음으로 만져본 것은 "Transistor Tester" 라는 기기였습니다.


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


왼쪽 / 오른쪽으로 끝없이 돌려도 되면서,

위로부터 꾹 누르면 스위치의 "select" 도 구현되어 있는 센서였습니다.



기술 발전이란...




2. 원리


원리는 원반에 구멍이 일정 간격으로 뚫려 있고,

파형상 90도 차이나는 광원을 배치해, 각각 입력되는 펄스의 변화를 가지고 방향 인지 및 count 를 한다 합니다.



입력 시그널은 아래와 같이 나오며, 시계방향과 반시계방향의 펄스 입력값의 차이에 따라 알수 있겠죠.



값의 변화는 다음과 같이 되구요.



시작점을 11 값이라고 본다면, 각 방향으로 돌렸을 때의 변화값이 다르다는 것을 알 수 있습니다.



결국 저 작은 뭉퉁이에 photo diode 와 conuter 가 들어있다는 거네요.

예전같으면 불가능 했겠지만, sensor 들이 작아지면서 가능한 부품이 탄생한 것 같습니다.


참고한 사이트는 아래 두곳입니다.


http://howtomechatronics.com/tutorials/arduino/rotary-encoder-works-use-arduino/


- http://openhardware.ro/rotary-encoders-experiments/





3. AliExpress 에서 구매


Rotary Encoder 로 검색하면 여러가지 제품이 나옵니다.

그중에 가장 적당한 것으로 골랐습니다.


이걸 고른 이유는, 항상 LED 가 켜져 있어서 알려주는 indicator 가 없어서 였고 (눈부심),

괜찮게 저렴했기 때문이지요.



구매 링크는 다음과 같고, 사양은 아래와 같이 나와 있습니다.


https://ko.aliexpress.com/item/Rotary-Encoder-Module-Brick-Sensor-Development-Board-For-Arduino/1893663630.html


"rotation counts are not limited" 라고 되어 있어서, 어느 방향으로나 영원히 돌릴 수 있고,

"With the buttons on the rotary encoder can be reset to its initial state, that starts counting from 0" 라고 되어 있어서,

버튼 스위치가 구현되어 있다고 하네요.


=======================================

100% Brand new and high quality

Material: Electronic components + PCB

Size: About 31 * 19 * 29mm / 1.22" * 0.75" * 1.14"

Main color: Black

Working voltage: 5V

Pulse circle: 20

  

By rotating the rotary encoder can be counted in the positive direction and the reverse direction during rotation of the output pulse frequency, unlike rotary potentiometer count, this rotation counts are not limited. With the buttons on the rotary encoder can be reset to its initial state, that starts counting from 0. 

=======================================


다만, 가장 좋은 외형은 아래와 같이,

중간에 나사산이 있고, 윗부분에 어떤이라도 씌울 수 있는 돌기가 세겨져 있는 것이 좋을 듯 합니다.



비슷한 제품은 역시 괜찮은 sensor 들을 만들고 있는 SparkFun 에 있네요.

배송만 문제 없으면 이걸 구입하고 싶은데, 그냥 AliExpress 구매 제품으로도 만족합니다.





4. 도착


잊고 있었는데, 어느새 도착했습니다.

HDD 포장하는 것처럼 정전기 방지 비닐로 왔습니다.



필요한 단자는 다 있는 듯 합니다.



뒷면입니다.

중간에 R1 하나가 빠져 있는데, 괜찮은지 모르겠습니다.

아무래도 ripple 관련하여 있으면 좋지만 없어도 되는 부분을 뺀듯 합니다.


기회되면 나중에 10K 짜리 저항을 달아줘야겠습니다.





5. Layout


Pin 배열은 다음과 같습니다.


  Rotay  |
  Encder | Arduino Nano
-------------------------
    CLK  |     D2
    DT   |     D3
    SW   |   (empty)
     +   |     3.3V
    GND  |     GND
-------------------------

  SSD1306 | Arduino Nano
-------------------------
    VCC   |     3.3V
    GND   |     GND
    SDC   |     A5
    SDA   |     A4
-------------------------


전체 layout 은 다음과 같아요.






6. Sketch


Sketch 소스는 다음 link 를 참조하였습니다.


http://domoticx.com/arduino-rotary-encoder-met-oled-scherm/


원 저작자는

------------------------------------------------

"U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST); // Dev 0, Fast I2C / TWI"

------------------------------------------------


을 로딩했지만, 저는 SSD1306 OLED 이므로, 다음과 같이 수정하였습니다.

------------------------------------------------

"U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST);   // Fast I2C / TWI"

-----------------------------------------------


// U8glib Bibliotheek importeren
#include "U8glib.h"
// U8glib Bibliotheek configureren voor het juiste display
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST);   // Fast I2C / TWI
 
// Encoder pins configureren.
int pinEncA=2;
int pinEncB=3;
 
static byte abOud;       // Initialiseer status.
volatile int teller = 0; // rotatie teller.
int teller_oud;          // oude rotatie teller.
 
// Waarden voor variabel getal reserveren.
enum {BufSize=6};
char tellerStr[BufSize];
 
void setup() {
  // Encoder pinnen instellen.
  pinMode(pinEncA, INPUT);
  pinMode(pinEncB, INPUT);
 
  // Interrupts instellen (pin hoog-laag verandering).
  // Interrupt 0 = Pin 2 op de Arduino UNO.
  // Interrupt 1 = Pin 3 op de Arduino UNO.
  attachInterrupt(0, pinActie, CHANGE);
  attachInterrupt(1, pinActie, CHANGE);
 
  u8g.setFont(u8g_font_5x8); // Lettertype instellen voor u8glib.
}
 
void loop() {
  // IF loop wanneer er aan de encoder is gedraaid.
  if (teller_oud != teller) {
    teller_oud = teller;  
    snprintf(tellerStr, BufSize, "%d", teller);  // Converteer de "teller" INT naar STR (tbv OLED scherm)
  
    // OLED scherm loop.
    u8g.firstPage();  
    do {
      u8g.drawStr(0, 10, "Encoder:");
      
      u8g.drawBox(0, 14, 128, 16);    // Teken een witte rechthoek, 0px vanaf links, 14px van boven, 128px breed, 16px hoog.
      u8g.setColorIndex(0);           // zet kleur negatief (pixel uit).
      u8g.setScale2x2();              // maak het lettertype 2x groter.
      u8g.drawStr(25, 14, tellerStr); // print "teller" tekst.
      
      u8g.undoScale();                // zet het lettertype weer terug.
      u8g.setColorIndex(1);           // zet de kleur positief (pixel aan).
    } while( u8g.nextPage() );
  }
  // Overige code...
}
 
// Wanneer een interrupt heeft plaatsgevonden, lees de input pinnen, bereken nieuwe status, pas de telling aan.
void pinActie() {
  enum { upMask = 0x66, downMask = 0x99 };
  byte abNieuw = (digitalRead(pinEncA) << 1) | digitalRead(pinEncB);
  byte criteria = abNieuw^abOud;
  if (criteria==1 || criteria==2) {
    if (upMask & (1 << (2*abOud + abNieuw/2)))
      teller++;    // tel naar boven.
    else teller--; // tel naar beneden.
  }
  abOud = abNieuw; // bewaar nieuwe status.
}




7. 구동


아래는 실제 구동 영상 입니다.



IDE 로 메뉴 프로그래밍만 잘 하면 멋진걸 만들 수 있을것 같습니다.




FIN


단순한 입력 센서가 아닌, 설정하고 조정하는 조절센서로는 처음인것 같습니다.

여러가지로 활용해 봐야지.

And

Hardware | TSSR 3.5mm audio jack 구매하기

|

1. Safecast bGeigie Nano


시간이 나면, 짬짬이 방사능 측정기를 조립하고 있습니다.


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



조립 메뉴얼을 보면,

option 으로 분류되어 있으며 구성품에 포함되어 있지 않은 부품이 한개 있습니다.


https://github.com/Safecast/bGeigieNanoKit/wiki/Assembly-Manual


이는 "TSSR 3.5mm audio out jack" 으로,

부착하고 싶으면 따로 구매를 해야 합니다.



부품리스트에서 자세히 보면, 아래 제품이라는 것을 알 수 있습니다.


* SparkFun TRRS 3.5mm Jack Breakout

https://www.sparkfun.com/products/11570


bGeigie Nano 구매하고 구성품 받기까지 오래 걸리기도 하거니와

배대지를 이용해야 해서 여간 복잡한게 아니였습니다.


완성도 있게 만들고 싶은데, 이 부품이 빠지면 아쉬울 것 같아, AliExpress 도와줘요~ 해봅니다.




2. TSSR 3.5mm Audio Socket Breakout


AliExpress, 아니 중국은 대단한것 맞습니다.

완벽히 똑같은 카피품을 판매하고 있네요.


https://ko.aliexpress.com/item/3-5mm-Plug-Jack-Stereo-Plastic-Metal-TRRS-Headset-Audio-Socket-Breakout-Board-Extension-Module-Approx/32757253027.html



모양, pin 이름, 크기 모두가 똑같습니다.



여기에 더하여 가격이 1/4 가격입니다.

정품은 3.95 USD, 카피품은 1.09 USD 에 더하여 배송비 무료 입니다.



저같이 돈은 없지만, 전자부품으로 놀고 싶은 사람에게는 AliExpress 는 천국입니다.




3. 도착


아래는 도착샷 입니다.

평범하게 도착했습니다. 한 3주 걸린것 같아요.



앞면입니다.

프린트된 문구도 같네요.



뒷면입니다. TRRS Breakout 보드라고 표시되어 있네요.





4. 테스트


OLED 를 가지고 VU meter 를 만들어 볼 때, 테스트 해봤습니다.


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


Arduino 와의 연결에, Male Pin 납땜을 하고싶지 않아서 Probe Clip 을 사용하였습니다.


http://chocoball.tistory.com/entry/Hardware-Probe-Clip


여기서는 VU meter 를 구성하는 과정은 생략하고 결과만 올립니다.



iPhone 과 연결에 문제가 없네요.

확인 동영상 입니다.





FIN


방사능 측정기는 언제 조립을...


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
prev | 1 | ··· | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | next