안녕하세요. 호랑인 입니다. 오늘은 제가 제 친구와 같이 진행한 프로젝트를 소개하려고 합니다.
바로 Brinter 프로젝트인데요, 이게 뭐고, 어떻게 진행했으며, 어떤 결과가 나왔는지를 지금부터 보시죠!
0. 실험 동기
실험 동기는 단순했습니다. 빵에 토스트 된 정도를 사용해서 그림을 그릴 수 있으면 축제와 같은 행사에 사용하기 매우 좋을 것 같았습니다. 그래서 만들기로 했는데, 기존에는 어떤 방법으로 이를 했는지에 대해 조사를 했습니다.
1. 레이저 커터의 강도를 매우 약하게 한 뒤에, 원하는 그림을 그립니다.
장점: 매우 빠릅니다. (15초 정도면 웬만한 그림을 그릴 수 있음)
단점: 먹을 수 없습니다. 엄밀하게 말하면 먹을 수는 있지만, 실제로 해보니 냄새도 정말 별로고 근처 사람들에게 음식 갖고 장난치지 말라는 평을 받았습니다. 실제로 이는 빵 표면을 그냥 태우는 것이기 때문에 매우 썼습니다.
2. 특정 모양의 틀을 토스터기와 빵 사이에 둔다.
장점: 가장 쉽습니다. 원하는 모양을 열에 강한 성분으로 만들어 이를 스텐실처럼 사용해 그림을 그립니다.
단점: 흑, 백 두 가지 색 밖에 표현을 할 수 없습니다. 무엇보다 새로운 그림을 그리기 위해서는 새로이 하나의 판을 만들어야 한다는 단점이 있습니다.
3. 뜨거운 인두기를 여럿 설치한 뒤, 예열하고 이를 빵에 찍어서 그림을 그립니다.
장점: 흰색부터 검은색까지 모든 색을 그릴 수 있습니다.
단점: 만들기가 어렵고, 픽셀의 크기가 매우 크며, 이미지가 전반적으로 점박이 모양이라 예쁘지가 않습니다. 그리고 실제로 칼을 불에 달궈 구워 먹어보니, 썩 맛있지는 않았습니다.
이에 따라 저희는 완전히 새로운 방법으로 빵을, 열풍을 사용해 구워 더 맛있게 함과 동시에, 다양한 색을 표현하고 픽셀의 크기 또한 작게 해 보는 실험을 하게 되었습니다.
1. 실험 개요
1.1. Brinter 란 무엇인가?
Brinter는 Bread와 Printer의 합성어로, 빵에 원하는 그림이나 사진을 프린팅 해주는 기계를 의미합니다.
1.2. Brinter의 기본 동작 원리
Brinter는 히트건의 열풍을 사용하여 특정 부위의 빵을 더 많이 구워, 결과적으로 생기는 색의 차이를 통해 빵을 굽습니다.
위의 그림처럼 히트건은 지속적으로 뜨거운 바람을 불어주고, 이는 노즐을 통해 빵으로 전해져 빵을 굽게 됩니다. 이때 노즐을 움직여 빵에 그림을 그릴 수 있습니다.
노즐을 원하는 방향 (x, y, z) 로 이동할 수 있도록 하기 위한 장치가 필요했는데요, 이를 위해 조립형 3D Printer와 G-Code를 사용했습니다.
2. 실험 과정
2.1. 예비 실험 (Preliminary Experiment)
실제로 히트건의 열기로 빵이 구워지는지 여부를 확인해보는 과정이 필요했습니다. 이를 위해 직접 히트건을 손으로 들고 빵위에 분사하여 빵을 구워봤습니다.
실제로 구워보니, 빠잉 아주 잘 구워짐을 알 수 있었습니다. 무엇보다 이 실험에서 중요한 색이 잘 나타남을 알 수 있었습니다. 추가로, 열풍으로 구운 빵은 버터를 바르지 않았음에도 정말 맛있었습니다. 겉바속촉의 정석이더군요.
하지만 너무 온도를 높게 설정하면 빵이 구워지기 전에 표면이 탈 수도 있다는 것을 알 수 있었습니다.
2.2. 프린터 조립
조립식 3D Printer를 하나 구매하고 이를 조립했습니다. 모두 정상 작동합니다.
원래 3D Printer는 Heating Bed를 특정 온도가 될 때까지 가열합니다. 그러기 위해 전열선과 온도계가 같이 왔는데요, 나중에 G-Code 부분에서도 말씀드리겠지만, 이는 저희에게 필요 없는 기능이기 때문에 껐습니다.
2.3 열풍 전달
저희는 히트건을 사용해서 빵을 굽기로 했기 때문에, 히트건에서 나오는 뜨거운 공기를 빵에 분사시키기 위한 방법을 만들어야 했습니다. 이를 위해 저희는 샤워기 호스를 활용하기로 했습니다.
샤워기 호스를 열어보시면, 바깥에 쉽게 휠 수 있도록 환형 구조로 만들어놓은 알루미늄 선과 내부에 물을 통하게 해주는 고무관으로 이루어져 있습니다. 저희는 고무 호스가 필요가 없으니, 분리했습니다.
이제 마지막으로 3D Printer에서 원래 필라멘트가 나오는 노즐 부분과 샤워호스를 연결해야 했는데, 이를 해 줄 수 있는 마땅한 부품이 없었습니다. 그래서 하나 만들기로 했습니다.
실제로 이를 3D Printer를 사용해서 출력해보고, 연결해보니 잘 연결되는 것을 확인할 수 있었습니다.
그래서 이 파일을 그대로 넘겨드려 선반 집에 맡겼습니다. (원통형 알루미늄 봉의 외각에 나사선을 파는 과정입니다.)
2.4. G-CODE 만들기
이제 그림을 G-Code로 바꿔줄 수 있는 코드를 작성할 차례입니다.
언어는 python3를 사용했고, 이를 통해 .gcode의 확장자에 원하는 코드를 넣는 함수를 작성했습니다.
def writeStart(self):
self.file.write("G21;\n") # millis
self.file.write("G90;\n") # absolute position
self.file.write("M82;\n") # absolute extrusion
self.file.write("M107;\n") # fan off
self.file.write("G28 X0 Y0;\n") # move to min
self.file.write("G28 Z0;\n") # move z to min
self.file.write("G29\n") # precise z move; remove if trouble
self.file.write("G1 X0 Y0 F9000;\n") # move to origin
self.file.write("M117 Printing...;\n") # print to LCD
self.file.write("G1 Z9 F9000;\n")
def writeEnd(self):
self.file.write("M104 S0;\n") # turn off extruder
self.file.write("M140 S0;\n") # turn off heatbed
self.file.write("G91;\n") # relative position
self.file.write("G1 F9000;\n") # make it faster
#self.file.write("G1 X-20 Y-20 Z5;\n") # raise head
self.file.write("G1 Z25;\n") # use this line or upper line
self.file.write("G90;\n") # use absolute position
self.file.write("G28 X0 Y0;\n") # goto home
self.file.write("M84;\n") # disable motor
보시면 writeStart와 writeEnd라는 함수들이 있음을 알 수 있는데요, 각각 3D Printer를 초기화해주는 과정과 종료해주는 과정을 G-Code로 작성한 것입니다.
def writeImage(self):
self.file.write("G1 X0 Y0 F9000;\n") # move to origin
self.file.write("G1 X100 Y100 F9000;\n")
self.file.write("G1 X0 Y0 F9000;\n")
for row in range(self.imageSize[0]):
rowArr = self.imageArray[row];
x = round((self.breadSize-self.printSize)/2, 3)
y = round(((self.breadSize-self.printSize)/2)+(self.printSize/self.imageSize[0]*row), 3)
data = "G1 X" + str(x) + " Y" + str(y) + " F9000\n"
self.file.write(data)
for col in range(self.imageSize[1]):
x = round(((self.breadSize-self.printSize)/2)+(self.printSize/self.imageSize[1]*col), 3)
feed = self.colorToSpeed(rowArr[col])
data = "G1 X" + str(x) + " Y" + str(y) + " F" + str(feed) + str("\n")
self.file.write(data)
위의 writeImage가 본격적으로 image를 G-Code로 바꿔주는 함수입니다.
저희는 image를 왼쪽 위에서부터 오른쪽 아래를 향해 노즐을 움직이되, 움직이는 속도를 조절해서 그 명암을 조절했습니다. 그렇기 때문에 feed, 즉 모터가 움직일 속도를 image의 픽셀 값으로부터 계산하여 움직이는 것이죠.
feed = self.colorToSpeed()라는 부분에서 픽셀의 값으로부터 feed의 값을 계산해낼 것입니다.
2.5. 감도 조절하기
이제 모든 부품이 연결이 되었으니, 실제로 그림을 그려야 할 차례입니다. 그전에, 위에서 말한 colorToSpeed() 함수에 대해 생각해보자면, 어떻게 우리가 어떤 속도로 모터를 움직이는 것이 우리가 원하는 색을 나타내 줄 것이라 확신할 수 있을까요?
사실 이를 위해 다양한 방정식을 풀어가며 다가갔을 수도 있었겠지만, 저희는 직접 몸으로 뛰기로 했습니다.
그래서 위와 같이 생긴, test image를 만들었습니다. 이는 그림판에서 쉽게 찾을 수 있는 흰색, 연한 회색, 짙은 회색, 그리고 검은색이었습니다. 그리고 다양한 함수를 넣어가면서 이 test image를 출력해보게 했습니다.
아래는 실제 실험 결과 사진들입니다.
이렇게 다양한 함수를 넣어가며 각 색깔 별로 저희가 원하는 색을 가장 잘 만든 함수를 찾아냈습니다.
그 결과 검은색은 10, 짙은 회색은 144, 옅은 회색은 360, 횐색은 4545의 feed rate에서 가장 저희가 원하는 색이 나옴을 알 수 있었습니다.
이를 그래프로 그려보면, 아래와 같은 그래프가 나옵니다.
그래서 이를 그대로 코드에 다시 넣어 사용했습니다.
3. 실험 결과
3.1. 실제 구조
3.2. 사진 출력 결과
4. 실험 결론
저희는 실험 결과에 만족했습니다. 엄청난 퀄리티를 자랑한 것은 아니었으나, 사진이 나왔고, 맛있게 구워졌기 때문입니다. 실험에 사용된 모든 빵은 당시 실험을 지켜보고 있었던 아이디어 팩토리 근무자가 맛있는 빵 구워지는 냄새를 참지 못하고 다 먹었습니다. 물론 저도 맛있게 먹었고요.
이상 호랑인이었습니다. 감사합니다.
'프로젝트 > 프로젝트 [Brinter]' 카테고리의 다른 글
[Brinter] 최종 발표회 (0) | 2020.04.09 |
---|