ESP8266+OLED에 Bad Apple(동영상) 표시
개요
ESP8266에 연결된 128x64pixel 흑백 OLED에 동영상을 표시할 수 있었으므로, 그 구성, 구조 등에 대해 설명한다.
이번에 작성한 프로그램은 GitHub에서 공개하고 있는 h-nari/HSES_NODE_OLED_Sample_programs에 NetOLED라는 이름으로 들어있다.
- 동영상: ESP8266+OLED로 Bad Apple (youtube) (소리가 나옵니다)
배경
ESP8266(ESP-WROOM-02)과 2.4 인치 컬러 LCD을 조합한 기판이나 0.96인치 OLED를 결합한 기판을 작성하고 있다. 이런 기판으로, 언젠가는 동영상을 표시시키고 싶다고 생각하고 있었지만 2.4 인치·칼라 LCD의 쪽은 SPI 접속으로 CPU-LCD간의 속도 넥으로 무리. OLED도 SPI 접속이지만, 이쪽은 화소수가 적기 때문에 시험해 보았다.
메커니즘
ESP8266 측
사용하고 있는 보드는 HSES-NODE-OLED, 회로도도 포함한 기술 정보도 공개하고 있으므로 자세한 것은 제품 페이지를 참조해 받고 싶다.
ESP8266 측에서는, udp 패킷을 수신하고, 포함되는 화상 데이터를, 그대로 OLED에 보내는 프로그램이 움직이고 있다. 이미지 데이터의 포맷은 OLED의 데이터 포맷 그대로이다. 1화면분의 사이즈는 128 x 64/8 = 1024byte 가 되어, udp 패킷 1개로 보낼 수 있다.
sketch_netOLED.ino의 일부
void loop()
{
if(udp.parsePacket()){
PacketHeader h;
int len = udp.read((uint8_t *)&h, sizeof(h));
if(len < sizeof(h)){
Serial.printf("Bad length:%d\n",len);
} else {
while(udp.available()){
uint8_t buf[1024];
int len = udp.read(buf, sizeof(buf));
oled.writeData(buf, len);
}
}
}
}
PC측
PC측에서는 동영상의 파일을 읽어들여, 일정 주기로 udp 패킷을 송출하는 dispImage.py라고 하는 python의 프로그램이 움직이고 있다. 이것을 다음과 같이 시작하십시오.
$ python dispImage.py -r 30 192.168.0.136 ba_bmp/ba*.bmp
-r 30은 30fps로 이미지를 보내는 지정, 192.168.0.136은 esp8266 기판의 IP 주소, ba_bmp/ba*.bmp는 표시하는 이미지 파일로, 이번에는 Bad Apple 그림자 (니코 니코 동영상, YouTube) 파일을 ffmpeg로 1프레임씩 bmp파일로 변환한 것을 사용했다.
파이썬 라이브러리
Python의 이미지 처리 라이브러리 PIL(Pillow)의 Image 객체에서 128x64dot 흑백 OLED 데이터 포맷으로 변환하는 라이브러리를 준비했다. Image 모드의 변환이나 사이즈의 조정 처리를 제외하면, 아래와 같이 된다
def make_img_data(self, im, w = 128, h = 64):
px = im.load()
bdata = b''
for page in range(int(h/8)):
for x in range(w):
d = 0
for i in range(8):
b = px[x,page*8+i]
if b:
d += 1 << i
bdata += struct.pack('B',d)
return bdata
그리고는, 약간의 헤더를 추가해, udp로 보낼 뿐.
def send_data(self,bdata,frame):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
with closing(sock):
msg = b'HSESNODE'
msg += struct.pack('I', frame)
msg += bdata
sock.sendto(msg, (self.host, self.port))
def send_img(self, img, frame = 0):
self.send_data(self.make_img_data(img), frame)
이미지 파일 준비
이미 쓴 대로 이번에는 동영상 파일을 ffmpeg로, 프레임마다 bmp 파일로 변환해 표시시키고 있다.
이 때, 사이즈의 변환, 종횡비를 보존하기 위한 패딩의 추가 등도 실시하고 있다.
명령줄은 다음과 같습니다.
$ ffmpeg -i bad_apple_mono.mp4 -vf pad=768:384:128:0 -s 128x64 -r 30 -y ba_bmp/ba%04d.bmp
동기화 처리
Windows나 Linux등의 멀티태스킹 OS로, 동영상의 재생과 같은 1정 주기로 실시하는 처리를, 어떻게 할 수 있으면 좋을지 몰랐지만, 어쨌든 처리의 지연이 누적되지 않도록 아래와 같은 프로그램으로 시험해 보았는데, 잘 갔다. 촬영 후 편집으로 Bad Apple의 음성을 합성했지만, 소리 어긋남은 전혀 일어나지 않았다.
dispImage.py의 일부
for file in args['<img_file>']:
wait = start + period - time.time();
start += period
if verbose:
print(file,wait)
if(wait > 0):
im = Image.open(file)
oled.send_img(im)
time.sleep(wait)
동작 동영상
표시 데모 프로그램 dispDemo.py의 동영상, Bad Apple 전체를 카메라 고정 그대로 촬영한 동영상도 작성했으므로, 링크를 붙인다.
ESP8266(ESP-WROOM-02)과 2.4 인치 컬러 LCD을 조합한 기판이나 0.96인치 OLED를 결합한 기판을 작성하고 있다. 이런 기판으로, 언젠가는 동영상을 표시시키고 싶다고 생각하고 있었지만 2.4 인치·칼라 LCD의 쪽은 SPI 접속으로 CPU-LCD간의 속도 넥으로 무리. OLED도 SPI 접속이지만, 이쪽은 화소수가 적기 때문에 시험해 보았다.
메커니즘
ESP8266 측
사용하고 있는 보드는 HSES-NODE-OLED, 회로도도 포함한 기술 정보도 공개하고 있으므로 자세한 것은 제품 페이지를 참조해 받고 싶다.
ESP8266 측에서는, udp 패킷을 수신하고, 포함되는 화상 데이터를, 그대로 OLED에 보내는 프로그램이 움직이고 있다. 이미지 데이터의 포맷은 OLED의 데이터 포맷 그대로이다. 1화면분의 사이즈는 128 x 64/8 = 1024byte 가 되어, udp 패킷 1개로 보낼 수 있다.
sketch_netOLED.ino의 일부
void loop()
{
if(udp.parsePacket()){
PacketHeader h;
int len = udp.read((uint8_t *)&h, sizeof(h));
if(len < sizeof(h)){
Serial.printf("Bad length:%d\n",len);
} else {
while(udp.available()){
uint8_t buf[1024];
int len = udp.read(buf, sizeof(buf));
oled.writeData(buf, len);
}
}
}
}
PC측
PC측에서는 동영상의 파일을 읽어들여, 일정 주기로 udp 패킷을 송출하는 dispImage.py라고 하는 python의 프로그램이 움직이고 있다. 이것을 다음과 같이 시작하십시오.
$ python dispImage.py -r 30 192.168.0.136 ba_bmp/ba*.bmp
-r 30은 30fps로 이미지를 보내는 지정, 192.168.0.136은 esp8266 기판의 IP 주소, ba_bmp/ba*.bmp는 표시하는 이미지 파일로, 이번에는 Bad Apple 그림자 (니코 니코 동영상, YouTube) 파일을 ffmpeg로 1프레임씩 bmp파일로 변환한 것을 사용했다.
파이썬 라이브러리
Python의 이미지 처리 라이브러리 PIL(Pillow)의 Image 객체에서 128x64dot 흑백 OLED 데이터 포맷으로 변환하는 라이브러리를 준비했다. Image 모드의 변환이나 사이즈의 조정 처리를 제외하면, 아래와 같이 된다
def make_img_data(self, im, w = 128, h = 64):
px = im.load()
bdata = b''
for page in range(int(h/8)):
for x in range(w):
d = 0
for i in range(8):
b = px[x,page*8+i]
if b:
d += 1 << i
bdata += struct.pack('B',d)
return bdata
그리고는, 약간의 헤더를 추가해, udp로 보낼 뿐.
def send_data(self,bdata,frame):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
with closing(sock):
msg = b'HSESNODE'
msg += struct.pack('I', frame)
msg += bdata
sock.sendto(msg, (self.host, self.port))
def send_img(self, img, frame = 0):
self.send_data(self.make_img_data(img), frame)
이미지 파일 준비
이미 쓴 대로 이번에는 동영상 파일을 ffmpeg로, 프레임마다 bmp 파일로 변환해 표시시키고 있다.
이 때, 사이즈의 변환, 종횡비를 보존하기 위한 패딩의 추가 등도 실시하고 있다.
명령줄은 다음과 같습니다.
$ ffmpeg -i bad_apple_mono.mp4 -vf pad=768:384:128:0 -s 128x64 -r 30 -y ba_bmp/ba%04d.bmp
동기화 처리
Windows나 Linux등의 멀티태스킹 OS로, 동영상의 재생과 같은 1정 주기로 실시하는 처리를, 어떻게 할 수 있으면 좋을지 몰랐지만, 어쨌든 처리의 지연이 누적되지 않도록 아래와 같은 프로그램으로 시험해 보았는데, 잘 갔다. 촬영 후 편집으로 Bad Apple의 음성을 합성했지만, 소리 어긋남은 전혀 일어나지 않았다.
dispImage.py의 일부
for file in args['<img_file>']:
wait = start + period - time.time();
start += period
if verbose:
print(file,wait)
if(wait > 0):
im = Image.open(file)
oled.send_img(im)
time.sleep(wait)
동작 동영상
표시 데모 프로그램 dispDemo.py의 동영상, Bad Apple 전체를 카메라 고정 그대로 촬영한 동영상도 작성했으므로, 링크를 붙인다.
void loop()
{
if(udp.parsePacket()){
PacketHeader h;
int len = udp.read((uint8_t *)&h, sizeof(h));
if(len < sizeof(h)){
Serial.printf("Bad length:%d\n",len);
} else {
while(udp.available()){
uint8_t buf[1024];
int len = udp.read(buf, sizeof(buf));
oled.writeData(buf, len);
}
}
}
}
$ python dispImage.py -r 30 192.168.0.136 ba_bmp/ba*.bmp
def make_img_data(self, im, w = 128, h = 64):
px = im.load()
bdata = b''
for page in range(int(h/8)):
for x in range(w):
d = 0
for i in range(8):
b = px[x,page*8+i]
if b:
d += 1 << i
bdata += struct.pack('B',d)
return bdata
def send_data(self,bdata,frame):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
with closing(sock):
msg = b'HSESNODE'
msg += struct.pack('I', frame)
msg += bdata
sock.sendto(msg, (self.host, self.port))
def send_img(self, img, frame = 0):
self.send_data(self.make_img_data(img), frame)
$ ffmpeg -i bad_apple_mono.mp4 -vf pad=768:384:128:0 -s 128x64 -r 30 -y ba_bmp/ba%04d.bmp
for file in args['<img_file>']:
wait = start + period - time.time();
start += period
if verbose:
print(file,wait)
if(wait > 0):
im = Image.open(file)
oled.send_img(im)
time.sleep(wait)
표시 데모 프로그램 dispDemo.py의 동영상, Bad Apple 전체를 카메라 고정 그대로 촬영한 동영상도 작성했으므로, 링크를 붙인다.
마지막으로
Reference
이 문제에 관하여(ESP8266+OLED에 Bad Apple(동영상) 표시), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/h_nari/items/12f7231b2460fc37c83e텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)