tag:blogger.com,1999:blog-67622367265395174082024-03-14T18:52:27.674+09:00기술 여행자 (ArsViator)관심가는 다양한 기술분야에 관한 내용을 적는 블로그입니다. 내용을 퍼가는 경우 출처를 확실하게 명시해 주시기 바랍니다.ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.comBlogger315125tag:blogger.com,1999:blog-6762236726539517408.post-27696152044171001712021-04-04T15:21:00.006+09:002021-04-04T15:21:56.405+09:00샤오미 AX3600 글로벌 롬 (메뉴 영문화)<p>샤오미 공유기 AX3600은 중국버젼 롬으로 나와 메뉴가 전부 중국어로 나온다. </p><p>물론 크롬의 자동번역기능등을 사용하면 그럭저럭 설정하는데 문제는 없어도 아무래도 불편하다.</p><p>이 글로벌 롬으로 펌웨어 업데이트를 하면 언어 선택이 가능해진다.</p><p>글로벌 펌웨어 버젼은 v3.0.22이고 참고로 글로벌 롬으로 가면 중국롬일때에 비해 무선 출력이 약간 줄어든다고 한다. 아마 각국의 무선 규제 때문에 중국 이외 국가용은 출력을 일부러 낮춘듯.</p><p>글로벌롬으로 업데이트 하면 언어 설정이 영어 이외에도 다른 언어로도 변경 가능하지만 아직 한국어는 없음.</p><p>그리고 글로벌롬에서 언어를 중국어로 해도 무선 출력은 중국어롬일때로 돌아가지는 않는다.<br /></p><p><a href="https://1drv.ms/u/s!Ag8W9V9UpDh11H327yKaqN3miZPs?e=H67Ncl ">AX3600 Global Firmware v3.0.22</a></p><p>위의 링크에서 다운받아 수동으로 설치해주면 된다. </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1jH48Ot_SDp4m9CwxStZYuHM1IMN4DpPfuoatyMoIY2ouMN3hvxwmTkTY5Hppi1FPfC9emyYRUfaOMeBhFyE5PVsKWPdTp6iKb9MZJtoyzoNMy9b8XC3uXNACX8Qqwx-LITtRZUKtscM/s1193/210106_freeboard_2011_be1791e2350bc9c8bb3ca558f3dfccfbe6628af4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="778" data-original-width="1193" height="417" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1jH48Ot_SDp4m9CwxStZYuHM1IMN4DpPfuoatyMoIY2ouMN3hvxwmTkTY5Hppi1FPfC9emyYRUfaOMeBhFyE5PVsKWPdTp6iKb9MZJtoyzoNMy9b8XC3uXNACX8Qqwx-LITtRZUKtscM/w640-h417/210106_freeboard_2011_be1791e2350bc9c8bb3ca558f3dfccfbe6628af4.png" width="640" /></a></div><br /><p><br /></p>ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-5817403717525782862020-05-26T16:25:00.000+09:002020-05-26T16:25:33.693+09:00Argon 1 case for Raspberry Pi 4 (라즈베리 파이 4용 아르곤 1 케이스)<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNxUhFmL4yvYtTp1IYtx0QFCQQTNo9OeaVqrjvMMQDyO4LqE69Nx2YJ_XVuQnVJN9uFpXgIxkUTx2vRJ_-6juRCZ0PnrchSQvGITPRN0Hgn2nee88T6lgkkCqlWWO_uTiHdOG8-11_QdM/s1600/IMG_3029.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1487" data-original-width="1600" height="594" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNxUhFmL4yvYtTp1IYtx0QFCQQTNo9OeaVqrjvMMQDyO4LqE69Nx2YJ_XVuQnVJN9uFpXgIxkUTx2vRJ_-6juRCZ0PnrchSQvGITPRN0Hgn2nee88T6lgkkCqlWWO_uTiHdOG8-11_QdM/s640/IMG_3029.jpg" width="640" /></a></div>
<br />
라즈베리 파이 4용으로 나온 Argon 1 케이스를 구입했다. 가장 큰 장점이 데스크탑들 처럼 모든 포트와 전원스위치를 한쪽으로 몰아 놨고 상판이 전부 알루미늄으로 되어 있어 방열처리도 잘 되어 있는것이 장점이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0H034trCB69PzxWDN6Gsl_P3lqRSlY5vT1IfaO7vtWlqMauJ2M_A8q8DPAN-6-IdNxd5PY9rKBmgYWoGPeh94jpX8YeGQsfx9Bdb58kcQOMcvFKBh0E61-gpjWc3gLRpNbP_EqVLtzaI/s1600/IMG_3030.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1212" data-original-width="1600" height="484" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0H034trCB69PzxWDN6Gsl_P3lqRSlY5vT1IfaO7vtWlqMauJ2M_A8q8DPAN-6-IdNxd5PY9rKBmgYWoGPeh94jpX8YeGQsfx9Bdb58kcQOMcvFKBh0E61-gpjWc3gLRpNbP_EqVLtzaI/s640/IMG_3030.jpg" width="640" /></a></div>
<br />
박스 안에는 위와 같은 부품이 들어 있다. 상판부에는 팬이 붙어 있고 전체가 알루미늄으로 되어 있지만 하판부는 플라스틱 재질이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcTAfEJe1xXJDOUn5xiUOUebjoOy9qAF2yIAEI28hNiJ1vN2WguzbpGtBZmp_MsUon4D-R4PiIuDPejzyvwuthNI1fS3vV-rlMj1r7nMgxt94PEZqNkjUSaaqAmH0UkiVfzsqhqKlPkuU/s1600/IMG_3031.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1286" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcTAfEJe1xXJDOUn5xiUOUebjoOy9qAF2yIAEI28hNiJ1vN2WguzbpGtBZmp_MsUon4D-R4PiIuDPejzyvwuthNI1fS3vV-rlMj1r7nMgxt94PEZqNkjUSaaqAmH0UkiVfzsqhqKlPkuU/s640/IMG_3031.jpg" width="514" /></a></div>
<br />
상판부의 GPIO 커넥터 부분은 뚜껑으로 덮혀 있는데 뚜겅부는 별도의 나사 없이 두개의 강력 자석으로 고정되게 되어 있어 평상시 잘 고정되어 있지만 손으로도 쉽게 열 수 있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZZbdIYRDoNjRfjAxPgshOwd7HgLfcLgRsx3ufLmmYUn4qo9qMNjG1AtcYIqIJH7hij5_6W7p8o5EFA7yoKc1L5KoZjY3utdvDd3jjS4gBhBGSLqQxF9uN0PUnA0RJSOdqQu6BJt_Bv44/s1600/IMG_3032.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1497" data-original-width="1600" height="598" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZZbdIYRDoNjRfjAxPgshOwd7HgLfcLgRsx3ufLmmYUn4qo9qMNjG1AtcYIqIJH7hij5_6W7p8o5EFA7yoKc1L5KoZjY3utdvDd3jjS4gBhBGSLqQxF9uN0PUnA0RJSOdqQu6BJt_Bv44/s640/IMG_3032.jpg" width="640" /></a></div>
<br />
먼저 라즈베리 파이 4에 커넥터들이 붙어 있는 보드를 연결해 준다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKaIH9OBql2-OvEw19Ss6cqKal7AjfK0jv_o2vzXEOjMrOF-g9dLgjYfZocZ-glTPJ4QBil7pCbgMos1rjaHcezpDek9CgB41n0Gym-IM0DbaGUPQCZqKRNEw3kPkw-MAPtz4Klu37pFo/s1600/IMG_3033-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKaIH9OBql2-OvEw19Ss6cqKal7AjfK0jv_o2vzXEOjMrOF-g9dLgjYfZocZ-glTPJ4QBil7pCbgMos1rjaHcezpDek9CgB41n0Gym-IM0DbaGUPQCZqKRNEw3kPkw-MAPtz4Klu37pFo/s640/IMG_3033-2.jpg" width="480" /></a></div>
<br />
다음은 상판부의 팬 옆쪽에 튀어나온 곳에 사진과 같이 실리콘 방열판 패드를 부착한다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN37VQMMZN-CJ3cWinLIVaoeUUOwc1tSdU-iMQ2z4Kk7jYDjchUP8Tark6balqB-disBN8A6SDXCH5qlYHM1ByEX5XUMJ5VYPu-kYY4LYVHJU2DdXUFoxg-wfsfdBbxk7Ty_vKddaQW00/s1600/IMG_3034-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1457" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN37VQMMZN-CJ3cWinLIVaoeUUOwc1tSdU-iMQ2z4Kk7jYDjchUP8Tark6balqB-disBN8A6SDXCH5qlYHM1ByEX5XUMJ5VYPu-kYY4LYVHJU2DdXUFoxg-wfsfdBbxk7Ty_vKddaQW00/s640/IMG_3034-2.jpg" width="582" /></a></div>
<br />
라즈베리 파이를 케이스 상판에 연결해 준 다음 표시한 부분에 flat-head 볼트(짤은 볼트)를 체결해서 보드를 상판에 고정시켜 준다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpb7BdaNqFUOsAAqu5DY60uIgE24QJKKMQ7e7Fgh3V_cef02y0NQ3czRAroqs4xIk5lIBCl8qCd8SJPK41LT1Hza4jzHle5z7aDvIHidAr-58BCQyEVSL-F5EaeCka_skP4aCrV_hSiWY/s1600/IMG_3036-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpb7BdaNqFUOsAAqu5DY60uIgE24QJKKMQ7e7Fgh3V_cef02y0NQ3czRAroqs4xIk5lIBCl8qCd8SJPK41LT1Hza4jzHle5z7aDvIHidAr-58BCQyEVSL-F5EaeCka_skP4aCrV_hSiWY/s640/IMG_3036-2.jpg" width="480" /></a></div>
<br />
그 후 하판을 상판에 덮어 준 다음 빨간색 부분에 round-head 볼트(긴 볼트)를 체결하고, 파란색 부분에 미끄럼 방지 고무를 부착해 주면 완성이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdMcjkAft3bsQaaPSI3Swhh_w4CjKW9YyrKSVnHRTpov6ycKyG2ZEPuoVJ9vZSgac8quY0zg6Zg1guOP16DJDWTyJVEAa7DGPvjEZi8LmbFxo-bbGgbjWp6Cw3q1gbfLOFfLqs7o7q18k/s1600/IMG_3037.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="703" data-original-width="1600" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdMcjkAft3bsQaaPSI3Swhh_w4CjKW9YyrKSVnHRTpov6ycKyG2ZEPuoVJ9vZSgac8quY0zg6Zg1guOP16DJDWTyJVEAa7DGPvjEZi8LmbFxo-bbGgbjWp6Cw3q1gbfLOFfLqs7o7q18k/s640/IMG_3037.jpg" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgewbxl5OimJRMtvGRqWxq6lTC5vzPl5CD1lBjuz1QYpPcfqz3usymWsnrXu2TOPYrMH7ynJgkIXnaxFpt8MklWt0bECkUmcgiWghAgrDgA0x7XbzWpmmj-sbgj_aoQBijJRkTziSWLwGc/s1600/IMG_3038.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="689" data-original-width="1600" height="274" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgewbxl5OimJRMtvGRqWxq6lTC5vzPl5CD1lBjuz1QYpPcfqz3usymWsnrXu2TOPYrMH7ynJgkIXnaxFpt8MklWt0bECkUmcgiWghAgrDgA0x7XbzWpmmj-sbgj_aoQBijJRkTziSWLwGc/s640/IMG_3038.jpg" width="640" /></a></div>
<br />
제품에 들어 있는 설명서의 뒤쪽 부분에 보면 이 케이스를 편하게 사용할 수 있는 프로그램 설치법 및 관련 내용이 써 있다.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-30080014725806035862020-05-18T16:42:00.002+09:002020-05-18T16:43:31.472+09:00자동차 HUD C1 사용기알리에서 판매하는 C1이라는 모델의 HUD를 구입하였다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKHG-0tdiuQ78sgkoXdcBf7ThVhi44Y-zadxpUROmhn1g2vPrGpvYydEk3wSwUfE_4wywrDHWC_wV6IYLPmUra9PCGpT54omW87wuUkE_plLYj52M3SYtSvffyudMS3eFKxNfogWdMvGc/s1600/Newest_Head_Up_Display_OBD2_Car_HUD_Mirror_Display_C1_Car_GPS_Speedometer_Overspeed_Warning_OBD2_GPS_Dual_Mode_Faulty_Code_Scan_Head-up_Display__-_AliExpress.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="630" data-original-width="1054" height="382" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKHG-0tdiuQ78sgkoXdcBf7ThVhi44Y-zadxpUROmhn1g2vPrGpvYydEk3wSwUfE_4wywrDHWC_wV6IYLPmUra9PCGpT54omW87wuUkE_plLYj52M3SYtSvffyudMS3eFKxNfogWdMvGc/s640/Newest_Head_Up_Display_OBD2_Car_HUD_Mirror_Display_C1_Car_GPS_Speedometer_Overspeed_Warning_OBD2_GPS_Dual_Mode_Faulty_Code_Scan_Head-up_Display__-_AliExpress.png" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4rATWDiNe8nBxYczXJCK_hKV9joWGdExEAcLSLfz77kyZ4yIwCVkiGqTh5wOA5c46WULzhuf2OfRc769uTCZfBvFKeEJSywcO4EFwqnapjtnW8UGJfmk25EnIyCDzpgUCQdfxlvdMaKI/s1600/IMG_2986.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1272" data-original-width="1600" height="508" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4rATWDiNe8nBxYczXJCK_hKV9joWGdExEAcLSLfz77kyZ4yIwCVkiGqTh5wOA5c46WULzhuf2OfRc769uTCZfBvFKeEJSywcO4EFwqnapjtnW8UGJfmk25EnIyCDzpgUCQdfxlvdMaKI/s640/IMG_2986.HEIC" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
박스를 열면 본체, OBD 케이블(OBD-to-MiniUSB), USB 케이블(USB A-to-MiniUSB)이 들어 있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjQLi3xCuwdHvWhcxGUvtWfzFaUiwMQ79KI5Ic2j7f-BNlLTCZDY60X_w8fjHgmhh7fe0c7pqvfHeWTI1njyRADdPgF9LilRJ9YZCPWxWSrKrjXJ4_nEcONjKwUzFj7ybgDD07JSIxRRM/s1600/IMG_2993.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1447" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjQLi3xCuwdHvWhcxGUvtWfzFaUiwMQ79KI5Ic2j7f-BNlLTCZDY60X_w8fjHgmhh7fe0c7pqvfHeWTI1njyRADdPgF9LilRJ9YZCPWxWSrKrjXJ4_nEcONjKwUzFj7ybgDD07JSIxRRM/s640/IMG_2993.HEIC" width="578" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheaqWYak2pvBnTshRyvDXRN6b8DKZQ7KiiE8bBaVrmc3Lf4qZJS3mGACl_asjD9LcCn78Kw1bVoafVu9lE5MzcGqo1-nrfQQmVZZvcVQ4QQab0faYHovX88YuEAHTnOcD-cbDTVoGjdz0/s1600/IMG_2994.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1515" data-original-width="1600" height="606" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheaqWYak2pvBnTshRyvDXRN6b8DKZQ7KiiE8bBaVrmc3Lf4qZJS3mGACl_asjD9LcCn78Kw1bVoafVu9lE5MzcGqo1-nrfQQmVZZvcVQ4QQab0faYHovX88YuEAHTnOcD-cbDTVoGjdz0/s640/IMG_2994.HEIC" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrAAtTtXhiK4yPkcbRQsSe9PYVbCaJPOnTdGZ24zW73FUSw58zmQkYblectXNXhesUgPPkmM4Mgv_iuh59iilQ1fXyCG5XKn883AMKN_Jh0dQB1JMq3KczDTqtLEV0ongoakJkKJFesRY/s1600/IMG_2997.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1270" data-original-width="1600" height="508" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrAAtTtXhiK4yPkcbRQsSe9PYVbCaJPOnTdGZ24zW73FUSw58zmQkYblectXNXhesUgPPkmM4Mgv_iuh59iilQ1fXyCG5XKn883AMKN_Jh0dQB1JMq3KczDTqtLEV0ongoakJkKJFesRY/s640/IMG_2997.HEIC" width="640" /></a></div>
<br />
이 부분에 miniUSB 커넥터를 연결해 주면 된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb-FUH6JuxRG-O5EZFjxnZ68u_Ke3zVXe-0USDE4-F83968hC_7CmVK6EhKidd_U04f4Hx6BnbKw1fGmJEEnJ8kDLahsM227eOcGrE7QsMbpfj8wOdS9DRbp5urnA7JpoAoIbugGEen6A/s1600/IMG_2995.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="753" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb-FUH6JuxRG-O5EZFjxnZ68u_Ke3zVXe-0USDE4-F83968hC_7CmVK6EhKidd_U04f4Hx6BnbKw1fGmJEEnJ8kDLahsM227eOcGrE7QsMbpfj8wOdS9DRbp5urnA7JpoAoIbugGEen6A/s640/IMG_2995.HEIC" width="640" /></a></div>
<br />
다만 이 장치는 자동차에서 동작하는 것이기 때문에 12V 전원이 공급되어야 동작하게 되는데 USB 커넥터를 사용해 혼란을 주기 쉽게 되어 있는것은 아쉽다.<br />
OBD2 + GPS라고 써 있는것처럼 OBD를 연결하지 않으면 자체 GPS 수신기만으로 동작해 GPS로 계산한 속도를 표시할 수도 있도록 되어 있는데 이 경우 동봉되어 있는 USB 케이블로 연결해 줘야 한다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6ggq_SgTKqCt-1O5ssK-nHzcn1sdc3vCu31TewWjBnDTx5Enfx-nDW1tGxcrFSaunLjwWSOKrDg_m_xJPrY63zW5OEtwdnRqmBw68G2s966gVD2dc4PLusnQhYL2nmVgh5Zi_0LbQIlE/s1600/IMG_2998.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1219" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6ggq_SgTKqCt-1O5ssK-nHzcn1sdc3vCu31TewWjBnDTx5Enfx-nDW1tGxcrFSaunLjwWSOKrDg_m_xJPrY63zW5OEtwdnRqmBw68G2s966gVD2dc4PLusnQhYL2nmVgh5Zi_0LbQIlE/s640/IMG_2998.jpg" width="486" /></a></div>
<br />
하지만 이 경우 USB 커넥터로 12V를 공급해줘야 하는데 일반적으로 자동차에 USB-A 타입 커넥터에서 12V가 나오는 경우는 없기 때문에 자동차의 USB 커넥터에 케이블을 연결하면 전압 부족으로 장치가 정상적으로 동작하지 못하게 된다.<br />
<br />
물론 OBD 연결하지 않고 그냥 GPS모드로만 이용하려고 이걸 사는 사람은 많지 않을거라 생각되니 큰 문제는 아닐수도 있지만 조금만 더 섬세하게 만들었다면 좋았을 뻔 했다. 차라리 저 케이블에서 USB-A 대신 시거잭에 꼽을 수 있게 해 놨다면 혼란을 줄일 수 있을 것이다.<br />
<br />
동작은 매우 단순하다. 자동차의 OBD 포트와 이 장치에 케이블을 연결하고 장치의 전원 스위치를 ON으로 해 놓은 상태에서 자동차 시동을 걸면 바로 화면이 나온다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0YxGj_Qp_0msGkeGAOoThbw6Epb3_QubVkbUiqjvWdz9zvBbu71b8WisL3hMt2xeAkBdZSg6TrJI4ChAAadR05v4caD7h8oq8quaqzO-kUFiE1b7J6iftRUW6hfPhytRQMUcBGBpS85s/s1600/IMG_2996.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="865" data-original-width="1600" height="344" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0YxGj_Qp_0msGkeGAOoThbw6Epb3_QubVkbUiqjvWdz9zvBbu71b8WisL3hMt2xeAkBdZSg6TrJI4ChAAadR05v4caD7h8oq8quaqzO-kUFiE1b7J6iftRUW6hfPhytRQMUcBGBpS85s/s640/IMG_2996.HEIC" width="640" /></a></div>
<br />
오른쪽이 전원 스위치, 왼쪽이 조그셔틀(좌/우/푸쉬)이다.<br />
<br />
동작중에는 조그셔틀을 누르면 화면 표시 모드가 변경되고, 조그셔틀 좌 또는 우로 화면에 표시되는 내용을 변경할 수 있다.<br />
또한 조그셔틀을 누르고 몇초 있으면 설정 모드로 들어가 설정을 변경해 줄 수 있게 된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikWAPw0tW5ETB1EMhSbT_d7vHuLlu59qpPGC2sPAMXnKAhCOBKaN6XgsZXX17KdJS2UXf47MW8yHxB5sQKBStjmq1VJtE6WSSo8GmXPzL2FMLQXxfSV1lwLRKyWB_nVz9oIPVmZkyOlyQ/s1600/IMG_2988.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1193" data-original-width="1600" height="476" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikWAPw0tW5ETB1EMhSbT_d7vHuLlu59qpPGC2sPAMXnKAhCOBKaN6XgsZXX17KdJS2UXf47MW8yHxB5sQKBStjmq1VJtE6WSSo8GmXPzL2FMLQXxfSV1lwLRKyWB_nVz9oIPVmZkyOlyQ/s640/IMG_2988.HEIC" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuwcsEK95y6bO5yMOMo1cfaZU2uGTsJI5f9GUTDSw5j1jzrisRz76ZQF1z3xK_8PjUKfS1gVFdsYcmzaNX3JKLH1gcWh54YWOLO3zsVRo0-uCOxUfldEte_sVMyTQZxpKGHd7yx8HoMjU/s1600/IMG_2989.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1232" data-original-width="1600" height="492" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuwcsEK95y6bO5yMOMo1cfaZU2uGTsJI5f9GUTDSw5j1jzrisRz76ZQF1z3xK_8PjUKfS1gVFdsYcmzaNX3JKLH1gcWh54YWOLO3zsVRo0-uCOxUfldEte_sVMyTQZxpKGHd7yx8HoMjU/s640/IMG_2989.HEIC" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEeiB1A8YmVvN4IqBz5kEPPD54140C8_p69EOOvFQu0lQyluiHYRcAJdtE4HftNLxXf5E0LFzGIPMjt1XApAf1pFKL90tTP6DHWfH-YPtdxOv-An4cwr8vRQh4rWxKf9TgoFCJtUiYKwc/s1600/IMG_2990.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1251" data-original-width="1600" height="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEeiB1A8YmVvN4IqBz5kEPPD54140C8_p69EOOvFQu0lQyluiHYRcAJdtE4HftNLxXf5E0LFzGIPMjt1XApAf1pFKL90tTP6DHWfH-YPtdxOv-An4cwr8vRQh4rWxKf9TgoFCJtUiYKwc/s640/IMG_2990.HEIC" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg41V89vt5q9RrFAUbUl50UYv19zPwIRqbPYblZXib6lk0CPBnupA7Dr4GOul-GbsZhrLZFmvZ1RkU-lJ7m66_2VY2Iokg6u5tRsKumYF8huAV9c-uCFxZd610l_4sTG_nWVRFZ9Kf0aY/s1600/IMG_2991.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1190" data-original-width="1600" height="476" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg41V89vt5q9RrFAUbUl50UYv19zPwIRqbPYblZXib6lk0CPBnupA7Dr4GOul-GbsZhrLZFmvZ1RkU-lJ7m66_2VY2Iokg6u5tRsKumYF8huAV9c-uCFxZd610l_4sTG_nWVRFZ9Kf0aY/s640/IMG_2991.HEIC" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkCFfI5FOt3SiY7GaYN6-L10dGy7MDsqZRiawL5hh35FFQfEF6F_MZXtA9Qd6sE_kGiNi5Zc1NcvafO6yDDY6pMlo6A9XwIEVAnm78W6qILfGC2AEvQsEAHxSjzanpdrBX8-ZFmmstukg/s1600/IMG_2992.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1058" data-original-width="1600" height="422" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkCFfI5FOt3SiY7GaYN6-L10dGy7MDsqZRiawL5hh35FFQfEF6F_MZXtA9Qd6sE_kGiNi5Zc1NcvafO6yDDY6pMlo6A9XwIEVAnm78W6qILfGC2AEvQsEAHxSjzanpdrBX8-ZFmmstukg/s640/IMG_2992.HEIC" width="640" /></a></div>
<br />
화면 표시모드는 여러가지가 있고 첫번째, 두번째 화면의 경우 조그셔틀로 RPM. DIS 부분 또는 RPM, RTC 부분에 어떤 내용을 표시할지 고를 수 있다. 즉 DIS(운전거리)대신 배터리 전압이라던지 냉각수 온도, 타이어압력 등 선택할 수 있는 옵션은 꽤 다양하다.<br />
<br />
운전중 촬영을 할 수 없어 주차장에서 세워 놓은 상태에서 사진을 찍었지만 햇빛이 쨍한 낮에 운전해도 화면은 충분히 잘 보인다.<br />
<br />
물론 본체의 재질은 프라스틱으로 그렇게 고급스럽게 보이지는 않지만 원하는 기능은 충분하게 제공해 주는거 같다.<br />
<br />
* 참고로 설치한 차종은 14년식 스포티지이다.<br />
<br />
아래는 제품에 들어 있는 사용설명서를 스캔한 것이다. 구입에 관심이 있으면 자신이 원하는 기능이 있는지 보는 것이 좋을 것이다. (이미지를 클릭하면 확대된다.)<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPnlPmnq9GRYbCJYwM2eGiDhnocsRpQmthel9VRWhOpHGEJSvgboG6lFBaBi0nrDnaBWf4ihnWXt7C07ds-8jyhQBsB61mFSL95Ae2SeqHmaTc57_4MwM3xTToK_1aCkWuUWRyZiW4oyE/s1600/IMG_2975.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="753" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPnlPmnq9GRYbCJYwM2eGiDhnocsRpQmthel9VRWhOpHGEJSvgboG6lFBaBi0nrDnaBWf4ihnWXt7C07ds-8jyhQBsB61mFSL95Ae2SeqHmaTc57_4MwM3xTToK_1aCkWuUWRyZiW4oyE/s640/IMG_2975.JPG" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXMwLKcXAyX_sgvte0GvaZ7Oy1__KIUXcpiWw8PP3LaaP6O-bH5oR0tYcG2CxoN6GNJkWWKeqW5pxojTxyy2OokqiZp6MqVdlK8S-Dv_I0q-5zc_1bG4Zitjdnnb0QiwRswfid9HjHjbM/s1600/IMG_2976.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="728" data-original-width="1600" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXMwLKcXAyX_sgvte0GvaZ7Oy1__KIUXcpiWw8PP3LaaP6O-bH5oR0tYcG2CxoN6GNJkWWKeqW5pxojTxyy2OokqiZp6MqVdlK8S-Dv_I0q-5zc_1bG4Zitjdnnb0QiwRswfid9HjHjbM/s640/IMG_2976.JPG" width="640" /></a></div>
ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-33223763559397247512020-04-22T18:03:00.001+09:002020-04-24T00:19:49.089+09:00샤오미 AX3600 공유기 개봉 및 초기 사용기4월 초에 주문한 샤오미 AX3600 공유기를 약 18일만에 받았다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisAM-rHmjDvy9ISAz72237mTD_CMug-3mdMIRTylZnrSwS0Gn6WJNI1pW81YUYbgs6HqhaMECGCac0yK-KNakvQSJVgpC6CGWkfdtq6l9_xPv6xb-nyVymJifyC3G94_HfZ1CBKE9-1U8/s1600/IMG_2910.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="470" data-original-width="800" height="376" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisAM-rHmjDvy9ISAz72237mTD_CMug-3mdMIRTylZnrSwS0Gn6WJNI1pW81YUYbgs6HqhaMECGCac0yK-KNakvQSJVgpC6CGWkfdtq6l9_xPv6xb-nyVymJifyC3G94_HfZ1CBKE9-1U8/s640/IMG_2910.HEIC" width="640" /></a></div>
<br />
박스부터 거대하다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiD6F2RJJFMKTi48ULc0siU9sIcbZ6XjljtT_MjimO43ZsXN3JNXL8RCN41vLcosUq2_y0fkYZvu3icjF0MDEtL70gfuKyLfGHSwS3SHOVYCnOIBuc1nDNEe_WssLR7FLQWecKMMfRGQU/s1600/IMG_2911.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="541" data-original-width="800" height="432" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiD6F2RJJFMKTi48ULc0siU9sIcbZ6XjljtT_MjimO43ZsXN3JNXL8RCN41vLcosUq2_y0fkYZvu3icjF0MDEtL70gfuKyLfGHSwS3SHOVYCnOIBuc1nDNEe_WssLR7FLQWecKMMfRGQU/s640/IMG_2911.HEIC" width="640" /></a></div>
<br />
박스를 열어보면 공유기, 아답터, 짧은 랜케이블 하나....단촐하게 들어있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZuKKskFB8RoeMMxUtJuy9066GVwkHBUEKHWSiUoEyH3a43kZSf6i53BKMbZGPxBGbug3w0V1gUx1XcbqzjBppbsKryhw-cx19oy1-pF8bXZxJdCg0ai3AgvZDTfUuv22v1QVyZhgchYA/s1600/IMG_2912.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="674" data-original-width="800" height="538" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZuKKskFB8RoeMMxUtJuy9066GVwkHBUEKHWSiUoEyH3a43kZSf6i53BKMbZGPxBGbug3w0V1gUx1XcbqzjBppbsKryhw-cx19oy1-pF8bXZxJdCg0ai3AgvZDTfUuv22v1QVyZhgchYA/s640/IMG_2912.HEIC" width="640" /></a></div>
<br />
상대적 크기를 보여주기 위해 IPTIME의 A2008과 찍어 본 사진이다. 삼각형 프리즘 모양이라 폭은 좁지만 옆쪽으로 길이는 A2008의 두배가 넘는다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXCBJY-nDYoDbC4UIhHzoI5OKoY9azLKyMcNVm7RBpHr1y7mQWsJf6AJ1iH1My-xORnAX11PKGYZK_aWA8Bd5l6Xdu4HZ_PLQUV4Sr2cQ6aBv24xTbDamksSFbQC89atIuSKKM29zWsOQ/s1600/IMG_2914.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="436" data-original-width="800" height="348" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXCBJY-nDYoDbC4UIhHzoI5OKoY9azLKyMcNVm7RBpHr1y7mQWsJf6AJ1iH1My-xORnAX11PKGYZK_aWA8Bd5l6Xdu4HZ_PLQUV4Sr2cQ6aBv24xTbDamksSFbQC89atIuSKKM29zWsOQ/s640/IMG_2914.HEIC" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJigYUg-u21c4PGwnbujiq81tXDCDPwpZHHiOLCU2oBRoGnL-ZCM3gYuPXrLOM59_WBEkqYQjRm54FkJTSpPhVzybINRIi2rxPpKqcboD2n8YvaHjFYQ51ykxtixIrjMzVGO5VpDZu_Xs/s1600/IMG_2915.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1007" data-original-width="800" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJigYUg-u21c4PGwnbujiq81tXDCDPwpZHHiOLCU2oBRoGnL-ZCM3gYuPXrLOM59_WBEkqYQjRm54FkJTSpPhVzybINRIi2rxPpKqcboD2n8YvaHjFYQ51ykxtixIrjMzVGO5VpDZu_Xs/s640/IMG_2915.HEIC" width="508" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSwiTXWAMXJeFIrqJ_r_CZhHYpv-u7jcy3XsNU1soTgICNFCMbfeDgPUpVfmiaa5VEMeNLv82-hlCbtJBjC4eC12aivOnAjpdJjqehCZbJ620gi_9-g27u0xiBFAsOJgKkC4mbpYV3hhA/s1600/IMG_2916.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="674" data-original-width="800" height="538" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSwiTXWAMXJeFIrqJ_r_CZhHYpv-u7jcy3XsNU1soTgICNFCMbfeDgPUpVfmiaa5VEMeNLv82-hlCbtJBjC4eC12aivOnAjpdJjqehCZbJ620gi_9-g27u0xiBFAsOJgKkC4mbpYV3hhA/s640/IMG_2916.HEIC" width="640" /></a></div>
<br />
각각의 길이는 위의 사진과 같다. 이 공유기를 사용하려면 기존 공유기를 놓았던 공간에 놓지 못할수가 있으니 미리 확인해 보는게 좋다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf0HGVuPVXqaWaiga378xkRiw6H6PNuyeT7hlgfkHAut8EInE0Cs-aHO4k4zshM_RG9n9Ue9pW6fJF5llb1LukQBh08v_sU-JILxy9vQGGOaNDcicWJn5v_A0H-I71V8ZjbU7w84mswYY/s1600/IMG_2913.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="391" data-original-width="800" height="312" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf0HGVuPVXqaWaiga378xkRiw6H6PNuyeT7hlgfkHAut8EInE0Cs-aHO4k4zshM_RG9n9Ue9pW6fJF5llb1LukQBh08v_sU-JILxy9vQGGOaNDcicWJn5v_A0H-I71V8ZjbU7w84mswYY/s640/IMG_2913.HEIC" width="640" /></a></div>
<br />
뒷쪽 포트는 단촐하다. 왼쪽부터 1개의 WAN, 3개의 LAN, 전원 커넥터, 리셋버튼 순이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ7cxh3686BY7VKigxHvpsiF8064M1tSaaK0ouwIs9cYr6KugMT7ZKYQ4O4PJnb-OIl_3J07nDU74EHmbitGRRQtf3EDx1aYfpk2A_QSsrcPc47X2QAGd7YuEOcax-wqhZAp60Dh-DxvM/s1600/IMG_2917.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="501" data-original-width="800" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ7cxh3686BY7VKigxHvpsiF8064M1tSaaK0ouwIs9cYr6KugMT7ZKYQ4O4PJnb-OIl_3J07nDU74EHmbitGRRQtf3EDx1aYfpk2A_QSsrcPc47X2QAGd7YuEOcax-wqhZAp60Dh-DxvM/s640/IMG_2917.HEIC" width="640" /></a></div>
<br />
아답터는 12V 2A...크기나 기능에 비해 전력소모는 생각보다 작은거 같다. 그건 결국 발열도 덜할 것이라 예상된다. (참고로 지금까지 사용하던 TP-Link Archer C9는 12V 3.3A의 아답터가 들어있다)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEich__AYEhm7GMFLX-v2kQlM0AJ-KKTe8qMYDH0xYL5qalMhlu_R-gN5XkKbFqJECm8Fo9LdsKvN2qlmdZqE4aVzcrcDyFPPw9B5fGZNw3eaoXLdRpvQHb-JylQuo6M7v5u9ZiJRq0fqY0/s1600/IMG_2918.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="728" data-original-width="800" height="582" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEich__AYEhm7GMFLX-v2kQlM0AJ-KKTe8qMYDH0xYL5qalMhlu_R-gN5XkKbFqJECm8Fo9LdsKvN2qlmdZqE4aVzcrcDyFPPw9B5fGZNw3eaoXLdRpvQHb-JylQuo6M7v5u9ZiJRq0fqY0/s640/IMG_2918.HEIC" width="640" /></a></div>
<br />
아답터 잭은 일반적인 외경 5.5파이가 아니고 외경 4파이 짜리를 사용하고 있다.<br />
<br />
일단 무선 성능 비교를 위해 먼저 기존에 사용하던 Archer C9의 무선 속도를 측정해 보았다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpI9dcsbXveBh1kuMWWuEtgSqsRM8N-2ob0uZ-6mMks7rL9zCOptOxfnOy-1VxJxQHvUd7BwBzN58tdb8hdWTPUQM0prTmZqd-QFG-dVCR5gozue2v9oRwiqCT2KYP7UzRZKXtFyeaZrQ/s1600/IMG_2908-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="666" data-original-width="800" height="532" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpI9dcsbXveBh1kuMWWuEtgSqsRM8N-2ob0uZ-6mMks7rL9zCOptOxfnOy-1VxJxQHvUd7BwBzN58tdb8hdWTPUQM0prTmZqd-QFG-dVCR5gozue2v9oRwiqCT2KYP7UzRZKXtFyeaZrQ/s640/IMG_2908-2.png" width="640" /></a></div>
<br />
아이폰11을 사용했고 아이폰과 공유기 사이에는 LoS가 확보(중간에 가로막는 장애물이 없음) 된 상태이고 거리는 다음과 같다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUdNlTo7n3pZZsDygP8stgTb3AjQZaWSqDhW7En__lgZPdBS3OFLW_yFK4e-Az8iWgTMkSRbAx9iKGyeWy9NlVWK6uHt_jD0oKNZrrWZZoXygGgl4amLNCp45iRpwhyphenhyphenUP9TnM3ylIdh7A/s1600/IMG_2909.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="818" data-original-width="800" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUdNlTo7n3pZZsDygP8stgTb3AjQZaWSqDhW7En__lgZPdBS3OFLW_yFK4e-Az8iWgTMkSRbAx9iKGyeWy9NlVWK6uHt_jD0oKNZrrWZZoXygGgl4amLNCp45iRpwhyphenhyphenUP9TnM3ylIdh7A/s400/IMG_2909.HEIC" width="390" /></a></div>
<br />
동일 조건에서 AX3600을 설치한 후 측정한 결과이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNin_aqB7GZF66z1Ggh8qru30iXpjEXGxlrM4rou6yF5yjXqWIlLzASmAGfZNO5_o4EAR0ZmHpk3WCKdv4leKgcBdnJ9Gx_r0kFoSeO4V5wsbeuLJpuxhCXuR8pveeOkhaZF6VwKEe5tk/s1600/IMG_2924-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="574" data-original-width="800" height="458" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNin_aqB7GZF66z1Ggh8qru30iXpjEXGxlrM4rou6yF5yjXqWIlLzASmAGfZNO5_o4EAR0ZmHpk3WCKdv4leKgcBdnJ9Gx_r0kFoSeO4V5wsbeuLJpuxhCXuR8pveeOkhaZF6VwKEe5tk/s640/IMG_2924-2.png" width="640" /></a></div>
<br />
상세한 성능은 좀 더 사용해 봐야 알겠지만 일단 무선 성능은 대략 2배 가까이 좋아진걸 확인할 수 있다.<br />
<br />
다만 이 장비의 단점은 아직 메뉴를 영문으로 바꿀 수가 없다는 것이 가장 큰 문제이다.<br />
<br />
처음 연결하고 웹브라우져로 접근하면 다음과 같은 화면이 나온다. (처음 사용하면 공유기는 192.168.31.x 주소를 사용하고 공유기 주소는 192.168.33.1이 된다.)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW3-9YFtLUXwqwN9WHP4Pz7ZG4L8awdiPPhGQU5LC3ZsnKqoJzipPdXhsaY1_PYEkVlHxysTrTiIE-mph8MimTDdNGXtGq9JaEYkB-GtCWM80NgCGbJE60PUGyi-957TNWnRg7wRtAYRQ/s1600/IMG_2919.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="740" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW3-9YFtLUXwqwN9WHP4Pz7ZG4L8awdiPPhGQU5LC3ZsnKqoJzipPdXhsaY1_PYEkVlHxysTrTiIE-mph8MimTDdNGXtGq9JaEYkB-GtCWM80NgCGbJE60PUGyi-957TNWnRg7wRtAYRQ/s640/IMG_2919.PNG" width="295" /></a></div>
<br />
중국어는 몰라도 대강 한자하고 눈치로 때려잡기+google translate를 활용하면 큰 문제는 없다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcCLjt7YhMuMQ3fxv0vKavjVXKEu4xBdJimpL4cys6E5XW7nwB3AeGk0_tBfnYD-WZ7E1wX5t2IBA3FUBeanZk4pcettKMprWR6dc5T1t4ZAQEXApCT3yeRQxiB1bBJKOthMjZGyTnxzk/s1600/IMG_2919-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="501" data-original-width="808" height="395" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcCLjt7YhMuMQ3fxv0vKavjVXKEu4xBdJimpL4cys6E5XW7nwB3AeGk0_tBfnYD-WZ7E1wX5t2IBA3FUBeanZk4pcettKMprWR6dc5T1t4ZAQEXApCT3yeRQxiB1bBJKOthMjZGyTnxzk/s640/IMG_2919-2.png" width="640" /></a></div>
<br />
중간 부분에 관리자 암호를 넣고 등록해준다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaO62r2JsnyaKs3gGaO4rcFizOzEaiybauyOdG9eIaGWpwIwmc8FCiRRB1BJYiP3A9Gkt6Tb-gOVhbvRhauGbf9T-afyQuCYooyGeS_f6SIeIN4pEgMBXkqlDEMwZdDv61IDufeUCTHgM/s1600/IMG_2920-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="747" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaO62r2JsnyaKs3gGaO4rcFizOzEaiybauyOdG9eIaGWpwIwmc8FCiRRB1BJYiP3A9Gkt6Tb-gOVhbvRhauGbf9T-afyQuCYooyGeS_f6SIeIN4pEgMBXkqlDEMwZdDv61IDufeUCTHgM/s640/IMG_2920-2.png" width="298" /></a></div>
<br />
인터넷을 뒤져보면 AX3600 메뉴 영어로 바꾸는 방법이 있다고 나오는데 막상 해 보면 그런 메뉴가 없고, 대부분은 이전 모델에만 적용되는 방법이라 영문화는 좀 더 기다려야 가능해 지지 않을까 싶다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI9FtxhQFxzXkE_DtLwZKlwN_EICqsNmMZn-FQU7HgTFh_7mXKEDOot5CuR-rlzzsFe-rWwIwk1QpSJDBwNx-hIbgpiUaFuvA7vrfETo2U-s-AZ6BsRjzv2EJy_noy17JqMyqZlNfbreQ/s1600/IMG_2925.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="241" data-original-width="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI9FtxhQFxzXkE_DtLwZKlwN_EICqsNmMZn-FQU7HgTFh_7mXKEDOot5CuR-rlzzsFe-rWwIwk1QpSJDBwNx-hIbgpiUaFuvA7vrfETo2U-s-AZ6BsRjzv2EJy_noy17JqMyqZlNfbreQ/s1600/IMG_2925.PNG" /></a></div>
스마트폰용 앱인 Mi WiFi를 사용하면 스마트폰에서는 영문 메뉴를 사용할 수 있다. <br />
다만 앱에 자신의 공유기를 추가해야 하는데 자신의 위치를 한국으로 하면 AX3600이 보이지 않는다. 아마도 해당 국가에서 판매되는 제품만 설정이 가능하도록 되어 있는거 같다.<br />
그래서 국가 선택할 때는 mainland china를 선택하고 언어는 영여로 해 주면 장치 추가시 AX3600이 나타나서 추가할 수 있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiC4fT3Eovds9ihl6kI5y44D3OG8Xm85GhPbGF-SCiPYyhYvrH_uX2Kg1x476ulTAogof9lqLb6aiT5WKPumejRK7dMIqLpqwm3On2NKMT05NUGIyL7IQ6Y-AqRb1IipBmRdEJ5ToVoVw/s1600/IMG_2926.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="740" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiC4fT3Eovds9ihl6kI5y44D3OG8Xm85GhPbGF-SCiPYyhYvrH_uX2Kg1x476ulTAogof9lqLb6aiT5WKPumejRK7dMIqLpqwm3On2NKMT05NUGIyL7IQ6Y-AqRb1IipBmRdEJ5ToVoVw/s640/IMG_2926.PNG" width="294" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0XpeuBLZIHBk1GKBQXDnFOo_dCNbEe7FBEfo7QoFgwI5fD_q-cRvnhwybfSmDxUeBbemzvwtt-Gslbmu0UreC1X601Fw31vsuqOSG0DN7cSCLks8AP8eOVWc2er0iSNxy7bFaCz2iTjI/s1600/IMG_2927.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="740" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0XpeuBLZIHBk1GKBQXDnFOo_dCNbEe7FBEfo7QoFgwI5fD_q-cRvnhwybfSmDxUeBbemzvwtt-Gslbmu0UreC1X601Fw31vsuqOSG0DN7cSCLks8AP8eOVWc2er0iSNxy7bFaCz2iTjI/s640/IMG_2927.PNG" width="294" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYKovzNH-Xtjwt2BkHL3NzywFRSd-YAN9T1h5AfHxx8y6MQevAa8E-9N3FpZTvxO6LeYJ83JKv3k1CQSuqYmizRBypriym434cp6yWe6cXUlVa2ScW1zLWMzkUBwjz-gFSvBG2Gh9Rb88/s1600/IMG_2928-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="740" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYKovzNH-Xtjwt2BkHL3NzywFRSd-YAN9T1h5AfHxx8y6MQevAa8E-9N3FpZTvxO6LeYJ83JKv3k1CQSuqYmizRBypriym434cp6yWe6cXUlVa2ScW1zLWMzkUBwjz-gFSvBG2Gh9Rb88/s640/IMG_2928-2.png" width="294" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM5fn1xPhK3SDmQoeB-bbCmPM2DMLk5NDBeiXiPf2X79Nzij3TNsOq8hpdY39WF0FiZSnizPiNPPHmkr_EzN6vapZoZpLGm-VIcbrpISx5yJIO7pV0KIQ8LLWWx_eIMy9KVSIVsZHfv3M/s1600/IMG_2929-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="740" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM5fn1xPhK3SDmQoeB-bbCmPM2DMLk5NDBeiXiPf2X79Nzij3TNsOq8hpdY39WF0FiZSnizPiNPPHmkr_EzN6vapZoZpLGm-VIcbrpISx5yJIO7pV0KIQ8LLWWx_eIMy9KVSIVsZHfv3M/s640/IMG_2929-2.png" width="294" /></a></div>
<br />
위의 화면과 같이 기본적인 설정은 스마트폰에서 영어메뉴로 가능해진다.<br />
<br />
다만 port forwarding, DHCP, VPN등의 고급기능 설정은 관리자 페이지로 가서 해야만 하기 때문에 불편한 것은 어쩔 수 없다.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1iDfhiboA0hIALxGwqpTPDGlAqE0MzNkNQgWt_JUq_MXaD23H-RRDKzfXB9Wv_BPx9p5sMGNYPyvDi-afMjukcG0nWg2sUqFlcKfsHaczFntg6nYh3wBA9PEuG3tT2Gai3cyPFx0i76I/s1600/%25E5%25B0%258F%25E7%25B1%25B3%25E8%25B7%25AF%25E7%2594%25B1%25E5%2599%25A8.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="827" data-original-width="1215" height="434" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1iDfhiboA0hIALxGwqpTPDGlAqE0MzNkNQgWt_JUq_MXaD23H-RRDKzfXB9Wv_BPx9p5sMGNYPyvDi-afMjukcG0nWg2sUqFlcKfsHaczFntg6nYh3wBA9PEuG3tT2Gai3cyPFx0i76I/s640/%25E5%25B0%258F%25E7%25B1%25B3%25E8%25B7%25AF%25E7%2594%25B1%25E5%2599%25A8.png" width="640" /></a> <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigQ-HcLYbOxauJI97rOKvLhEcjxhW1HqEKEdlUxTITvo1RxKFB2msMmawe_wfAzDuNm-R-AqWuzJslFrr2ARbgjzLI3q0MwS3SvB1ok4g9eH0ns-Q0kadL8dozv2FPX2c2FqDhnQQVsO8/s1600/%25E5%25B0%258F%25E7%25B1%25B3%25E8%25B7%25AF%25E7%2594%25B1%25E5%2599%25A8-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="816" data-original-width="1193" height="436" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigQ-HcLYbOxauJI97rOKvLhEcjxhW1HqEKEdlUxTITvo1RxKFB2msMmawe_wfAzDuNm-R-AqWuzJslFrr2ARbgjzLI3q0MwS3SvB1ok4g9eH0ns-Q0kadL8dozv2FPX2c2FqDhnQQVsO8/s640/%25E5%25B0%258F%25E7%25B1%25B3%25E8%25B7%25AF%25E7%2594%25B1%25E5%2599%25A8-2.png" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEfmW8ModkwriQilXHdthx-M-_AUyT0cUu6ofKNo1I7ucm1_Pgfpfv7281h41AyYWUSUpJmrzMzRNkdwcmhI5RUqnEvTOUmeOSmbrfD-xE-FK0o8wK-WetYB908tIQHzBoG4CC-24mw_s/s1600/%25E5%25B0%258F%25E7%25B1%25B3%25E8%25B7%25AF%25E7%2594%25B1%25E5%2599%25A8-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="685" data-original-width="1200" height="364" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEfmW8ModkwriQilXHdthx-M-_AUyT0cUu6ofKNo1I7ucm1_Pgfpfv7281h41AyYWUSUpJmrzMzRNkdwcmhI5RUqnEvTOUmeOSmbrfD-xE-FK0o8wK-WetYB908tIQHzBoG4CC-24mw_s/s640/%25E5%25B0%258F%25E7%25B1%25B3%25E8%25B7%25AF%25E7%2594%25B1%25E5%2599%25A8-3.png" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-4OfeLe0XCiUWarHStLFWE8ErPItazEiozRnYM3usm4Ab1tNsrYzpNgWwk-mMcTPmuPbu9RAD2O8feFi4BvKnYqPRNm_cJPgBAEL1GT_A-UmZF-TqwxlyTzoyiFsCwpGezQtBv6rDvqU/s1600/%25E5%25B0%258F%25E7%25B1%25B3%25E8%25B7%25AF%25E7%2594%25B1%25E5%2599%25A8-4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1160" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-4OfeLe0XCiUWarHStLFWE8ErPItazEiozRnYM3usm4Ab1tNsrYzpNgWwk-mMcTPmuPbu9RAD2O8feFi4BvKnYqPRNm_cJPgBAEL1GT_A-UmZF-TqwxlyTzoyiFsCwpGezQtBv6rDvqU/s640/%25E5%25B0%258F%25E7%25B1%25B3%25E8%25B7%25AF%25E7%2594%25B1%25E5%2599%25A8-4.png" width="464" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmJyxj0RtUfWloK8m0e12kyFz-FqeD0w7rReplfrrTj1Z08vMHeRpGNojP3zgqC0uZaYyr10vd_KCsJ1lAUYS1cQYEzh_KZB7jCMGerXTjxzBlP-sn1UdFS8-2LVkncQhltuOMAu1vE6M/s1600/%25E5%25B0%258F%25E7%25B1%25B3%25E8%25B7%25AF%25E7%2594%25B1%25E5%2599%25A8-5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="901" data-original-width="1197" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmJyxj0RtUfWloK8m0e12kyFz-FqeD0w7rReplfrrTj1Z08vMHeRpGNojP3zgqC0uZaYyr10vd_KCsJ1lAUYS1cQYEzh_KZB7jCMGerXTjxzBlP-sn1UdFS8-2LVkncQhltuOMAu1vE6M/s640/%25E5%25B0%258F%25E7%25B1%25B3%25E8%25B7%25AF%25E7%2594%25B1%25E5%2599%25A8-5.png" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com3tag:blogger.com,1999:blog-6762236726539517408.post-81310019043014387392019-12-12T14:54:00.000+09:002019-12-12T14:58:21.087+09:00라즈베리 파이에서 REST API 사용해서 스마트폰으로 제어하기 (Use REST API in Raspberry Pi for controlling from smartphone)라즈베리 파이에서 flask를 사용해 REST API를 구현하여 스마트폰이나 컴퓨터에서 원격으로 센서값을 읽거나 장치를 제어할 수 있도록 간단하게 구현 해 보았다.<br />
HTTP GET과 POST method를 사용할 수 있도록 해 놓았고 POST method에서 파라미터는 JSON으로 넘겨주면 된다.<br />
아래 코드가 구현해 놓은 API는 다음과 같다.<br />
<br />
* /api/led :<br />
method: POST<br />
parameter: {'ledId': [id], 'val': [OnOff]} - [id]는 조작하고자 하는 LED번호, [OnOff]에는 LED를 켜고 싶으면 1, 끄고 싶으면 0<br />
return: 명령이 실행되고난 후 LED 상태<br />
<br />
<br />
* /api/led :<br />
method: POST<br />
parameter: {'ledId': [id], 'val': [OnOff]} - [id]는 조작하고자 하는 LED번호, [OnOff]에는 LED를 켜고 싶으면 1, 끄고 싶으면 0<br />
return: 명령이 실행되고난 후 LED 상태<br />
<br />
* /api/sw :<br />
method: POST<br />
parameter: {'id': [id]} - [id]는 상태를 알고 싶은 스위치 번호<br />
return: 현재 스위치 상태<br />
<br />
* /api/sensor/[sensorName] :현재 sensorName에 올 수 있는 센서는 temperature, humidity, pressure, light <br />
method:GET<br />
return:지정한 센서에서 읽은 값<br />
<br />
* /api/sensors :<br />
method: GET<br />
return: 전체 센서 값 (JSON 포맷)<br />
<br />
* /api/sensors :<br />
method: POST<br />
parameter: {'sensorList': [sensor list]} -값을 읽고 싶은 센서 이름. 한개 이상이 올 수 있고 복수개일 경우 ','로 구분<br />
return: 지정한 센서에서 읽은 값 (JSON 포맷)<br />
<br />
* /api/exec :<br />
method: POST<br />
parameter: {'cmd': [command line]} - [commnad line]은 라즈베리 파이에서 실행할 명령<br />
return: 명령 실행 결과<br />
<br />
코드를 실행하면 라즈베리 파이에 다음과 같은 화면이 나오게 된다.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyN-5dG3hOa_ZK-yVJQ-XYjyNyPdkh1YcW6gM91oC6IOIjm9OyH6NjiGgyWUrD9yZIJMgxjAV4zjFThoG-RK2VdxKLEPANQApenneHXoGjwKwVDjmAF2r2LeL3Ox0S9nk45xOMYWPOi10/s1600/rest01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="263" data-original-width="760" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyN-5dG3hOa_ZK-yVJQ-XYjyNyPdkh1YcW6gM91oC6IOIjm9OyH6NjiGgyWUrD9yZIJMgxjAV4zjFThoG-RK2VdxKLEPANQApenneHXoGjwKwVDjmAF2r2LeL3Ox0S9nk45xOMYWPOi10/s640/rest01.png" width="640" /></a></div>
<br />
PC의 브라우저에 [ip]:5000/api/sensors 를 입력해 주면 다음과 같은 결과를 얻을 수 있다. 이 경우 4개의 센서값을 모두 JSON 포맷으로 리턴해 준다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0xG-nsxmx2axti67kIlHh8t3v2VGUEWSzKpgpURnz0UiDVzkd_oc6LRBJG2vWJXH5EuUX4mvaKYjzdnCooyiiA_hvYRTbsFVOLfVjen2J3cC_I_yu4KWV1QhtxqPwteglYO7CkIqGOMQ/s1600/rest02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="297" data-original-width="1275" height="148" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0xG-nsxmx2axti67kIlHh8t3v2VGUEWSzKpgpURnz0UiDVzkd_oc6LRBJG2vWJXH5EuUX4mvaKYjzdnCooyiiA_hvYRTbsFVOLfVjen2J3cC_I_yu4KWV1QhtxqPwteglYO7CkIqGOMQ/s640/rest02.png" width="640" /></a></div>
<br />
[ip]:5000/api/sensor/temperature 를 읿력해 주면 다음과 같이 온도센서 값만 리턴 해 준다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiOIDSqHzPVD5-6Zf45ZzUXszYpi5RPvUTQaiPNpJ7GWh4A1X76Alvoi4-51wwN2pJOL66PK4Y0q7ojq0DSAv4S3xcCM4PYBUL0zHPnN2qaZdsljAOizmEgR36evKzUW0_vupqobcUe8U/s1600/rest03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="337" data-original-width="1429" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiOIDSqHzPVD5-6Zf45ZzUXszYpi5RPvUTQaiPNpJ7GWh4A1X76Alvoi4-51wwN2pJOL66PK4Y0q7ojq0DSAv4S3xcCM4PYBUL0zHPnN2qaZdsljAOizmEgR36evKzUW0_vupqobcUe8U/s640/rest03.png" width="640" /></a></div>
<br />
지금까지는 브라우저의 주소창에 입력했는데 이 경우 GET method를 사용하는 것이다. POST method를 확인하려면 curl, postman, rested 같은 툴을 사용해야 한다. 여기서는 파이어폭스에 설치한 rested를 사용했다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgA9syrYVE8HoFPZC0DSwxLBb9NlruC7LVU9TGJc60NS3B59bHNn5yl6y6F34nu2T7HZ56HlXL42OT0VmTlwSxB2kv6PgdOfA5EjJ7GAJ4XolfGxBTYm5wrc9nIeHyJgsY8itNnwyRiLRM/s1600/rest04.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="812" data-original-width="1322" height="392" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgA9syrYVE8HoFPZC0DSwxLBb9NlruC7LVU9TGJc60NS3B59bHNn5yl6y6F34nu2T7HZ56HlXL42OT0VmTlwSxB2kv6PgdOfA5EjJ7GAJ4XolfGxBTYm5wrc9nIeHyJgsY8itNnwyRiLRM/s640/rest04.png" width="640" /></a></div>
앞으로 파란색 부분은 저 값으로 고정시켜 놓고 빨간색 부분만 바꿔주면서 테스트 하면 된다. 위의 사진은 api/led 를 호출해 원하는 LED를 on/off 하는 예제이다. 소스코드의 @app.route('/api/led', methods = ['POST']) 에서 빨간색 굵은 부분이 주소가 된다. 단 여기서는 flask 서버가 5000번 포트를 사용하고 있으므로 주소 뒤에 ':5000'을 추가해 줘야 한다.<br />
Request Body 부분에 id와 val 이라는 두개의 키가 있어 id의 값 부분에 조작할 LED 번호를 넣어주고, val의 값 부분에 LED on/off 를 넣어주면 된다.<br />
실행이 되면 바뀐 LED 상태값이 리턴된다. 위의 예에서는 4번 LED를 ON 시킨 것이다. 맨 마지막 부분에 결과로 'ON'이 리턴되었다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi95T7OB-6QUEoDRkGhFomaPT2dHtL3q7okpPcitrYMbKTn_ZzjJwOn8eSpJgb8z_AgfixTjTMNLNJ41qPZw8nE2LGrZwsaX08ES9_sxH1c1rhDm75Ecz6R5xEHrmsQHxluji_HHHTKtxY/s1600/rest05.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="388" data-original-width="880" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi95T7OB-6QUEoDRkGhFomaPT2dHtL3q7okpPcitrYMbKTn_ZzjJwOn8eSpJgb8z_AgfixTjTMNLNJ41qPZw8nE2LGrZwsaX08ES9_sxH1c1rhDm75Ecz6R5xEHrmsQHxluji_HHHTKtxY/s640/rest05.png" width="640" /></a></div>
<br />
라즈베리 파이 화면을 보면 이번엔 /api/led 주소로 POST emethod를 사용했음을 확인할 수 있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ1S0_pxcMcPPmK4Mqc35Cjjvu6NAJJOmMyOSVHj2Mt8XXHNrHDIyCQ9WMc5RfZa-yRcdDYQv69hcKtfiXc-TcYEtNbkIYDt0NDYI_bnkxPhXGb-rPUI5rQkiHtNF0s4MrYVugT7bnOwA/s1600/rest06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="764" data-original-width="1327" height="368" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZ1S0_pxcMcPPmK4Mqc35Cjjvu6NAJJOmMyOSVHj2Mt8XXHNrHDIyCQ9WMc5RfZa-yRcdDYQv69hcKtfiXc-TcYEtNbkIYDt0NDYI_bnkxPhXGb-rPUI5rQkiHtNF0s4MrYVugT7bnOwA/s640/rest06.png" width="640" /></a></div>
위의 화면은 LED를 끄는 것이다. 나머지 부분은 동일하고 val 의 값만 '0'으로 보내주면 된다.<br />
<br />
다음은 /api/sw를 통해 스위치 상태를 확인해 본 것이다. URL 부분이 /api/led에서 /api/sw로 바뀌었다. 또한 이번엔 파라미터로 id만 보내주면 된다. 여기서는 2번 스위치의 상태를 확인해 본 것이다. 현재 스위치 상태 값이 리턴된 걸 확인할 수 있다. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpOD8Ta7hgppvE_bO0uhtg6eWg8uo6lLc-di5631KTNYZR0aZnyVVyNZVppuD0wGX4-sh3aT4-nFWR_thDlgk7nw2eX1nScgrOpkpp3S7mtSY4r_GQtiuNJMK6AFtHbvE2PwxqWXR01_4/s1600/rest07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="691" data-original-width="1312" height="336" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpOD8Ta7hgppvE_bO0uhtg6eWg8uo6lLc-di5631KTNYZR0aZnyVVyNZVppuD0wGX4-sh3aT4-nFWR_thDlgk7nw2eX1nScgrOpkpp3S7mtSY4r_GQtiuNJMK6AFtHbvE2PwxqWXR01_4/s640/rest07.png" width="640" /></a></div>
<br />
다음은 /api/sensors를 호출하는데 위쪽에서는 GET method로 호출해서 모든 센서 값을 읽어왔는데 여기서는 POST method를 사용해 값을 읽기를 원하는 센서만 지정할 수 있다. sensorList 의 값 부분에 원하는 센서 이름을 넣어주면 된다. 두개 이상을 넣을 땐 센서 이름 사이에 ','로 구분해 주면 된다. 여기서는 temperature와 humidity 센서 값을 읽도록 해 보았다. 결과값으로 두 센서값이 JSON 포맷으로 리턴되었다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheT_qsYQequd2e5sw42OOwBtZS4Taj67llS1nn1bbzv01bQ0jCK20RMcDC-qeZr2ZeitR9AXNelsv6iRguUiWhuxBlsprzD1qtucLp7vSPYtbKA7sBikW9K_gNe6zV91T0x8X482SPEq4/s1600/rest08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="716" data-original-width="1328" height="344" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheT_qsYQequd2e5sw42OOwBtZS4Taj67llS1nn1bbzv01bQ0jCK20RMcDC-qeZr2ZeitR9AXNelsv6iRguUiWhuxBlsprzD1qtucLp7vSPYtbKA7sBikW9K_gNe6zV91T0x8X482SPEq4/s640/rest08.png" width="640" /></a></div>
<br />
마지막으로는 라즈베리 파이에서 명령을 실행할 수도 있다. /api/exe에 POST method로 실행하기 원하는 명령을 보내주면 된다. 실행된 결과가 리턴된다. 이 방법을 이용하면 라즈베리 파이에 연결해 놓은 장치가 API를 제공해 주지 않거나 python module이 없고 CLI로 제어하는 프로그램만 있어도 원격에서 제어가 가능해 진다. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUYspos37Ex3wkJFiDLffyjNIcnXOguG2_30QCBFSRhpVxIQkRfxqqLamhiV9e8JS-WyaTcYP97t_3mnw2DrvKWyF_CcYMIoAgHu-wdSpQSf8KWUPNi0vIIbvj4ilGpVx9AxKqvxA3IFo/s1600/rest09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="724" data-original-width="1338" height="346" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUYspos37Ex3wkJFiDLffyjNIcnXOguG2_30QCBFSRhpVxIQkRfxqqLamhiV9e8JS-WyaTcYP97t_3mnw2DrvKWyF_CcYMIoAgHu-wdSpQSf8KWUPNi0vIIbvj4ilGpVx9AxKqvxA3IFo/s640/rest09.png" width="640" /></a></div>
<br />
전체 코드는 다음과 같다. 이 코드는 Raspberry Pi 4에서 python3를 사용해 동작시켜 보았는데 python3만 지원하는 환경이면 어디에서나 동작하는데 문제는 없을 것이다.<br />
<br />
* 여기서는 Raspberry Pi에서 실행되는 서버 코드만 설명하고 있다. 스마트폰 앱에서 제어하려면 해당하는 GET, POST 메소드로 API를 사용하면 된다. 해당 부분 코드 작성은 직접 하지 않아도 postman같이 자동으로 생성해주는 툴을 사용하면 매우 간단하게 사용할 수 있다. 다음 포스트에서는 postman을 사용해 클라이언트의 http request 부분의 코드를 자동으로 생성하는걸 설명하겠다.<br />
<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">#!/usr/bin/python3<br /><br />from flask import Flask, request, jsonify<br />import os, ntpath<br />import json<br />import subprocess<br /><br />app = Flask(__name__)<br /><br /># 실제로는 GPIO library를 사용해 읽은 스위치 값을 리턴해줘야 함<br />def readSwitch(id):<br /> print ("# readSwitch is called for switch %d" % id)<br /> return 1<br /><br /># 실제로는 온도센서 값을 읽어 리턴해 줘야 함<br />def readTemp():<br /> return str(25.3)<br /><br /># 실제로는 습도센서 값을 읽어 리턴해 줘야 함<br />def readHumid():<br /> return str(73)<br /><br /># 실제로는 압력센서 값을 읽어 리턴해 줘야 함<br />def readPressure():<br /> return str(1025)<br /><br /># 실제로는 조도센서 값을 읽어 리턴해 줘야 함<br />def readLight():<br /> return str(419)<br /><br />def readSensor(s):<br /> return sensorFunc[s]()<br /><br />sensorFunc = {'temperature': readTemp, 'humidity': readHumid, 'pressure': readPressure, 'light': readLight}<br /><br />@app.route('/api/led', methods = ['POST'])<br />def ledSvc():<br /> data = request.json<br /> #ledId = data['id']<br /> #onOff = data['val']<br /> ledId = int(data['id'])<br /> onOff = int(data['val'])<br /> if onOff == 0:<br /> newLedState = 'OFF'<br /> # 여기에 해당 LED(LED번호는 변수 ledId에 들어 있음)를 끄는 코드를 집어 넣어 줌<br /> else:<br /> newLedState = 'ON'<br /> # 여기에 해당 LED(LED번호는 변수 ledId에 들어 있음)를 켜는 코드를 집어 넣어 줌<br /> print ("Turn LED %d to %s" % (ledId, newLedState))<br /> return newLedState<br /><br />@app.route('/api/sw', methods = ['POST'])<br />def swStatus():<br /> data = request.json<br /> ledId = int(data['id'])<br /> swState = readSwitch(ledId) # readSwitch() 함수에서 스위치(ledId) 값을 읽어 리턴해 줌<br /> print ("Switch %d state : %d" % (ledId,swState))<br /> return str(swState)<br /><br />@app.route('/api/sensor/<string:sensorName>', methods = ['GET'])<br />def readSensor(sensorName):<br /> try:<br /> ret = sensorFunc[sensorName]()<br /> return ret<br /> except:<br /> return 'Wrong Sensor'<br /><br />@app.route('/api/sensors', methods = ['GET', 'POST'])<br />def readSensors():<br /> if request.method == 'GET':<br /> result = {}<br /> for s in sensorFunc:<br /> result[s] = sensorFunc[s]()<br /> elif request.method == 'POST':<br /> result = {}<br /> sl = request.json['sensorList']<br /> print (sl)<br /> sl = sl.split(',')<br /> for s in sl:<br /> print (s)<br /> result[s] = readSensor(s)<br /><br /> return json.dumps(result)<br /><br />@app.route('/api/exec', methods = ['POST'])<br />def externalPgm():<br /> data = request.json<br /> cmds = data['cmd']<br /> print (cmds)<br /> cmdl = cmds.split(' ')<br /> result = subprocess.check_output(cmdl)<br /> return result<br /><br />if __name__=='__main__':<br /> app.run(host='0.0.0.0', debug=True)</span><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-18538916419238391162019-07-09T14:35:00.000+09:002019-07-09T14:35:55.911+09:00ESP32에서 블루투스(SPP profile) 사용하기ESP32를 사용하면 아두이노에서처럼 따로 HC-05/06 모듈을 붙일 필요 없이 Bluetooth Classic 뿐 아니라 Bluetooth Low Energy(BLE)를 바로 사용할 수 있다.<br />
<br />
여기서는 먼저 Bluetooth Classic 프로파일중에 하나인 SPP(Serial Port Profile)을 사용해 보겠다.<br />
<br />
아두이노 IDE를 사용하면 Arduino core for ESP32에 필요한 라이브러리가 이미 들어있어 매우 간단하게 사용할 수 있다.<br />
<br />
먼저 헤더파일을 include 해 줘야 한다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">#include "BluetoothSerial.h"</span><br />
<br />
그 다음 BluetoothSeria 클래스의l 오브젝트를 선언해준다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">BluetoothSerial bt;</span><br />
<br />
BluetoothSerial 클래스 오브젝트가 선언되면 시리얼 오브젝트와 거의 동일하게 사용할 수 있다. 일단 setup()에서 오브젝트를 초기화 시켜준다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">void setup()</span><br />
<span style="font-family: "Courier New", Courier, monospace;">{</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> ... </span><br />
<span style="font-family: "Courier New", Courier, monospace;"> bt.begin("ESP32_SPP"); </span><br />
<span style="font-family: "Courier New", Courier, monospace;"> ...</span><br />
<span style="font-family: "Courier New", Courier, monospace;">}</span><br />
<br />
Serial.begin()에서는 파라미터로 통신속도를 넘겨주는데 여기서는 bluetooth device name을 넘겨준다. 다른 기기에서 블루투스 장치를 검색할 때 이 이름으로 보이게 된다.<br />
<br />
초기화가 끝나면 Serial 오브젝트와 동일하게 사용해 주면 된다. 즉 bt.read(), bt.write(), bt.available(), bt.print() 등을 Serial과 동일하게 호출할 수 있다.<br />
<br />
여기서는 예제로 13번 핀에 LED가 연결되어 있을 때 블루투스로 '+'를 보내면 LED가 켜지고, '-'를 보내면 LED가 꺼지는 코드를 만들어 보겠다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">#include "BluetoothSerial.h"<br /><br />BluetoothSerial bt;<br /><br />void setup() {<br /> Serial.begin(115200);<br /> bt.begin("ESP32_SPP");<br /> Serial.println("Waiting for pairing");<br /><br /> pinMode(13, OUTPUT);<br />}<br /><br />void loop() {<br /> <br /> if (bt.available()) {<br /> ch = bt.read();<br /> if ('+' == ch) {<br /> digitalWrite(13, HIGH);<br /> bt.println("LED(13) turned ON");<br /> } else if ('-' == ch) {<br /> digitalWrite(13, LOW);<br /> bt.println("LED(13) turned OFF");<br /> }<br /> }<br /> delay(50);<br />} </span><br />
<br />
위의 스케치를 ESP32에 업로드하고 시리얼 포트를 열면 다음과 같은 출력이 나올 것이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMenswCcTKvSchNhVAbZxQlShLtdKc8lcC6LUNscx6rJvzAv5fn9mRrxd7crfsHzihmHD3J7dng-GoqZ3KRDhtzB2c91XVgnAUOsVhMyeL9VH-hO-6SRPeFEHU1MGIuQ_aYQqnDEzqj2Q/s1600/_dev_cu_SLAB_USBtoUART_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_sketch_jul08b___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_9_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_Blogger__%25E1%2584%2580%25E1%2585%25B5%25E1%2584%2589%25E1%2585%25AE%25E1%2586%25AF_%25E1%2584%258B%25E1%2585%25A7%25E1%2584%2592%25E1%2585%25A2%25E1%2586%25BC%25E1%2584%258C%25E1%2585%25A1__ArsViator__-_Create_post.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="321" data-original-width="563" height="364" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMenswCcTKvSchNhVAbZxQlShLtdKc8lcC6LUNscx6rJvzAv5fn9mRrxd7crfsHzihmHD3J7dng-GoqZ3KRDhtzB2c91XVgnAUOsVhMyeL9VH-hO-6SRPeFEHU1MGIuQ_aYQqnDEzqj2Q/s640/_dev_cu_SLAB_USBtoUART_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_sketch_jul08b___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_9_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_Blogger__%25E1%2584%2580%25E1%2585%25B5%25E1%2584%2589%25E1%2585%25AE%25E1%2586%25AF_%25E1%2584%258B%25E1%2585%25A7%25E1%2584%2592%25E1%2585%25A2%25E1%2586%25BC%25E1%2584%258C%25E1%2585%25A1__ArsViator__-_Create_post.png" width="640" /></a></div>
<br />
맨 아랫줄에 Waiting for pairing 이라고 출력을 해 블루투스로 연결할 준비가 되었음을 알 수 있다.<br />
<br />
이제 컴퓨터 또는 안드로이드폰에서 블루투스 장치를 검색해보면 ESP32_SPP 라는 이름의 장치가 보일 것이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgG01jkR8tmZGYwX5aVwZQy8FoGwa8460MgwRY3AYZqQsRsVaIO9hqtf3W1_UkHdyBIlRnyMQW7kJjrAPLe0_p3FSBCzPQcnJhkSF0v4VSH8LgdXAd9E4DL9bLKZbzwBe_25X3RkS6fFY/s1600/Bluetooth.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="344" data-original-width="589" height="372" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgG01jkR8tmZGYwX5aVwZQy8FoGwa8460MgwRY3AYZqQsRsVaIO9hqtf3W1_UkHdyBIlRnyMQW7kJjrAPLe0_p3FSBCzPQcnJhkSF0v4VSH8LgdXAd9E4DL9bLKZbzwBe_25X3RkS6fFY/s640/Bluetooth.png" width="640" /></a></div>
<br />
ESP32_SPP 를 연결해 주면 된다.<br />
<br />
그 다음 시리얼 터미널 프로그램으로 가서 해달 포트를 오픈한다. 여기서는 맥이어서 'ESP32_SPP-ESP32_SPP_SER이라는 이름의 시리얼 포트가 된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqFGRCLOXSu-PFnDmP-M_9Wbxt9yGIjhiCdhIEnAuzuib81jtnTXNBLIWFkqitCvgwF9TPAvUtHlCu_lxE6cR9n3zBNEnmjAD9lnYtyIH2HCTTLrLMpTqhvFh_90UxFLY6XjBvjPd-bJw/s1600/Untitled_0_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_sketch_jul08b___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="555" data-original-width="685" height="518" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqFGRCLOXSu-PFnDmP-M_9Wbxt9yGIjhiCdhIEnAuzuib81jtnTXNBLIWFkqitCvgwF9TPAvUtHlCu_lxE6cR9n3zBNEnmjAD9lnYtyIH2HCTTLrLMpTqhvFh_90UxFLY6XjBvjPd-bJw/s640/Untitled_0_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_sketch_jul08b___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_9.png" width="640" /></a></div>
<br />
포트를 오픈한 다음 '+' 또는 '-'를 입력해주면 각각 LED(13) turned ON 또는 LED(13) turned OFF가 터미널에 출력되며 ESP32의 13번 핀에 연결되어 있는 LED가 켜지거나 꺼지게 된다.<br />
* 위의 화면에서는 입력된 글자를 확인하기 위해 local echo를 켜 놓았다. 즉 +/-는 사용자가 터미널에서 입력한 글자이고 LED(13) turned ON/OFF는 ESP32가 출력한 글자이다.<br />
<br />
<br />
<br />
<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-51012315484258593482019-06-18T14:02:00.001+09:002019-06-18T14:04:18.030+09:00LTE modem 사용LTE modem 모델은 Huawei E8372h-153<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL7co63zsa5WxaNQvFwKqI-dtGF4tAJxyQO2s-GmPio28NRNoNZfkNNaDgBZPPFqw5tIqLiGQSbWSlEnBiY386r3F65pvjMjEinycl197y5CAB_wNRHRR17gn7vR-hAX_Pl0nbP8Yn80o/s1600/IMG_1334.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="854" data-original-width="1600" height="340" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL7co63zsa5WxaNQvFwKqI-dtGF4tAJxyQO2s-GmPio28NRNoNZfkNNaDgBZPPFqw5tIqLiGQSbWSlEnBiY386r3F65pvjMjEinycl197y5CAB_wNRHRR17gn7vR-hAX_Pl0nbP8Yn80o/s640/IMG_1334.jpg" width="640" /></a></div>
<br />
aliexpress에서 $30~40에 구할 수 있다. 워낙 많은 통신사에서 사용하는 모델이다 보니 제품 윗면의 로고는 다를 수 있는데 신경 쓸 필요 없음<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvyx6mZCoKCtK8NkOwv4UrJvbGI-DudO2Yj6tm884JGn42s7enJwjPq_1F2AgyNrAPSrvutXJrDMUf7ImfOQ1lBpGEfupE9qp0Edu9C6AK8IdWQRKmSqXX-lbthCxjLZuHd5xHeOXS704/s1600/IMG_1333.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="803" data-original-width="1600" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvyx6mZCoKCtK8NkOwv4UrJvbGI-DudO2Yj6tm884JGn42s7enJwjPq_1F2AgyNrAPSrvutXJrDMUf7ImfOQ1lBpGEfupE9qp0Edu9C6AK8IdWQRKmSqXX-lbthCxjLZuHd5xHeOXS704/s640/IMG_1333.jpg" width="640" /></a> </div>
<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
뒷면에보면 모델명을 확인할 수 있음</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEdFIc9zE8fFKkXes5oD39SZA8zIAaN0Bvd_gILUzXAEKUTYLgTJjUCw5Iy17WTpRFtyec_gb-dmaSNgtcfRoRKUyEh493u8AzaHtpmJ62N-KlOGN4v7UxzcY9h5nt_-7Yo9GsNJOSb5Q/s1600/IMG_1335.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="770" data-original-width="1600" height="306" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEdFIc9zE8fFKkXes5oD39SZA8zIAaN0Bvd_gILUzXAEKUTYLgTJjUCw5Iy17WTpRFtyec_gb-dmaSNgtcfRoRKUyEh493u8AzaHtpmJ62N-KlOGN4v7UxzcY9h5nt_-7Yo9GsNJOSb5Q/s640/IMG_1335.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
기본적으로 내부에 안테나가 들어있어 그대로 사용해도 되지만 신호 수신을 좋게하기 위해 옆면에 외부 안테나를 부착할 수 있는 포트가 마개로 덮혀 있음</div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh54IWzzzXLb3NWXVLDWopMuLxRwdVux0eWt9_VBW1FW5hjr3SCNK6dQ8k3QVGD0DlBvcctJZcqCBFwfge5ut9YEQeGpFv2h2z5GiV7B8QJ_O6NRfaCbGGqKImYSsehia3fHdGYZwUhiQ/s1600/IMG_1337.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1424" data-original-width="1600" height="568" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh54IWzzzXLb3NWXVLDWopMuLxRwdVux0eWt9_VBW1FW5hjr3SCNK6dQ8k3QVGD0DlBvcctJZcqCBFwfge5ut9YEQeGpFv2h2z5GiV7B8QJ_O6NRfaCbGGqKImYSsehia3fHdGYZwUhiQ/s640/IMG_1337.jpg" width="640" /></a></div>
<br />
이런식으로 외부 안테나 부착이 가능함 <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFuI770q8ufMYJ02XY6oGXpHT6G3KS92W7Vuf7pvH8Fu9jE5XJWg4g4EgpYURdauAzPDez25WeZWgWa1VzR39GSAzjXRpepsoAtFlJaVZHsb2jUXP-QSKfhbtCzdsF_GwbALlg_thV_Ig/s1600/IMG_1336-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="878" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFuI770q8ufMYJ02XY6oGXpHT6G3KS92W7Vuf7pvH8Fu9jE5XJWg4g4EgpYURdauAzPDez25WeZWgWa1VzR39GSAzjXRpepsoAtFlJaVZHsb2jUXP-QSKfhbtCzdsF_GwbALlg_thV_Ig/s640/IMG_1336-2.jpg" width="350" /></a></div>
<br />
로고가 표시돠어 있는 윗면을 커넥터 반대쪽으로 살짝 밀면 뚜껑이 간단하게 분리된다. 내부에 위의 사진과 같이 MicroSD와 SIM card를 꼽을 수 있는 커넥터가 있다. SIM카드를 삽입하고 뚜껑을 덮어주면 됨<br />
<br />
통신망은 LG U+의 LTE를 사용.<br />
<br />
전원을 연결하면 잠시 후 제일 왼쪽 LED가 초록색으로 점멸하기 시작<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTk8pLqtKJqfOzZIJ7ftucvPGnUqQEN3VbRtf7hsSTjHqtfNeO92G8n6W_N6rQ3zjtRcXM0F_tnAFtZPxJPcQy45xwK18v86KFI1rsRWP5-dtJBMyTix9G-hODpR8Pj8fUcAmX4SkZJyc/s1600/leds.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="200" data-original-width="417" height="153" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTk8pLqtKJqfOzZIJ7ftucvPGnUqQEN3VbRtf7hsSTjHqtfNeO92G8n6W_N6rQ3zjtRcXM0F_tnAFtZPxJPcQy45xwK18v86KFI1rsRWP5-dtJBMyTix9G-hODpR8Pj8fUcAmX4SkZJyc/s320/leds.jpg" width="320" /></a></div>
<br />
무선랜을 선택해 LTE모뎀에 접속 (SSID, WiFi key는 뚜껑을 열어보면 확인할 수 있음. 장치 홈페이지에서 관리자 ID/PW는 둘 다 admin/admin <br />
<br />
맨 처음 연결하면 프로파일을 만들어 줘야 함. LG U+ LTE이므로 프로파일 이름은 임의로 설정, ID/PW는 없음, APN은 internet.lguplus.co.kr 을 넣어주면 됨<br />
<br />
정상적으로 설정이 끝나 통신망에 접속하면 제일 왼쪽 LED가 푸른색으로 켜져 있음<br />
<br />
제일 오른쪽 LED는 무선랜 상태를 표시. 녹색으로 켜져 있음 정상 동작하는 것임<br />
<br />
* 이 방식의 장점은 LTE 데이터를 여러 장비에서 공유가 가능. 또한 USB를 꼭 컴퓨터가 아니고 휴대폰 충전기나 휴대용 배터리에 연결해서 사용할 수 있음<br />
ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com3tag:blogger.com,1999:blog-6762236726539517408.post-91045134268476166102019-06-14T12:21:00.003+09:002019-06-14T12:21:27.425+09:00ESP32에서 CAN bus 사용하기CAN버스는 Controller Area Network를 말하는데 이 프로토콜은 주로 자동차에서 널리 이용되고 있다. CAN에 대해 더 자세히 알고 싶으면 다음의 링크들을 참고하면 된다.<br />
<br />
- <a href="http://www.ni.com/white-paper/2732/en">http://www.ni.com/white-paper/2732/en</a><br />
- <a href="http://www.ti.com/lit/an/sloa101b/sloa101b.pdf">http://www.ti.com/lit/an/sloa101b/sloa101b.pdf</a><br />
<br />
ESP32는 CAN 인터페이스를 지원하기 때문에 CAN bus를 쉽게 사용할 수 있다. <br />
이 데모에서는 2개의 ESP32 모듈을 사용해, 첫번째 모듈은 'hellocan' 이라는 메시지를 보내고 두번째 모듈은 받은 메시지의 문자열을 전부 대문자로 바꿔 첫번째 모듈로 돌려보낸다. 그러면 첫번째 모듈은 받은 메시지를 터미널로 출력하게 된다.<br />
<br />
ESP32는 CAN controller만을 내장하고 있기 때문에 CAN 버스를 사용하려면 CAN transceiver가 필요하다. 아래 사진의 CAN transceiver를 2개 사용했다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggOfJ56tgNmsxBZHNG7tSR14vtZncjChxmzUYG7-AFRnFuSDXejiYOWZtjg3b_ip8shkZWi0Z7N-GvlWjILmjAMF0I8C6ZAnyFPuHN6ITap1Jc8Hg_uik_t9ciQvl3IqDYz17Dc18IPQo/s1600/SN65HVD230_CAN_bus_transceiver_communication_module_for-in_Integrated_Circuits_from_Electronic_Components___Supplies_on_Aliexpress_com___Alibaba_Group.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="423" data-original-width="526" height="514" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggOfJ56tgNmsxBZHNG7tSR14vtZncjChxmzUYG7-AFRnFuSDXejiYOWZtjg3b_ip8shkZWi0Z7N-GvlWjILmjAMF0I8C6ZAnyFPuHN6ITap1Jc8Hg_uik_t9ciQvl3IqDYz17Dc18IPQo/s640/SN65HVD230_CAN_bus_transceiver_communication_module_for-in_Integrated_Circuits_from_Electronic_Components___Supplies_on_Aliexpress_com___Alibaba_Group.png" width="640" /></a></div>
* aliexpress에서 개당 약 $1 정도로 구입할 수 있다.<br />
<br />
ESP32와 CAN transceiver 모듈의 연결은 다음과 같이 해 주면 된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3Du86tj4YzB-PVFE3K4_NiOw6_eI3TDW4Q_ExMOdthc12F47Ku7ZdzmEBmbyw_IzdJ4klMAhWhN4F2Jiduh1rwdoE2EaIWruq9JkUXJWI02sFNXs49MQQHn0QPz_kNjzjl23fq0f08y0/s1600/espcan.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="396" data-original-width="1224" height="206" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3Du86tj4YzB-PVFE3K4_NiOw6_eI3TDW4Q_ExMOdthc12F47Ku7ZdzmEBmbyw_IzdJ4klMAhWhN4F2Jiduh1rwdoE2EaIWruq9JkUXJWI02sFNXs49MQQHn0QPz_kNjzjl23fq0f08y0/s640/espcan.png" width="640" /></a></div>
<br />
CAN library로는 Thomas Barth가 만든 CAN driver를 사용했다.<br />
<br />
<a href="https://github.com/ThomasBarth/ESP32-CAN-Driver/tree/master/components/can">https://github.com/ThomasBarth/ESP32-CAN-Driver/tree/master/components/can</a><br />
<br />
라이브러리를 다운받아 설치해주면 된다.<br />
<br />
첫번째 ESP32 (위의 그림에서 ESP32 (1)에 해당)에는 아래와 같은 코드를 넣어준다.<br />
<br />
<pre style="line-height: 125%; margin: 0;"><span style="color: #557799;">#include <ESP32CAN.h></span>
<span style="color: #557799;">#include <CAN_config.h></span>
<span style="color: #888888;">/* the variable name CAN_cfg is fixed, do not change */</span>
CAN_device_t CAN_cfg;
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">setup</span>() {
Serial.begin(<span style="color: #0000dd; font-weight: bold;">115200</span>);
Serial.println(<span style="background-color: #fff0f0;">"iotsharing.com CAN demo"</span>);
<span style="color: #888888;">/* set CAN pins and baudrate */</span>
CAN_cfg.speed<span style="color: #333333;">=</span>CAN_SPEED_1000KBPS;
CAN_cfg.tx_pin_id <span style="color: #333333;">=</span> GPIO_NUM_5;
CAN_cfg.rx_pin_id <span style="color: #333333;">=</span> GPIO_NUM_4;
<span style="color: #888888;">/* create a queue for CAN receiving */</span>
CAN_cfg.rx_queue <span style="color: #333333;">=</span> xQueueCreate(<span style="color: #0000dd; font-weight: bold;">10</span>,<span style="color: #008800; font-weight: bold;">sizeof</span>(CAN_frame_t));
<span style="color: #888888;">//initialize CAN Module</span>
ESP32Can.CANInit();
}
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">loop</span>() {
CAN_frame_t rx_frame;
<span style="color: #888888;">//receive next CAN frame from queue</span>
<span style="color: #008800; font-weight: bold;">if</span>(xQueueReceive(CAN_cfg.rx_queue,<span style="color: #333333;">&</span>rx_frame, <span style="color: #0000dd; font-weight: bold;">3</span><span style="color: #333333;">*</span>portTICK_PERIOD_MS)<span style="color: #333333;">==</span>pdTRUE){
<span style="color: #888888;">//do stuff!</span>
<span style="color: #008800; font-weight: bold;">if</span>(rx_frame.FIR.B.FF<span style="color: #333333;">==</span>CAN_frame_std)
printf(<span style="background-color: #fff0f0;">"New standard frame"</span>);
<span style="color: #008800; font-weight: bold;">else</span>
printf(<span style="background-color: #fff0f0;">"New extended frame"</span>);
<span style="color: #008800; font-weight: bold;">if</span>(rx_frame.FIR.B.RTR<span style="color: #333333;">==</span>CAN_RTR)
printf(<span style="background-color: #fff0f0;">" RTR from 0x%08x, DLC %d</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\r\n</span><span style="background-color: #fff0f0;">"</span>,rx_frame.MsgID, rx_frame.FIR.B.DLC);
<span style="color: #008800; font-weight: bold;">else</span>{
printf(<span style="background-color: #fff0f0;">" from 0x%08x, DLC %d</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>,rx_frame.MsgID, rx_frame.FIR.B.DLC);
<span style="color: #888888;">/* convert to upper case and respond to sender */</span>
<span style="color: #008800; font-weight: bold;">for</span>(<span style="color: #333399; font-weight: bold;">int</span> i <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>; i <span style="color: #333333;"><</span> <span style="color: #0000dd; font-weight: bold;">8</span>; i<span style="color: #333333;">++</span>){
<span style="color: #008800; font-weight: bold;">if</span>(rx_frame.data.u8[i] <span style="color: #333333;">>=</span> <span style="color: #0044dd;">'a'</span> <span style="color: #333333;">&&</span> rx_frame.data.u8[i] <span style="color: #333333;"><=</span> <span style="color: #0044dd;">'z'</span>){
rx_frame.data.u8[i] <span style="color: #333333;">=</span> rx_frame.data.u8[i] <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">32</span>;
}
}
}
<span style="color: #888888;">//respond to sender</span>
ESP32Can.CANWriteFrame(<span style="color: #333333;">&</span>rx_frame);
}
}</pre>
<br />
두번째 ESP32 (위의 그림에서 ESP32 (2)에 해당)에는 아래와 같은 코드를 넣어준다.<br />
<br />
<pre style="line-height: 125%; margin: 0;"><span style="color: #557799;">#include <ESP32CAN.h></span>
<span style="color: #557799;">#include <CAN_config.h></span>
<span style="color: #888888;">/* the variable name CAN_cfg is fixed, do not change */</span>
CAN_device_t CAN_cfg;
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">setup</span>() {
Serial.begin(<span style="color: #0000dd; font-weight: bold;">115200</span>);
Serial.println(<span style="background-color: #fff0f0;">"iotsharing.com CAN demo"</span>);
<span style="color: #888888;">/* set CAN pins and baudrate */</span>
CAN_cfg.speed<span style="color: #333333;">=</span>CAN_SPEED_1000KBPS;
CAN_cfg.tx_pin_id <span style="color: #333333;">=</span> GPIO_NUM_5;
CAN_cfg.rx_pin_id <span style="color: #333333;">=</span> GPIO_NUM_4;
<span style="color: #888888;">/* create a queue for CAN receiving */</span>
CAN_cfg.rx_queue <span style="color: #333333;">=</span> xQueueCreate(<span style="color: #0000dd; font-weight: bold;">10</span>,<span style="color: #008800; font-weight: bold;">sizeof</span>(CAN_frame_t));
<span style="color: #888888;">//initialize CAN Module</span>
ESP32Can.CANInit();
}
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">loop</span>() {
CAN_frame_t rx_frame;
<span style="color: #888888;">//receive next CAN frame from queue</span>
<span style="color: #008800; font-weight: bold;">if</span>(xQueueReceive(CAN_cfg.rx_queue,<span style="color: #333333;">&</span>rx_frame, <span style="color: #0000dd; font-weight: bold;">3</span><span style="color: #333333;">*</span>portTICK_PERIOD_MS)<span style="color: #333333;">==</span>pdTRUE){
<span style="color: #888888;">//do stuff!</span>
<span style="color: #008800; font-weight: bold;">if</span>(rx_frame.FIR.B.FF<span style="color: #333333;">==</span>CAN_frame_std)
printf(<span style="background-color: #fff0f0;">"New standard frame"</span>);
<span style="color: #008800; font-weight: bold;">else</span>
printf(<span style="background-color: #fff0f0;">"New extended frame"</span>);
<span style="color: #008800; font-weight: bold;">if</span>(rx_frame.FIR.B.RTR<span style="color: #333333;">==</span>CAN_RTR)
printf(<span style="background-color: #fff0f0;">" RTR from 0x%08x, DLC %d</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\r\n</span><span style="background-color: #fff0f0;">"</span>,rx_frame.MsgID, rx_frame.FIR.B.DLC);
<span style="color: #008800; font-weight: bold;">else</span>{
printf(<span style="background-color: #fff0f0;">" from 0x%08x, DLC %d</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>,rx_frame.MsgID, rx_frame.FIR.B.DLC);
<span style="color: #008800; font-weight: bold;">for</span>(<span style="color: #333399; font-weight: bold;">int</span> i <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>; i <span style="color: #333333;"><</span> <span style="color: #0000dd; font-weight: bold;">8</span>; i<span style="color: #333333;">++</span>){
printf(<span style="background-color: #fff0f0;">"%c</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\t</span><span style="background-color: #fff0f0;">"</span>, (<span style="color: #333399; font-weight: bold;">char</span>)rx_frame.data.u8[i]);
}
printf(<span style="background-color: #fff0f0;">"</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\n</span><span style="background-color: #fff0f0;">"</span>);
}
}
<span style="color: #008800; font-weight: bold;">else</span>
{
rx_frame.FIR.B.FF <span style="color: #333333;">=</span> CAN_frame_std;
rx_frame.MsgID <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">1</span>;
rx_frame.FIR.B.DLC <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">8</span>;
rx_frame.data.u8[<span style="color: #0000dd; font-weight: bold;">0</span>] <span style="color: #333333;">=</span> <span style="color: #0044dd;">'h'</span>;
rx_frame.data.u8[<span style="color: #0000dd; font-weight: bold;">1</span>] <span style="color: #333333;">=</span> <span style="color: #0044dd;">'e'</span>;
rx_frame.data.u8[<span style="color: #0000dd; font-weight: bold;">2</span>] <span style="color: #333333;">=</span> <span style="color: #0044dd;">'l'</span>;
rx_frame.data.u8[<span style="color: #0000dd; font-weight: bold;">3</span>] <span style="color: #333333;">=</span> <span style="color: #0044dd;">'l'</span>;
rx_frame.data.u8[<span style="color: #0000dd; font-weight: bold;">4</span>] <span style="color: #333333;">=</span> <span style="color: #0044dd;">'o'</span>;
rx_frame.data.u8[<span style="color: #0000dd; font-weight: bold;">5</span>] <span style="color: #333333;">=</span> <span style="color: #0044dd;">'c'</span>;
rx_frame.data.u8[<span style="color: #0000dd; font-weight: bold;">6</span>] <span style="color: #333333;">=</span> <span style="color: #0044dd;">'a'</span>;
rx_frame.data.u8[<span style="color: #0000dd; font-weight: bold;">7</span>] <span style="color: #333333;">=</span> <span style="color: #0044dd;">'n'</span>;
ESP32Can.CANWriteFrame(<span style="color: #333333;">&</span>rx_frame);
}
}</pre>
<br />
양쪽의 보드를 동작시키고 첫번째 ESP32의 시리얼 터미널의 출력은 다음과 같다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGlcjiUNwz3_OEniVDr8Jy7o9m49DNavLJQjJ-1-JJg6Cc8C5DNJ-xhKdojJ6K45mXmL32HyHLyaUgy49GKYoyfNZUR2jzL1BA0R7vvn6BuLcXtKO8cR37ZZ4WVIDUZoaM6afqE5ahotI/s1600/Demo_31__How_to_use_Arduino_ESP32_CAN_interface___IoT_Sharing.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="404" data-original-width="544" height="474" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGlcjiUNwz3_OEniVDr8Jy7o9m49DNavLJQjJ-1-JJg6Cc8C5DNJ-xhKdojJ6K45mXmL32HyHLyaUgy49GKYoyfNZUR2jzL1BA0R7vvn6BuLcXtKO8cR37ZZ4WVIDUZoaM6afqE5ahotI/s640/Demo_31__How_to_use_Arduino_ESP32_CAN_interface___IoT_Sharing.png" width="640" /></a></div>
<br />
<br />
<br />
* Original credit goes to <a href="http://www.iotsharing.com/2017/09/how-to-use-arduino-esp32-can-interface.html">http://www.iotsharing.com/2017/09/how-to-use-arduino-esp32-can-interface.html</a><br />
<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com1tag:blogger.com,1999:blog-6762236726539517408.post-78316629235461953462019-04-26T12:51:00.001+09:002019-04-26T12:52:20.062+09:00아두이노 우노에서 ADXL335 가속도 센서 사용하기 (Using ADXL335 accelerometer on Arduino Uno)Original Document: <a href="https://lastminuteengineers.com/adxl335-accelerometer-arduino-tutorial/">https://lastminuteengineers.com/adxl335-accelerometer-arduino-tutorial/ </a><br />
<h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2beJVh1z3x9eqwv-JD9WOCVzu1GwHWhukwcQYck5p3wv6JVfwMQNR_ay0OiBrbvi5sOEdg1ueOJ_rMoa_dVfyM_awLyfSmyHY6qNUlIBvvqSHuDmOJwVEsBkkwr5OoetVy-EyYcPPeis/s1600/Tutorial-for-Interfacing-ADXL335-Accelerometer-Module-with-Arduino.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="437" data-original-width="764" height="366" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2beJVh1z3x9eqwv-JD9WOCVzu1GwHWhukwcQYck5p3wv6JVfwMQNR_ay0OiBrbvi5sOEdg1ueOJ_rMoa_dVfyM_awLyfSmyHY6qNUlIBvvqSHuDmOJwVEsBkkwr5OoetVy-EyYcPPeis/s640/Tutorial-for-Interfacing-ADXL335-Accelerometer-Module-with-Arduino.jpg" width="640" /></a></div>
</h3>
<h3>
가속도 센서의 동작 원리</h3>
가속도 센서의 동작원리를 이해하려면 3차원 큐브 속에 공이 들어 있는걸 상상하면 된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicKCyzqqQDGl-of5o9nDgnftjl8O8oKoDnCI3ABshxtLvTrnqshHQnV0h_Pb-8DGuXEyj1XfxM-5VNkk7-65WA4AkAAyswTMx8nqUC5c2vOlWGjxzGTBcIqnki3n07A8yUOjvvze-gWN0/s1600/Accelerometer-Working-Illustration-Weightless-State.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="512" height="374" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicKCyzqqQDGl-of5o9nDgnftjl8O8oKoDnCI3ABshxtLvTrnqshHQnV0h_Pb-8DGuXEyj1XfxM-5VNkk7-65WA4AkAAyswTMx8nqUC5c2vOlWGjxzGTBcIqnki3n07A8yUOjvvze-gWN0/s640/Accelerometer-Working-Illustration-Weightless-State.jpg" width="640" /></a></div>
<br />
<br />
만일 이 큐브가 우주에 있어 모든것이 무게가 없는 상태라고 한다면 공은 큐브 가운데에 가만히 떠 있을 것이다. 위의 그림에서 큐브의 각 벽면이 특정 축을 나타낸다고 생각해 보자.<br />
<br />
박스가 갑자기 왼쪽으로 가속도 1g의 가속도로 가속되어 움직이면 공은 큐브의 X 벽에 부딛히게 될 것이다. 공이 벽X를 때리는 힘을 측정한다면 X축에 1G의 출력값을 얻을 수 있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI8sZOefwVZ5ZpuAK6B2u_16PNHbiAgi4_aSKTtge7WVGUeWWvIKLMRYPGmZoWVhbI1_YX08Ff2NhUU17ayaqVz-IKtI54qDQL8WmvjYEy-U4foPG8Myx1hJ1ErWK2dm-Q_ZwAiMkOf-4/s1600/Accelerometer-Working-Illustration-Sudden-Movement.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="490" height="390" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI8sZOefwVZ5ZpuAK6B2u_16PNHbiAgi4_aSKTtge7WVGUeWWvIKLMRYPGmZoWVhbI1_YX08Ff2NhUU17ayaqVz-IKtI54qDQL8WmvjYEy-U4foPG8Myx1hJ1ErWK2dm-Q_ZwAiMkOf-4/s640/Accelerometer-Working-Illustration-Sudden-Movement.jpg" width="640" /></a></div>
<br />
<br />
만일 큐브를 지표면으로 가져온다면 공은 벽 Z로 떨어질것이고 벽Z에 1G의 힘을 가할 것이다.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMlc-almmX-i2h2LxNKF6gH0_SHZwTw1q6L1l1sNIV_Q9uWYrTVkbSE29mgfiHe8spx5XrJnR42nHdIV5aNXnNnz-BC1f-XStTcrUZo4zmsOD0jAVqM0cIT38oRa9wQ3Wc5hv3QJVfIJg/s1600/Accelerometer-Working-Illustration-Gravitation-Force.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="511" height="374" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMlc-almmX-i2h2LxNKF6gH0_SHZwTw1q6L1l1sNIV_Q9uWYrTVkbSE29mgfiHe8spx5XrJnR42nHdIV5aNXnNnz-BC1f-XStTcrUZo4zmsOD0jAVqM0cIT38oRa9wQ3Wc5hv3QJVfIJg/s640/Accelerometer-Working-Illustration-Gravitation-Force.jpg" width="640" /></a></div>
<br />
<br />
이 경우 큐브는 움직이지 않았지만 그래도 Z축으로 1G의 값을 얻었다. 이는 중력 가속도가 1G의 힘으로 공을 아래로 당기고 있기 때문이다.<br />
<br />
* 가속도 센서는 기울어짐 측정 어플리케이션에서 정적 가속도(static acceleration) 뿐 아니고 모션, 쇼크, 진동에 의한 동적 가속도(dynamic acceleration)도 측정한다.<br />
<br />
<h3>
MEMS 가속도 센서의 동작 원리</h3>
MEMS(Micro Electro Mechanical Systems) 가속도 센서는 실리콘 웨이퍼 위에 매주 작은 기계가공된 구조(micro-machined structure)로 이루어져 있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib-B9Q4jtHo4QcNbeS6oMn8KAxB4sQoI046ev8OIxV6-jZQMbIb4MQ9HkLwPj7e4E9SeEtj03rvsn-UhKRRzxYkn3ipxuBLC9Su9JJ-133qBrqX8E0yO1CXB7eQjMOkT6YGjjCBg_EmoY/s1600/ADXL335-MEMS-Accelerometer-Internal-Working.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="282" data-original-width="600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib-B9Q4jtHo4QcNbeS6oMn8KAxB4sQoI046ev8OIxV6-jZQMbIb4MQ9HkLwPj7e4E9SeEtj03rvsn-UhKRRzxYkn3ipxuBLC9Su9JJ-133qBrqX8E0yO1CXB7eQjMOkT6YGjjCBg_EmoY/s640/ADXL335-MEMS-Accelerometer-Internal-Working.gif" width="640" /></a></div>
<br />
<br />
이 구조는 폴리실리콘 스프링에 매달려 있다. 특정 축에 가속도가 가해지면 이 구조가 편향될 수 있게 해 준다.<br />
<br />
편향으로 인해 고정된 플레이트와 매달려 있는 구조 사이의 정전용량(capacitance)이 바뀌게 된다. 이 정전용량의 변화는 축에 가해진 가속도에 비례한다.<br />
<br />
센서는 정전용량의 변화를 처리해 아날로그 출력전압으로 변환한다.<br />
<br />
<h3>
ADXL335 가속도 센서의 하드웨어</h3>
모듈의 핵심은 아날로그 디바이스에서 나온 소형, 저전력, 저잡음의 3축 MEMS 가속도 센서인 ADXL335이다. 이 센서는 +-3g 범위 내의 값을 측정할 수 있다. 기울기 감지 어플리케이션에서 중력가속도로 인한 정적 가속도 뿐 아니고 모션, 쇼크, 진동에 의한 동적 가속도도 측정할 수 있다.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9XYz_0_yB4IPBeajGK7ohuiScwWy37BWhWAmndnmeG9knjWNeSy_LhT3eM1_I7ny4SN01y259m4xyQulxE24bzQL8dVmZh7TH9DVhHpa9iBV5smVeXgAGCmGwEzHNhQ9P3EuoqeCxyoM/s1600/ADXL335-Accelerometer-Module-Hardware-Overview.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="301" data-original-width="499" height="386" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9XYz_0_yB4IPBeajGK7ohuiScwWy37BWhWAmndnmeG9knjWNeSy_LhT3eM1_I7ny4SN01y259m4xyQulxE24bzQL8dVmZh7TH9DVhHpa9iBV5smVeXgAGCmGwEzHNhQ9P3EuoqeCxyoM/s640/ADXL335-Accelerometer-Module-Hardware-Overview.png" width="640" /></a></div>
<br />
이 센서는 1.8~3.6V DC에서 동작하고 약 350uA의 전류를 소비한다. 하지만 모듈에 3.3V 레귤레이터가 들어있기 때문에 아두이노같이 5V를 사용하는 마이크로 컴트롤러에서 사용하는데도 문제가 없다.<br />
<br />
빵판에서도 사용하기 쉽게 ADXL335의 모든 핀이 2.54mm 피치의 6핀 헤더로 연결되어 있다. 여기에는 X, Y, Z 3축의 아날로그 출력, 2개의 전원핀, 셀프테스트 핀이 들어 있다.<br />
<br />
아날로그 출력은 ratiometic한데 이건 즉 0g는 3.3V 공급 전압의 중간(1.65V)을 출력하고, -3g는 0V, 3g는 3.3V를 출력하고 그 사이 값은 정확하게 비례한 전압이 출력된다.<br />
<br />
다음은 ADXL335 가속도 센서 IC의 풀 스펙이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYBNKlbha0Ux6elDYxjUkahN11vk5rPseU15Ar-1cTsvzB4Ovg1QpiR6t4UaoGzVmAW3HJCm17qFh2qlbV3JHNeb7okc4gPTGU-9KPSZDi8g-JmdakHLT2CtRcqIfaSROVq7qSeM1Gkqo/s1600/In-Depth__How_Accelerometer_works__Interface_ADXL335_with_Arduino.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="481" data-original-width="898" height="342" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYBNKlbha0Ux6elDYxjUkahN11vk5rPseU15Ar-1cTsvzB4Ovg1QpiR6t4UaoGzVmAW3HJCm17qFh2qlbV3JHNeb7okc4gPTGU-9KPSZDi8g-JmdakHLT2CtRcqIfaSROVq7qSeM1Gkqo/s640/In-Depth__How_Accelerometer_works__Interface_ADXL335_with_Arduino.png" width="640" /></a></div>
<br />
<br />
더 상세한 내용은 데이터쉬트를 참조하면 된다.<br />
<br />
<br />
<h3>
ADXL335 가속도 센서 핀아웃</h3>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjePfB0sFs6iKUpkzgrwmPAF_vVxPCrB4Qs8rsHvI28yJCxAd-iYgWVojycH-YEgimm4yZkmWqsT70UXlDlxGfnIceUDJXcyyn49crGFZeYMqdPxQSDOlIfz7qwI0BHRGKhH8ABFZXqTqM/s1600/ADXL335-Accelerometer-Module-Pinout.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="205" data-original-width="408" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjePfB0sFs6iKUpkzgrwmPAF_vVxPCrB4Qs8rsHvI28yJCxAd-iYgWVojycH-YEgimm4yZkmWqsT70UXlDlxGfnIceUDJXcyyn49crGFZeYMqdPxQSDOlIfz7qwI0BHRGKhH8ABFZXqTqM/s640/ADXL335-Accelerometer-Module-Pinout.png" width="640" /></a></div>
<br />
<br />
<h3>
아두이노 우노와 연결</h3>
연결은 매우 쉽다. Vcc핀은 우노의 5V핀에, GND핀은 우노의 그라운드 핀에 연결해 준다. 그리고 X, Y, Z 출력은 각각 우노의 A0, A1, A2에 연결해 주면 된다.<br />
<br />
정확한 결과를 위해 아두이노 우노의 아날로그 레퍼런스 (AREF) 전압을 변경해 줄 필요가 있다. 여기서는 우노의 3.3V 핀을 우노의 AREF핀에 연결(아래 그림에서 빨간색 점선 부분)해 주면 된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg58sFs2lGuG5HZ-wZ4AgULi9NcdsqoVaw77twjkyQF6312JIkrFN-3xJi6QlL6vMMduc800MMQMKbrHBjb05fFa1ca0uasBqp_GyQ-PHUAQHJdAY26UWuIE7_l5QuXbjRBuLAv9KUDzY0/s1600/Wiring-ADXL335-Accelerometer-Module-to-Arduino-UNO.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="297" data-original-width="516" height="368" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg58sFs2lGuG5HZ-wZ4AgULi9NcdsqoVaw77twjkyQF6312JIkrFN-3xJi6QlL6vMMduc800MMQMKbrHBjb05fFa1ca0uasBqp_GyQ-PHUAQHJdAY26UWuIE7_l5QuXbjRBuLAv9KUDzY0/s640/Wiring-ADXL335-Accelerometer-Module-to-Arduino-UNO.png" width="640" /></a></div>
<br />
<h3>
예제 코드</h3>
<br />
<pre class=" language-c"><code class=" language-c"><span class="lme-keyword">const</span> <span class="lme-keyword">int</span> xInput = A0;
<span class="lme-keyword">const</span> <span class="lme-keyword">int</span> yInput = A1;
<span class="lme-keyword">const</span> <span class="lme-keyword">int</span> zInput = A2;
<span class="lme-comment">// initialize minimum and maximum Raw Ranges for each axis</span>
<span class="lme-keyword">int</span> RawMin = <span class="lme-number">0</span>;
<span class="lme-keyword">int</span> RawMax = <span class="lme-number">1023</span>;
<span class="lme-comment">// Take multiple samples to reduce noise</span>
<span class="lme-keyword">const</span> <span class="lme-keyword">int</span> sampleSize = <span class="lme-number">10</span>;
<span class="lme-keyword">void</span> <span class="lme-function">setup</span>()
{
<span class="lme-function">analogReference</span>(EXTERNAL);
Serial.<span class="lme-function">begin</span>(<span class="lme-number">115200</span>);
}
<span class="lme-keyword">void</span> <span class="lme-function">loop</span>()
{
<span class="lme-comment">//Read raw values</span>
<span class="lme-keyword">int</span> xRaw = <span class="lme-function">ReadAxis</span>(xInput);
<span class="lme-keyword">int</span> yRaw = <span class="lme-function">ReadAxis</span>(yInput);
<span class="lme-keyword">int</span> zRaw = <span class="lme-function">ReadAxis</span>(zInput);
<span class="lme-comment">// Convert raw values to 'milli-Gs"</span>
<span class="lme-keyword">long</span> xScaled = <span class="lme-function">map</span>(xRaw, RawMin, RawMax, -<span class="lme-number">3000</span>, <span class="lme-number">3000</span>);
<span class="lme-keyword">long</span> yScaled = <span class="lme-function">map</span>(yRaw, RawMin, RawMax, -<span class="lme-number">3000</span>, <span class="lme-number">3000</span>);
<span class="lme-keyword">long</span> zScaled = <span class="lme-function">map</span>(zRaw, RawMin, RawMax, -<span class="lme-number">3000</span>, <span class="lme-number">3000</span>);
<span class="lme-comment">// re-scale to fractional Gs</span>
<span class="lme-keyword">float</span> xAccel = xScaled / <span class="lme-number">1000.0</span>;
<span class="lme-keyword">float</span> yAccel = yScaled / <span class="lme-number">1000.0</span>;
<span class="lme-keyword">float</span> zAccel = zScaled / <span class="lme-number">1000.0</span>;
Serial.<span class="lme-function">print</span>(<span class="lme-string">"X, Y, Z :: "</span>);
Serial.<span class="lme-function">print</span>(xRaw);
Serial.<span class="lme-function">print</span>(<span class="lme-string">", "</span>);
Serial.<span class="lme-function">print</span>(yRaw);
Serial.<span class="lme-function">print</span>(<span class="lme-string">", "</span>);
Serial.<span class="lme-function">print</span>(zRaw);
Serial.<span class="lme-function">print</span>(<span class="lme-string">" :: "</span>);
Serial.<span class="lme-function">print</span>(xAccel,<span class="lme-number">0</span>);
Serial.<span class="lme-function">print</span>(<span class="lme-string">"G, "</span>);
Serial.<span class="lme-function">print</span>(yAccel,<span class="lme-number">0</span>);
Serial.<span class="lme-function">print</span>(<span class="lme-string">"G, "</span>);
Serial.<span class="lme-function">print</span>(zAccel,<span class="lme-number">0</span>);
Serial.<span class="lme-function">println</span>(<span class="lme-string">"G"</span>);
<span class="lme-function">delay</span>(<span class="lme-number">200</span>);
}
<span class="lme-comment">// Take samples and return the average</span>
<span class="lme-keyword">int</span> <span class="lme-function">ReadAxis</span>(<span class="lme-keyword">int</span> axisPin)
{
<span class="lme-keyword">long</span> reading = <span class="lme-number">0</span>;
<span class="lme-function">analogRead</span>(axisPin);
<span class="lme-function">delay</span>(<span class="lme-number">1</span>);
<span class="lme-keyword">for</span> (<span class="lme-keyword">int</span> i = <span class="lme-number">0</span>; i < sampleSize; i++)
{
reading += <span class="lme-function">analogRead</span>(axisPin);
}
<span class="lme-keyword">return</span> reading/sampleSize;
}</code></pre>
<br />
위의 코드에서는 가장 먼저 센서의 X,Y, Z 출력이 아두이노 우노의 어느 아날로그 입력에 연결되어 있는가를 선언해 준다.<br />
<br />
다음은 아날로그입력의 최소/최대값을 지정해 준다. 아두이노 우노의 경우 10-bit ADC를 사용하므로 0~3.3V의 전압은 0~1023 사이의 값으로 변환된다.<br />
<br />
sampleSize 변수는 더 정확한 결과를 얻기 위해 각 출력값에 몇개의 샘플값을 사용하는지를 지정한다.<br />
<br />
<u><b>* 주의 </b></u><br />
<u><b>analogReference(EXTERNAL)을 호출하는걸 빼먹으면 내부적으로 생성된 reference 전압과 AREF핀을 쇼트시키게 되므로 아두이노 우노를 망가트릴 수도 있으므로 가장 먼저 호출하는걸 잊어먹으면 안된다.</b></u><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">analogReference(EXTERNAL);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Serial.begin(115200); </span><br />
<br />
loop() 함수에서 매 200ms마다 아날로그 출력값을 읽는다. analogRead() 함수 대신 ReadAxis() 함수를사용한다. 이 함수에서는 10개의 ADC 변환값을 읽어 평균값을 리턴해준다.<br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">// Read raw values</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">int xRaw = ReadAxis(xInput);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">int yRaw = ReadAxis(yInput);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">int zRaw = ReadAxis(zInput);</span><br />
<br />
<h3>
ADXL335 출력을 가속도로 변환하기</h3>
센서의 아날로그 출력값을 실제 가속도로 변환해 줘야 한다. 여기서는 아두이노에 기본으로 들어 있는 map() 함수를 사용한다. map(xRaw, RawMin, RawMax, -3000, 3000); 를 호출하면 RawMin(0)은 -3000으로, RawMax(1023)는 3000으로, 0~1023 사이 값은 -3000~3000 사이에 비례하는 값으로 변환된다.<br />
<br />
* 여기서 -3000, 3000은 임의의 값이 아니다. 이 값은 센서에서 측정된 실제 중력 가속도(1/1000 G 단위)를 나타낸다. <br />
<br />
<ul>
<li>센서의 X축이 0V를 출력하면 (xRaw=0) map() 함수는 -3000을 리턴할 것이고 이는 즉 -3G를 나타낸다</li>
<li>센서의 X축이 3.3V를 출력하면 (xRaw=1023) map() 함수는 3000을 리턴할 것이고 이는 즉 3G를 나타낸다.</li>
<li>센서의 X축이 1.65V를 출력하면 (xRaw=511) map() 함수는 0을 리턴할 것이고 이는 즉 0G (가속도가 없음)을 나타낸다.</li>
</ul>
<br />
아래 그림은 모듈을 각각 다른 방향으로 놓았을 때 가속도 센서의 출력값을 보여준다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDIpX4xbhu0lVgJ7yOoOHxwcSCRw5Kyqnz5UmkirLH0IfnyzaKQwciPk_w0lDPsQyAIEv_C-GBl09Bqn1HdOCyTY8nTZornrbEijs3rN4s8zD0wny5u6bmG76ssEt9ox-1g7rTCM7zy2A/s1600/aaaa.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1242" data-original-width="638" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDIpX4xbhu0lVgJ7yOoOHxwcSCRw5Kyqnz5UmkirLH0IfnyzaKQwciPk_w0lDPsQyAIEv_C-GBl09Bqn1HdOCyTY8nTZornrbEijs3rN4s8zD0wny5u6bmG76ssEt9ox-1g7rTCM7zy2A/s1600/aaaa.png" /></a></div>
<br />
<h3>
ADXL335 셀프 테스트</h3>
ADXL335는 최종 어플리케이션에서 센서의 동작을 확인하기 위한 셀프테스트 기능을 가지고 있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidDL-fpjEzAYhy4aDCKGcIjfkr2cgL4-zrAdu1RcUG7MPj6eK4ys9-e7gQeYR4nDhA7hcXqOC2vR9IaYKAr9p2T162NKVlRxv8CLwXCU3EXQ3_lVyo4O-yPHSYKk_dZiR3glTn1j8uklw/s1600/ADXL335-Module-SelfTest-Pin.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="221" data-original-width="225" height="392" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidDL-fpjEzAYhy4aDCKGcIjfkr2cgL4-zrAdu1RcUG7MPj6eK4ys9-e7gQeYR4nDhA7hcXqOC2vR9IaYKAr9p2T162NKVlRxv8CLwXCU3EXQ3_lVyo4O-yPHSYKk_dZiR3glTn1j8uklw/s400/ADXL335-Module-SelfTest-Pin.jpg" width="400" /></a></div>
<br />
<br />
모듈에 있는 ST(self-test)핀으로 이 기능을 제어한다.<br />
<br />
ST핀이 3.3V에 연결되어 있으면 내부적으로 가속도계에 정전력이 가해진다. 이로 인해 사용자는 가속도 센서가 정상적으로 동작하는지 확인할 수 있다.<br />
<br />
이로 인한 출력의 변화는 다음과 같다.<br />
<br />
<ul>
<li>X축으로 -1.08g (-325mV)</li>
<li>Y축으로 +1.08g (+325mV)</li>
<li>Z축으로 +1.83g (+550mV)</li>
</ul>
<br />
정상동작시 ST핀은 오픈시켜 놓거나 GND에 연결해주면 된다.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
ㅇ <br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com3tag:blogger.com,1999:blog-6762236726539517408.post-44392909183880239482019-04-19T13:13:00.001+09:002019-04-19T13:13:24.084+09:00ESP32 딥슬립과 깨어나기 (ESP32 Deep Sleep & Wake-up source)<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: left;">
Original document : <a href="https://lastminuteengineers.com/esp32-deep-sleep-wakeup-sources/">ESP32 Deep Sleep & Wake-up Source </a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg93DI2ezfjKC537-wBWfJx9xaeR9VMHUOAacG-1lllgOJGxOZFaM-br2GPdGaWjDaQthdLlFqGWz3-05OuWkMv2b3tncoJ8OokrOjHTay19bg5HLXc6cAp7a4ApI_xLvhPORsqI3Sc_zA/s1600/Tutorial-For-ESP32-Deep-Sleep-Wakeup-Sources.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="436" data-original-width="763" height="365" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg93DI2ezfjKC537-wBWfJx9xaeR9VMHUOAacG-1lllgOJGxOZFaM-br2GPdGaWjDaQthdLlFqGWz3-05OuWkMv2b3tncoJ8OokrOjHTay19bg5HLXc6cAp7a4ApI_xLvhPORsqI3Sc_zA/s640/Tutorial-For-ESP32-Deep-Sleep-Wakeup-Sources.png" width="640" /></a></div>
<h3>
</h3>
<h3>
ESP32에서 deep sleep이 왜 필요할까?</h3>
<br />
어떤 상태에 있는가에 따라 ESP32는 상대적으로 전력소모가 큰 디바이스가 될 수도 있다. 일반적인 동작시 약 75mA 정도의 전류를 소비하지만 WiFi로 데이터를 전송하는 경우는 240mA 정도까지 소비하게 된다.<br />
<br />
개발하는것이
외부 아답터를 사용하는 경우라면 전력소모에 대해 별로 신경 쓰지 않겠지만 배터리로 동작하는 경우라면 수 mA라도 크게 신경을
써야 한다. 이 문제의 해결책으로 deep sleep 모드롤 활용해 ESP32의 전력 사용을 줄여줄 수 있다.<br />
<br />
ESP32의 다른 슬립모드에 대한 자세한 내용은 이전 포스트를 참조하면 된다.<br />
<br />
<h3>
ESP32 Deep Sleep</h3>
Deep Sleep 모드에서는 CPU, 대부분의 RAM과 모든 디지털 페리페럴의 전원이 꺼진다. 전원이 공급되는 부분은 RTC controller, RTC 페리페럴(ULP 코프로세서를 포함), RTC 메모리(slow & fast) 뿐이다.<br />
<br />
ULP를 사용하는 경우 약 0.15mA, ULP도 꺼져있는 경우 약 10uA의 전류를 소비한다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEc33R1gIV8UXU0f0qCQqCWu41cp6xCHl3LUX1H-qBU-5ZhnvseSbB-esOlrhFZC33L-1NKPD_4W1_ZNt85RVskdHqvWjaTqjjW2UaUmeWBXgdVXmDtbxLh9BebkAlxhmuLc2HotNq4jg/s1600/ESP32-Deep-Sleep-Functional-Block-Diagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="391" data-original-width="696" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEc33R1gIV8UXU0f0qCQqCWu41cp6xCHl3LUX1H-qBU-5ZhnvseSbB-esOlrhFZC33L-1NKPD_4W1_ZNt85RVskdHqvWjaTqjjW2UaUmeWBXgdVXmDtbxLh9BebkAlxhmuLc2HotNq4jg/s1600/ESP32-Deep-Sleep-Functional-Block-Diagram.png" /></a></div>
<br />
<br />
Deep Sleep mode동안 메인 CPU는 전원이 꺼져 있지만 ULP 코프로세서가 센서 값을 읽어 측정된 값에 따라 메인
시스템을 깨울 수 있다. 이런 sleep pattern은 ULP sensor-monitored pattern이라고 한다.<br />
<br />
CPU뿐 아니고 칩의 메인 메모리도 전원이 꺼지기 때문에 메모리에 저장된 모든 내용은 사라지고 억세스 할 수 없다.<br />
<br />
하지만 RTC 메모리는 전원이 유지되기 때문에 deep sleep mode에서도 내용이 유지되고 메인 프로세서가 깨어난 다음에
내용을 읽을 수 있다. 그렇기 때문에 ESP32가 WiFi와 블루투스를 끄기 전에 연결 데이터를 RTC 메모리에 저장하는 것이다.<br />
<br />
그러므로 리부팅 후에 데이터를 사용하려면 전역변수를 선언할 때 RTC_DATA_ATTR attribute를 사용해 RTC 메모리에
저장해야 한다. 예를 들어 RTC_DATA_ATTR int bootCount = 0; 같이 해 주면 된다.<br />
<br />
Deep Sleep mode에서는 RTC 모듈을 제외한 칩 전체의 전원이 꺼지기 때문에 RTC recovery memory에 들어
있지 않은 내용은 모두 사라지고 RESET으로 칩을 재시작한다. 즉 프로그램 실행은 다시 한번 맨 처음부터 다시 시작하게 된다는
의미이다.<br />
<br />
* TIP<br />
ESP32는 deep sleep에서 깨어날 때 deep sleep wake stub을 실행하는걸 지원한다. 이 함수는 칩이
깨어나자 마자 다른 어떤 코드 (정상적인 초기화 또는 부트로더 코드)보다 먼저 곧바로 실행된다. Wake stub 이 실행된 후에
칩은 sleep mode로 돌아가거나 또는 정상적으로 시작할 수 있다.<br />
<br />
다른 sleep mode와 달리 시스템이 deep sleep mode로는 자동으로 들어갈 수 없다. Wake-up 소스를 설정한 후
esp_deep_sleep_start() 함수를 호출하면 곧바로 deep sleep mode로 들어가게 된다.<br />
<br />
기본적으로 ESP32는 wake-up 소스에 필요 없는 모든 페리페럴의 전원을 자동으로 꺼 버리지만 옵션으로 모든 페리페럴들애 대해 전원을 끌지 여부를 결정할 수도 있다.<br />
<br />
<br />
<h3>
ESP32 Deep Sleep Wake-up Sources</h3>
여러가지 방법으로 Deep Sleep mode에서 깨어나게 할 수 있다.<br />
<br />
<ul>
<li>Timer</li>
<li>Touch pad</li>
<li>External wakeup (ext0 & ext1)</li>
</ul>
Wake-up source는 여러개를 동시에 사용할 수도 있다. 이 경우 여러개의 소스 중 하나가 트리거되면 칩이 깨어나게 된다.<br />
<br />
이 소스들은 sleep modㄷ로 들어가기 전에 아무때나 설정할 수 있다.<br />
<br />
* 주의<br />
아무 Wake-up source를 설정하지 않고 deep sleep 모드로 들어갈 수도 있는데, 이 경우 칩은 외부에서 리셋을 시켜주기 전에는 무한히 deep sleep mode에 있게 된다.<br />
<br />
<h3>
ESP32 Wake-up Source : Timer</h3>
RTC controller는 타이머를 내장하고 있어 정해진 시간 후에 칩을 깨울 수 있다.<br />
<br />
시간은 us 단위로 지정하지만 실제 resolution은 선택된 클럭 소스에 따라 결정된다. <br />
<br />
타이머를 사용하는 경우 esp_sleep_enable_timer_wakeup() 함수로 sleep wake-up을 활성화 시킬 수 있다.<br />
<br />
다음은 타이머를 wake-up 소스로 사용하고 리부팅 될 때 마다 사용하기 위해 RTC 메모리에 데이터를 저장하는 가장 기본적인 예제이다.<br />
<br />
<pre class=" language-c"><code class=" language-c">#define uS_TO_S_FACTOR 1000000 <span class="lme-comment">//Conversion factor for micro seconds to seconds</span>
#define TIME_TO_SLEEP 5 <span class="lme-comment">//Time ESP32 will go to sleep (in seconds)</span>
RTC_DATA_ATTR <span class="lme-keyword">int</span> bootCount = <span class="lme-number">0</span>;
<span class="lme-keyword">void</span> <span class="lme-function">setup</span>(){
Serial.<span class="lme-function">begin</span>(<span class="lme-number">115200</span>);
<span class="lme-function">delay</span>(<span class="lme-number">1000</span>); <span class="lme-comment">//Take some time to open up the Serial Monitor</span>
<span class="lme-comment">//Increment boot number and print it every reboot</span>
++bootCount;
Serial.<span class="lme-function">println</span>(<span class="lme-string">"Boot number: "</span> + <span class="lme-function">String</span>(bootCount));
<span class="lme-comment">//Print the wakeup reason for ESP32</span>
<span class="lme-function">print_wakeup_reason</span>();
<span class="lme-comment">//Set timer to 5 seconds</span>
<span class="lme-function">esp_sleep_enable_timer_wakeup</span>(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.<span class="lme-function">println</span>(<span class="lme-string">"Setup ESP32 to sleep for every "</span> + <span class="lme-function">String</span>(TIME_TO_SLEEP) +
<span class="lme-string">" Seconds"</span>);
<span class="lme-comment">//Go to sleep now</span>
<span class="lme-function">esp_deep_sleep_start</span>();
}
<span class="lme-keyword">void</span> <span class="lme-function">loop</span>(){}
<span class="lme-comment">//Function that prints the reason by which ESP32 has been awaken from sleep</span>
<span class="lme-keyword">void</span> <span class="lme-function">print_wakeup_reason</span>(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = <span class="lme-function">esp_sleep_get_wakeup_cause</span>();
<span class="lme-keyword">switch</span>(wakeup_reason)
{
<span class="lme-keyword">case</span> <span class="lme-number">1</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by external signal using RTC_IO"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">2</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by external signal using RTC_CNTL"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">3</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by timer"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">4</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by touchpad"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">5</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by ULP program"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">default</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup was not caused by deep sleep"</span>); <span class="lme-keyword">break</span>;
}
}</code></pre>
<br />
<h3>
ESP32 Wake-up Source : Touch Pad</h3>
RTC IO 모듈은 터치센서 인터럽트가 발생할 때 wake-up 시키는 회로를 가지고 있다.<br />
<br />
칩이 deep sleep모드로 들어가기 전에 touch pad interrupt를 설정해 줘야 한다.<br />
<br />
이 wake-up source를 활성화 하려면 esp_sleep_enable_touchpad_wakeup() 함수를 사용한다.<br />
<br />
다음은 touch pad를 wake-up 소스로 사용하고 리부팅 될 때 마다 사용하기 위해 RTC 메모리에 데이터를 저장하는 가장 기본적인 예제이다.<br />
<br />
<pre class=" language-c"><code class=" language-c"><span class="lme-comment">//Define touch sensitivity. Greater the value, more the sensitivity.</span>
#define Threshold 40
RTC_DATA_ATTR <span class="lme-keyword">int</span> bootCount = <span class="lme-number">0</span>;
touch_pad_t touchPin;
<span class="lme-keyword">void</span> <span class="lme-function">callback</span>(){
<span class="lme-comment">//placeholder callback function</span>
}
<span class="lme-keyword">void</span> <span class="lme-function">setup</span>(){
Serial.<span class="lme-function">begin</span>(<span class="lme-number">115200</span>);
<span class="lme-function">delay</span>(<span class="lme-number">1000</span>);
<span class="lme-comment">//Increment boot number and print it every reboot</span>
++bootCount;
Serial.<span class="lme-function">println</span>(<span class="lme-string">"Boot number: "</span> + <span class="lme-function">String</span>(bootCount));
<span class="lme-comment">//Print the wakeup reason for ESP32 and touchpad too</span>
<span class="lme-function">print_wakeup_reason</span>();
<span class="lme-function">print_wakeup_touchpad</span>();
<span class="lme-comment">//Setup interrupt on Touch Pad 3 (GPIO15)</span>
<span class="lme-function">touchAttachInterrupt</span>(T3, callback, Threshold);
<span class="lme-comment">//Configure Touchpad as wakeup source</span>
<span class="lme-function">esp_sleep_enable_touchpad_wakeup</span>();
<span class="lme-comment">//Go to sleep now</span>
<span class="lme-function">esp_deep_sleep_start</span>();
}
<span class="lme-keyword">void</span> <span class="lme-function">loop</span>(){}
<span class="lme-comment">//Function that prints the reason by which ESP32 has been awaken from sleep</span>
<span class="lme-keyword">void</span> <span class="lme-function">print_wakeup_reason</span>(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = <span class="lme-function">esp_sleep_get_wakeup_cause</span>();
<span class="lme-keyword">switch</span>(wakeup_reason)
{
<span class="lme-keyword">case</span> <span class="lme-number">1</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by external signal using RTC_IO"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">2</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by external signal using RTC_CNTL"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">3</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by timer"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">4</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by touchpad"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">5</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by ULP program"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">default</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup was not caused by deep sleep"</span>); <span class="lme-keyword">break</span>;
}
}
<span class="lme-comment">//Function that prints the touchpad by which ESP32 has been awaken from sleep</span>
<span class="lme-keyword">void</span> <span class="lme-function">print_wakeup_touchpad</span>(){
touch_pad_t pin;
touchPin = <span class="lme-function">esp_sleep_get_touchpad_wakeup_status</span>();
<span class="lme-keyword">switch</span>(touchPin)
{
<span class="lme-keyword">case</span> <span class="lme-number">0</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Touch detected on GPIO 4"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">1</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Touch detected on GPIO 0"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">2</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Touch detected on GPIO 2"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">3</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Touch detected on GPIO 15"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">4</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Touch detected on GPIO 13"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">5</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Touch detected on GPIO 12"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">6</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Touch detected on GPIO 14"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">7</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Touch detected on GPIO 27"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">8</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Touch detected on GPIO 33"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">9</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Touch detected on GPIO 32"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">default</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup not by touchpad"</span>); <span class="lme-keyword">break</span>;
}
}</code></pre>
<br />
<h3>
ESP32 Wake-up Source : External Wake-up</h3>
ESP32를 Deep Sleep에서 깨어나게 해 주는 두가지 타입의 외부 트리거가 있다.<br />
<ul>
<li>ext0 - 특정 핀에 의해서만 칩을 wake-up 하고 싶을 때 사용</li>
<li>ext1 - 여러 버튼으로 wake-up 하고 싶을 때 사용</li>
</ul>
<h4>
ext0 External Wake-up Source</h4>
RTC controller는 특정 핀이 미리 지정된 로직 레벨로 될 때 wake-up 시키는 회로를 가지고 있다. 여기에는 RTC GPIO 핀들 (0, 2, 4, 12~15, 25~27, 32~39) 중에 하나를 사용할 수 있다.<br />
<br />
이 wake-up source를 활성화 시키려면 esp_sleep_enable_ext0_wakeup(GPIO_PIN, LOGIC_LEVEL) 함수를 사용한다. 이 함수는 두개의 파라미터가 필요하다. 첫번째는 어떤 핀을 사용할 것인가이고 두번째는 핀 상태가 어떨 때 (HIGH 또는 LOW) wake-up 시킬까를 결정한다.<br />
<br />
ext0는 wake-up을 위해 RTC IO를 사용하기 때문에 이 wake-up source를 사용ㅎ면 deep sleep 동안에도 RTC 페리페럴에 전원이 공급된다.<br />
<br />
이 모드에서 RTC IO 모듈이 활성화 되어 있으므로 내부 pull-up/down 역시 사용할 수 있다. 이 경우 esp_sleep_start()를 호출하기 전에 어플리케이션에서 rtc_gpio_pullup_en(), rtc_gpio_pulldown_en() 함수를 사용해 설정해 줘야 한다.<br />
<br />
아래는 푸쉬버튼을 ext0 wake-up source로 동작시키기 위해 어떻게 연결했는가를 보여주는 회로도이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkzRPeW9iKVjrhhuX8rJstmSJJaSqangqpcnHJK0E-fxAjrBKSxaKggkzxCjth09QN-MZqRRdZ9O-Uj9NBmiYiElqBx84i98taXJwOt8IhSi_L2DJbcFCmoEbXkoqp9sMi_KziM2KZE9I/s1600/Connecting-Button-to-ESP32-for-ext0-External-Wakeup-Source.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="255" data-original-width="450" height="362" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkzRPeW9iKVjrhhuX8rJstmSJJaSqangqpcnHJK0E-fxAjrBKSxaKggkzxCjth09QN-MZqRRdZ9O-Uj9NBmiYiElqBx84i98taXJwOt8IhSi_L2DJbcFCmoEbXkoqp9sMi_KziM2KZE9I/s640/Connecting-Button-to-ESP32-for-ext0-External-Wakeup-Source.png" width="640" /></a></div>
<br />
<br />
다음은 ext0를 wake-up source로 사용하는 가장 기초적인 예제 코드이다.<br />
<br />
<pre class=" language-c"><code class=" language-c">RTC_DATA_ATTR <span class="lme-keyword">int</span> bootCount = <span class="lme-number">0</span>;
<span class="lme-keyword">void</span> <span class="lme-function">setup</span>(){
Serial.<span class="lme-function">begin</span>(<span class="lme-number">115200</span>);
<span class="lme-function">delay</span>(<span class="lme-number">1000</span>);
<span class="lme-comment">//Increment boot number and print it every reboot</span>
++bootCount;
Serial.<span class="lme-function">println</span>(<span class="lme-string">"Boot number: "</span> + <span class="lme-function">String</span>(bootCount));
<span class="lme-comment">//Print the wakeup reason for ESP32</span>
<span class="lme-function">print_wakeup_reason</span>();
<span class="lme-comment">//Configure GPIO33 as ext0 wake up source for HIGH logic level</span>
<span class="lme-function">esp_sleep_enable_ext0_wakeup</span>(GPIO_NUM_33,<span class="lme-number">1</span>);
<span class="lme-comment">//Go to sleep now</span>
<span class="lme-function">esp_deep_sleep_start</span>();
}
<span class="lme-keyword">void</span> <span class="lme-function">loop</span>(){}
<span class="lme-comment">//Function that prints the reason by which ESP32 has been awaken from sleep</span>
<span class="lme-keyword">void</span> <span class="lme-function">print_wakeup_reason</span>(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = <span class="lme-function">esp_sleep_get_wakeup_cause</span>();
<span class="lme-keyword">switch</span>(wakeup_reason)
{
<span class="lme-keyword">case</span> <span class="lme-number">1</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by external signal using RTC_IO"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">2</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by external signal using RTC_CNTL"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">3</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by timer"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">4</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by touchpad"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">5</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by ULP program"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">default</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup was not caused by deep sleep"</span>); <span class="lme-keyword">break</span>;
}
}</code></pre>
<br />
<h4>
ext1 External Wake-up Source</h4>
ESP32는 여러개의 GPIO 핀을 사용해 deep sleep mode에서 깨어나게 할 수도 있다. 이 경우 RTC GPIO핀들 (32~39)을 사용할 수 있다.<br />
<br />
ext1 wake-up source는 RTC controller를 사용하기 때문에 RTC 페리페럴이나 RTC 메모리를 켜 줄 필요가 없다. 즉 내부 pull-up/down 저항을 사용할 수 없다.<br />
<br />
내부 pull-up/down 저항을 사용하려면 deep sleep동안 RTC 페리페럴이 켜져 있도록 요청하고 sleep에 들어가기 전에 rtc_gpio_ 함수들을 사용해 pull-up/down 저항을 설정해 줘야 한다. <br />
<br />
이 wake-up source를 활성화 시키려면 esp_sleep_enable_ext1_wakeup(BUTTON_PIN_MASK, LOGIC_LEVEL) 함수를 사용한다. 이 함수는 두개의 파라미터가 필요하다. 첫번째는 ESP32에게 어떤 핀들을 사용할지 알려주는 pin mask이다.<br />
<br />
두번째는 핀 상태가 어떨 때 (HIGH 또는 LOW) wake-up 시킬까를 결정한다.<br />
<br />
<ul>
<li>ESP_EXT1_WAKEUP_ANY_HIGH - 선택된 핀들 중 어느 하나가 HIGH일 때 wake-up</li>
<li>ESP_EXT1_WAKEUP_ANY_LOW - 선택된 핀들 중 어느 하나가 LOW일 때 wake-up</li>
</ul>
PIN MASK를 이해하는 가장 쉬운 방법은 바이너리 형태로 써 보는 것이다.<br />
<br />
<br />
<br />
<br />
<ul>
<li>0 - masked pin. 즉 이 핀은 외부 인터럽트 소스로 사용하지 않음 </li>
<li>1 - wake-up source로 활성화 된 핀</li>
</ul>
LSB가 GPIO0을 나타내고 MSB가 GPIO39를 나타낸다.<br />
<br />
만일 어떤 GPIO핀도 wake-up source로 사용하고 싶지 않으면 모든 위치에 '0'을 써 넣으면 된다.<br />
<br />
아래는 여러개의 푸쉬버튼을 ext1 wake-up source로 동작시키기 위해 어떻게 연결했는가를 보여주는 회로도이다.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjjwYsXcp2PowXp9jLOWW78XiDqjqoiqXyhGGsV4ej31_83tlMTKH8MRTe2DUA8qW4AWebz6P1ZYq39cP1KEYKq8eHu3AlcfiH3bON_5u87RlFu2Ws_4XsqeSYIQcEcVSuRY1luzxp6e4/s1600/Connecting-Multiple-Buttons-to-ESP32-for-ext1-External-Wakeup-Source.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="254" data-original-width="455" height="356" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjjwYsXcp2PowXp9jLOWW78XiDqjqoiqXyhGGsV4ej31_83tlMTKH8MRTe2DUA8qW4AWebz6P1ZYq39cP1KEYKq8eHu3AlcfiH3bON_5u87RlFu2Ws_4XsqeSYIQcEcVSuRY1luzxp6e4/s640/Connecting-Multiple-Buttons-to-ESP32-for-ext1-External-Wakeup-Source.png" width="640" /></a></div>
<br />
<br />
다음은 ext1을 wake-up source로 사용하는 가장 기초적인 예제 코드이다.<br />
<br />
<pre class=" language-c"><code class=" language-c"><span class="lme-comment">//Pushbuttons connected to GPIO32 & GPIO33</span>
#define BUTTON_PIN_BITMASK 0x300000000
RTC_DATA_ATTR <span class="lme-keyword">int</span> bootCount = <span class="lme-number">0</span>;
<span class="lme-keyword">void</span> <span class="lme-function">setup</span>(){
Serial.<span class="lme-function">begin</span>(<span class="lme-number">115200</span>);
<span class="lme-function">delay</span>(<span class="lme-number">1000</span>);
<span class="lme-comment">//Increment boot number and print it every reboot</span>
++bootCount;
Serial.<span class="lme-function">println</span>(<span class="lme-string">"Boot number: "</span> + <span class="lme-function">String</span>(bootCount));
<span class="lme-comment">//Print the wakeup reason for ESP32</span>
<span class="lme-function">print_wakeup_reason</span>();
<span class="lme-comment">//Configure GPIO32 & GPIO33 as ext1 wake up source for HIGH logic level</span>
<span class="lme-function">esp_sleep_enable_ext1_wakeup</span>(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);
<span class="lme-comment">//Go to sleep now</span>
<span class="lme-function">esp_deep_sleep_start</span>();
}
<span class="lme-keyword">void</span> <span class="lme-function">loop</span>(){}
<span class="lme-comment">//Function that prints the reason by which ESP32 has been awaken from sleep</span>
<span class="lme-keyword">void</span> <span class="lme-function">print_wakeup_reason</span>(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = <span class="lme-function">esp_sleep_get_wakeup_cause</span>();
<span class="lme-keyword">switch</span>(wakeup_reason)
{
<span class="lme-keyword">case</span> <span class="lme-number">1</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by external signal using RTC_IO"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">2</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by external signal using RTC_CNTL"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">3</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by timer"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">4</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by touchpad"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">case</span> <span class="lme-number">5</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup caused by ULP program"</span>); <span class="lme-keyword">break</span>;
<span class="lme-keyword">default</span> : Serial.<span class="lme-function">println</span>(<span class="lme-string">"Wakeup was not caused by deep sleep"</span>); <span class="lme-keyword">break</span>;
}
}</code></pre>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com11tag:blogger.com,1999:blog-6762236726539517408.post-22622095516058599122019-04-19T12:16:00.000+09:002019-04-19T12:21:41.398+09:00ESP32의 슬립모드와 전력소모 (ESP32 Sleep modes and their power consumption)Original document : <a href="https://lastminuteengineers.com/esp32-sleep-modes-power-consumption/">Insight into ESP32 Sleep Modes & Their Power Consumption</a> <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdheABDnYENziS1SyRkI_ZvyOMVHqr3jDrPjmHHLLZb5wQu9aEk34pM4D24ZbKXj3Fd1JjSbpLJ5xmsLLw8fVW_33JUj3W_Wh7QozuiS5OxQsmQ8Jq9lBW90O1ZsydZwgeneStv77ROXc/s1600/Tutorial-ESP32-Sleep-Modes-Modem-Sleep-Light-Sleep-Deep-Sleep-Hibernation-Their-Power-Consumption.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="436" data-original-width="763" height="364" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdheABDnYENziS1SyRkI_ZvyOMVHqr3jDrPjmHHLLZb5wQu9aEk34pM4D24ZbKXj3Fd1JjSbpLJ5xmsLLw8fVW_33JUj3W_Wh7QozuiS5OxQsmQ8Jq9lBW90O1ZsydZwgeneStv77ROXc/s640/Tutorial-ESP32-Sleep-Modes-Modem-Sleep-Light-Sleep-Deep-Sleep-Hibernation-Their-Power-Consumption.png" width="640" /></a></div>
<br />
<h3>
Inside ESP32 chip </h3>
ESP32의 전력관리에 대해 이해하기 위해 먼저 ESP32 칩 내부의 구조를 알 필요가 있다. 아래 그림은 ESP32 칩 내부의 기능별 블록 다이어그램이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBtoD5nFp2p-PM25HFo2-g2OtHjtG3qoAiKA8HFRBRCcErsNXjvHXgVuoDeYPSjd49UX_2-oq7cjk0IExbBBK6XhegwsbyfGfAkgLOljX6AK4UtS4EvIHauM26oIcW8UbuLmAkRbQP9xs/s1600/Block-Diagrams.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="374" data-original-width="374" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBtoD5nFp2p-PM25HFo2-g2OtHjtG3qoAiKA8HFRBRCcErsNXjvHXgVuoDeYPSjd49UX_2-oq7cjk0IExbBBK6XhegwsbyfGfAkgLOljX6AK4UtS4EvIHauM26oIcW8UbuLmAkRbQP9xs/s1600/Block-Diagrams.png" /></a></div>
<br />
<br />
ESP32칩에는 듀얼코어 32-bit 마이크로프로세서와 448KB의 ROM, 520KB의 SRAM과 4MB의 플래쉬가 들어 있다.<br />
<br />
또한 WiFI, Bluetooth, Cryptographic accelerator, RTC 및 다양한 페리페럴을 가지고 있다.<br />
<br />
<h3>
ESP32 Power Modes</h3>
<br />
ESP32의 전력 관리 모드로는 다음의 5가지가 있다. <br />
<ul>
<li>Active mode</li>
<li>Modem Sleep mode</li>
<li>Light Sleep mode</li>
<li>Deep Sleep mode</li>
<li>Hibernation mode</li>
</ul>
각 모드별로 서로 다른 특징과 소비전력 절약 기능을 가지고 있다. 각 모드에 대해 하나씩 확인해 보자.<br />
<br />
<h3>
Active mode</h3>
일반적으로 사용하는 모드이다. 이 모드에서는 칩의 모든 기능이 활성화 된다.<br />
<br />
액티브 모드에서는 칩의 모든 기능(WiFi, 프로세서 코어, 블루투스 등)을 켜 놓기 때문에 동작시 240mA 이상의 전류를 소모할 수 있다. 또한 WiFi와 블루투스를 동시에 사용하는 경우 순간적으로 최대 790mA까지 전류를 소모하는 경우도 있음을 주의해야 한다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6umxVpI-TATMJ3Ha2u6rOLalcLNofkrE0OJK_Guxutmqhq_FKm_AnDTKrGWwB-d8OmfMdsuAxI2vkajZWLl9ajiNazZo_m0dlG1ptLZHmNhB3OPHoGyRSGVU9pI1FY-VtYUask19eKas/s1600/ESP32-Active-Mode-Functional-Block-Diagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="391" data-original-width="696" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6umxVpI-TATMJ3Ha2u6rOLalcLNofkrE0OJK_Guxutmqhq_FKm_AnDTKrGWwB-d8OmfMdsuAxI2vkajZWLl9ajiNazZo_m0dlG1ptLZHmNhB3OPHoGyRSGVU9pI1FY-VtYUask19eKas/s1600/ESP32-Active-Mode-Functional-Block-Diagram.png" /></a></div>
<br />
<br />
ESP32 데이터쉬트를 보면 액티브 모드에서 RF가 동작시 전력소모는 다음과 같다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMQmfM5RNVhXT75rAmv9i8XluDfnQbb9DZj6qDrP-ylirpS2t2fLbGK393kr3s5ARR6xhtnXv_fnGzU7_5sWyvas-3S5Elk8AEZx2b46bLrgiHJkn-ui8jUED3IN6s8fwMLphQ5JvQxMg/s1600/Insight_Into_ESP32_Sleep_Modes___Their_Power_Consumption.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="220" data-original-width="747" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMQmfM5RNVhXT75rAmv9i8XluDfnQbb9DZj6qDrP-ylirpS2t2fLbGK393kr3s5ARR6xhtnXv_fnGzU7_5sWyvas-3S5Elk8AEZx2b46bLrgiHJkn-ui8jUED3IN6s8fwMLphQ5JvQxMg/s640/Insight_Into_ESP32_Sleep_Modes___Their_Power_Consumption.png" width="640" /></a></div>
<br />
<br />
확실히 가장 많은 전류를 소비하는 비효율적인 모드이다. 그러므로 전력소모를 줄이고 싶으면 기능을 사용하지 않는 경우 적절한 다른 전력 모드로 스위칭 해 필요없는 기능을 비활성화시켜 줘야만 한다.<br />
<br />
<h3>
Modem Sleep mode</h3>
이 모드에서는 WiFi, 블루투스, RF를 제외한 모든 부분이 활성화 된다. 이 모드에서 slow speed라면 약 3mA, high speed라면 약 20mA 정도의 전류를 소비한다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisB6vmljMnWio7HiyOHWLORUIPuhyphenhyphensdHtChdVme3Fy_oZE3vq0gnn2snJdqM3x0czTUPjRetTIZlqCwCwRWcaLOvM6Ym1LL9uaAC1Y57rqP4okuTN20i0L57tDJTXRF4CqkuSjVHdMBoc/s1600/ESP32-Modem-Sleep-Functional-Block-Diagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="391" data-original-width="696" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisB6vmljMnWio7HiyOHWLORUIPuhyphenhyphensdHtChdVme3Fy_oZE3vq0gnn2snJdqM3x0czTUPjRetTIZlqCwCwRWcaLOvM6Ym1LL9uaAC1Y57rqP4okuTN20i0L57tDJTXRF4CqkuSjVHdMBoc/s1600/ESP32-Modem-Sleep-Functional-Block-Diagram.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
WiFI/블루투스 연결을 유지하려면 CPU, WiFi, 블루투스, RF가 Association Sleep pattern이라는 미리 지정된 간격으로 깨어나야 한다.<br />
<br />
이 sleep pattern동안 전원 모드는 active mode와 modem sleep mode를 왔다갔다 해야 한다.<br />
<br />
ESP32가 스테이션 모드에서 공유기에 연결되었을 때만 modem sleep 모드에 들어갈 수 있다. 이 경우 DTIM beacon mechanism을 통해 공유기 연결을 유지한다.<br />
<br />
전력 소비를 줄이기 위해 ESP32는 DTIM beacon interval 사이에는 WiFi 모듈을 비활성화 시키고 다음번 Beacon interval이 돌아오기 전에 자동으로 깨어나게 한다.<br />
<br />
Sleep time은 공유기의 DTIM Beacon interval time에 의해 결정되는되 일반적으로 100ms ~ 1000ms 정도 된다.<br />
<br />
<h3>
Light Sleep mode</h3>
Light sleep mode는 modem sleep mode와 비슷하고 association sleep pattern도 따른다. 차이점은 디지털 페리페럴, 대부분의 RAM, CPU가 clock-gated가 된다.<br />
<br />
<br />
Light Sleep mode동안 CPU는 클럭펄스를 꺼 버림으로서 pause되지만 RTC와 ULP 코프로세서는 활성화 되어 있다. 그러므로 modem sleep mode보다도 더 전력소모를 줄여 약 0.8mA 정도의 전류를 소모한다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC05CGzXbgLQ6cLnTfnAw8So23bXAGlrg-ys6UHq-mZdxVkOboIITzqWwC4X3le9BuYJqKmK2Fsw-VB_YbiJTf-QT32Y5aonV4JCGLQnZqcrQ2n3aZKwqYfAskY2MTigL8AT8IOsnVs8c/s1600/ESP32-Light-Sleep-Functional-Block-Diagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="391" data-original-width="696" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC05CGzXbgLQ6cLnTfnAw8So23bXAGlrg-ys6UHq-mZdxVkOboIITzqWwC4X3le9BuYJqKmK2Fsw-VB_YbiJTf-QT32Y5aonV4JCGLQnZqcrQ2n3aZKwqYfAskY2MTigL8AT8IOsnVs8c/s1600/ESP32-Light-Sleep-Functional-Block-Diagram.png" /></a></div>
<br />
<br />
Light Sleep mode로 들어가기 전에 ESP32는 내부상태를 저장하고 sleep에서 깨어나면 동작을 재개하는데 이를 Full RAM Retention이라 한다.<br />
<br />
Wake-up 소스를 설정한 후 esp_light_sleep_start() 함수를 사용해 light sleep mode로 들어갈 수 있다.<br />
<h3>
Deep Sleep mode </h3>
Deep Sleep mode에서는 CPU, 대부분의 RAM과 모든 디지털 페리페럴이 꺼진다. 전원이 켜져 있는 부분은 RTC 컨트롤러, RTC 페리페럴(ULP 코프로세서를 포함), RTC 메모리 (slow & fast) 뿐이다.<br />
<br />
이 경우 ULP 코프로세서가 켜져 있는 경우 약 0.15mA, 그렇지 않은 경우 10uA 정도의 전류만을 소비한다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2NsZ0Gsie1hIZd7RkF5k_orZ1CDw9Qti99ZVfSGinq3TRjm59a6xyPSDxKlh31fzS7A8MUK640P9E_leCeifEkXLJB2gk5t3VUWS7ZdCKxw5y1QNqSCsZC6BjyJ7COanwL7X1NE8u9z8/s1600/ESP32-Deep-Sleep-Functional-Block-Diagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="391" data-original-width="696" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2NsZ0Gsie1hIZd7RkF5k_orZ1CDw9Qti99ZVfSGinq3TRjm59a6xyPSDxKlh31fzS7A8MUK640P9E_leCeifEkXLJB2gk5t3VUWS7ZdCKxw5y1QNqSCsZC6BjyJ7COanwL7X1NE8u9z8/s1600/ESP32-Deep-Sleep-Functional-Block-Diagram.png" /></a></div>
<br />
<br />
Deep Sleep mode동안 메인 CPU는 전원이 꺼져 있지만 ULP 코프로세서가 센서 값을 읽어 측정된 값에 따라 메인 시스템을 깨울 수 있다. 이런 sleep pattern은 ULP sensor-monitored pattern이라고 한다.<br />
<br />
CPU뿐 아니고 칩의 메인 메모리도 전원이 꺼지기 때문에 메모리에 저장된 모든 내용은 사라지고 억세스 할 수 없다.<br />
<br />
하지만 RTC 메모리는 전원이 유지되기 때문에 deep sleep mode에서도 내용이 유지되고 메인 프로세서가 깨어난 다음에 내용을 읽을 수 있다. 그렇기 때문에 ESP32가 WiFi와 블루투스를 끄기 전에 연결 데이터를 RTC 메모리에 저장하는 것이다.<br />
<br />
그러므로 리부팅 후에 데이터를 사용하려면 전역변수를 선언할 때 RTC_DATA_ATTR attribute를 사용해 RTC 메모리에 저장해야 한다. 예를 들어 RTC_DATA_ATTR int bootCount = 0; 같이 해 주면 된다.<br />
<br />
Deep Sleep mode에서는 RTC 모듈을 제외한 칩 전체의 전원이 꺼지기 때문에 RTC recovery memory에 들어 있지 않은 내용은 모두 사라지고 RESET으로 칩을 재시작한다. 즉 프로그램 실행은 다시 한번 맨 처음부터 다시 시작하게 된다는 의미이다.<br />
<br />
* TIP<br />
ESP32는 deep sleep에서 깨어날 때 deep sleep wake stub을 실행하는걸 지원한다. 이 함수는 칩이 깨어나자 마자 다른 어떤 코드 (정상적인 초기화 또는 부트로더 코드)보다 먼저 곧바로 실행된다. Wake stub 이 실행된 후에 칩은 sleep mode로 돌아가거나 또는 정상적으로 시작할 수 있다.<br />
<br />
다른 sleep mode와 달리 시스템이 deep sleep mode로는 자동으로 들어갈 수 없다. Wake-up 소스를 설정한 후 esp_deep_sleep_start() 함수를 호출하면 곧바로 deep sleep mode로 들어가게 된다.<br />
<br />
기본적으로 ESP32는 wake-up 소스에 필요 없는 모든 페리페럴의 전원을 자동으로 꺼 버리지만 옵션으로 모든 페리페럴들애 대해 전원을 끌지 여부를 결정할 수도 있다.<br />
<br />
<h3>
Hibernation mode</h3>
Deep Sleep mode와 다르게 Hibernation mode는 내부 8MHz 오실레이터와 ULP 코프로세서까지도 전원을 꺼 버린다. RTC recovery 메모리까지도 전원을 꺼 버리기 때문에 hibernation mode에서는 어떤 데이터도 보관할 수 없다.<br />
<br />
Slow clock상의 RTC timer와 일부 RTC GPIO만 활성화 되어 있고 나머지는 모두 전원이 꺼진다. 활성화 된 부분이 hibernation mode에서 깨어나는걸 담당한다.<br />
<br />
이 모드는 전력소비를 극단적으로 줄여 약 2.5uA의 전류를 소비한다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZud1SLoWkfIfsJiy6wfNDfUI2ncBNvc8VAPfA2nUKnoxZm6R4c9mvrD18DjC2x7im8zgFjNCehinDkZGuKakkSriHu_8uLiOXNSU0n8fJZBzPcdIF26bq8iGeLGZ5VQ_hUV8j2FdsHzA/s1600/ESP32-Hibernation-Mode-Functional-Block-Diagram.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="391" data-original-width="696" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZud1SLoWkfIfsJiy6wfNDfUI2ncBNvc8VAPfA2nUKnoxZm6R4c9mvrD18DjC2x7im8zgFjNCehinDkZGuKakkSriHu_8uLiOXNSU0n8fJZBzPcdIF26bq8iGeLGZ5VQ_hUV8j2FdsHzA/s1600/ESP32-Hibernation-Mode-Functional-Block-Diagram.png" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-1021563654961233372019-04-12T11:27:00.000+09:002019-04-12T11:27:26.489+09:00ESP32에서 멀티코어 사용하기 (Use multicore on ESP32)ESP32는 2개의 Xtensa 32-bit LX6 마이크로 프로세서 코어를 가지고 있다. 아두이노 IDE에서 코드를 실행하면 디폴토로 코어 1에서 실행된다. 여기서는 태스크를 만들어 두번째 코어에서 코드를 실행하는 방법을 설명한다. 그렇게 하면 두개의 코어에서 동시에 코드를 실행해서 멀티태스킹을 할 수 있다. <br /><br />코드가 어느 코어에서 실행되고 있는가를 확인하려면 <span style="font-family: "Courier New", Courier, monospace;">xPortGetCoreID()</span> 함수를 사용하면 된다.<br /><br />아래의 간단한 테스크 코드를 실행시켜 보면 setup(), loop() 함수 모두 코어 1에서 실행되는걸 확인할 수 있다.<br /><br /><span style="font-family: "Courier New", Courier, monospace;">void setup()<br />{<br /> Serial.begin(115200);<br /> Serial.print("* setup() is running on core ");<br /> Serial.println(xPortGetCoreID());<br />}<br /><br />void loop()<br />{<br /> Serial.print("* loop() is running on core ");<br /> Serial.println(xPortGetCoreID());<br /> delay(100);<br />}</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3OdwupKcFj04xpC4pjSiSvhpoZfZ9P5X419zhp_RPRrigpsKyPMZOne9awHbrbFFS9Rfrqu0JvyJMFCsfRWske2-gapY_5G_wdYlrwOZYo5jIxGU80EUXnVfP0WQMQS99l4Qrx14Wxu4/s1600/_dev_cu_SLAB_USBtoUART.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="361" data-original-width="520" height="444" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3OdwupKcFj04xpC4pjSiSvhpoZfZ9P5X419zhp_RPRrigpsKyPMZOne9awHbrbFFS9Rfrqu0JvyJMFCsfRWske2-gapY_5G_wdYlrwOZYo5jIxGU80EUXnVfP0WQMQS99l4Qrx14Wxu4/s640/_dev_cu_SLAB_USBtoUART.png" width="640" /></a></div>
<br />
<br />
ESP32를 아두이노 IDE에서 사용할 때 기본적으로 리얼타임 OS인 FreeRTOS를 지원한다. 그러므로 FreeRTOS를 사용하면 여러개의 태스크를 독립적으로 병렬로 실행할 수 있다.<br /><br />태스크는 무언가를 수행하는 코드의 조각이다. 예를 들어 LED를 깜빡이거나 네트웍 통신, 센서 읽기, 센서값을 네트워그로 전송등 다양한 작업을 수행할 수 있다.<br /><br />코드의 특정 부분이 특정 코어에서 실행되도록 할당하려면 태스크를 만들어 줘야 한다. 태스크를 만들 때 우선순위 뿐 아니고 어느 코어에서 실행할지 고를 수 있다. 우선순위는 0에서 시작하고 0이 가장 우선순위가 낮다. 프로세서는 우선순위가 높은 태스크를 먼저 실행한다. <br />
<br />
<br />
<br />
<br /><br />
1. 태스크를 만들려면 먼저 태스크 핸들을 만들어 준다.<br /><br /><span style="font-family: "Courier New", Courier, monospace;">TaskHandle_t Task1;</span><br /><br />2. setup()에서 xTaskCreatePinnedToCore 함수를 사용해 특정 코어에 고정된 태스크를 만들어 준다. <br /><br /><span style="font-family: "Courier New", Courier, monospace;">xTaskCreatePinnedToCore (<br /> Task1code, // 태스크를 구현한 함수<br /> “Task1”, // 태스크 이름<br /> 10000, // 스택 크기 (word단위)<br /> NULL, // 태스크 파라미터<br /> 0, // 태스크 우선순위<br /> &Task1, // 태스크 핸들<br /> 0 ); // 태스크가 실행될 코어</span><br /><br />3. 만들어 진 태스크가 실행할 코드가 들어있는 함수를 만들어 줘야만 한다. 위의 예제에서는 Task1Code 함수를 만들어 줘야 한다. <br /><br /><span style="font-family: "Courier New", Courier, monospace;">void Task1Code( void *param)<br />{<br /> while (1) {<br /> // 태스크 1이 실행할 코드가 들어갈 부분<br /> // 무한루프로 실행됨<br /> }<br />}</span><br /><br />코드가 실행되는 도중 만들어 진 태스크를 삭제하고 싶으면 vTaskDelete() 함수를 사용하면 된다. 이 함수의 파리미터로 지우고자 하는 태스크의 핸들(위의 예제에서는 Task1)을 넘겨준다.<br /><br />
<h3>
<span style="font-size: small;">예제</span></h3>
<br />ESP32의 2번핀에 LED1을, 4번핀에 LED2를 연결하고 두개의 서로 다른 태스크가 각각 LED1은 1000ms마다, LED2는 700ms마다 깜빡이게 만든다. 여기서 Task1은 코어 0에서, Task2는 코어 1에서 실행된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWCi_o6-v8pNZLzyAEJou3dXme-TocfbKXri48RMCU1oZR7QZs3SiBNuwIjoQidgF9tjGsP5_vKgcpR4jxypymCbdeLbYIvlmuDJEsash04nkR1PB9u0NwbzWv9AKgrpVXk2d-qjafdJA/s1600/Untitled_Sketch_fzz_-_Fritzing_-__Breadboard_View_-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="666" data-original-width="559" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWCi_o6-v8pNZLzyAEJou3dXme-TocfbKXri48RMCU1oZR7QZs3SiBNuwIjoQidgF9tjGsP5_vKgcpR4jxypymCbdeLbYIvlmuDJEsash04nkR1PB9u0NwbzWv9AKgrpVXk2d-qjafdJA/s640/Untitled_Sketch_fzz_-_Fritzing_-__Breadboard_View_-2.png" width="536" /></a></div>
<br />
<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">#define LED1 2<br />#define LED2 4<br /><br />TaskHandle_t Task1;<br />TaskHandle_t Task2;<br /><br />void setup()<br />{<br /> Serial.begin(115200);<br /> pinMode(LED1, OUTPUT);<br /> pinMode(LED2, OUTPUT);<br /><br /> xTaskCreatePinnedToCore(<br /> blink1000, // 태스크 함수<br /> "Task1", // 테스크 이름<br /> 10000, // 스택 크기(워드단위)<br /> NULL, // 태스크 파라미터<br /> 1, // 태스크 우선순위<br /> &Task1, // 태스크 핸들<br /> 0); // 실행될 코어<br /><br /> xTaskCreatePinnedToCore(<br /> blink700, // 태스크 함수<br /> "Task2", // 테스크 이름<br /> 10000, // 스택 크기(워드단위)<br /> NULL, // 태스크 파라미터<br /> 1, // 태스크 우선순위<br /> &Task2, // 태스크 핸들<br /> 1); // 실행될 코어<br />}<br /><br />void blink1000 ( void *param )<br />{<br /> Serial.print("# Task 1 running on core ");<br /> Serial.println(xPortGetCoreID());<br /><br /> while (1) {<br /> digitalWrite(LED1, HIGH);<br /> delay(1000);<br /> digitalWrite(LED1, LOW);<br /> delay(1000);<br /> }<br />}<br /><br />void blink700 ( void *param )<br />{<br /> Serial.print("# Task 2 running on core ");<br /> Serial.println(xPortGetCoreID());<br /><br /> while (1) {<br /> digitalWrite(LED2, HIGH);<br /> delay(700);<br /> digitalWrite(LED2, LOW);<br /> delay(700);<br /> }<br />}<br /><br />void loop()<br />{<br />}</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmXrRPZTXjRb-9QyP-jxOuX-qStskbhZJioaHdsvn7IC_r8kilyFGv-vlVrbQg6ECC6MGjWXBpFcn-qt-a2EWmR69_wgFK0Z3mCMoF3edU3CzfaI2Xmjav3lWsXY6XPhDQ5s3_pCb6cYQ/s1600/_dev_cu_SLAB_USBtoUART-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="296" data-original-width="529" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmXrRPZTXjRb-9QyP-jxOuX-qStskbhZJioaHdsvn7IC_r8kilyFGv-vlVrbQg6ECC6MGjWXBpFcn-qt-a2EWmR69_wgFK0Z3mCMoF3edU3CzfaI2Xmjav3lWsXY6XPhDQ5s3_pCb6cYQ/s640/_dev_cu_SLAB_USBtoUART-2.png" width="640" /></a></div>
<br />
<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-10823466152458267532018-11-23T11:32:00.000+09:002018-11-23T11:32:42.988+09:00ESP32에서 SPIFFS 사용하기ESP32는 SPIFFS(Serial Peripheral Interface Flash File System)을 가지고 있다. SPIFFS는 SPI 버스에 연결된 플래쉬 칩을 가지고 있는 ESP32같은 마이크로 컨트롤러를 위해 만들어 진 경랑(lightweight) 파일 시스템이다. <br />
<br />
SPIFFS를 사용하면 플래쉬 메모리를 컴퓨터에서 일반 파일을 억세스 하는 것 처럼 사용할 수 있게 해 준다. 물론 더 간단하지만 기능은 제한적이다. 파일을 읽고, 쓰고, 삭제하는 것이 가능하다. 현재 시점에서는 디렉토리를 지원하지 않으므로 모든 파일은 flat한 구조에 저장된다.<br />
<br />
ESP32 Filesystem Uploader 설치<br />
<br />
아두이노 IDE에서 코드를 작성해 ESP32 파일시스템에 파일을 만들어 내용을 기록해 줄 수 있지만, 이 방법은 파일 내용을 전부 아두이노 스케치 코드에 타이핑 해 줘야만 하므로 유용하지 못하다.<br />
다행히도 아두이노 IDE용 플러그인이 있어 컴퓨터의 폴더에서 ESP32 파일시스템으로 파일을 직접 업로드 할 수가 있다. 이를 위해 ESP32 Filesystem Uploader를 설치해 준다.<br />
<br />
* 먼저 최신 버젼의 아두이노 IDE가 설치되어 있고 아두이노용 ESP32 개발환경이 설정되어 있어야만 한다.<br />
<br />
1. <a href="https://github.com/me-no-dev/arduino-esp32fs-plugin/releases/">Arduino-esp32fs-plugin 페이지</a>에서 <a href="https://github.com/me-no-dev/arduino-esp32fs-plugin/releases/download/v0.1/ESP32FS-v0.1.zip">ESP32FS-v01.zip</a> 을 다운받는다.<br />
2. 아두이노 IDE 디렉토리로 가서 Tools 폴더를 연다.<br />
맥의 경우는 ~/Documents/Arduino 폴더 안에 tools 폴더를 만들어 주면 된다. <br />
3. tools 폴더에서 다운받은 zip 파일 압축을 풀어준다.<br />
4. 아두이노 IDE를 재시동한다.<br />
5. 아두이노 IDE의 Tools 메뉴에 "ESP32 Sketch Data Upload" 항목이 보이면 정상적으로 설치가 된 것이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCSLNUBodJfSMLB47Owpx4KCnKL188MbE9MA0rqMbDbi-GF9NxD1Td9RQGRqtt-dLBCXfwHbjvcfB8pmHx6hLNJs6uef72fG1Z6GXHQwaMSQexxoi1Vzu0WLp2fDFTsubxapBNFlk8618/s1600/sketch-data-upload.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="391" data-original-width="295" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCSLNUBodJfSMLB47Owpx4KCnKL188MbE9MA0rqMbDbi-GF9NxD1Td9RQGRqtt-dLBCXfwHbjvcfB8pmHx6hLNJs6uef72fG1Z6GXHQwaMSQexxoi1Vzu0WLp2fDFTsubxapBNFlk8618/s640/sketch-data-upload.png" width="482" /></a></div>
<br />
Filesystem Uploader를 사용해서 파일 업로드하기<br />
<br />
1. 아두이노 스케치를 만들어 저장한다. 여기서는 파일 업로드 데모이므로 빈 스케치를 사용한다.<br />
2. 스케치 폴더를 열어 준다. Sketch 메뉴에서 'Show Sketch Folder'를 선택하면 스케치가 저장되어 있는 폴더가 열린다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLZarPvI5aElgwPstXbJq7cndMqGB-4X4aLvHrSoCtDQ45hjBGg89rvyd5KowZfDjwxvAZPRftfk1tIHW8lguDa5bnC5tpa8sJOKX0sn1iczdWwusLUK5V1U_iElvCSLXlG-8B-OzGpFw/s1600/show-sketch-folder.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="241" data-original-width="486" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLZarPvI5aElgwPstXbJq7cndMqGB-4X4aLvHrSoCtDQ45hjBGg89rvyd5KowZfDjwxvAZPRftfk1tIHW8lguDa5bnC5tpa8sJOKX0sn1iczdWwusLUK5V1U_iElvCSLXlG-8B-OzGpFw/s640/show-sketch-folder.png" width="640" /></a></div>
<br />
3. 폴더 안에 data 라는 이름의 폴더를 만들어 준다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdzdmgmt2D6xMgAUkG56IsTQyWGBZH8uR6lVY-PaL7BnKiFMGv7yta4pHCyURKSg8jC0I0d6NTBDYlBEG1AxHmmr8QEpW5fSgirU5OfxApbayeJNV-mlcrtYMBuVn1Dx9JA-hxX-Sy7M4/s1600/data.fodler.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="128" data-original-width="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdzdmgmt2D6xMgAUkG56IsTQyWGBZH8uR6lVY-PaL7BnKiFMGv7yta4pHCyURKSg8jC0I0d6NTBDYlBEG1AxHmmr8QEpW5fSgirU5OfxApbayeJNV-mlcrtYMBuVn1Dx9JA-hxX-Sy7M4/s1600/data.fodler.png" /></a></div>
<br />
4. data 폴더 안에 ESP32 파일시스템에 저장하고 싶은 파일들을 넣어주면 된다. 여기서는 예제로 test_example.txt 라는 파일을 만들어 간단한 내용을 넣어 준다.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCfhhC0lIpoyUTgbs73_7peTeR1zs_7p2zw_j0bnyfwCzwaBMT7W0cKbNh1LMMFB8HmyJTUl_UmlwYqGPsG2xzSrVO6wD2QBQg04flqAM8E0QSznehbdX1CCdMyKuvZxDV_Hfn9fiosxU/s1600/text_txt.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="172" data-original-width="575" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCfhhC0lIpoyUTgbs73_7peTeR1zs_7p2zw_j0bnyfwCzwaBMT7W0cKbNh1LMMFB8HmyJTUl_UmlwYqGPsG2xzSrVO6wD2QBQg04flqAM8E0QSznehbdX1CCdMyKuvZxDV_Hfn9fiosxU/s640/text_txt.png" width="640" /></a></div>
<br />
5. Tools -> ESP32 Sketch Data Upload 를 선택해서 데이터를 업로드 하면 된다.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2QBFykMDd5-gM4rFTKV2RuKwbqbpr8hYbcgi6Qth06hncsL5zkpN5kPJxssWQPlXYrqk3pwl01ovDUDfp7QJZhw9u6YZujD6rfRFJjfXqcnAKrwI2pTQZpIfuMHPr_uOcr0K7jGMQ6o4/s1600/sketch-data-upload.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="391" data-original-width="295" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2QBFykMDd5-gM4rFTKV2RuKwbqbpr8hYbcgi6Qth06hncsL5zkpN5kPJxssWQPlXYrqk3pwl01ovDUDfp7QJZhw9u6YZujD6rfRFJjfXqcnAKrwI2pTQZpIfuMHPr_uOcr0K7jGMQ6o4/s640/sketch-data-upload.png" width="482" /></a></div>
<br />
<br />
예제<br />
<br />
1. ESP32_SPIFFS_test 라는 이름으로 스케치를 만들고 스케치 폴더 내에 data 폴더를 만들어 준다.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSF9PhIfQv67M9JRQjI99Osk40rslTlvbNF9dcaeopJw_95AgngTJAFguhAJjPNvwhpptWhGdQf9tI-Vf64FlsRdOI3AFdCIqRxj6OvMrxMx42fnVBEvQzuFqz0UjaLQWbkxNZTr-SEf4/s1600/ESP32_SPIFFS_test.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="193" data-original-width="438" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSF9PhIfQv67M9JRQjI99Osk40rslTlvbNF9dcaeopJw_95AgngTJAFguhAJjPNvwhpptWhGdQf9tI-Vf64FlsRdOI3AFdCIqRxj6OvMrxMx42fnVBEvQzuFqz0UjaLQWbkxNZTr-SEf4/s640/ESP32_SPIFFS_test.png" width="640" /></a></div>
<br />
2. 데이터 폴더 안에 'data.txt'라는 이름의 텍스트 파일을 만들고 간단한 내용을 넣어 준다. 여기서는 'Hello World!'를 넣어주었다.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV69R6xzm66BoE1w4pBTbwRzXnV3Jj-Ld3cWmO2hCwTWO4PdwAUOaQfouzh34En2LKqYMAxt7WaaVe43qSzXx99MAiU7Td78eXU1StlVpYadtl2zTL7t_PYgr-2Q79qPMe5mFdWBchmy0/s1600/data_txt_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_data_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_Blogger__%25E1%2584%2580%25E1%2585%25B5%25E1%2584%2589%25E1%2585%25AE%25E1%2586%25AF_%25E1%2584%258B%25E1%2585%25A7%25E1%2584%2592%25E1%2585%25A2%25E1%2586%25BC%25E1%2584%258C%25E1%2585%25A1__ArsViator__-_Edit_post_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_cv2_VideoWriter_Python_Example.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="353" data-original-width="513" height="440" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV69R6xzm66BoE1w4pBTbwRzXnV3Jj-Ld3cWmO2hCwTWO4PdwAUOaQfouzh34En2LKqYMAxt7WaaVe43qSzXx99MAiU7Td78eXU1StlVpYadtl2zTL7t_PYgr-2Q79qPMe5mFdWBchmy0/s640/data_txt_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_data_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_Blogger__%25E1%2584%2580%25E1%2585%25B5%25E1%2584%2589%25E1%2585%25AE%25E1%2586%25AF_%25E1%2584%258B%25E1%2585%25A7%25E1%2584%2592%25E1%2585%25A2%25E1%2586%25BC%25E1%2584%258C%25E1%2585%25A1__ArsViator__-_Edit_post_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_cv2_VideoWriter_Python_Example.png" width="640" /></a></div>
<br />
3. 위의 설명대로 SPIFFS에 파일을 업로드 해 준다.<br />
<br />
4. 다음의 스케치 코드를 입력해서 보드에 업로드 해 준다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">#include "SPIFFS.h"<br /><br />void setup() {<br /> Serial.begin(115200);<br /><br /> if (!SPIFFS.begin(true)) {<br /> Serial.println("# ERROR: can not mount SPIFFS");<br /> while (1) ;<br /> }<br />}<br /><br />void loop() {<br /> File f = SPIFFS.open("/data.txt");<br /> if (!f) { // can not open file<br /> Serial.println("# ERROR: can not open file");<br /> delay(5000);<br /> return;<br /> }<br /><br /> while (f.available()) {<br /> Serial.write(f.read());<br /> }<br /> Serial.println("");<br /><br /> f.close();<br /> delay(5000);<br />}</span><br />
<br />
5. 실행 결과는 다음과 같다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWrOmef8IwimnhST1A7ddHV4eGZiO-m5JGRKkUmZOIWVIx7EjSKOPJTTGgA8fM52_fh30LzbArRfn47MnZG7smy13_x72oaqEwCnXQikL2wJ6n_zma416qo0Bd0_IjTWfVkocvGiaHTus/s1600/_dev_cu_SLAB_USBtoUART.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="276" data-original-width="534" height="330" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWrOmef8IwimnhST1A7ddHV4eGZiO-m5JGRKkUmZOIWVIx7EjSKOPJTTGgA8fM52_fh30LzbArRfn47MnZG7smy13_x72oaqEwCnXQikL2wJ6n_zma416qo0Bd0_IjTWfVkocvGiaHTus/s640/_dev_cu_SLAB_USBtoUART.png" width="640" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-51332818312462122692018-11-22T15:39:00.001+09:002018-11-22T15:39:38.656+09:00ESP32에서 인터럽트 사용하기ESP32는 26개의 GPIO핀을 인터럽트 소스로 사용할 수 있다.<br />
<br />
* 아두이노 우노/메가에서는 인터럽트 소스로 사용할 수 있는 핀이 몇개 안된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyujJ8098Migojp_0uEDqGsg-cjeGjTnUxtBPzcsHKG42-oMEbjWiJU00RNzAr_9EoiFnR5MA835oQ4_YhoK2dP7SrXhT5vuNm81qI4pR14X5DKoy21fDjAoy_EvjbMTjeYF-YgU2utrI/s1600/Arduino_Reference.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="386" data-original-width="860" height="286" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyujJ8098Migojp_0uEDqGsg-cjeGjTnUxtBPzcsHKG42-oMEbjWiJU00RNzAr_9EoiFnR5MA835oQ4_YhoK2dP7SrXhT5vuNm81qI4pR14X5DKoy21fDjAoy_EvjbMTjeYF-YgU2utrI/s640/Arduino_Reference.png" width="640" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGGwQpOZ-ZJ-nhl1-mfFpGKoI5RyNzvNX8oPeIn2dLOAYkPisl6y1JS7NuMwjXmDRAC8EVYTYsk8idr7WBiZkSKHgILPfzqjJ4sZ8VGkz53xJL5C-bpHCafltZ9vHFSKvLCxMiqluB5Cs/s1600/ESP32-DOIT-DEVKIT-V1-Board-Pinout-36-GPIOs-updated-2-2-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="508" data-original-width="342" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGGwQpOZ-ZJ-nhl1-mfFpGKoI5RyNzvNX8oPeIn2dLOAYkPisl6y1JS7NuMwjXmDRAC8EVYTYsk8idr7WBiZkSKHgILPfzqjJ4sZ8VGkz53xJL5C-bpHCafltZ9vHFSKvLCxMiqluB5Cs/s640/ESP32-DOIT-DEVKIT-V1-Board-Pinout-36-GPIOs-updated-2-2-2.jpg" width="430" /></a></div>
<br />
위의 그림에서 빨간색 사각형 안에 들어있는 GPIO 핀들이 인터럽트 소스로 사용 가능한 핀이다.<br />
<br />
아두이노에서 인터럽트를 사용하려면 attachInterrupt() 함수로 인터럽트를 설정해 줘야 한다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">attachInterrupt (digitalPinToInterrupt(GPIO), function, mode);</span><br />
<br />
첫번째 파라미터는 인터럽트 소스로 사용할 GPIO 핀 번호인데 번호를 그냥 사용하지 말고 digitalPinToInterrupt(GPIO) 로 넣어줘야 한다. 예를 들어 GPIO 13을 인터럽트 소스로 사용하려면 digitalPinToInterrupt(13) 을 넣어주면 된다.<br />
<br />
두번째 파라미터는 인터럽트가 발생했을 때 호출될 함수(Interrupt Service Routine)의 이름이다.<br />
<br />
세번째 파라미터는 인터럽트 발생 조건이다. 총 5가지 모드중에 하나를 선택하면 된다.<br />
<br />
* LOW - 인터럽트 핀 상태가 LOW면 인터럽트가 발생<br />
* HIGH - 인터럽트 핀 상태가 HIGH면 인터럽트가 발생<br />
* CHANGE - 인터럽트 핀 상태가 바뀌면 인터럽트가 발생. 즉 HIGH에서 LOW로 바뀌거나, LOW에서 HIGH로 바뀌면 인터럽트가 발생<br />
* FALLING - 인터럽트 핀 상태가 HIGH에서 LOW로 바뀔 때 인터럽트가 발생<br />
* RISING - 인터럽트 핀 상태가 LOW에서 HIGH로 바뀔 때 인터럽트가 발생<br />
<br />
그러므로 인터럽트를 사용하는 경우 코드의 구조는 다음과 같이 된다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">// 인터럽트가 발생하면 이 함수가 호출됨 </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">void <span style="color: red;">IRAM_ATTR</span> intSvc() </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // 스위치가 눌렸을 때 원하는 동작 코드를 이 부분에 넣어줌 </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println("# Button pressed"); </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">} </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">void setup()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ...</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> attachInterrupt(digitalPinToInterrupt(13), intSvc, LOW); // GPIO13번 핀에 연결된 스위치가 눌리면 인터럽트가 발생해 intSvc 함수를 호출하도록 설정 </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ... </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">} </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">void loop()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
위의 코드를 잘 보면 인터럽트가 발생했을 때 호출될 함수 선언에 IRAM_ATTR 이라는 것이 추가되어 있는것을 알 수 있을 것이다. IRAM_ATTR을 넣어줘야 인터럽트 처리 함수가 RAM에 들어가게 된다. IRAM_ATTR이 없으면 인터럽트 처리 함수가 플래쉬에 들어가게 되어 실행 속도가 느려진다. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfJrvzQ_KsmHrh9uJy8uOHu1jLhjBLx84IU4m2hhmAKU3_ftGV8NMiRFLdnYFd0Hs8lpq-_uRGqbOMOQ6UXn5-yXBq3bt5t0dSKFbA_ABI9KmqMIHeNdNZ9-C30-iCXV6eH7VUUNd_u-M/s1600/Untitled_Sketch_fzz_-_Fritzing_-__Breadboard_View_.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="830" data-original-width="808" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfJrvzQ_KsmHrh9uJy8uOHu1jLhjBLx84IU4m2hhmAKU3_ftGV8NMiRFLdnYFd0Hs8lpq-_uRGqbOMOQ6UXn5-yXBq3bt5t0dSKFbA_ABI9KmqMIHeNdNZ9-C30-iCXV6eH7VUUNd_u-M/s640/Untitled_Sketch_fzz_-_Fritzing_-__Breadboard_View_.png" width="622" /></a></div>
<br />
위와 같이 연결 해 놓고 스위치를 누를 때 마다 LED가 토글되는 코드는 다음과 같다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">#define LED 25</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#define SW 13</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">volatile boolean gLedState = LOW;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">void IRAM_ATTR toggle() </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> gLedState = !gLedState;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(LED, gLedState); <br />} </span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">void setup()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> pinMode(SW, INPUT_PULLUP);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> attachInterrupt(digitalPinToInterrupt(SW), toggle, LOW); // GPIO13번 핀에 연결된 스위치가 눌리면 toggle 함수를 호출하도록 설정 </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> pinMode(LED, OTUPUT);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">} </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">void loop()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
<br />
<br />
<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-22612674524106245462018-11-20T12:39:00.001+09:002018-11-20T14:07:02.549+09:00ESP32 PWM 사용하기ESP32에는 16개의 독립적인 LED PWM 채널을 가지고 있어 각각 다른 속성의 PWM 신호를 만들어 낼 수 있다.<br />
<br />
1. 어떤 PWM 채널을 사용할 지 골라야 한다. 0~15 사이의 값을 사용할 수 있다.<br />
2. PWM 주파수를 설정해 줘야 한다. LED의 경우 5000 Hz 정도면 충분하다.<br />
3. PWM duty cycle resolution을 설정해 줘야 한다. 해상도(resolution)은 1비트에서 16비트까지 지정할 수 있다. 여기서는 8 bit 해상도를 사용하는데 그 경우 LED 밝기 값은 0에서 255가 될 수 있다. 만일 16 bit로 설정하면 좀 더 세밀하게 (0~65535) 밝기 값을 조정할 수 있게 된다.<br />
<br />
ledcSetup(ch, freq, resolution); // ch: PWM channel (0~15), freq: PWM 주파수, resolution: PWM 해상도<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitMrB3qTol5cMpNE4HDtVLDAdv_w5h2zk0Duv2a3lk69HGejhQm41Esb0CsA3cnGzYDW2vGx6GKgDcRPui7FSR6A5vSH0uBtpWmGtC7fUIw1ntBW5T2rDNg-gN19MC0EK5yz5x_F1puAI/s1600/%25E1%2584%2586%25E1%2585%25AE%25E1%2584%258C%25E1%2585%25A6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="261" data-original-width="1600" height="104" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitMrB3qTol5cMpNE4HDtVLDAdv_w5h2zk0Duv2a3lk69HGejhQm41Esb0CsA3cnGzYDW2vGx6GKgDcRPui7FSR6A5vSH0uBtpWmGtC7fUIw1ntBW5T2rDNg-gN19MC0EK5yz5x_F1puAI/s640/%25E1%2584%2586%25E1%2585%25AE%25E1%2584%258C%25E1%2585%25A6.png" width="640" /></a></div>
<br />
PWM 주파수는 1초에 몇번 신호를 ON/OFF 할 것인지 결정한다. 위의 그림에서 처럼 PWM 주파수를 4 Hz로 한다면 CH0에 연결되어 있는 LED는 4번 on/off를 반복할 것이다. 8 Hz인 경우 CH1에 연결되어 있는 LED는 8번 on/off를 하게 될 것이다. 아두이노 우노의 경우 PWM 주파수는490 Hz(5,6번 핀은 980 Hz)로 고정되어 있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirJtdMaTAQVRR_gLNlm4gnjtGiPY8atEHYajPBHbWECglNi2vFZe8LoDzNCi6TDykvhJnf9jemh0T4yHbLfZloYXXg-IME12cQwHplnGFxrKUNTZFDIFoI8P4VY7ikEmSiKp1FKE3tKAQ/s1600/%25E1%2584%2586%25E1%2585%25AE%25E1%2584%258C%25E1%2585%25A6-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="472" data-original-width="1600" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirJtdMaTAQVRR_gLNlm4gnjtGiPY8atEHYajPBHbWECglNi2vFZe8LoDzNCi6TDykvhJnf9jemh0T4yHbLfZloYXXg-IME12cQwHplnGFxrKUNTZFDIFoI8P4VY7ikEmSiKp1FKE3tKAQ/s640/%25E1%2584%2586%25E1%2585%25AE%25E1%2584%258C%25E1%2585%25A6-2.png" width="640" /></a></div>
Resolution은 한 주기 내에서 얼마나 세밀하게 시간을 지정할 수 있는가를 결정한다. 8-bit resolution인 경우 2^8 = 256 등분으로 나누지만 10-bit resolution이 되면 2^10 = 1024 등분으로 나뉘어 훨씬 더 정밀하게 제어가 가능해진다. ESP32에서는 1-bit 부터 16-bit까지 resolution을 지정할 수 있다. 아두이노 우노의 경우에는 analogWrite()의 resolution은 8-bit로 고정되어 있어 출력값으로 0~255 사이의 값을 사용해야 한다.<br />
<br />
4. 설정한 채널의 출력을 어느 GPIO 핀으로 보낼것인지 지정해야 한다. <br />
<br />
ledcAttachPin(gpio, ch); // gpio : GPIO 핀 번호, ch : PWM channel<br />
<br />
5. 이제 ledcWrite() 함수를 사용해 LED 밝기를 조절할 수 있다.<br />
<br />
ledcWrite(ch, duty); // ch : PWM channel, duty : Duty cycle<br />
<br />
duty 값은 한 주기 내에서 ON 시간과 OFF 시간의 비율을 결정하는 값이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhW9EfpkB8fiXKwXqtNdO44_KCxvnR0LQupkKFH8TCiUPhK2Ls0Ct5De0rcVRhLWJroe8Pd_m-xXImAj7IIS_VtVScf2ahfpw7WOuhgj0eia1QOI9n4MK_6tBwDZTvhae_dgvwKt46mXG8/s1600/%25E1%2584%2586%25E1%2585%25AE%25E1%2584%258C%25E1%2585%25A6-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="301" data-original-width="1600" height="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhW9EfpkB8fiXKwXqtNdO44_KCxvnR0LQupkKFH8TCiUPhK2Ls0Ct5De0rcVRhLWJroe8Pd_m-xXImAj7IIS_VtVScf2ahfpw7WOuhgj0eia1QOI9n4MK_6tBwDZTvhae_dgvwKt46mXG8/s640/%25E1%2584%2586%25E1%2585%25AE%25E1%2584%258C%25E1%2585%25A6-3.png" width="640" /></a></div>
<br />
위의 그림을 보면 알 수 있듯이 PWM 주파수가 다르면 같은 duty 값이라도 ON 되어 있는 시간이 달라진다. 다만 전체적으로 ON 시간의 합과 OFF 시간의 합의 비율은 동일하다. <br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwvik_lNSxZjcPZbBpdInB3qRqHJmWxPGF65q9pT0VsPX5JeMwYWPiS5WBkZ49jWUx9Scdkfg4OwpOCVVYmL2IF-bfKyyJjHSXq4HmVPMPr38q-xdN2xXnzqBqXyfHGV5TqPyhDsB7s4E/s1600/LED_PWM_Example.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="440" data-original-width="700" height="402" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwvik_lNSxZjcPZbBpdInB3qRqHJmWxPGF65q9pT0VsPX5JeMwYWPiS5WBkZ49jWUx9Scdkfg4OwpOCVVYmL2IF-bfKyyJjHSXq4HmVPMPr38q-xdN2xXnzqBqXyfHGV5TqPyhDsB7s4E/s640/LED_PWM_Example.jpg" width="640" /></a></div>
<br />
<br />
위와 같이 LED를 연결한 경우 LED가 점점 밝아졌다가 다시 점점 어두워지는걸 반복하는 코드는 다음과 같다.<br />
<br />
<pre class="prettyprint"><span style="font-family: "courier new" , "courier" , monospace;"><span class="kwd"><span class="kwd">const</span></span><span class="pln"><span class="pln"> </span></span><span class="kwd"><span class="kwd">int</span></span><span class="pln"><span class="pln"> ledPin </span></span><span class="pun"><span class="pun">=</span></span><span class="pln"><span class="pln"> </span></span><span class="lit"><span class="lit">16</span></span><span class="pun"><span class="pun">;</span></span><span class="pln"><span class="pln"> </span></span><span class="com"><span class="com">// 16 corresponds to GPIO16</span></span><span class="pln"><span class="pln">
</span></span><span class="com"><span class="com">// setting PWM properties</span></span><span class="pln"><span class="pln">
</span></span><span class="kwd"><span class="kwd">const</span></span><span class="pln"><span class="pln"> </span></span><span class="kwd"><span class="kwd">int</span></span><span class="pln"><span class="pln"> freq </span></span><span class="pun"><span class="pun">=</span></span><span class="pln"><span class="pln"> </span></span><span class="lit"><span class="lit">5000</span></span><span class="pun"><span class="pun">;</span></span><span class="pln"><span class="pln">
</span></span><span class="kwd"><span class="kwd">const</span></span><span class="pln"><span class="pln"> </span></span><span class="kwd"><span class="kwd">int</span></span><span class="pln"><span class="pln"> ledChannel </span></span><span class="pun"><span class="pun">=</span></span><span class="pln"><span class="pln"> </span></span><span class="lit"><span class="lit">0</span></span><span class="pun"><span class="pun">;</span></span><span class="pln"><span class="pln">
</span></span><span class="kwd"><span class="kwd">const</span></span><span class="pln"><span class="pln"> </span></span><span class="kwd"><span class="kwd">int</span></span><span class="pln"><span class="pln"> resolution </span></span><span class="pun"><span class="pun">=</span></span><span class="pln"><span class="pln"> </span></span><span class="lit"><span class="lit">8</span></span><span class="pun"><span class="pun">;</span></span></span></pre>
<pre class="prettyprint"><span class="pun"><span class="pun"> </span></span><span class="pln"><span class="pln">
</span></span></pre>
<span style="font-family: "courier new" , "courier" , monospace;"></span><br />
<pre class="prettyprint"><span style="font-family: "courier new" , "courier" , monospace;"><span class="kwd"><span class="kwd">void</span></span><span class="pln"><span class="pln"> setup</span></span><span class="pun"><span class="pun">(){</span></span><span class="pln"><span class="pln"></span></span><span class="com"><span class="com"></span></span><span class="pln"><span class="pln">
ledcSetup</span></span><span class="pun"><span class="pun">(</span></span><span class="pln"><span class="pln">ledChannel</span></span><span class="pun"><span class="pun">,</span></span><span class="pln"><span class="pln"> freq</span></span><span class="pun"><span class="pun">,</span></span><span class="pln"><span class="pln"> resolution</span></span><span class="pun"><span class="pun">); </span></span></span><span style="font-family: "courier new" , "courier" , monospace;"><span class="pun"><span class="pun"></span></span><span class="pln"><span class="pln">
<span style="font-family: "courier new" , "courier" , monospace;"><span class="pln"><span class="pln"></span></span><span class="com"><span class="com">// configure LED PWM functionalitites</span></span></span> </span></span><span class="pln"><span class="pln">
ledcAttachPin</span></span><span class="pun"><span class="pun">(</span></span><span class="pln"><span class="pln">ledPin</span></span><span class="pun"><span class="pun">,</span></span><span class="pln"><span class="pln"> ledChannel</span></span><span class="pun"><span class="pun">); </span></span></span><span style="font-family: "courier new" , "courier" , monospace;"><span class="pun"><span class="pun"></span></span><span class="pln"><span class="pln">
<span style="font-family: "courier new" , "courier" , monospace;"><span class="pln"><span class="pln"> </span></span><span class="com"><span class="com">// attach the channel to the GPIO to be controlled</span></span><span class="pln"><span class="pln">
</span></span></span></span></span><span class="pun"><span class="pun">}</span></span><span class="pln"><span class="pln">
</span></span><span class="kwd"><span class="kwd">void</span></span><span class="pln"><span class="pln"> loop</span></span><span class="pun"><span class="pun">(){</span></span><span class="pln"><span class="pln">
</span></span><span class="com"><span class="com">// increase the LED brightness</span></span><span class="pln"><span class="pln">
</span></span><span class="kwd"><span class="kwd">for</span></span><span class="pun"><span class="pun">(</span></span><span class="kwd"><span class="kwd">int</span></span><span class="pln"><span class="pln"> dutyCycle </span></span><span class="pun"><span class="pun">=</span></span><span class="pln"><span class="pln"> </span></span><span class="lit"><span class="lit">0</span></span><span class="pun"><span class="pun">;</span></span><span class="pln"><span class="pln"> dutyCycle </span></span><span class="pun"><span class="pun"><=</span></span><span class="pln"><span class="pln"> </span></span><span class="lit"><span class="lit">255</span></span><span class="pun"><span class="pun">;</span></span><span class="pln"><span class="pln"> dutyCycle</span></span><span class="pun"><span class="pun">++){</span></span><span class="pln"><span class="pln">
</span></span><span class="com"><span class="com">// changing the LED brightness with PWM</span></span><span class="pln"><span class="pln">
ledcWrite</span></span><span class="pun"><span class="pun">(</span></span><span class="pln"><span class="pln">ledChannel</span></span><span class="pun"><span class="pun">,</span></span><span class="pln"><span class="pln"> dutyCycle</span></span><span class="pun"><span class="pun">);</span></span><span class="pln"><span class="pln">
delay</span></span><span class="pun"><span class="pun">(</span></span><span class="lit"><span class="lit">15</span></span><span class="pun"><span class="pun">);</span></span><span class="pln"><span class="pln">
</span></span><span class="pun"><span class="pun">}</span></span><span class="pln"><span class="pln">
</span></span><span class="com"><span class="com">// decrease the LED brightness</span></span><span class="pln"><span class="pln">
</span></span><span class="kwd"><span class="kwd">for</span></span><span class="pun"><span class="pun">(</span></span><span class="kwd"><span class="kwd">int</span></span><span class="pln"><span class="pln"> dutyCycle </span></span><span class="pun"><span class="pun">=</span></span><span class="pln"><span class="pln"> </span></span><span class="lit"><span class="lit">255</span></span><span class="pun"><span class="pun">;</span></span><span class="pln"><span class="pln"> dutyCycle </span></span><span class="pun"><span class="pun">>=</span></span><span class="pln"><span class="pln"> </span></span><span class="lit"><span class="lit">0</span></span><span class="pun"><span class="pun">;</span></span><span class="pln"><span class="pln"> dutyCycle</span></span><span class="pun"><span class="pun">--){</span></span><span class="pln"><span class="pln">
</span></span><span class="com"><span class="com">// changing the LED brightness with PWM</span></span><span class="pln"><span class="pln">
ledcWrite</span></span><span class="pun"><span class="pun">(</span></span><span class="pln"><span class="pln">ledChannel</span></span><span class="pun"><span class="pun">,</span></span><span class="pln"><span class="pln"> dutyCycle</span></span><span class="pun"><span class="pun">);</span></span><span class="pln"><span class="pln">
delay</span></span><span class="pun"><span class="pun">(</span></span><span class="lit"><span class="lit">15</span></span><span class="pun"><span class="pun">);</span></span><span class="pln"><span class="pln">
</span></span><span class="pun"><span class="pun">}</span></span><span class="pln"><span class="pln">
</span></span><span class="pun"><span class="pun">}</span></span></span></pre>
<br />
PWM 신호의 frequency를 조정할 수 있으므로 16개의 서보모터를 동시에 제어할 수도 있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNEPucdw28onKF9Y0UZZu0ZQvzQlvqOGUyEl00km_02jS9ABBJo2XKJKeUrwZOSsrUlI_cxQ0TUWSiz7iZyh81U0-Ex1goE4V7-o2KCtN29fvC-Qzsy5fbyEI8dbJQqtkfNKtspHnAtz0/s1600/servo_signal-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="367" data-original-width="468" height="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNEPucdw28onKF9Y0UZZu0ZQvzQlvqOGUyEl00km_02jS9ABBJo2XKJKeUrwZOSsrUlI_cxQ0TUWSiz7iZyh81U0-Ex1goE4V7-o2KCtN29fvC-Qzsy5fbyEI8dbJQqtkfNKtspHnAtz0/s640/servo_signal-2.png" width="640" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
서보모터는 위와 같은 PWM 신호로 제어를 하기 때문에 PWM frequency를 50 Hz로 해 주고 16-bit resolution을 사용하는 경우 duty값 3277이 0도, 4915가 90도, 6554가 180도가 된다.<br />
<br />
즉 GPIO16에 연결된 서보모터를 CH0를 사용해서 제어한다고 하면 다음과 같이 할 수 있다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">void setup()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ...</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ledcSetup(0, 50, 16); // PWM CH 0, Freq. 50 Hz, 16-bit resolution</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ledcAttach(16, 0); // PWM CH 0을 GPIO 16번으로 출력</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ...</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">// deg는 0~180도 까지 </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">void servoWrite(int ch, int deg)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> int duty = deg*18.2 + 3277;</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> ledcWrite(ch, duty); </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">void loop()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ...</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> servoWrite(0, 90); // CH 0에 연결된 서보를 90도로 </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ...</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-37750038910658067332018-11-16T16:36:00.001+09:002018-11-16T16:36:47.355+09:00ESP32에서 NTP(Network Time Protocol) 서버로부터 시간 가져오기<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4zg9ZTQFI90VLlzka-odJbNxsD0LfLs63vhmUVHC2a_E9ugi45puZrcIGlS5DNQ_gHTquQkr3Ehu0ECL3PRjvXhH3wTlWhCXlkHXKirbhf97jdPnxFCr4uWltz8ftR1R0a_NSPI1_iEA/s1600/ntp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="290" data-original-width="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4zg9ZTQFI90VLlzka-odJbNxsD0LfLs63vhmUVHC2a_E9ugi45puZrcIGlS5DNQ_gHTquQkr3Ehu0ECL3PRjvXhH3wTlWhCXlkHXKirbhf97jdPnxFCr4uWltz8ftR1R0a_NSPI1_iEA/s1600/ntp.png" /></a></div>
<br />
<br />
인터넷에서 정확한 시간을 알기 위해 사용하는 프로토콜로 NTP(Network Time Protocol)이 있다. 곳곳에 운영중인 NTP서버에 접속해 정확한 현재 날짜와 시간을 가져 올 수 있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2SXL0QLbul-8iUjJ6albdIz5h1k6Z9oKbCS-gj_LINVXElRghANKQQRl9fR2K7iTfSmt0A-uMURY8mxQ6MahR_vp9kBQLL1-ZN11kS84wePYar5DXjIbHwszwIwc5PobMLycJi42RO-E/s1600/stratum.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="686" data-original-width="794" height="552" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2SXL0QLbul-8iUjJ6albdIz5h1k6Z9oKbCS-gj_LINVXElRghANKQQRl9fR2K7iTfSmt0A-uMURY8mxQ6MahR_vp9kBQLL1-ZN11kS84wePYar5DXjIbHwszwIwc5PobMLycJi42RO-E/s640/stratum.png" width="640" /></a></div>
<br />
<br />
ESP32에서도 NTP를 사용할 수 있게 이미 NTP client 라이브러리가 공개되어 있다. <br />
<br />
<a href="https://github.com/taranais/NTPClient/archive/master.zip">Download NTP Client Library</a><br />
<br />
위의 링크를 클릭하면 라이브러리를 다운받아 설치해주면 된다.<br />
<br />
코드 구조는 다음과 같다.<br />
<br />
1. WiFi.h, WiFiUdp.h, NTPClient.h 를 include 해 줘야 한다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">#include <WiFi.h></span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#include <WiFiUdp.h></span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#include <NTPClient.h></span><br />
<br />
2. 인터넷 연결을 위해 공유기 설정을 해 준다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">const char* ssid = "<span style="color: red;"><b>XXXXX</b></span>";</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">const char* password = "<span style="color: red;"><b>YYYYY</b></span>";</span><br />
<br />
위에서 XXXXX 대신 사용할 공유기의 이름(SSID)로, YYYYY 대신 공유기의 암호로 바꿔줘야 한다.<br />
<br />
3. 이제 NTP client를 만들어 준다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">WiFiUdp ntpUDP;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">NTPClient timeClient(ntpUdp);</span><br />
<br />
4. 공유기에 접속한 후 NTP client를 시작한다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">....</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">timeClient.begin();</span><br />
<br />
5. 자신의 timezone에 맞게 시간을 조정하기 위해 setTimeOffset() 메소드를 사용할 수 있는데 이때 offset은 초 단위로 지정해 줘야 한다. 즉 1시간은 3600초이므로 한국의 경우 GMT+9 이니까 3600*9 = 32400이 된다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">timeClient.setTimeOffset(32400);</span><br />
<br />
6. NTP 서버에 요청해 시간을 가져온다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">while (!timeClient.update()) {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> timeClient.forceUpdate();</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
7. NTP 서버에게서 읽어온 값을 사람이 볼 수 있는 형태로 변환해준다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">formattedDate = timeClient.getFormattedDate();</span><br />
<br />
getFormattedDate()가 리턴한 값은 다음과 같은 포맷이다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">2018-11-09<span style="color: red;"><b>T</b></span>07:34:21<span style="color: red;"><b>z</b></span></span><br />
<br />
T 앞쪽이 날짜가 되고 T에서 z까지가 시간이므로 각각을 기준으로 원하는 내용을 추출해서 출력해주면 된다.<br />
<br />
실행 가능한 전체 코드는 다음과 같다. <br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">#include <WiFi.h><br />#include <WiFiUdp.h></span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;">#include <NTPClient.h></span></span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">const char* ssid = "<span style="color: red;"><b>XXXXX</b></span>"; // <b><span style="color: red;">XXXXX</span></b> 를 접속할 공유기 SSID로 변경<br />const char* password = "<span style="color: red;"><b>YYYYY</b></span>" // <span style="color: red;"><b>YYYYY</b></span> 를 접속할 공유기 암호로 변경<br /><br />// Define NTP Client to get time<br />WiFiUDP ntpUDP;<br />NTPClient timeClient(ntpUDP);<br /><br />// Variables to save date and time<br />String formattedDate;<br />String dayStamp;<br />String timeStamp;<br /><br />void setup() {<br /> Serial.begin(115200);<br /> Serial.print("Connecting to ");<br /> Serial.println(ssid);<br /> WiFi.begin(ssid, password);<br /> while (WiFi.status() != WL_CONNECTED) {<br /> delay(500);<br /> Serial.print(".");<br /> }<br /> Serial.println("");<br /> Serial.println("WiFi connected.");<br /> Serial.println("IP address: ");<br /> Serial.println(WiFi.localIP());<br /><br /> timeClient.begin(); // NTP 클라이언트 초기화<br /> // 자신의 timezone에 맞게 초 단위로 time offset을 설정해준다. 예를 들어<br /> // GMT +1 = 3600<br /> // GMT +8 = 28800<br /> // GMT -1 = -3600<br /> // GMT 0 = 0<br /> timeClient.setTimeOffset(32400); // 한국은 GMT+9이므로 9*3600=32400<br />}<br />void loop() {<br /> while(!timeClient.update()) {<br /> timeClient.forceUpdate();<br /> }<br /> // formattedDate 은 다음과 같은 형태임<br /> // 2018-11-12T16:00:13Z<br /> formattedDate = timeClient.getFormattedDate();<br /> Serial.println(formattedDate);<br /><br /> // 날짜 추출<br /> int splitT = formattedDate.indexOf("T");<br /> dayStamp = formattedDate.substring(0, splitT);<br /> Serial.print("DATE: ");<br /> Serial.println(dayStamp);<br /> // 시간 추출<br /> timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);<br /> Serial.print("HOUR: ");<br /> Serial.println(timeStamp);<br /> delay(1000);<br />}</span><br />
<br />
코드의 실행 결과이다. <br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">Connecting to XXXXX</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">.......<br />WiFi connected.<br />IP address: <br />172.20.10.13<br />2018-11-09T08:53:26Z<br />DATE: 2018-11-09<br />HOUR: 08:53:26<br />2018-11-09T08:53:27Z<br />DATE: 2018-11-09<br />HOUR: 08:53:27<br />2018-11-09T08:53:28Z<br />DATE: 2018-11-09<br />HOUR: 08:53:28</span><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com3tag:blogger.com,1999:blog-6762236726539517408.post-84433097828326808162018-11-09T16:06:00.000+09:002018-11-09T16:08:01.867+09:00ESP32에서 터치센서 사용하기 (Using ESP32 Capacitive Touch Sensor)<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeoXuqj9Z7TSpa36z_KnnpnuYSk8DeYSH54y7m3CEehFzMmudxGF8RggiXwK1D1aJfVJv0jhvnuaF52xQmKTnQy3xh5EE_Ck0m6kv7MEQ6O2VwTdkv6RHrPrLOpuCD1Gxp7K0uD3gGxJQ/s1600/ESP32_Touch08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1467" height="348" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeoXuqj9Z7TSpa36z_KnnpnuYSk8DeYSH54y7m3CEehFzMmudxGF8RggiXwK1D1aJfVJv0jhvnuaF52xQmKTnQy3xh5EE_Ck0m6kv7MEQ6O2VwTdkv6RHrPrLOpuCD1Gxp7K0uD3gGxJQ/s640/ESP32_Touch08.png" width="640" /></a></div>
<br />
<br />
이전 포스트(<a href="https://arsviator.blogspot.com/2018/11/esp32-gpio.html">ESP32 GPIO 레퍼런스</a>)에서 소개했던 것 처럼 ESP32에는 총 10개의 터치 센서가 들어 있다. 이를 사용하면 아무런 추가 하드웨어 없이 터치 스위치를 만들 수 있다. 10개 터치 센서의 핀 매핑은 다음과 같다.<br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">static const uint8_t T0 = 4;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">static const uint8_t T1 = 0;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">static const uint8_t T2 = 2;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">static const uint8_t T3 = 15;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">static const uint8_t T4 = 13;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">static const uint8_t T5 = 12;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">static const uint8_t T6 = 14;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">static const uint8_t T7 = 27;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">static const uint8_t T8 = 33;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">static const uint8_t T9 = 32;</span><br />
<br />
사용법 역시 매우 간단하다. 푸쉬버튼을 사용하는 경우 먼저 setup()에서 스위치가 연결된 핀을 pinMode()로 설정을 해 주고 digitalRead()로 상태를 읽어야 하는데 터치의 경우 별도의 설정은 필요 없고 touchRead() 함수로 값을 읽으면 된다.<br />
<br />
아래 예제 코드는 T0 (4번핀)를 터치 스위치로 사용해서 LED를 토글시키는 것이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSzqUKbObGT0Rlz9rFFnnbiGMdiw3UQKcyvu_iBiiYTzT8hv2a2RSWdjO2fwRrDBqJIJG3aL2HWQhyphenhyphentAx_EreyZvk0n2ugX7WaL0wujO_9_NyHk3NqRBeaLJvIPvviXhxYqvgGQ8_6HcA/s1600/%25E1%2584%2580%25E1%2585%25B5%25E1%2584%2589%25E1%2585%25AE%25E1%2586%25AF_%25E1%2584%258B%25E1%2585%25A7%25E1%2584%2592%25E1%2585%25A2%25E1%2586%25BC%25E1%2584%258C%25E1%2585%25A1__ArsViator_.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="566" data-original-width="778" height="464" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSzqUKbObGT0Rlz9rFFnnbiGMdiw3UQKcyvu_iBiiYTzT8hv2a2RSWdjO2fwRrDBqJIJG3aL2HWQhyphenhyphentAx_EreyZvk0n2ugX7WaL0wujO_9_NyHk3NqRBeaLJvIPvviXhxYqvgGQ8_6HcA/s640/%25E1%2584%2580%25E1%2585%25B5%25E1%2584%2589%25E1%2585%25AE%25E1%2586%25AF_%25E1%2584%258B%25E1%2585%25A7%25E1%2584%2592%25E1%2585%25A2%25E1%2586%25BC%25E1%2584%258C%25E1%2585%25A1__ArsViator_.png" width="640" /></a></div>
<br />
<span style="font-family: "courier new" , "courier" , monospace;">#define TOUCH_SW T0 // connected to 4</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#define LED A13 // connected to 15</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">int touchVal = 100;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">void setup()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.begin(115200);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println("ESP32 Touch Example");</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> pinMode(LED, OUTPUT);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">void loop()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> static boolean led_state = LOW;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> static boolean prevState = LOW; </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> static boolean touchState;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> touchVal = touchRead(TOUCH_SW); // read touch switch state</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> touchState = touchVal < 50 ? HIGH:LOW; </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if ((LOW == prevState) && (HIGH == touchState)) {</span><span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println("Switch touched");</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"></span><span style="font-family: "courier new" , "courier" , monospace;"> led_state = !led_state;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> digitalWrite(LED, led_state); </span><span style="font-family: "courier new" , "courier" , monospace;"> </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> } </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> prevState = touchState;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> delay(50); </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
<br />
<br />
<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-22513897705621342632018-11-07T18:11:00.000+09:002018-11-07T18:11:20.336+09:00ESP32 GPIO 레퍼런스 ESP32에는 총 48개의 핀이 있는데 각 핀들은 여러가지 기능을 가지고 있다. 물론 ESP32 개발보드에서 모든 핀을 다 사용할 수 있는것은 아니다. 그래서 여기서는 어떤 핀을 사용해야 하고 어떤 핀을 사용하지 않아야 하는지에 대해 설명하겠다.<br />
<br />
ESP32는 다음과 같은 peripheral을 가지고 있다.<br />
<br />
* 18 ADC(Analog-to-Digital Converter) channel<br />
* 3 SPI<br />
* 3 UART<br />
* 2 I2C<br />
* 16 PWM<br />
* 2 DAC (Digital-to-Analog Converter)<br />
* 2 I2S<br />
* 10 Capacitive sensing GPIO<br />
<br />
ADC와 DAC 기능은 특정 핀에 고정되어 있다. 하지만 UART, I2C, SPI, PWM등의 기능은 어느 핀에 사용할지 결정해서 코드에서 지정해 줘야 한다.<br />
<br />
소프트웨어에서 핀의 속성을 정의해 줄 수 있지만, 각 핀들은 디폴트로 지정되어 있는 기능들이 있다. ESP32 DEVKIT V1-DOIT의 경우 디폴트 핀 배열은 다음과 같다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7xAG0_rrWjLbDZA6dz7ZlIOzEXLZa9lUNLzlJcfxSEcoWtugKWC7FiaCKnBuy8ZchlrDB5zvVB2W-1KeAZ0xtq3hkCa43Uv59ujo1XtQxEfxck4TRAvudw_sIJt6TIIOoyzi21JlNp50/s1600/ESP32-DOIT-DEVKIT-V1-Board-Pinout-36-GPIOs-updated.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="538" data-original-width="750" height="458" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7xAG0_rrWjLbDZA6dz7ZlIOzEXLZa9lUNLzlJcfxSEcoWtugKWC7FiaCKnBuy8ZchlrDB5zvVB2W-1KeAZ0xtq3hkCa43Uv59ujo1XtQxEfxck4TRAvudw_sIJt6TIIOoyzi21JlNp50/s640/ESP32-DOIT-DEVKIT-V1-Board-Pinout-36-GPIOs-updated.jpg" width="640" /></a></div>
<span id="goog_1183283464"></span><span id="goog_1183283465"></span><br />
<br />
<br />
또한 특정한 기능의 핀들은 프로젝트마다 사용하기에 적합할 수도 그렇지 않을 수도 있다.<br />
<br />
아래 그림은 ESP-WROOM-32의 핀 배치이다. 만일 칩만 가지고 자작 보드를 만든다면 아래 그림을 레퍼런스로 삼을 수 있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmjDqDg7T2BPikq08h_EHuIdlWJ-i4L63ItizaG4or4sOGzOomBbNWU18BJ0RyBzSe6jce1tqxlV99MtT2R-fo-V98jMxRCOuWK3dbubfl1irnLViVk8uAoiFAdCbMnDpInZFudFc_YAk/s1600/esp32-pinout-chip-ESP-WROOM-32.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="523" data-original-width="1024" height="326" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmjDqDg7T2BPikq08h_EHuIdlWJ-i4L63ItizaG4or4sOGzOomBbNWU18BJ0RyBzSe6jce1tqxlV99MtT2R-fo-V98jMxRCOuWK3dbubfl1irnLViVk8uAoiFAdCbMnDpInZFudFc_YAk/s640/esp32-pinout-chip-ESP-WROOM-32.png" width="640" /></a></div>
<br />
<br />
<h2>
Input Only Pins</h2>
GPIO 34부터 39까지는 입력 전용 핀이다. 그리고 이 핀들은 내부적으로 풀업/풀다운 저항이 없다. 출력으로 사용할 수 없으므로 입력으로만 사용해야 한다.<br />
<br />
* GPIO 34<br />
* GPIO 35<br />
* GPIO 36<br />
* GPIO 37<br />
* GPIO 38<br />
* GPIO 39<br />
<br />
<h2>
ESP-WROOM-32에 들어 있는 SPI Flash</h2>
일부 보드들은 GPIO 6부터 11까지의 핀도 사용할 수 있게 되어 있다. 하지만 이 핀들은 ESP-WROOM-32 칩에 내장된 SPI Flash에 연결되어 있기 때문에 다른 용도로 사용하는걸 권장하지 않는다.<br />
<br />
* GPIO 6 (SCK/CLK)<br />
* GPIO 7 (SDO/SD0)<br />
* GPIO 8 (SDI/SD1)<br />
* GPIO 9 (SHD/SD2)<br />
* GPIO 10 (SWP/SD3)<br />
* GPIO 11 (CSC/CMD)<br />
<br />
<h2>
Capacitive Touch GPIO (정전식 터치 입력)</h2>
ESP32는 10개의 정전식 터치 입력 센서를 가지고 있다. 이 센서는 사람의 피부 같이 전하를 가진 것들의 전하 변화를 측정할 수 있다. 그러므로 손가락으로 GPIO를 터치할 때 유도되는 변하를 감지할 수 있다. 이 핀들은 전하 패드에 연결해 기계식 버튼을 대치할 수 있다. 정전식 터치 핀은 ESP32를 deep sleep에서 깨어나게 하는데 사용할 수도 있다.<br />
<br />
이 내부 터치 센서는 다음의 GPIO에 연결되어 있다.<br />
<br />
* T0 (GPIO 4) <br />
* T1 (GPIO 0) <br />
* T2 (GPIO 2) <br />
* T3 (GPIO 15) <br />
* T4 (GPIO 13) <br />
* T5 (GPIO 12) <br />
* T6 (GPIO 14) <br />
* T7 (GPIO 27) <br />
* T8 (GPIO 33) <br />
* T9 (GPIO 32) <br />
<br />
<h2>
ADC (Analog-to-Digital Converter)</h2>
ESP32는 18개의 12-bit ADC 채널을 가지고 있다. (ESP8266의 경우는 1개의 10-bit ADC만 가지고 있음) 다음의 GPIO 는 각각 해당 ADC 채널로 사용될 수 있다. <br />
<br />
* ADC1_CH0 (GPIO 36)<br />
* ADC1_CH1 (GPIO 37)<br />
* ADC1_CH2 (GPIO 38)<br />
* ADC1_CH3 (GPIO 39)<br />
* ADC1_CH4 (GPIO 32)<br />
* ADC1_CH5 (GPIO 33)<br />
* ADC1_CH6 (GPIO 34)<br />
* ADC1_CH7 (GPIO 35)<br />
* ADC2_CH0 (GPIO 4)<br />
* ADC2_CH1 (GPIO 0)<br />
* ADC2_CH2 (GPIO 2)<br />
* ADC2_CH3 (GPIO 15)<br />
* ADC2_CH4 (GPIO 13)<br />
* ADC2_CH5 (GPIO 12)<br />
* ADC2_CH6 (GPIO 14)<br />
* ADC2_CH7 (GPIO 27)<br />
* ADC2_CH8 (GPIO 25)<br />
* ADC2_CH9 (GPIO 26)<br />
<br />
ADC 입력 채널은 12-bit 해살도를 가지고 있다. 즉 아날로그 값을 읽으면 0~4095 사이의 값을 얻을 수 있다. 여기서 0은 0V, 4095는 3.3V를 의미한다. 또한 코드에서 각 채널의 해설도나 ADC 범위를 조정할 수도 있다.<br />
<br />
ESP32 ADC 핀은 리니어 한 속성을 가지고 있지 않으므로 주의해야 한다. 0V와 0.1V, 또는 3.2V와 3.3V를 거의 구별하지 못할 것이다. 그러므로 ADC를 사용할 때 이 점을 염두에 두어야만 한다. 아래 그래프와 같은 속성을 가진다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXbRw8KgZzUqtXcsdJu27TzuhqAwrMl5Jd0WHwQS5_J_DnJ-dleAebNwkLxxPl3XnAfGfwe_mPkF3rKTqznS_7F9wSxWKTcu8iCCILMGxmiC33TBJGl7GeVQ-mwRVtshX_IVLnrxwYxPA/s1600/ADC-non-linear-768x474.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="474" data-original-width="768" height="394" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXbRw8KgZzUqtXcsdJu27TzuhqAwrMl5Jd0WHwQS5_J_DnJ-dleAebNwkLxxPl3XnAfGfwe_mPkF3rKTqznS_7F9wSxWKTcu8iCCILMGxmiC33TBJGl7GeVQ-mwRVtshX_IVLnrxwYxPA/s640/ADC-non-linear-768x474.png" width="640" /></a></div>
<br />
<h2>
DAC (Digital-to-Analog Converter)</h2>
ESP32에는 2개의 8-bit DAC 채널이 있어 디지털 신호를 아날로그 전압으로 바꿔 출력해 준다.<br />
<br />
* DAC1 (GPIO 25)<br />
* DAC2 (GPIO 26)<br />
<br />
<h2>
RTC GPIO</h2>
ESP32는 RTC GPIO를 지원한다. ESP32가 deep sleep 모드에 있을 때 RTC의 low-power subsystem에 연결된 GPIO를 사용할 수 있다. 이 RTC GPIO는 ULP(Ultra Low Power) 코프로세서가 실행중일 때 ESP32를 deep sleep에서 깨어나게 하는데 사용된다. 다음의 GPIO들이 외부 wake up 소스로 사용될 수 있다.<br />
<br />
* RTC_GPIO0 (GPIO 36)<br />
* RTC_GPIO3 (GPIO 39)<br />
* RTC_GPIO4 (GPIO 34)<br />
* RTC_GPIO5 (GPIO 35)<br />
* RTC_GPIO6 (GPIO 25)<br />
* RTC_GPIO7 (GPIO 26)<br />
* RTC_GPIO8 (GPIO 33)<br />
* RTC_GPIO9 (GPIO 32)<br />
* RTC_GPIO10 (GPIO 4)<br />
* RTC_GPIO11 (GPIO 0)<br />
* RTC_GPIO12 (GPIO 2)<br />
* RTC_GPIO13 (GPIO 15)<br />
* RTC_GPIO14 (GPIO 13)<br />
* RTC_GPIO15 (GPIO 12)<br />
* RTC_GPIO16 (GPIO 14)<br />
* RTC_GPIO17 (GPIO 27)<br />
<br />
<h2>
PWM (Pulse Width Modulation)</h2>
ESP32 LED PWM controller는 16개의 독립적인 채널을 가지고 있어 각각 다른 속성의 PWM 신호를 만들어 내도록 설정할 수 있다. 출력으로 사용할 수 있는 모든 핀은 PWM 으로 사용할 수 있다. (즉 GPIO 34~39는 PWM을 만들 수 없다)<br />
<br />
PWM 신호를 만들어주려면 코드에서 다음의 파라미터를 정해줘야 한다.<br />
<br />
* Signal Frequency<br />
* Duty Cycle<br />
* PWM Channel<br />
* 신호를 출력할 GPIO핀<br />
<br />
<h2>
I2C</h2>
아두이노 IDE에서 ESP32를 사용할 때는 다음의 디폴트 핀을 사용해야만 한다.<br />
<br />
* GPIO 21 (SDA)<br />
* GPIO 22 (SCL)<br />
<br />
<h2>
SPI</h2>
디폴트로 SPI핀은 다음과 같이 매핑되어 있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr7elhRJk5AMjPa_FIjwHPnJnui0CbSYEgRT2RD9w0M5XV4EE44GFhiQia3mhQUdano3blsH5vcy__QxH2d-95XGgl7lYYvjSEC9dgu9Dn87JFMxz6aZ6JlAIIhxcGNu6Mm2UMBXmQZ1A/s1600/ESP32_Pinout_Reference__Which_GPIO_pins_should_you_use____Random_Nerd_Tutorials.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="219" data-original-width="772" height="181" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr7elhRJk5AMjPa_FIjwHPnJnui0CbSYEgRT2RD9w0M5XV4EE44GFhiQia3mhQUdano3blsH5vcy__QxH2d-95XGgl7lYYvjSEC9dgu9Dn87JFMxz6aZ6JlAIIhxcGNu6Mm2UMBXmQZ1A/s640/ESP32_Pinout_Reference__Which_GPIO_pins_should_you_use____Random_Nerd_Tutorials.png" width="640" /></a></div>
<h2>
Interrupt</h2>
모든 GPIO 핀은 인터럽트로 설정할 수 있다.<br />
<br />
<h2>
Enable (EN)</h2>
Enable (EN)은 3.3V 레귤레이터의 enable 핀이다. 이 핀은 풀업이 되어 있으므로, GND에 연결하면 3.3V 레귤레이터가 비활성화 된다. 즉 이 핀을 푸쉬버튼에 연결해 놓으면 ESP32를 재시동하는데 사용할 수 있다.<br />
<br />
<h2>
GPIO current draw</h2>
ESP32 데이터쉬트에 있는 "권장하는 동작 조건(Recommended Operating Condition)"에 따르면 GPIO마다 최대 40mA의 전류를 흘릴 수 있다.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com1tag:blogger.com,1999:blog-6762236726539517408.post-58998337442767231942018-11-01T13:12:00.000+09:002018-11-01T13:12:24.114+09:00ESP32에 static IP 사용하기 (Using static IP address on ESP32)ESP32를 사용해 무선랜에 접속하는 경우 기본적으로 DHCP를 사용해 IP주소를 받아오게 된다.<br />
하지만 ESP32가 서버로 동작하는 경우 IP주소를 고정시켜 놓아햐 할 필요가 있다. 또한 배터리로 동작시 deep sleep 모드를 활용하게 되는데 이때 deep sleep에서 깨어날 때 마다 공유기에 접속 후 DHCP로 IP를 받아오는 과정을 수행해야 하면 그에 따른 배터리 소모도 무시할 수 없다.<br />
<br />
그래서 ESP32 무선랜이 DHCP를 사용하지 않고 수동으로 IP주소를 설정하는 방법을 설명하겠다.<br />
<br />
DHCP를 사용하건 아니건 공유기에 접속을 해야만 하므로 접속할 공유기 정보(SSID, password) 는 필요하다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">const char * ssid = "<b><span style="color: red;">REPLACE_YOUR_SSID</span></b>";</span><br />
<span style="font-family: "Courier New", Courier, monospace;">const char * pwd = "<b><span style="color: red;">REPLACE_YOUR_PASSWORD</span></b>"; </span><br />
<br />
저기서 빨간색 부분을 자신에게 맞게 바꿔주면 된다. 만일 공유기 이름이 myhome 이고 공유기 암호가 hello12345 라고 한다면 다음과 같이 바뀌게 된다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">const char * ssid = "myhome";</span><br />
<span style="font-family: "Courier New", Courier, monospace;">const char * pwd = "hello12345"; </span><br />
<br />
다음은 static IP 를 지정해 준다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">IPAddress local_IP(<span style="color: red;"><b>192, 168, 1, 200</b></span>); // ESP32가 사용할 IP address</span><br />
<span style="font-family: "Courier New", Courier, monospace;">IPAddress gateway(<b><span style="color: red;">192, 168, 1, 1</span></b>); // Gateway IP address (공유기 IP주소)</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">IPAddress subnet(<span style="color: red;"><b>255, 255, 255, 0</b></span>); // subnet mask</span><br />
<span style="font-family: "Courier New", Courier, monospace;">IPAddress primaryDNS(<span style="color: red;"><b>8, 8, 8, 8</b></span>); // primary DNS server IP address</span><br />
<span style="font-family: "Courier New", Courier, monospace;">IPAddress secondaryDNS(<span style="color: red;"><b>8, 8, 4, 4</b></span>); // secondary DNS server IP address</span><br />
<br />
여기서도 물론 빨간색 부분은 자신의 환경에 맞게 바꿔줘야 한다.<br />
<br />
* 주소 사이에 '.'이 아니고 ','를 사용하고 있음을 주의할 것<br />
<br />
이제 setup() 에서 WiFi.config() 메소드로 위의 설정값들을 ESP32에 할당해 준다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Serial.println("STA failed to configure");</span><br />
<span style="font-family: "Courier New", Courier, monospace;">}</span><br />
<br />
* 위에서 primaryDNS와 secondaryDNS 는 옵션이라 생략해도 된다.<br />
<br />
지금까지 설명한 부분을 정리한 코드이다. 공유기 ssid는 "myhome", 공유기 password는"hello12345", ESP32 IP address는 192.168.1.200, gatewaIP(공유기IP)는192.168.1.1 인 경우의 코드이다. <br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">#include <WiFi.h></span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">const char * ssid = "myhome";</span><br />
<span style="font-family: "Courier New", Courier, monospace;">const char * pwd = "hello12345"; </span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">IPAddress local_IP(192, 168, 1, 200); // ESP32가 사용할 IP address</span><br />
<span style="font-family: "Courier New", Courier, monospace;">IPAddress gateway(192, 168, 1, 1); // Gateway IP address (공유기 IP주소)</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">IPAddress subnet(255, 255, 255, 0); // subnet mask</span><br />
<span style="font-family: "Courier New", Courier, monospace;">IPAddress primaryDNS(8, 8, 8, 8); // primary DNS server IP address</span><br />
<span style="font-family: "Courier New", Courier, monospace;">IPAddress secondaryDNS(8, 8, 4, 4); // secondary DNS server IP address</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">...</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">void setup()</span><br />
<span style="font-family: "Courier New", Courier, monospace;">{</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Serial.begin(115200);</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;"> if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Serial.println("STA failed to configure");</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> }</span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;"> WiFi.begin(ssid, pwd);</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> while (WiFi.status() != WL_CONNECTED) P</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> delay(500);</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Serial.print(".");</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> }</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> </span><br />
<span style="font-family: "Courier New", Courier, monospace;"> ...</span><br />
<span style="font-family: "Courier New", Courier, monospace;">}</span><br />
<br />
---<br />
<br />
다른 방법으로는 ESP32의 코드는 따로 건드리지 않고 ESP32의 MAC address를 알아내 공유기의 DHCP가 고정된 IP를 할당하도록 해 주는 방법도 있다. 하지만 이 경우 IP는 일정하지만 DHCP가 매번 동작하기 때문에 deep sleep에서 깨어나는 경우 배터리 소모를 피할 수 없다.ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-41336077561555326312018-07-24T16:38:00.000+09:002018-07-24T16:38:04.609+09:00ESP32용 Asynchronous HTTP 웹서버 아두이노 코어를 실행하는 ESP32에서 비동기식(asynchronous) HTTP 웹서버를 설정하는 방법에 대해 설명해 보도록 하겠다.<br />
여기서 설명에 사용할 예제는 단순하게 접속하는 클라이언트에게 'hello world'라는 메시지를 리턴하는 웹서버이다.<br />
<br />
여기서 필요한 라이브러리는 ESPAsyncWebServer와 AsyncTCP 두개이다.<br />
<br />
ESPAsyncWebServer 라이브러리는 <a href="https://github.com/me-no-dev/ESPAsyncWebServer">https://github.com/me-no-dev/ESPAsyncWebServer</a> 에서 다운받을 수 있다.<br />
<br />
이 라이브러리는 비동기식 HTTP (및 웹소켓) 서버를 설정해서 하나 이상의 클라이언트를 동시에 처리할 수 있게 해 준다. 또한 코드에서 볼 수 있는 것 처럼 서버 콜백 함수만 등록을 해 놓으면 메인루프에서 클라이언트 처리 함수를 주기적으로 호출할 필요가 없다.<br />
<br />
AsyncTCP 라이브러리는 ESPAsyncWebServer를 위해 필요한 라이브러리라 필요하긴 하지만 코드에서 이 라이브러리를 직접 사용할 일은 없고 그냥 include만 해 주면 된다. <a href="https://github.com/me-no-dev/AsyncTCP">https://github.com/me-no-dev/AsyncTCP</a> 에서 다운받을 수 있다. <br />
<br />
이 라이브러리는 ESP32용 비동기 TCP 라이브러리로 ESPAsyncWebServer 라이브러리 구현을 위한 기반이다.<br />
<br />
코드를 위해서는 몇 가지 라이브러리를 include 해야 한다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">#include <WiFi.h></span><br />
<span style="font-family: "Courier New", Courier, monospace;">#include <FS.h></span><br />
<span style="font-family: "Courier New", Courier, monospace;">#include <AsyncTCP.h></span><br />
<span style="font-family: "Courier New", Courier, monospace;">#include <ESPAsyncWebServer.h></span><br />
<br />
그 후 공유기 접속을 위한 정보가 따라온다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">const char *ssid = "Your network";</span><br />
<span style="font-family: "Courier New", Courier, monospace;">const char *password = "Your password";</span><br />
<br />
또한 AsyncWebServer 클래스의 변수를 선언해 Asynchronous ESP32 HTTP 서버를 설정 하는데 사용한다.<br />
<br />
Constructor의 입력으로 몇번 포트를 사용할 것인지를 넘겨준다. 여기서는 HTTP 디폴트 포트인 80번을 사용한다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">AsyncWebServer server(80);</span><br />
<br />
setup() 함수에서는 먼저 기본적인 작업들...시리얼 포트 초기화, 무선랜 접속 등..을 수행한다. 코드는 다음과 같다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">void setup()</span><br />
<span style="font-family: "Courier New", Courier, monospace;">{</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Serial.begin(115200);</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> </span><br />
<span style="font-family: "Courier New", Courier, monospace;"> WiFi.begin(ssid, password);</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> while (WiFi.status() != WL_CONNECTED) {</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> delay(1000);</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Serial.println("Connecting to WiFi...");</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> }</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Serial.println(WiFi.localIP());</span><br />
<br />
이제 HTTP request를 받기 위해 서버가 listen을 할 route를 설정해 주고, 해당 route로 request가 수신될 때 실행될 함수를 만들어 준다.<br />
<br />
server 오브젝트의 on 메소드를 호출해 콜백함수를 지정해 준다. on 메소드의 첫번째 파라미터는 패스를 저정하는 문자열이 된다. 여기서는 '/hello' route에 대한 request를 listen하도록 설정할 것이다.<br />
<br />
두번째 파라미터는 WebRequestMethod 타입의 enum 값으로 해당 route에 대해 어떤 타입의 HTTP request를 허욜할지 지정한다. 여기서는 HTTP GET request만 받을 것이므로 HTTP_GET 값을 사용한다.<br />
<br />
세번째 파라미터는ArRequestHandlerFunction 타입에 의해 signature가 정의된 함수가 온다. ArRequestHandlerFunction 타입 정의는 <a href="https://github.com/me-no-dev/ESPAsyncWebServer/blob/63b5303880023f17e1bca517ac593d8a33955e94/src/ESPAsyncWebServer.h">https://github.com/me-no-dev/ESPAsyncWebServer/blob/63b5303880023f17e1bca517ac593d8a33955e94/src/ESPAsyncWebServer.h</a> 에서 확인할 수 있다.<br />
<br />
여기서 지정하는 처리 함수는 파라미터로 AsyncWebServerRequest 타압 오브젝트의 포인터를 넘겨 받고 리턴값은 없다. 각 incoming client는 이 클래스 오브젝트로 wrap 되어 있고 두 오브젝트는 커넥션이 끊어질 때 까지 같이 살아 있다.<br />
<br />
이 문법을 간단하게 하기 위해서 이 처리함수를 C++ lambda function으로 선언한다. 그러므로 내부적으로 선언한 이름 없는 함수로 지정할 수 있게 된다. 여러개의 route를 가지는 서버의 경우 이렇게 하는것이 각 route에 대해 각각 이름을 가지는 함수로 선언하는 것 보다 더 깔끔하고 컴팩트 해 진다.<br />
<br />
다음과 같은 lambda 문법을 사용할 것이다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">[captures] (params) {body}</span><br />
<br />
여기서는 따로 captures를 사용하지 않을 것이기 때문에 단순히 '[]'를 사용한다. params의 경우 앞에서 언급한 처리 함수의 signature를 따를 필요가 있다. 그러므로 lambda는 AsyncWebServerRequest 타입 오브젝트의 포인터를 파라미터로 받는다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request) {</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> // Lambda body implementation</span><br />
<span style="font-family: "Courier New", Courier, monospace;">});</span><br />
<br />
이 예제에서는 클라이언트에게 단순히 'hello world'라는 메시지를 돌려주면 된다. 앞에서 언급한 것 처럼 각 클라이언트는 AsyncWebServerRequest 오브젝트에 연결되어 있고, 이 오브젝트는 응답할 HTTP response를 지정할 수 있게 해 주는 send라는 메소드를 가지고 있다.<br />
<br />
이 메소드는 첫번째 파라미터로 HTTP response code를 받는데 여기서는 200을 넘겨준다. 이 HTTP response code는 "OK"를 의미한다.<br />
<br />
두번쨔 파라미터는 response의 content-type 값이다. 여기서는 'hello world'라는 문자열을 리턴할 것이기 때문에 "text/plain"을 사용하고 있다.<br />
<br />
여기서 우리는 오브젝트 자체가 아니고 오브젝트에 대한 포인터를 다루는 것이기 때문에 AsyncWebServerRequest 오브젝트의 send 메소드를 호출할 때 '->' 를 사용해야 한다는 것을 주의해라.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request) {</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> request->send(200, "text/plain", "Hello World"); </span><br />
<span style="font-family: "Courier New", Courier, monospace;">});</span><br />
<br />
마지막으로 설정을 끝내기 위해 server 오브젝트의 begin 메소드를 호출해 줘야만 한다. begin 메소드를 호출하면 서버를 시작시킨다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">server.begin();</span><br />
<br />
여기서 만든 서버는 비동기식(asynchronous)이기 때문에 메인루프에서 따로 처리함수등을 호출할 필요가 없다. 위에서 선언한 route 처리함수는 클라이언트에서 request가 들어오면 자동으로 호출된다.<br />
<br />
전체 코드는 다음과 같다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">#include <WiFi.h></span><br />
<span style="font-family: "Courier New", Courier, monospace;">#include <FS.h></span><br />
<span style="font-family: "Courier New", Courier, monospace;">#include <AsyncTCP.h></span><br />
<span style="font-family: "Courier New", Courier, monospace;">#include <ESPAsyncWebServer.h></span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">const char *ssid = "Your network";</span><br />
<span style="font-family: "Courier New", Courier, monospace;">const char *password = "Your password";</span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">AsyncWebServer server(80);</span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">void setup()</span><br />
<span style="font-family: "Courier New", Courier, monospace;">{</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Serial.begin(115200);</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> </span><br />
<span style="font-family: "Courier New", Courier, monospace;"> WiFi.begin(ssid, password);</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> while (WiFi.status() != WL_CONNECTED) {</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> delay(1000);</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Serial.println("Connecting to WiFi...");</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> }</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Serial.println(WiFi.localIP());</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> </span><br />
<span style="font-family: "Courier New", Courier, monospace;"> server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request) {</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> request->send(200, "text/plain", "Hello World"); </span><br />
<span style="font-family: "Courier New", Courier, monospace;"> });</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> server.begin();</span><br />
<span style="font-family: "Courier New", Courier, monospace;">}</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">void loop()</span><br />
<span style="font-family: "Courier New", Courier, monospace;">{</span><br />
<span style="font-family: "Courier New", Courier, monospace;">}</span><br />
<br />
<br />
<br />
<h3>
코드 테스트</h3>
<br />
코드를 컴파일 해서 ESP32에 업로드 해 준다. 시리얼 모니터를 보면 무선랜에 접속되면 ESP32 보드의 IP 주소가 찍힌다.<br />
이제 웹브라우져로 가서 주소창에 다음의 주소를 입력해 주면 된다.<br />
<br />
http:[IP address]/hello<br />
<br />
여기서 [IP address] 부분을 ESP32 보드의 IP 주소로 바꿔줘야 한다.<br />
<br />
정상적으로 동작한다면 웹브라우져에 다음과 같이 출력될 것이다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjA-inhules51ex5QRi-U1h3xzLj7SsSw1UXe88EM7UyeZ3JUsNHc_q67PKD5w1sYIfuXiULGz3K2iZ0Jt4bBcnaRBrZ0p08SXwIBaCTl5C6POq2ZcWz9qCrQhPpHk93gLE97yOLm-FgUw/s1600/esp32-arduino-async-http-webserver-hello-world.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="98" data-original-width="251" height="249" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjA-inhules51ex5QRi-U1h3xzLj7SsSw1UXe88EM7UyeZ3JUsNHc_q67PKD5w1sYIfuXiULGz3K2iZ0Jt4bBcnaRBrZ0p08SXwIBaCTl5C6POq2ZcWz9qCrQhPpHk93gLE97yOLm-FgUw/s640/esp32-arduino-async-http-webserver-hello-world.png" width="640" /></a></div>
<br />
<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-72188263146651073042018-07-17T14:09:00.002+09:002018-07-20T00:19:46.341+09:00ESP32에서 웹소켓 서버 실행 (Websocket server on ESP32)ESP32에 웹소켓(web socket) 서버를 만들는 방법을 설명하겠다. 이번에 만드는 웹소켓 서버는 가장 단순한 echo 서버로 클라이언트가 보낸 데이터를 그대로 클라이언트에 되돌려 준다.<br />
또한 작성한 웹소켓 서버를 테스트 하기 위해 간단한 파이썬 클라이언트를 작성했다.<br />
<br />
ESP32에서 웹소켓을 사용하기 위해 Websocket 라이브러리를 사용하였다. 이 라이브러리는 일반적으로 아두이노에서 TCP 서버를 만드는데 사용되는 WiFiServer 라이브러리 상에서 동작한다. <br />
이 라이브러리는 ESP8266용으로 만들어 져 아직 공식적으로 ESP32를 지원하지는 않지만 약간만 수정하면 ESP32에서도 잘 동작한다.<br />
<br />
라이브러리는 <a href="https://github.com/morrissinger/ESP8266-Websocket">https://github.com/morrissinger/ESP8266-Websocket</a> 에서 다운받을 수 있다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjr4mIXC2HiVt4JnLGBBtG2NakzJ5UynOr8NxDvY6jTDhpntbMyTafuUSRKITE7oJXOtEKazpM_BeWmHb72IpG3Yr1Oyiu8ms8h6NM8E02cHl1jWdPNLSBOdgC8upkTIwOgFRWzmsMJ5r4/s1600/GitHub_-_morrissinger_ESP8266-Websocket__A_websocket_library_for_the_ESP-8266_.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="625" data-original-width="1017" height="392" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjr4mIXC2HiVt4JnLGBBtG2NakzJ5UynOr8NxDvY6jTDhpntbMyTafuUSRKITE7oJXOtEKazpM_BeWmHb72IpG3Yr1Oyiu8ms8h6NM8E02cHl1jWdPNLSBOdgC8upkTIwOgFRWzmsMJ5r4/s640/GitHub_-_morrissinger_ESP8266-Websocket__A_websocket_library_for_the_ESP-8266_.png" width="640" /></a></div>
<br />
우측 상단의 녹색 (1)번 버튼 (Clone or download) 을 누르면 풀다운 창이 열리고 그곳에서 Download ZIP을 눌러주면 된다. 그러면 ESP8266-Websocket-master.zip 이라는 파일이 다운로드 될 것이다. 이 파일의 압축을 풀면 ESP8266-Websocket-master 이라는 이름의 폴더가 생기게 된다. .<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNVApwySO8TfA6v5CRpnf9kXtLeGdlWISJjXPPzZsmt2TIz0j3tJnehnYBvs3KOxH4S9Juo7srcVKxM-VS5RQfUIKSoVOkwPmyg9Ap88xunx24n2Gc-FzwrQmLe9xM0pIMFgTDi4_6NfY/s1600/%25E1%2584%2583%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25AE%25E1%2586%25AB%25E1%2584%2585%25E1%2585%25A9%25E1%2584%2583%25E1%2585%25B3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="225" data-original-width="359" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNVApwySO8TfA6v5CRpnf9kXtLeGdlWISJjXPPzZsmt2TIz0j3tJnehnYBvs3KOxH4S9Juo7srcVKxM-VS5RQfUIKSoVOkwPmyg9Ap88xunx24n2Gc-FzwrQmLe9xM0pIMFgTDi4_6NfY/s1600/%25E1%2584%2583%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25AE%25E1%2586%25AB%25E1%2584%2585%25E1%2585%25A9%25E1%2584%2583%25E1%2585%25B3.png" /> </a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
이 폴더의 이름을 ESP8266-Websocket (뒷쪽의 "-master' 부분을 제거)로 만들어 준 다음 다시 ZIP 파일로 압축한다 </div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiZ-CK2bLT6gaFu2uYu_Q6cKiX0VTQBnBUU8WsjCHIhYQ_W7bBQ6__g9JxZ5izt4dqU1RvfApqS3XsGK0ChiiHiICH5rMfoyz-KbWIxteuC23wYQB1vH7M_aoqGETXLuXAU88OpJKA_hY/s1600/%25E1%2584%2583%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25AE%25E1%2586%25AB%25E1%2584%2585%25E1%2585%25A9%25E1%2584%2583%25E1%2585%25B3-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="259" data-original-width="358" height="231" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiZ-CK2bLT6gaFu2uYu_Q6cKiX0VTQBnBUU8WsjCHIhYQ_W7bBQ6__g9JxZ5izt4dqU1RvfApqS3XsGK0ChiiHiICH5rMfoyz-KbWIxteuC23wYQB1vH7M_aoqGETXLuXAU88OpJKA_hY/s320/%25E1%2584%2583%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25AE%25E1%2586%25AB%25E1%2584%2585%25E1%2585%25A9%25E1%2584%2583%25E1%2585%25B3-2.png" width="320" /></a></div>
<br />
아두이노의 메뉴에서 스케치->라이브러리 포함하기->.ZIP 라이브러리 추가 를 선택 해 준다. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEVEvTxEB1BbNOYB_kqoblo8aZuw3Gh644sEkAdybBWW_xMt9ASp4LAKN-f0-IucdGqx12AGi53M8S3BrnyxM5H1MnVSuzWN5Z3iaABv6iyIygrAyxOI37GTD7ylTojd0_fCfA7YwwTVI/s1600/%25E1%2584%258C%25E1%2585%25A5%25E1%2586%25AB%25E1%2584%258E%25E1%2585%25A6%25E1%2584%2592%25E1%2585%25AA%25E1%2584%2586%25E1%2585%25A7%25E1%2586%25AB_2018__7__17__%25E1%2584%258B%25E1%2585%25A9%25E1%2584%258C%25E1%2585%25A5%25E1%2586%25AB_11_21.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="269" data-original-width="529" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEVEvTxEB1BbNOYB_kqoblo8aZuw3Gh644sEkAdybBWW_xMt9ASp4LAKN-f0-IucdGqx12AGi53M8S3BrnyxM5H1MnVSuzWN5Z3iaABv6iyIygrAyxOI37GTD7ylTojd0_fCfA7YwwTVI/s1600/%25E1%2584%258C%25E1%2585%25A5%25E1%2586%25AB%25E1%2584%258E%25E1%2585%25A6%25E1%2584%2592%25E1%2585%25AA%25E1%2584%2586%25E1%2585%25A7%25E1%2586%25AB_2018__7__17__%25E1%2584%258B%25E1%2585%25A9%25E1%2584%258C%25E1%2585%25A5%25E1%2586%25AB_11_21.png" /></a></div>
<br />
<br />
앞축파일을 찾아 선택해서 설치 해 준다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxwtyU6I3XyLtZPDE3t7rXdcQaKwyIexnKLXEPOZ-U4veIsRZsPwIU0mTGjnW-V1OmfFZj31_eQGm5L69RE1Qj6h5xzBw8AgbpLPaeP_TK49IG7R5x5XNYWiiyqVQLHUVM8Mkk-dWlU0M/s1600/%25E1%2584%258E%25E1%2585%25AE%25E1%2584%2580%25E1%2585%25A1%25E1%2584%2592%25E1%2585%25A1%25E1%2584%2585%25E1%2585%25A7%25E1%2584%2582%25E1%2585%25B3%25E1%2586%25AB_zip_%25E1%2584%2591%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25B5%25E1%2586%25AF_%25E1%2584%2584%25E1%2585%25A9%25E1%2584%2582%25E1%2585%25B3%25E1%2586%25AB_%25E1%2584%2585%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2587%25E1%2585%25B3%25E1%2584%2585%25E1%2585%25A5%25E1%2584%2585%25E1%2585%25B5%25E1%2584%2585%25E1%2585%25B3%25E1%2586%25AF_%25E1%2584%2591%25E1%2585%25A9%25E1%2584%2592%25E1%2585%25A1%25E1%2586%25B7%25E1%2584%2592%25E1%2585%25A1%25E1%2584%2582%25E1%2585%25B3%25E1%2586%25AB_%25E1%2584%2591%25E1%2585%25A9%25E1%2586%25AF%25E1%2584%2583%25E1%2585%25A5%25E1%2584%2585%25E1%2585%25B3%25E1%2586%25AF_%25E1%2584%2589%25E1%2585%25A5%25E1%2586%25AB%25E1%2584%2590%25E1%2585%25A2%25E1%2586%25A8%25E1%2584%2592%25E1%2585%25A1%25E1%2584%2589%25E1%2585%25A6%25E1%2584%258B%25E1%2585%25AD_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_QRCode___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="254" data-original-width="589" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxwtyU6I3XyLtZPDE3t7rXdcQaKwyIexnKLXEPOZ-U4veIsRZsPwIU0mTGjnW-V1OmfFZj31_eQGm5L69RE1Qj6h5xzBw8AgbpLPaeP_TK49IG7R5x5XNYWiiyqVQLHUVM8Mkk-dWlU0M/s1600/%25E1%2584%258E%25E1%2585%25AE%25E1%2584%2580%25E1%2585%25A1%25E1%2584%2592%25E1%2585%25A1%25E1%2584%2585%25E1%2585%25A7%25E1%2584%2582%25E1%2585%25B3%25E1%2586%25AB_zip_%25E1%2584%2591%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25B5%25E1%2586%25AF_%25E1%2584%2584%25E1%2585%25A9%25E1%2584%2582%25E1%2585%25B3%25E1%2586%25AB_%25E1%2584%2585%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2587%25E1%2585%25B3%25E1%2584%2585%25E1%2585%25A5%25E1%2584%2585%25E1%2585%25B5%25E1%2584%2585%25E1%2585%25B3%25E1%2586%25AF_%25E1%2584%2591%25E1%2585%25A9%25E1%2584%2592%25E1%2585%25A1%25E1%2586%25B7%25E1%2584%2592%25E1%2585%25A1%25E1%2584%2582%25E1%2585%25B3%25E1%2586%25AB_%25E1%2584%2591%25E1%2585%25A9%25E1%2586%25AF%25E1%2584%2583%25E1%2585%25A5%25E1%2584%2585%25E1%2585%25B3%25E1%2586%25AF_%25E1%2584%2589%25E1%2585%25A5%25E1%2586%25AB%25E1%2584%2590%25E1%2585%25A2%25E1%2586%25A8%25E1%2584%2592%25E1%2585%25A1%25E1%2584%2589%25E1%2585%25A6%25E1%2584%258B%25E1%2585%25AD_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_QRCode___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_2.png" /></a></div>
<br />
이제 라이브러리 설치가 완료되었다. 윈도우의 경우 디폴트 위치가 C:\Users\[username]\Documents\Arduino\libraries 가 된다. Mac의 경우/Users/[username]/Docunemts/Arduino/libraries<br />
<br />
라이브러리 설치는 끝났지만 그냥 컴파일을 하면 에러가 발생하므로 ESP32에서 사용할 수 있도록 약간의 수정을 해 준다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeV95QkUUODXPQadlWWrWJ_RRDyvXfYFgQcptDH39-hPeOEOdHjxVtEjpeU57g04i27qEyNj_XkAJv2Wg33r_CltiwfbFKzytj3b6QvYH03Nv6PxulJLIWv39N12YRsoWfHp8p27elM8Q/s1600/ESP8266-Websocket_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_ESP32_Arduino__Websocket_client___techtutorialsx_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_Blogger__%25E1%2584%2580%25E1%2585%25B5%25E1%2584%2589%25E1%2585%25AE%25E1%2586%25AF_%25E1%2584%258B%25E1%2585%25A7%25E1%2584%2592%25E1%2585%25A2%25E1%2586%25BC%25E1%2584%258C%25E1%2585%25A1__ArsViator__-_Create_post_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_1__pi_raspberrypi_____bash_.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="421" data-original-width="598" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeV95QkUUODXPQadlWWrWJ_RRDyvXfYFgQcptDH39-hPeOEOdHjxVtEjpeU57g04i27qEyNj_XkAJv2Wg33r_CltiwfbFKzytj3b6QvYH03Nv6PxulJLIWv39N12YRsoWfHp8p27elM8Q/s1600/ESP8266-Websocket_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_ESP32_Arduino__Websocket_client___techtutorialsx_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_Blogger__%25E1%2584%2580%25E1%2585%25B5%25E1%2584%2589%25E1%2585%25AE%25E1%2586%25AF_%25E1%2584%258B%25E1%2585%25A7%25E1%2584%2592%25E1%2585%25A2%25E1%2586%25BC%25E1%2584%258C%25E1%2585%25A1__ArsViator__-_Create_post_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_1__pi_raspberrypi_____bash_.png" /></a></div>
라이브러리가 설치된 폴더를 보면 위와 같은 파일이 있는데 그 중 MD5.c, MD5.h 파일을 수정해 줘야 한다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglHbrL_7BJPNkOezChyphenhypheniN-qSVbL5eHHA9Pb0fEMg7wWu4EPMOhYX9bWRW3f9dMxN3hEx-QxS91akE3DVnFmzdnMBp6rzV3giaFEO_YQXFekMrQX39-5baTqTffEMJNLbQgiXubzHJvMkw/s1600/MD5_c_%25E2%2580%2594___Documents_Arduino_libraries_ESP8266-Websocket.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="594" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglHbrL_7BJPNkOezChyphenhypheniN-qSVbL5eHHA9Pb0fEMg7wWu4EPMOhYX9bWRW3f9dMxN3hEx-QxS91akE3DVnFmzdnMBp6rzV3giaFEO_YQXFekMrQX39-5baTqTffEMJNLbQgiXubzHJvMkw/s1600/MD5_c_%25E2%2580%2594___Documents_Arduino_libraries_ESP8266-Websocket.png" /></a></div>
<br />
MD5.c 파일을 오픈 한 화면이다. 파일에서 위의 빨간색 부분 (함수 이름)을 다음과 같이 바꿔주면 된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu5eTmcf0bdlVAtNA47na2KLFKGNw24eCMDXHoFbhnktIfEMe35Y5x9NIWXdJ4RzZqMST8R02XfwXs69Gci2Mq2gMbPJg-2qHlgG0JSOcKlCzyeXxXx1xmKN7UE14W57jKWopYyPW_hvw/s1600/MD5_c_%25E2%2580%2594___Documents_Arduino_libraries_ESP8266-Websocket-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1253" data-original-width="631" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu5eTmcf0bdlVAtNA47na2KLFKGNw24eCMDXHoFbhnktIfEMe35Y5x9NIWXdJ4RzZqMST8R02XfwXs69Gci2Mq2gMbPJg-2qHlgG0JSOcKlCzyeXxXx1xmKN7UE14W57jKWopYyPW_hvw/s1600/MD5_c_%25E2%2580%2594___Documents_Arduino_libraries_ESP8266-Websocket-2.png" /></a></div>
<br />
MD5.h 도 유사하게 이름을 바꿔주면 된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHOeG_PjQkC2zZp-72zDyFhIMNMpj3hyphenhyphenkaV_bTfDIvGFv0KrJwIGv1hVb_hNpl_V1TmRZYrwQJBRXS6eFdzr7F63rtBFv1yV6u0uOyCIJys_I45iIgaHqSaaCuw6jS_ecSwy0EYCf5eeo/s1600/MD5_h_%25E2%2580%2594___Documents_Arduino_libraries_ESP8266-Websocket.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="146" data-original-width="600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHOeG_PjQkC2zZp-72zDyFhIMNMpj3hyphenhyphenkaV_bTfDIvGFv0KrJwIGv1hVb_hNpl_V1TmRZYrwQJBRXS6eFdzr7F63rtBFv1yV6u0uOyCIJys_I45iIgaHqSaaCuw6jS_ecSwy0EYCf5eeo/s1600/MD5_h_%25E2%2580%2594___Documents_Arduino_libraries_ESP8266-Websocket.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhk4kOIN2L6I4xOV1i1rqvMJQDngfcMPoN7Djdd9JbPBpmYeBEobeHVSwxzAWoFZeHM2IZrECwCjpBF-ai2aghDS_M_PYUgVT5LfcFEhZwN2frdcqQ8W-V9BQ9KJp1t169xgnzSWycCLcs/s1600/MD5_h_%25E2%2580%2594___Documents_Arduino_libraries_ESP8266-Websocket-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="156" data-original-width="628" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhk4kOIN2L6I4xOV1i1rqvMJQDngfcMPoN7Djdd9JbPBpmYeBEobeHVSwxzAWoFZeHM2IZrECwCjpBF-ai2aghDS_M_PYUgVT5LfcFEhZwN2frdcqQ8W-V9BQ9KJp1t169xgnzSWycCLcs/s1600/MD5_h_%25E2%2580%2594___Documents_Arduino_libraries_ESP8266-Websocket-2.png" /></a></div>
<br />
이제 아두이노 메뉴에서 파일->예제->ESP8266-Websocket->WebsocketClient_Demo 를 열어본다.<br />
예제 파일을 컴파일 해 보면 ESP8266WiFi.h 파일을 찾을 수 없다는 에러가 발생한다. 그러므로 첫번째 줄의 #include <ESP8266WiFi.h> 를 #include <WiFi.h> 로 바꿔줘야 한다.<br />
또한 SSID HERE, PASSWORD HERE 부분에 자신이 사용할 공유기 정보를 넣어줘야 한다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlaurtzYEJXr1leAD33rvthjf-6l_hnaQIuKQDcRKVaEMTlpvR5MPjtmmwxuOw1H3BpOtVEigNpwxreihkthPR9PKxq-HYlAmgM3ZBXee_2NlnAYE7wkTqXZFPGCeeEbbxEGvrCldERp0/s1600/WebSocketClient_Demo___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="357" data-original-width="376" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlaurtzYEJXr1leAD33rvthjf-6l_hnaQIuKQDcRKVaEMTlpvR5MPjtmmwxuOw1H3BpOtVEigNpwxreihkthPR9PKxq-HYlAmgM3ZBXee_2NlnAYE7wkTqXZFPGCeeEbbxEGvrCldERp0/s1600/WebSocketClient_Demo___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_2.png" /></a></div>
<br />
<br />
만일 공유기 ssid가 wifitestap 이고 암호가 ap1234567890 라고 하면 다음과 같이 변경해주면 된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz92hgoy-B5fnngseV2kw_ZcNVc1-reWUM_TAE0FBNKyv-o6pheXuwJwCkHWH4Iq1uXEYTombbRB8U7U10-OESuclPJVnLKY_TNrYWZDo8wrW8DR-u27Q1zePTTKM3xs9cEISdTwYoTqo/s1600/WebSocketClient_Demo___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_2-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="299" data-original-width="371" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz92hgoy-B5fnngseV2kw_ZcNVc1-reWUM_TAE0FBNKyv-o6pheXuwJwCkHWH4Iq1uXEYTombbRB8U7U10-OESuclPJVnLKY_TNrYWZDo8wrW8DR-u27Q1zePTTKM3xs9cEISdTwYoTqo/s1600/WebSocketClient_Demo___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_2-2.png" /></a></div>
<br />
샘플코드에서는 analogRead 값을 서버로 보내고 있는데 여기서는 테스트 목적이라 그냥 "Hello" 라는 스트링을 보내도록 수정하였다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVak_GJUh7tnBXn3v8Kl9leSvjZT1yoM52My9F0Rv9yd0zcfyVp1lv13mfUWYYtD5jlUhXWaru7XmbyEX_zaWrzYJ2psEr0obRXg2BW5EX3z9NGE6kM90Qpy36nlAKprICuFb2tLZ23Js/s1600/WebSocketClient_Demo___Arduino_1_8_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="185" data-original-width="410" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVak_GJUh7tnBXn3v8Kl9leSvjZT1yoM52My9F0Rv9yd0zcfyVp1lv13mfUWYYtD5jlUhXWaru7XmbyEX_zaWrzYJ2psEr0obRXg2BW5EX3z9NGE6kM90Qpy36nlAKprICuFb2tLZ23Js/s1600/WebSocketClient_Demo___Arduino_1_8_2.png" /></a></div>
<br />
이제 ESP32 보드에 업로드 하고 시리얼 모니터로 결과를 확인할 수 있다. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoSObiCFyYZDdb46F7nzf0n2YH0ICwvgBowbtmuAx8y1hyphenhyphengkXjDw_v_Wy2pQ1GoRDBfiuNyAwggd5BpWYzygCRgYQEdYsniw3_oHOIGIpOeHjONnSEx7Dc0-32nlrTGYAmNEfa-Al9n3o/s1600/_dev_cu_SLAB_USBtoUART.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="320" data-original-width="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoSObiCFyYZDdb46F7nzf0n2YH0ICwvgBowbtmuAx8y1hyphenhyphengkXjDw_v_Wy2pQ1GoRDBfiuNyAwggd5BpWYzygCRgYQEdYsniw3_oHOIGIpOeHjONnSEx7Dc0-32nlrTGYAmNEfa-Al9n3o/s1600/_dev_cu_SLAB_USBtoUART.png" /></a></div>
<br />
테스트용 에코서버에 연결되면 반복적으로 "Hello"라는 스트링을 보내고 서버에서 리턴 된 문자를 출력한 것이다.<br />
<br />
ESP32용 websocket 라이브러리 설치가 확인되었으면 이제 파이선으로 테스트용 웹소켓 클라이언트를 만들어 보겠다.<br />
<br />
여기서는 websocket-client 모듈을 사용한다. 파이선에서 모듈 설치는 pip를 사용해 간단히 해결할 수 있다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">$ pip install websocket-client</span><br />
<br />
모듈을 사용하기 위해 먼저 import 해 줘야 한다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">import websocket</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import time</span><br />
<br />
import 한 다음 WebSocket 클래스의 오브젝트를 만들어 준다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">ws = websocket.WebSocket()</span><br />
<br />
이제 만들어 진 오브젝트의 connect() 메소드를 사용해 웹소켓 서버에 쉽게 접속할 수 있다. 메소드를 호출할 때 접속할 서버의 주소를 파라미터로 넘겨주면 되는데 웹소켓을 사용해 접속할 것이기 때문에 주소는 "ws://[server ip]/" 형태로 지정해 줘야 한다. 여기서 server ip는 웹서버가 실행되는 ESP32의 ip 주소를 넣어주면 된다.<br />
<br />
테스트 웹소켓 서버로 확인해보고 싶으면 ws://echo.websocket.org/ 를 사용하면 된다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">ws.connect("ws://echo.websocket.org/")</span><br />
<br />
이제 서버에 연결되었기 때문에 send 메소드로 원하는 데이터를 보낼 수 있다.<br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">ws.send("Hello world")</span><br />
<br />
recv 메소드로 서버에서 데이터를 받아 올 수 있다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">result = ws.recv()</span><br />
<br />
서버에 연결을 끊을 때는 close 메소드를 사용하면 된다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">result = ws.close()</span><br />
<br />
간단한 테스트 코드는 아래와 같다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">import websocket</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">import time</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">ws = websocket.WebSocket()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">ws.connect ("ws://echo.websocket.org/")</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">i=0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">nrOfMsgs = 10</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">while i<nrOfMsgs:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> ws.send("Msg no. "+str(i))</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> result = ws.recv()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> print (result)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> i=i+1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> time.sleep(1)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">ws.close()</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTe_CL4YTxo8_JL8jmFbh433B10ywZKuyr4f05t8YTsUG3qlYiGJGMGIjScoe_MQL8cVrZX8zdGsKhOFK428Mp5AnEi_s8-DjKueih9H90aI391Q0k3f0prXXmDe96OTZji1rFIP2RBzM/s1600/1__pi_raspberrypi____tmp__ssh_.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="693" data-original-width="451" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTe_CL4YTxo8_JL8jmFbh433B10ywZKuyr4f05t8YTsUG3qlYiGJGMGIjScoe_MQL8cVrZX8zdGsKhOFK428Mp5AnEi_s8-DjKueih9H90aI391Q0k3f0prXXmDe96OTZji1rFIP2RBzM/s1600/1__pi_raspberrypi____tmp__ssh_.png" /></a></div>
<br />
이제 ESP32에 웹소켓 서버를 만들어 보겠다.<br />
먼저 WebSocketServer.h 를 include 해 줘야 한다.<br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">#include <WiFi.h></span><br />
<span style="font-family: "courier new" , "courier" , monospace;">#include <WebSocketServer.h></span><br />
<br />
다음으로 WiFiServer 클래스 오브젝트 인스턴스로 TCP 서버를 만들어 줘야 한다. 웹소켓 서버는 이 서버 위에서 동작한다. 오브젝트 인스턴스의 파라미터는 옵션으로 서버 포트를 지정하는데 사용한다. 디폴트 값이 80이라 따로 지정하지 않아도 상관없지만 여기서는 명시적으로 80번 포트를 지정해 줬다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">WiFiServer server(80);</span><br />
<br />
그리고 WebSocketServer 클래스의 오브젝트 인스턴스도 만들어 줘야 한다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">WebSocketServer webSocketServer;</span><br />
<br />
마지막으로 공유기 접속을 위한 정보를 지정해 줘야 한다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">const char* ssid = "wifitestap";</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">const char *password = "ap1234567890";</span><br />
<br />
setup() 함수에서는 우선 무선랩에 접속 후 server 인스턴스의 begin 메소드를 호출해 초기화 해 준다. <br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">void setup()</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.begin(115200);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> WiFi.begin(ssid, password);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while (WiFi.status() != WL_CONNECTED) {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> delay(1000);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println("Connecting to WiFi...");</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println("Connected to the WiFi");</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(WiFi.localIP());</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> server.begin(80);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> delay(100);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
loop() 함수에서는 클라이언트와의 접속과 데이터 교환을 처리한다.<br />
<br />
먼저 incoming connection이 있는가 확인하기 위해 WiFiServer 오브젝트의 available 메소드를 호출한다. available 메소드는 incoming connection이 있으면 WiFiClient 오브젝트를 리턴한다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">WiFiClient client = server.available();</span><br />
<br />
주의할 점은 아직 웹소켓 클라이언트 레벨이 아니고 TCP 클라이언트 레벨에 있다는 것이다.<br />
<br />
TCP 클라이언트가 연결되어 있는지 확인하기 위해 위에서 리턴된 WiFiClient 오브젝트의 connected 메소드를 호출한다. 또한 WebSocketServer 오브젝트에 WiFiClient 오브젝트를 파라미터로 해서 handshake 메소드를 호출해서 프로토콜 핸드쉐이크를 처리하도록 한다.<br />
<br />
핸드쉐이크가 성공하면 true를 리턴한다. 이 값이 확인 돼야 클라이언트와 실제 통신을 진행할 수가 있게 된다.<br />
<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> if (client.connected() && webSocketServer.handshake(client)) {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // 클라이언트와 통신 코드 </span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> } </span><br />
<br />
여기서는 간단한 에코서버를 만드는 것이기 때문에 클라이언트에서 받은 데이터를 저장할 버퍼가 필요한데 메소드는 String 타입을 사용한다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">String data;</span><br />
<br />
클라이언트가 아무 때나 접속을 끊을 수 있기 때문에 while 루프를 돌면서 접속이 끊어지지 않았는가 확인해야 한다.<br />
<br />
또한 루프의 각 iteration 사이에 약간의 딜레이가 필요하다. 그렇지 않으면 첫번째 몇 바이트를 받은 다음 데이서 수신을 멈출 수 있기 때문에 매우 중요하다.<br />
<br />
그러므로 루프의 구조는 다음과 같다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">if (client.connected() && webSocketServer.handshake(client)) {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> String data;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while (client.connected()) {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // handle communication</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> delay(10); // delay needed for receiving data correctly</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
이제 while 루프 안에서 webSocketServer 오브젝트의 getData 메소드를 호출해 데이터를 수신한다. 이 메소드는 파라미터가 없고 수신한 데이터를 String 타입으로 리턴한다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> data = webSocketServer.getData();</span><br />
<br />
데이터를 수신하고 나면 그 내용을 시리얼 포트로 출력하고 클라이언트로 되돌려 보낸다.<br />
<br />
클라이언트로 데이터를 보낼 땐 webSocketServer 오브젝트의 sendData 메소드를 호출한다.<br />
<br />
클라이언트가 아무 데이터도 보내지 않는 경우도 있을 수 있으므로 데이터 버퍼의 길이를 먼저 확인한다. 그러므로 클라이언트에 데이터를 돌려보내기 위해서는 버퍼에 있는 데이터 길이가 0보다 커야만 한다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> if (data.length() > 0) {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println(data);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> webSocketServer.sendData(data);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<br />
<br />
위에서 설명하며 작성한 전체 코드는 다음과 같다.<br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<div style="color: #010101; font-family: "consolas" , "liberation mono" , "menlo" , "courier" , monospace "important"; line-height: 130%; margin: 0; padding: 0;">
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"><span style="color: #0086b3;">#include</span> <span style="color: #a71d5d;"><</span>WiFi.h<span style="color: #a71d5d;">></span></span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"><span style="color: #0086b3;">#include</span> <span style="color: #a71d5d;"><</span>WebSocketServer.h<span style="color: #a71d5d;">></span></span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;">WiFiServer server(<span style="color: #0099cc;">80</span>);</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;">WebSocketServer webSocketServer;</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"><span style="color: #a71d5d;">const</span> <span style="color: #066de2;">char</span><span style="color: #a71d5d;">*</span> ssid <span style="color: #a71d5d;">=</span> <span style="color: #63a35c;">"yourNetworkName"</span>;</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"><span style="color: #a71d5d;">const</span> <span style="color: #066de2;">char</span><span style="color: #a71d5d;">*</span> password <span style="color: #a71d5d;">=</span> <span style="color: #63a35c;">"yourNetworkPassword"</span>;</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"><span style="color: #a71d5d;">void</span> setup()</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;">{</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> Serial.<span style="color: #066de2;">begin</span>(<span style="color: #0099cc;">115200</span>);</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> WiFi.<span style="color: #066de2;">begin</span>(ssid, password);</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> <span style="color: #a71d5d;">while</span> (WiFi.status() <span style="color: #a71d5d;">!</span><span style="color: #a71d5d;">=</span> WL_CONNECTED) {</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> delay(<span style="color: #0099cc;">1000</span>);</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> Serial.println(<span style="color: #63a35c;">"Connecting to WiFi..."</span>);</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> }</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> Serial.println(<span style="color: #63a35c;">"Connected to the WiFi network"</span>);</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> Serial.println(WiFi.localIP());</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> server.<span style="color: #066de2;">begin</span>()</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> delay(<span style="color: #0099cc;">1000</span>);</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;">}</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"><span style="color: #a71d5d;">void</span> loop()</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;">{</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> WiFiClient client <span style="color: #a71d5d;">=</span> server.available();</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> </span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> <span style="color: #a71d5d;">if</span> (client.connected() <span style="color: #a71d5d;">&</span><span style="color: #a71d5d;">&</span> webSocketServer.handshake(client)) {</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> String data;</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> <span style="color: #a71d5d;">while</span> (client.connected()) {</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> data <span style="color: #a71d5d;">=</span> webSocketServer.getData();</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> <span style="color: #a71d5d;">if</span> (data.length() <span style="color: #a71d5d;">></span> <span style="color: #0099cc;">0</span>) {</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> Serial.println(data);</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> webSocketServer.sendData(data);</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> }</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> delay(<span style="color: #0099cc;">10</span>); <span style="color: #999999;">// Delay needed for receiving data correctly</span></span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> }</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> Serial.println(<span style="color: #63a35c;">"The client disconnected"</span>);</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> delay(<span style="color: #0099cc;">100</span>);</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> }</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;"> delay(<span style="color: #0099cc;">100</span>);</span></div>
<div style="line-height: 130%; padding: 0 6px; white-space: pre;">
<span style="font-family: "Courier New", Courier, monospace;">}</span></div>
</div>
<br />
작성한 코드를 테스트 하려면 먼저 ESP32에 업로드 해서 실행시킨다. 그럼 ESP32는 무선랜에 접속하고 local IP를 시리얼 포트로 출력해 준다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoZyRpKdagx2yJDLsYNp00OCk9IZ_BZVG0sOo5gt2uR-NPPRZl5gN7L-pMX_8R-uRXOAxm6BiRPxiYCsfBVaWHa7hBenAsGAYwaGfn1UFgxf9oUUvNrDUG0FzMO19PUYpGhWJ0q-v9WGY/s1600/_dev_cu_SLAB_USBtoUART_and_sketch_jul17b___Arduino_1_8_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="315" data-original-width="546" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoZyRpKdagx2yJDLsYNp00OCk9IZ_BZVG0sOo5gt2uR-NPPRZl5gN7L-pMX_8R-uRXOAxm6BiRPxiYCsfBVaWHa7hBenAsGAYwaGfn1UFgxf9oUUvNrDUG0FzMO19PUYpGhWJ0q-v9WGY/s1600/_dev_cu_SLAB_USBtoUART_and_sketch_jul17b___Arduino_1_8_2.png" /></a></div>
<br />
여기서 ESP32의 IP address는 192.168.0.14 이다.<br />
이제 파이썬 코드의 주소 부분을 ESP32의 IP address로 바꿔준다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcYi6d5F9jE_NpT1TG5LkIS_atAbN9apcZnNrAA8I2sFGua63nbV4XZS9mx5x9baQToV-WVn94gLDN8H_K2f8MZ9N3r8NtSgp_H7iBVi8rFUgREAThxdjQfjKNzRbfp-0NVOPzK4znMiM/s1600/_dev_cu_SLAB_USBtoUART_and_1__pi_raspberrypi____tmp__ssh__%25F0%259F%2594%2594_and_sketch_jul17b___Arduino_1_8_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="514" data-original-width="967" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcYi6d5F9jE_NpT1TG5LkIS_atAbN9apcZnNrAA8I2sFGua63nbV4XZS9mx5x9baQToV-WVn94gLDN8H_K2f8MZ9N3r8NtSgp_H7iBVi8rFUgREAThxdjQfjKNzRbfp-0NVOPzK4znMiM/s1600/_dev_cu_SLAB_USBtoUART_and_1__pi_raspberrypi____tmp__ssh__%25F0%259F%2594%2594_and_sketch_jul17b___Arduino_1_8_2.png" /></a></div>
<br />
주소를 변경했으면 python으로 작성한 클라이언트를 실행시켜 주면 된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXRPPOkrV1rwNbI8-Mkv1F6EDLoZbG5tkRSzoj2dkiDgLqAlHQpuc-ah4dcJ4aJ6TNjbjXvkoaoYUi0NOiev4G9A85fq4eusxChM9G3s709qF5qSzegsZ1clbfqC4FeqwzWlSFZxacylc/s1600/1__pi_raspberrypi____tmp__ssh__and__dev_cu_SLAB_USBtoUART_and_sketch_jul17b___Arduino_1_8_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="613" data-original-width="762" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXRPPOkrV1rwNbI8-Mkv1F6EDLoZbG5tkRSzoj2dkiDgLqAlHQpuc-ah4dcJ4aJ6TNjbjXvkoaoYUi0NOiev4G9A85fq4eusxChM9G3s709qF5qSzegsZ1clbfqC4FeqwzWlSFZxacylc/s1600/1__pi_raspberrypi____tmp__ssh__and__dev_cu_SLAB_USBtoUART_and_sketch_jul17b___Arduino_1_8_2.png" /></a></div>
<br />
파이썬 클라이언트(우측 화면)에서 Msg no.x 라는 문자열을 웹소켓을 통해 ESP32로 보내면 ESP32(좌측화면)가 수신한 데이터를 시리얼 포트에 출력하고 그 내용을 클라이언트로 되돌려 보내 준다. 파이썬 클라이언트는 서버에서 받은 데이터 내용을 화면에 출력한 것이다.<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com1tag:blogger.com,1999:blog-6762236726539517408.post-47869168055682139182018-07-12T12:09:00.000+09:002018-07-12T12:09:00.592+09:00ESP32에서 JSON 파싱ESP32에서 ArduinoJson 라이브러리를 사용해 JSON 메시지를 파싱 해 보겠다.<br />
<br />
먼저 ArduinoJson 라이브러리가 설치되어 있어야 한다.<br />
<br />
만일 설치되어 있지 않으면 메뉴의 스케치->라이브러리 포함하기->라이브러리 관리...를 선택해 준다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXL810x6XJMnZ3j06WOL3A7WkIW2eMmw-ANvlXs6VbuDZ7-Fk23PjCivT4eSNczABBO0by6Dwwp1U7sF7cFOQJnDZzA3YXwlxLR7FvC3KyWc-5lWu11CrdTDe_pMbCrPFTyIZ25W0AS-c/s1600/%25E1%2584%258C%25E1%2585%25A5%25E1%2586%25AB%25E1%2584%258E%25E1%2585%25A6%25E1%2584%2592%25E1%2585%25AA%25E1%2584%2586%25E1%2585%25A7%25E1%2586%25AB_2018__7__12__%25E1%2584%258B%25E1%2585%25A9%25E1%2584%258C%25E1%2585%25A5%25E1%2586%25AB_11_32.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="230" data-original-width="595" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXL810x6XJMnZ3j06WOL3A7WkIW2eMmw-ANvlXs6VbuDZ7-Fk23PjCivT4eSNczABBO0by6Dwwp1U7sF7cFOQJnDZzA3YXwlxLR7FvC3KyWc-5lWu11CrdTDe_pMbCrPFTyIZ25W0AS-c/s1600/%25E1%2584%258C%25E1%2585%25A5%25E1%2586%25AB%25E1%2584%258E%25E1%2585%25A6%25E1%2584%2592%25E1%2585%25AA%25E1%2584%2586%25E1%2585%25A7%25E1%2586%25AB_2018__7__12__%25E1%2584%258B%25E1%2585%25A9%25E1%2584%258C%25E1%2585%25A5%25E1%2586%25AB_11_32.png" /></a></div>
<br />
라이브러리 메니저 창이 열리면 1번 부분에 ArduinoJson 을 입력하면 해당 키워드를 가진 라이브러리 목록이 보인다. 목록중에 ArduinoJson을 찾아 그 부분을 클릭하면 3과 같이 라이브러리 우측 하단에 '설치' 버튼이 나타난다. '설치' 버튼을 눌러 설치해주면 된다. 설치가 완료되면 '닫기' 버튼을 눌러준다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFA191oiKPskDeN6W16ic7rDLh4VhkHZl9OwWhiveHEbORe1YVb4recD4oHzZptW_JxiuX9P9GnTMcT-JmPSdadLWKycxgBbBLHc0O6SBOkU8vABiECeQNKz7mlODHPsKiK-Jxa2pIne4/s1600/%25E1%2584%2585%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2587%25E1%2585%25B3%25E1%2584%2585%25E1%2585%25A5%25E1%2584%2585%25E1%2585%25B5_%25E1%2584%2586%25E1%2585%25A2%25E1%2584%2582%25E1%2585%25B5%25E1%2584%258C%25E1%2585%25A5_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_esp32wifi1___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="471" data-original-width="818" height="368" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFA191oiKPskDeN6W16ic7rDLh4VhkHZl9OwWhiveHEbORe1YVb4recD4oHzZptW_JxiuX9P9GnTMcT-JmPSdadLWKycxgBbBLHc0O6SBOkU8vABiECeQNKz7mlODHPsKiK-Jxa2pIne4/s640/%25E1%2584%2585%25E1%2585%25A1%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2587%25E1%2585%25B3%25E1%2584%2585%25E1%2585%25A5%25E1%2584%2585%25E1%2585%25B5_%25E1%2584%2586%25E1%2585%25A2%25E1%2584%2582%25E1%2585%25B5%25E1%2584%258C%25E1%2585%25A5_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_esp32wifi1___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_2.png" width="640" /></a></div>
<br />
이제 라이브러리를 가지고 실제 코드를 작성한다.<br />
<br />
가장 먼저 ArduinoJson 라이브러리를 include 해 줘야 한다. 또한 loop 함수에서 실제 파싱을 수행할 것이므로 결과를 확인하기 위해 시리얼 포트를 열어준다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">#include <ArduinoJson.h></span><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">void setup()</span><br />
<span style="font-family: "Courier New", Courier, monospace;">{</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Serial.begin(115200);</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Serial.println("JSON parsing using ArduinoJson library on ESP32");</span><br />
<span style="font-family: "Courier New", Courier, monospace;">}</span><br />
<br />
여기서는 네트웍에서 JSON 데이터를 불러오지 않고 하드코딩 된 JSON 메시지를 파싱 해 볼 것이기 때문에 이를 위한 변수를 선언해 준다. 여기에서 '\' 은 메지시 내에 들어가는 따옴표(")에 대한 escape character이다. JSON의 name에 따옴표(")가 있어야만 하기 때문에 필요하다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">char JSONMsg[] = " {\"SensorType\", \"Temperature\", \"Value\", 10}";</span><br />
<br />
Escape character가 없는 JSON 메시지의 구조는 다음과 같다. <br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">{</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> "SensorType" : "Temperature",</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> "Value" : 10</span><br />
<span style="font-family: "Courier New", Courier, monospace;">}</span><br />
<br />
주의) JSON 파서는 스트링 내용을 수정하기 때문에 내용을 재사용 할 수 없다. 그래서 여기서도 JSONMsg 변수를 전역변수가 아니고 loop 내에서 선언해 loop 함수가 끝나면 free 되고, 다음번에 다시 loop() 함수가 호출될 때 다시 할당되도록 해 놓았다.<br />
<br />
또한 파싱한 결과인 JSON object tree를 저장하기 위해 미리 할당된 메모리 풀을 위해 StaticJsonBuffer 클래스 오브젝트를 선언했다. 이 오브젝트는 메모리 풀이기 때문에 크기를 지정해 줘야 한다. 크기는 템플릿 파라미터(코드에서 < > 사이의 값)에 바이트 단위로 지정해 주면 된다. 여기서는 300바이트를 지정했는데 이 정도면 위의 JSON 메시지를 파싱하는데는 충분하다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">StaticJsonBuffer<300> JSONBuffer; // memory pool for parsed JSON object tree</span><br />
<br />
다음으로는 StaticJsonBuffer 오브젝트의 parseObject 메소드를 호출하면서 파싱하길 원하는 JSON 스트링을 넘겨준다. <br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">JsonObject &parsed = JSONBuffer.parseObject(JSONMsg);</span><br />
<br />
에러 없이 파싱이 끝났는지 확인하기 위해 JSONObject의 success 메소드를 호출할 수 있다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">if (!parsed.success()) { // check for errors in parsing</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> Serial.println("Parsing failed!");</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> delay(5000);</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> return;</span><br />
<span style="font-family: "Courier New", Courier, monospace;">}</span><br />
<br />
이제 JsonObject에서 이름으로 그에 해당하는 값을 가져오기 위해 subscript operator를 사용할 수 있다. 즉 key에 해당하는 값을 가져오기 위해 원하는 파라미터의 key 이름을 [ ]으로 둘러싸면 된다. 이 예제에서 사용하고 있는 key 이름은 "SensorType"과 "Value" 두 가지다.<br />
<br />
const char *sensorType = parsed["SensorType"]; // get sensor type value<br />
int value = parsed["Value"] // get value of the sensor measurement<br />
<br />
전체 코드는 다음과 같다.<br />
<br />
<div class="line number1 index0 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp preprocessor" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: gray !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">#include <ArduinoJson.h></code></span></span></div>
<div class="line number2 index1 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"> </span></span></div>
<div class="line number3 index2 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp keyword bold" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: rgb(0, 102, 153) !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: bold !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">void</code> <code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">setup() {</code></span></span></div>
<div class="line number4 index3 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"> </span></span></div>
<div class="line number5 index4 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">Serial.begin(115200);</code></span></span></div>
<div class="line number6 index5 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">Serial.println("JSON parsing using ArduinoJson library on ESP32");</code></span></span></div>
<div class="line number7 index6 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"></span></span></div>
<div class="line number8 index7 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">}</code></span></span></div>
<div class="line number9 index8 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"> </span></span></div>
<div class="line number10 index9 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp keyword bold" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: rgb(0, 102, 153) !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: bold !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">void</code> <code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">loop() {</code></span></span></div>
<div class="line number12 index11 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"> <code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"></code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">Serial.println(</code><code class="cpp string" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: blue !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">"Parsing start: "</code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">);</code></span></span></div>
<div class="line number14 index13 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"> <code class="cpp color1 bold" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: gray !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: bold !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">char</code> <code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">JSONMsg[] = </code><code class="cpp string" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: blue !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">" {\"SensorType\": \"Temperature\", \"Value\": 10}"</code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">; </code><code class="cpp comments" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: rgb(0, 130, 0) !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">//Original message</code></span></span></div>
<div class="line number15 index14 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"> </span></span></div>
<div class="line number16 index15 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">StaticJsonBuffer<300> JSONBuffer; </code><code class="cpp comments" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: rgb(0, 130, 0) !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">//Memory pool</code></span></span></div>
<div class="line number17 index16 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">JsonObject& parsed = JSONBuffer.parseObject(JSONMsg); </code><code class="cpp comments" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: rgb(0, 130, 0) !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">//Parse message</code></span></span></div>
<div class="line number18 index17 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"> </span></span></div>
<div class="line number19 index18 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp keyword bold" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: rgb(0, 102, 153) !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: bold !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">if</code> <code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">(!parsed.success()) { </code><code class="cpp comments" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: rgb(0, 130, 0) !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">//Check for errors in parsing</code></span></span></div>
<div class="line number21 index20 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">Serial.println(</code><code class="cpp string" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: blue !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">"Parsing failed!"</code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">);</code></span></span></div>
<div class="line number22 index21 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">delay(5000);</code></span></span></div>
<div class="line number23 index22 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp keyword bold" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: rgb(0, 102, 153) !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: bold !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">return</code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">;</code></span></span></div>
<div class="line number25 index24 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">}</code></span></span></div>
<div class="line number26 index25 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"> </span></span></div>
<div class="line number27 index26 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp keyword bold" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: rgb(0, 102, 153) !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: bold !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">const</code> <code class="cpp color1 bold" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: gray !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: bold !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">char</code> <code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">* sensorType = parsed[</code><code class="cpp string" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: blue !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">"SensorType"</code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">]; </code><code class="cpp comments" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: rgb(0, 130, 0) !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">//Get sensor type value</code></span></span></div>
<div class="line number28 index27 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp color1 bold" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: gray !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: bold !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">int</code> <code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">value = parsed[</code><code class="cpp string" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: blue !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">"Value"</code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">]; </code><code class="cpp comments" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: rgb(0, 130, 0) !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">//Get value of sensor measurement</code></span></span></div>
<div class="line number29 index28 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"> </span></span></div>
<div class="line number30 index29 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">Serial.print(</code><code class="cpp string" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: blue !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">"Sensor type: "</code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">);</code></span></span></div>
<div class="line number31 index30 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">Serial.println(sensorType);</code></span></span></div>
<div class="line number32 index31 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">Serial.print(</code><code class="cpp string" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: blue !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">"Sensor value: "</code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">);</code></span></span></div>
<div class="line number33 index32 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">Serial.println(value);</code></span></span></div>
<div class="line number34 index33 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"> </span></span></div>
<div class="line number35 index34 alt2" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">Serial.println();</code></span></span></div>
<div class="line number36 index35 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp spaces" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;"> </code><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">delay(5000);</code></span></span></div>
<div class="line number38 index37 alt1" style="-webkit-text-stroke-width: 0px; background: white none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: #333333; direction: ltr !important; float: none !important; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; height: auto !important; left: auto !important; letter-spacing: normal; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px 1em !important; position: static !important; right: auto !important; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; top: auto !important; vertical-align: baseline !important; white-space: pre !important; width: auto !important; word-spacing: 0px;">
<span style="font-size: small;"><span style="font-family: "Courier New", Courier, monospace;"><code class="cpp plain" style="background: rgba(0, 0, 0, 0) none repeat scroll 0% 0% !important; border-radius: 0px !important; border: 0px none !important; bottom: auto !important; box-shadow: none !important; box-sizing: content-box !important; color: black !important; direction: ltr !important; display: inline !important; float: none !important; font-style: normal !important; font-weight: normal !important; height: auto !important; left: auto !important; line-height: 1.1em !important; margin: 0px !important; outline: currentcolor none 0px !important; overflow: visible !important; padding: 0px !important; position: static !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; width: auto !important;">}</code></span></span></div>
<br />
<br />
위의 코드를 ESP32에 다운로드 해서 실행하고 시리얼모니터를 열면 다음과 같은 결과가 출력 될 것이다.<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">JSON parsing using ArduinoJson library on ESP32</span><br />
<span style="font-family: "Courier New", Courier, monospace;">Parsing start:</span><br />
<span style="font-family: "Courier New", Courier, monospace;">Sensor type: Temperature</span><br />
<span style="font-family: "Courier New", Courier, monospace;">Sensor value: 10</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">Parsing start:</span><br />
<span style="font-family: "Courier New", Courier, monospace;">Sensor type: Temperature</span><br />
<span style="font-family: "Courier New", Courier, monospace;">Sensor value: 10</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">Parsing start:</span><br />
<span style="font-family: "Courier New", Courier, monospace;">Sensor type: Temperature</span><br />
<span style="font-family: "Courier New", Courier, monospace;">Sensor value: 10</span><br />
<br />
...<br />
<br />
<br />
<br />
<br />
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-28548204187166939872018-07-10T15:57:00.000+09:002018-07-10T15:57:59.806+09:00아두이노 우노/메가 시리얼 포트에서 가능한 최대 통신속도는?아두이노 우노/메가 하드웨어 시리얼 포트를 사용하는 경우 가장 빠른 속도는 얼마까지 가능할까?<br />
<br />
ATmega 프로세서에서 사용하는 USART는 UBRRn 레지스터와 UCSRnA에 있는 U2Xn 플래그로 통신 속도가 결정된다. 프로세서 클럭이 분주되어 USART의 클럭으로 들어가는데 가장 빠르게 설정하면 (UBRRn = 0, U2Xn = 1 로 설정) 프로세서 클럭이 8분주 되어 USART에 들어가게 된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihQzJ-oVGQFWWUCSNhaIPwELXeDvCw5qTRcssHiQAwfWIH6WwIm5nK8EWy3zMoFex0WMUi1DOkGQJVNIay24bEePz61iYeDWNhc3gW8s-lwIJbn1x5cVKNn1FtAm5IpWBDusEv1GFIuNw/s1600/ATmega640_1280_1281_2560_2561_datasheet.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="573" data-original-width="1262" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihQzJ-oVGQFWWUCSNhaIPwELXeDvCw5qTRcssHiQAwfWIH6WwIm5nK8EWy3zMoFex0WMUi1DOkGQJVNIay24bEePz61iYeDWNhc3gW8s-lwIJbn1x5cVKNn1FtAm5IpWBDusEv1GFIuNw/s640/ATmega640_1280_1281_2560_2561_datasheet.png" width="640" /></a></div>
<br />
<br />
아두이노 우노/메가는 16MHz 클럭을 사용하므로 USART에는 2MHz의 클럭이 들어가게 되어 최대 2Mbps의 속도로 시리얼 통신이 가능하게 된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB2lp2XtUORNH53qzRbGSafha0YjnZM8-pXFAXrhA2Yt3FbGy9ifWOvBJmMSUQnRZ5T-nwiAkXqe01tFojSdBaRtAmRQPX52yPcD6p_C8Y9YLYEHCWvW0x0G8GnKR5MAk4jPxXi9FQwlU/s1600/ATmega640_1280_1281_2560_2561_datasheet-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="871" data-original-width="988" height="564" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB2lp2XtUORNH53qzRbGSafha0YjnZM8-pXFAXrhA2Yt3FbGy9ifWOvBJmMSUQnRZ5T-nwiAkXqe01tFojSdBaRtAmRQPX52yPcD6p_C8Y9YLYEHCWvW0x0G8GnKR5MAk4jPxXi9FQwlU/s640/ATmega640_1280_1281_2560_2561_datasheet-2.png" width="640" /></a></div>
테스트를 위해 간단한 코드를 만들어 실행시켜 보았다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbVShepG551pp09w4cnVUHddCTA_bi5vlnQtA1w_qmkZrCZgH3ChabpXIfy_yq1ENUPmnW9NFnUqFUsGeVgF96X312XheljhN-599a3WAwF4RUzg5aCN7Tpx7-pgWAmiOphEAaz3eR_GM/s1600/_dev_cu_usbmodem21__Arduino_Genuino_Mega_or_Mega_2560__%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_sketch_jul10b___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_2_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_atmega2560_USART_to_pc_terminal___AVR_Freaks.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="609" data-original-width="637" height="610" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbVShepG551pp09w4cnVUHddCTA_bi5vlnQtA1w_qmkZrCZgH3ChabpXIfy_yq1ENUPmnW9NFnUqFUsGeVgF96X312XheljhN-599a3WAwF4RUzg5aCN7Tpx7-pgWAmiOphEAaz3eR_GM/s640/_dev_cu_usbmodem21__Arduino_Genuino_Mega_or_Mega_2560__%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_sketch_jul10b___%25E1%2584%258B%25E1%2585%25A1%25E1%2584%2583%25E1%2585%25AE%25E1%2584%258B%25E1%2585%25B5%25E1%2584%2582%25E1%2585%25A9_1_8_2_%25E1%2584%2586%25E1%2585%25B5%25E1%2586%25BE_atmega2560_USART_to_pc_terminal___AVR_Freaks.png" width="640" /></a></div>
<br />
위의 화면에서 볼 수 있듯이 깔끔하게 출력이 되고 있다.<br />
<br />
확실하게 확인하기 위해 오실로 스코프로 신호를 잡아 보았다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiPpmVJrrnmGPc1PW6u0zL3JrTVXjE2kNIAd9FcClmcdmHGl6D1dqchf4MiXC5XdvvKM95OWhWkqfqFbyCeHMTh_OI54J9w8Niose-RUj0M7x0o3ejkvWgRBPQUFbwPIP3FMaJZ14lCsk/s1600/IMG_9939-2-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiPpmVJrrnmGPc1PW6u0zL3JrTVXjE2kNIAd9FcClmcdmHGl6D1dqchf4MiXC5XdvvKM95OWhWkqfqFbyCeHMTh_OI54J9w8Niose-RUj0M7x0o3ejkvWgRBPQUFbwPIP3FMaJZ14lCsk/s640/IMG_9939-2-2.jpg" width="640" /></a></div>
<br />
먼저 9600 bps일때의 파형이다.<br />
<br />
2초 간격으로 'A'를 출력하고 있는 코드이다. 'A'의 아스키코드 값은 65(0x41)이므로 2진수로 하면 01000001 이 된다. 시리얼 출력의 경우 먼저 1비트 길이의 start bit (무조건 '0') + 8비트 데이터 + 1비트 길이의 stop bit(무조건 '1')가 전송되고 데이터의 경우 LSB부터 먼저 전송되게 된다. 그러므로 위의 화면과 같이 0(start bit) 1(LSB) 0 0 0 0 0 1 0(MSB) 1(stop bit) 이 전송된다. 한 비트의 길이는 약 105us, 즉 9.5238Khz의 신호가 된다.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqFBHkoCzpZiomFgVuTQzIFMbgbK1K6946bL8N6ZO0iM9HbUinQ9CqoIxvBANeOM3qQUMAxfOPurH1k06Lq3vgBXYSXwkV422MNgcHdkXESXXSFDWR7W3hKl7q2TXT58hGTrYuvqJctk0/s1600/IMG_9940-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqFBHkoCzpZiomFgVuTQzIFMbgbK1K6946bL8N6ZO0iM9HbUinQ9CqoIxvBANeOM3qQUMAxfOPurH1k06Lq3vgBXYSXwkV422MNgcHdkXESXXSFDWR7W3hKl7q2TXT58hGTrYuvqJctk0/s640/IMG_9940-2.jpg" width="640" /></a></div>
<br />
2Mbps일때의 파형이다. 기본적으로 9600 bps일때와 동일한 모양이나 한 비트 길이가 500ns, 즉 2MHz의 신호가 된다. ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-11697619286150125192018-07-02T16:51:00.001+09:002018-07-02T16:51:43.549+09:00ESP32에서 FreeRTOS 사용 - TASK에 parameter 넘겨주기FreeRTOS에서 태스크를 만드는 방법은 이전 포스트에서 설명했다. 이때 사용하는 API에 보면 몇개의 파라미터가 있는데 "void *pvParameters", "UBaseType_t uxPriority", "TaskHandle_t *pxCreatedTask"를 사용하는 법을 설명하겠다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> const char * const pcName,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> uint16_t usStackDepth,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> void *pvParameters,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> UBaseType_t uxPriority,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> TaskHandle_t *pxCreatedTask)</span><br />
<br />
데모<br />
<br />
1) Task Parameter<br />
"void *pvParameters"는 TaskFunction_t에 입력을 전달해주기 위해 사용한다. 예를 들어 void hello_world_task(void *param) 이라는 태스크를 가지고 있으면 "void *pvParameters"는 "void *param"이다. 우리는 이 예제에서 태스크를 만들고 그 태스크에 파라미터를 전달할 때 이 파라미터가 태스크 함수에 전달되고, 터미널에 이 파라미터를 출력한다.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">void setup() {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.begin(115200);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> char task1Param[13] = "task1Param";</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"> xTaskCreate (task1, // task function</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> "task1", // name of task</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 10000, // stack size of task</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> (void *) task1Param, // parameter of the task</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 1, // priority of the task</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> NULL); // task handle to keep track of created task</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">void loop() {</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">}</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">// this function will be invoked when additionalTask was created </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">void task1 ( void * parameter )</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">{</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println((char *)parameter);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while (1) { // loop forever</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> Serial.println("task1 is running");</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> delay(1000);</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> vTaskDelete( NULL ); // delete a task when finish,</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // this will not happen</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> // because this is infinitely loop</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">} </span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-q52wqwqq5pk/WT_qyWrR8_I/AAAAAAAAEDA/UwskhO6O_TMT0yLmCvTSXUq6_2iZKkTYwCEw/s1600/esp32task_param.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="589" data-original-width="805" src="https://2.bp.blogspot.com/-q52wqwqq5pk/WT_qyWrR8_I/AAAAAAAAEDA/UwskhO6O_TMT0yLmCvTSXUq6_2iZKkTYwCEw/s1600/esp32task_param.png" /> </a></div>
2) Task Priorities<br />
<br />
FreeRTOS는 3가지 종류의 스케쥴링 방식을 지원한다.<br />
<br />
- Co-operative scheduling<br />
실행중인 태스크는 running 상태에서 blocked 상태로 바뀌거나 또는 taskYIELD()를 호출할 때 컨택스트 스위칭이 발생한다. 그럼 나머지 태스크 중에 가장 높은 우선순위를 가지고 있는 태스크가 실행되게 된다.<br />
<br />
- Prioritized pre-emptive scheduling with time slicing<br />
높은 우선순위(priority)를 가진 태스크가 낮은 우선순위를 가진 태스크를 preempt한다. 같은 우선순위를 가진 태스크 끼리는 time tick 인터럽트가 발생할 때 마다 순서를 바꿔 실행한다. (RTOS는 시간을 측정하기 위한 타이머 인터럽트를 가지고 있는데, 매번 인터럽트가 발생할 때 마다 RTOS는 태스크를 unblock 또는 깨울 시간인지 체크한다.)<br />
<br />
- Priotitized pre-emptive scheduling without time slicing<br />
높은 우선순위(priority)를 가진 태스크가 낮은 우선순위를 가진 태스크를 preempt한다. 같은 우선순위를 가진 태스크는 매번 time tick 인터럽트가 발생할 때마다 순서를 바꾸지 않는다. (실행중인 태스크는 더 높은 우선순위를 가진 태스크에 의해 preempt 될 때 까지 계속 실행한다.)<br />
<br />
2-1) Prioritized pre-emptive scheduling with time slicing 데모<br />
현재 Arduino ESP32의 FreeRTOS는 Prioritized pre-emptive scheduling with time slicing을 사용하도록 설정되어 있으므로 여기서는 이 방식의 스케쥴링 데모를 만들어 보았다. 2개의 태스크를 만드는데 task1은 우선순위 1, task2는 우선순위 4를 가진다. task1은 "task1 is running"과 "task1 is ending"이라는 글자를 터미널에 출력한다. task2는 "task2 is running"과 "task2 is ending"이라는 글자를 터미널에 출력한다. 그러므로 대부분의 시간은 task2가 터미널에 출력하는데 사용된다.<br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<br />
<pre style="line-height: 125%; margin: 0;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">setup</span>() {
Serial.begin(<span style="color: #0000dd; font-weight: bold;">115200</span>);
<span style="color: #333399; font-weight: bold;">char</span> task1Param[<span style="color: #0000dd; font-weight: bold;">12</span>] <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"taskParam"</span>;
xTaskCreate(
task1, <span style="color: #888888;">// Task function</span>
<span style="background-color: #fff0f0;">"task1"</span>, <span style="color: #888888;">// name of task</span>
<span style="color: #0000dd; font-weight: bold;">10000</span>, // <span style="color: #888888;">Stack size of task</span>
(<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #333333;">*</span>)task1Param, // <span style="color: #888888;">parameter of the task</span>
<span style="color: #0000dd; font-weight: bold;">1</span>, <span style="color: #888888;">// priority of the task </span>
<span style="color: #007020;">NULL</span>); <span style="color: #888888;">// Task handle to keep track of created task </span>
xTaskCreate(
task2, <span style="color: #888888;">// Task function. </span>
<span style="background-color: #fff0f0;">"task2"</span>, <span style="color: #888888;">// name of task. </span>
<span style="color: #0000dd; font-weight: bold;">10000</span>, //<span style="color: #888888;"> Stack size of task </span>
(<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #333333;">*</span>)task1Param, <span style="color: #888888;">// parameter of the task </span>
<span style="color: #0000dd; font-weight: bold;">4</span>, <span style="color: #888888;">// priority of the task </span>
<span style="color: #007020;">NULL</span>); <span style="color: #888888;">// Task handle to keep track of created task </span>
}
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">loop</span>() {
}
<span style="color: #888888;"> </span></span></pre>
<pre style="line-height: 125%; margin: 0;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #888888;">// this function will be invoked when additionalTask was created </span>
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">task1</span>( <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #333333;">*</span> parameter )
{
Serial.println((<span style="color: #333399; font-weight: bold;">char</span> <span style="color: #333333;">*</span>)parameter);
while(1){
Serial.println(<span style="background-color: #fff0f0;">"task1 is running"</span>);
Serial.println(<span style="background-color: #fff0f0;">"task1 is ending"</span>);
}
vTaskDelete( <span style="color: #007020;">NULL</span> );
}
</span><span style="font-family: "courier new" , "courier" , monospace;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #888888;">// this function will be invoked when additionalTask was created </span></span>
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">task2</span>( <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #333333;">*</span> parameter )
{
Serial.println((<span style="color: #333399; font-weight: bold;">char</span> <span style="color: #333333;">*</span>)parameter);
while <span style="color: #008800; font-weight: bold;"></span>(1){
Serial.println(<span style="background-color: #fff0f0;">"task2 is running"</span>);
Serial.println(<span style="background-color: #fff0f0;">"task2 is ending"</span>);
}
vTaskDelete( <span style="color: #007020;">NULL</span> );
} </span></pre>
<pre style="line-height: 125%; margin: 0;"> </pre>
<pre style="line-height: 125%; margin: 0;"> </pre>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-7yaO_jetQsg/WUAKD6-9yaI/AAAAAAAAEDQ/8BrgxBq1KQo6E7PLX7a3SUHaTz8DAMI3wCLcB/s1600/esp32task_priority.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="781" data-original-width="506" src="https://1.bp.blogspot.com/-7yaO_jetQsg/WUAKD6-9yaI/AAAAAAAAEDQ/8BrgxBq1KQo6E7PLX7a3SUHaTz8DAMI3wCLcB/s1600/esp32task_priority.png" /></a></div>
<pre style="line-height: 125%; margin: 0;"> </pre>
2-2) Task Handle<br />
<br />
Task Handle은 만들어 진 테스크의 레퍼런스를 가지고 있기 때문에 나중에 그 태스크를 삭제하거나 우선순위를 바꾸는 등의 작업을 할 수 있다. <br />
<br />
<br />
<br />
2-2-1) Task Handle 데모<br />
위의 2-1) 데모 코드를 재사용하는데 요구사항을 약간 바꿔 보았다. task2가 20번 실행되면 task1의 우선순위를 4로 바꾸고 task2의 우선순위를 1로 바꿔주어 이제부터는 터미널에 task1이 출력하는 내용이 대부분을 차지하게 된다.<br />
<br />
<pre style="line-height: 125%; margin: 0;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #888888;">// task handle variables to hold instances of tasks</span>
TaskHandle_t t1 <span style="color: #333333;">=</span> <span style="color: #007020;">NULL</span>;
TaskHandle_t t2 <span style="color: #333333;">=</span> <span style="color: #007020;">NULL</span>;
<span style="color: #333399; font-weight: bold;">int</span> count <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>;
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">setup</span>() {
Serial.begin(<span style="color: #0000dd; font-weight: bold;">115200</span>);
<span style="color: #333399; font-weight: bold;">char</span> task1Param[<span style="color: #0000dd; font-weight: bold;">12</span>] <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"taskParam"</span>; </span></pre>
<pre style="line-height: 125%; margin: 0;"><span style="font-family: "courier new" , "courier" , monospace;"> </span></pre>
<pre style="line-height: 125%; margin: 0;"><span style="font-family: "courier new" , "courier" , monospace;"> xTaskCreate(
task1, <span style="color: #888888;">// Task function. </span>
<span style="background-color: #fff0f0;">"task1"</span>, <span style="color: #888888;">// name of task. </span>
<span style="color: #0000dd; font-weight: bold;">10000</span>, <span style="color: #888888;">// Stack size of task </span>
(<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #333333;">*</span>)task1Param, <span style="color: #888888;">// parameter of the task </span>
<span style="color: #0000dd; font-weight: bold;">1</span>, //<span style="color: #888888;"> priority of the task </span>
<span style="color: #333333;">&</span>t1); //<span style="color: #888888;"> Task handle to keep track of created task </span><span style="color: #888888;"></span>
xTaskCreate(
task2, <span style="color: #888888;">// Task function. </span>
<span style="background-color: #fff0f0;">"task2"</span>, <span style="color: #888888;">// name of task. </span>
<span style="color: #0000dd; font-weight: bold;">10000</span>, //<span style="color: #888888;"> Stack size of task </span>
(<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #333333;">*</span>)task1Param, <span style="color: #888888;">// parameter of the task </span>
<span style="color: #0000dd; font-weight: bold;">4</span>, //<span style="color: #888888;"> priority of the task </span>
<span style="color: #333333;">&</span>t2); //<span style="color: #888888;"> Task handle to keep track of created task </span>
}
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">loop</span>() {
}
<span style="color: #888888;"> </span></span></pre>
<pre style="line-height: 125%; margin: 0;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #888888;">// this function will be invoked when additionalTask was created </span>
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">task1</span>( <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #333333;">*</span> parameter )
{
Serial.println((<span style="color: #333399; font-weight: bold;">char</span> <span style="color: #333333;">*</span>)parameter);
<span style="color: #008800; font-weight: bold;"></span>while (1){
Serial.println(<span style="background-color: #fff0f0;">"task1 is running"</span>);
Serial.println(<span style="background-color: #fff0f0;">"task1 is ending"</span>);
}
vTaskDelete( <span style="color: #007020;">NULL</span> );
}
<span style="color: #888888;">// this function will be invoked when additionalTask was created </span>
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">task2</span>( <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #333333;">*</span> parameter )
{
Serial.println((<span style="color: #333399; font-weight: bold;">char</span> <span style="color: #333333;">*</span>)parameter);
while (1) {
count<span style="color: #333333;">++</span>;
<span style="color: #888888;">// if count is 20 then we swap the priority of 2 tasks </span>
<span style="color: #008800; font-weight: bold;">if</span>(20 == count<span style="color: #0000dd; font-weight: bold;"></span>){
vTaskPrioritySet( t1, <span style="color: #0000dd; font-weight: bold;">4</span> );
vTaskPrioritySet( t2, <span style="color: #0000dd; font-weight: bold;">1</span> );
}
Serial.println(<span style="background-color: #fff0f0;">"task2 is running"</span>);
Serial.println(<span style="background-color: #fff0f0;">"task2 is ending"</span>);
}
vTaskDelete( <span style="color: #007020;">NULL</span> );
}
</span></pre>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://4.bp.blogspot.com/-YyNHGGEgi7g/WUAPAdUTrmI/AAAAAAAAEDg/bI0NrbUQPncX4UTL9ofl7E2lAJTtrNN6ACEw/s1600/esp32task_handle.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="784" data-original-width="425" src="https://4.bp.blogspot.com/-YyNHGGEgi7g/WUAPAdUTrmI/AAAAAAAAEDg/bI0NrbUQPncX4UTL9ofl7E2lAJTtrNN6ACEw/s1600/esp32task_handle.png" /></a></div>
<br />
<br />
2-3) Idle Task Hook Function<br />
<br />
Idle 태스크(백그라운드 태스크)는 다음과 같은 특징을 가진다.<br />
- 스케쥴러에 의해 만들어 짐<br />
- 가장 낮은 우선순위를 가짐 (우선순위 0)<br />
- 다른 모든 태스크들이 blocked 상태일 때 실행상태가 됨<br />
<br />
Idle 태스크에 함수를 hook하는것이 가능하다. 이 함수는 idle 태스크가 실행될 때 호출된다.<br />
이 태스크를 사용해 다음과 같은 일을 하는데 사용할 수 있다.<br />
- 백그라운드에서 어떤 작업 수행<br />
- 시스템의 spare time 측정<br />
- 할 일이 없을 떼 마이크로 프로세서를 low power mode로 진입시킴<br />
- 태스크가 삭제될 때 리소스 정리<br />
<br />
주의) 태스크 hook 함수내에서 idle 태스크를 block시키는 어떠한 작업도 하면 안된다.<br />
<br />
task hook 함수를 사용하려면 단순히 "bool vApplicationIdleHook(void)" 프로토타입의 함수를 구현해 주고 esp_register_freertos_idle_hool(vApplicationIdleHook)을 호출해 hook 함수를 등록해 주면 된다.<br />
<br />
2-3-1) 데모<br />
task hook 함수를 만들어 주고 이 함수가 호출될 때 마다 카운터를 1씩 증가시킨다. 생성된 태스크 함수에서는 단지 이 값을 출력한다.<br />
<br />
<pre style="line-height: 125%; margin: 0;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #557799;">#include "esp_freertos_hooks.h"</span>
<span style="color: #333399; font-weight: bold;">int</span> counter <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>;
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">setup</span>() {
Serial.begin(<span style="color: #0000dd; font-weight: bold;">115200</span>);
esp_register_freertos_idle_hook(vApplicationIdleHook);
<span style="color: #333399; font-weight: bold;">char</span> task1Param[<span style="color: #0000dd; font-weight: bold;">12</span>] <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"task1Param"</span>;
xTaskCreate(
task1, <span style="color: #888888;">// Task function. </span>
<span style="background-color: #fff0f0;">"task1"</span>, //<span style="color: #888888;"> name of task. </span>
<span style="color: #0000dd; font-weight: bold;">10000</span>, //<span style="color: #888888;"> Stack size of task </span>
(<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #333333;">*</span>)task1Param, <span style="color: #888888;">// parameter of the task </span>
<span style="color: #0000dd; font-weight: bold;">1</span>, <span style="color: #888888;">// priority of the task </span>
<span style="color: #007020;">NULL</span>); //<span style="color: #888888;"> Task handle to keep track of created task </span>
}
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">loop</span>() {
}
<span style="color: #888888;"> </span></span></pre>
<pre style="line-height: 125%; margin: 0;"><span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #888888;">// this function will be invoked when additionalTask was created </span>
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">task1</span>( <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #333333;">*</span> parameter )
{
Serial.println((<span style="color: #333399; font-weight: bold;">char</span> <span style="color: #333333;">*</span>)parameter);
<span style="color: #008800; font-weight: bold;"></span>while (1) {
Serial.print(<span style="background-color: #fff0f0;">"task1 is running and counter : "</span>);
Serial.println(counter);
<span style="color: #008800; font-weight: bold;">if</span>(counter <span style="color: #333333;">></span> <span style="color: #0000dd; font-weight: bold;">30000</span>)
{
counter <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>;
}
<span style="color: #888888;">// block this task so that Idle task has chance to run </span>
delay(<span style="color: #0000dd; font-weight: bold;">10</span>);
}
vTaskDelete( <span style="color: #007020;">NULL</span> );
}
<span style="color: #888888;">// define task hook function </span>
<span style="color: #333399; font-weight: bold;">bool</span> <span style="color: #0066bb; font-weight: bold;">vApplicationIdleHook</span>(<span style="color: #333399; font-weight: bold;">void</span>)
{
counter<span style="color: #333333;">++</span>;
}</span></pre>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-qc3cbaVqZc8/WUX1YNHpxuI/AAAAAAAAEEo/tBv62Ix6dAYIlgeBbf86ueWG8dC5_kFuQCLcBGAs/s1600/esp32freertostaskhook.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="771" data-original-width="560" src="https://3.bp.blogspot.com/-qc3cbaVqZc8/WUX1YNHpxuI/AAAAAAAAEEo/tBv62Ix6dAYIlgeBbf86ueWG8dC5_kFuQCLcBGAs/s1600/esp32freertostaskhook.png" /></a></div>
<br />ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0tag:blogger.com,1999:blog-6762236726539517408.post-34159075610061537372018-07-02T16:50:00.002+09:002018-07-02T16:50:54.549+09:00ESP32에서 FreeRTOS 사용 - Message Queue 사용하기FreeRTOS에서<br />
<br />
- Queue는 태스크 간 교환되는 데이터/메시지를저장하는데 사용<br />
- 데이터는 queue에 카피됨 (포인터로 참조되는게 아님)<br />
- 여러 태스크가 억세스 할 수 있음<br />
- Queue Read는 blocking 동작 (큐에 데이터가 없으면 데이터를 기다리기 위해 태스크는 blocked 상태가 됨)<br />
- Queue Write는 blocking 동작 (큐에 빈 공간이 없으면 빈 공간이 생기는걸 기디리기 위해 태스크는 blocked 상태가 됨)<br />
- mulitple queue에 대해 blocking 동작 (큐 그룹에 데이터가 들어오는걸 기다리기 위해 태스크는 blocked 상태가 됨)<br />
<br />
* 데모<br />
이 데모에서는 3개의 태스크를 만드는데, 2개의 태스크는 sending 태스크이고 1개는 receiving 태스크이다. sending 태스크는 sender id와 태스크의 카운트 값을 가지고 있는 데이터를 보낸다.<br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<pre style="line-height: 125%; margin: 0;"><span style="font-family: "Courier New", Courier, monospace;"><span style="color: #888888;">// structure that hold data</span>
<span style="color: #008800; font-weight: bold;">typedef</span> <span style="color: #008800; font-weight: bold;">struct</span>{
<span style="color: #333399; font-weight: bold;">int</span> sender;
<span style="color: #333399; font-weight: bold;">int</span> counter;
}Data;
<span style="color: #888888;">// this variable hold queue handle </span>
xQueueHandle xQueue;
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">setup</span>() {
Serial.begin(<span style="color: #0000dd; font-weight: bold;">115200</span>);
<span style="color: #888888;">// create the queue which size can contains 5 elements of Data</span>
xQueue <span style="color: #333333;">=</span> xQueueCreate(<span style="color: #0000dd; font-weight: bold;">5</span>, <span style="color: #008800; font-weight: bold;">sizeof</span>(Data));
xTaskCreate(
sendTask1, <span style="color: #888888;">// Task function. </span>
<span style="background-color: #fff0f0;">"sendTask1"</span>, <span style="color: #888888;">// name of task. </span>
<span style="color: #0000dd; font-weight: bold;">10000</span>, //<span style="color: #888888;"> Stack size of task </span>
<span style="color: #007020;">NULL</span>, //<span style="color: #888888;"> parameter of the task </span>
<span style="color: #0000dd; font-weight: bold;">2</span>, //<span style="color: #888888;"> priority of the task </span>
<span style="color: #007020;">NULL</span>); //<span style="color: #888888;"> Task handle to keep track of created task </span>
xTaskCreate(
sendTask2, </span><span style="font-family: "Courier New", Courier, monospace;"><span style="color: #888888;">// Task function. </span></span><span style="font-family: "Courier New", Courier, monospace;"><span style="color: #888888;"></span>
<span style="background-color: #fff0f0;">"sendTask2"</span>, //<span style="color: #888888;"> name of task. </span>
<span style="color: #0000dd; font-weight: bold;">10000</span>, //<span style="color: #888888;"> Stack size of task </span>
<span style="color: #007020;">NULL</span>, //<span style="color: #888888;"> parameter of the task </span>
<span style="color: #0000dd; font-weight: bold;">2</span>, //<span style="color: #888888;"> priority of the task </span>
<span style="color: #007020;">NULL</span>); //<span style="color: #888888;"> Task handle to keep track of created task </span>
xTaskCreate(
receiveTask, //<span style="color: #888888;"> Task function. </span>
<span style="background-color: #fff0f0;">"</span><span style="background-color: #fff0f0;">receiveTask"</span>, //<span style="color: #888888;"> name of task. </span>
<span style="color: #0000dd; font-weight: bold;">10000</span>, //<span style="color: #888888;"> Stack size of task </span>
<span style="color: #007020;">NULL</span>, //<span style="color: #888888;"> parameter of the task </span>
<span style="color: #0000dd; font-weight: bold;">1</span>, //<span style="color: #888888;"> priority of the task </span>
<span style="color: #007020;">NULL</span>); //<span style="color: #888888;"> Task handle to keep track of created task </span>
}
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">loop</span>() {
}
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">sendTask1</span>( <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #333333;">*</span> parameter )
{
BaseType_t xStatus; </span><span style="font-family: "Courier New", Courier, monospace;"><span style="font-family: "Courier New", Courier, monospace;"><span style="color: #888888;">// keep the status of sending data </span></span>
<span style="color: #888888;">// time to block the task until the queue has free space </span>
<span style="color: #008800; font-weight: bold;">const</span> TickType_t xTicksToWait <span style="color: #333333;">=</span> pdMS_TO_TICKS(<span style="color: #0000dd; font-weight: bold;">100</span>);
Data data; </span><span style="font-family: "Courier New", Courier, monospace;"><span style="font-family: "Courier New", Courier, monospace;"><span style="color: #888888;">// create data to send </span></span>
data.sender <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">1</span>; </span><span style="font-family: "Courier New", Courier, monospace;"><span style="font-family: "Courier New", Courier, monospace;"><span style="color: #888888;">// sender 1 has id is 1</span></span>
data.counter <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">1</span>;
<span style="color: #008800; font-weight: bold;">for</span>(;;){
Serial.println(<span style="background-color: #fff0f0;">"sendTask1 is sending data"</span>);
<span style="color: #888888;">// send data to front of the queue </span>
xStatus <span style="color: #333333;">=</span> xQueueSendToFront( xQueue, <span style="color: #333333;">&</span>data, xTicksToWait );
<span style="color: #888888;">// check whether sending is ok or not </span>
<span style="color: #008800; font-weight: bold;">if</span>( xStatus <span style="color: #333333;">==</span> pdPASS ) { </span><span style="font-family: "Courier New", Courier, monospace;"><span style="font-family: "Courier New", Courier, monospace;"><span style="color: #888888;">// increase counter of sender</span></span><span style="color: #888888;"></span>
data.counter <span style="color: #333333;">=</span> data.counter <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>;
}
<span style="color: #888888;">// we delay here so that receiveTask has chance to receive data</span>
delay(<span style="color: #0000dd; font-weight: bold;">1000</span>);
}
vTaskDelete( <span style="color: #007020;">NULL</span> );
}
<span style="color: #888888;"> </span></span></pre>
<pre style="line-height: 125%; margin: 0;"><span style="font-family: "Courier New", Courier, monospace;"><span style="color: #888888;">// this task is similar to sendTask1 </span>
<span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">sendTask2</span>( <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #333333;">*</span> parameter )
{
BaseType_t xStatus;
<span style="color: #008800; font-weight: bold;">const</span> TickType_t xTicksToWait <span style="color: #333333;">=</span> pdMS_TO_TICKS(<span style="color: #0000dd; font-weight: bold;">100</span>);
Data data;
data.sender <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">2</span>;
data.counter <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">1</span>;
<span style="color: #008800; font-weight: bold;">for</span>(;;){
Serial.println(<span style="background-color: #fff0f0;">"sendTask2 is sending data"</span>);
xStatus <span style="color: #333333;">=</span> xQueueSendToFront( xQueue, <span style="color: #333333;">&</span>data, xTicksToWait );
<span style="color: #008800; font-weight: bold;">if</span>( xStatus <span style="color: #333333;">==</span> pdPASS ) {
data.counter <span style="color: #333333;">=</span> data.counter <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>;
}
delay(<span style="color: #0000dd; font-weight: bold;">1000</span>);
}
vTaskDelete( <span style="color: #007020;">NULL</span> );
}</span></pre>
<pre style="line-height: 125%; margin: 0;"><span style="font-family: "Courier New", Courier, monospace;"> </span></pre>
<pre style="line-height: 125%; margin: 0;"><span style="font-family: "Courier New", Courier, monospace;"><span style="color: #333399; font-weight: bold;">void</span> <span style="color: #0066bb; font-weight: bold;">receiveTask</span>( <span style="color: #333399; font-weight: bold;">void</span> <span style="color: #333333;">*</span> parameter )
{
BaseType_t xStatus; </span><span style="font-family: "Courier New", Courier, monospace;"><span style="font-family: "Courier New", Courier, monospace;"><span style="color: #888888;">// keep the status of receiving data </span></span>
<span style="color: #888888;">// time to block the task until data is available </span>
<span style="color: #008800; font-weight: bold;">const</span> TickType_t xTicksToWait <span style="color: #333333;">=</span> pdMS_TO_TICKS(<span style="color: #0000dd; font-weight: bold;">100</span>);
Data data;
<span style="color: #008800; font-weight: bold;"></span>while (1) { </span><span style="font-family: "Courier New", Courier, monospace;"><span style="font-family: "Courier New", Courier, monospace;"> <span style="color: #888888;">// receive data from the queue</span></span>
xStatus <span style="color: #333333;">=</span> xQueueReceive( xQueue, <span style="color: #333333;">&</span>data, xTicksToWait );
<span style="color: #008800; font-weight: bold;">if</span>(xStatus <span style="color: #333333;">==</span> pdPASS){ </span><span style="font-family: "Courier New", Courier, monospace;"><span style="font-family: "Courier New", Courier, monospace;"><span style="color: #888888;">// check whether receiving is ok or not </span></span>
<span style="color: #888888;">// print the data to terminal </span>
Serial.print(<span style="background-color: #fff0f0;">"receiveTask got data: "</span>);
Serial.print(<span style="background-color: #fff0f0;">"sender = "</span>);
Serial.print(data.sender);
Serial.print(<span style="background-color: #fff0f0;">" counter = "</span>);
Serial.println(data.counter);
}</span></pre>
<pre style="line-height: 125%; margin: 0;"><span style="font-family: "Courier New", Courier, monospace;"> }
vTaskDelete( <span style="color: #007020;">NULL</span> );
} </span></pre>
<pre style="line-height: 125%; margin: 0;"> </pre>
<pre style="line-height: 125%; margin: 0;"> </pre>
<pre style="line-height: 125%; margin: 0;"> </pre>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-Cn4SodvfAU8/WUFbngXemXI/AAAAAAAAEDs/k4yHBd9U3WkroFeHi3oyrgiVhLeLRXLAQCLcBGAs/s1600/esp32task_queue.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="766" data-original-width="626" src="https://3.bp.blogspot.com/-Cn4SodvfAU8/WUFbngXemXI/AAAAAAAAEDs/k4yHBd9U3WkroFeHi3oyrgiVhLeLRXLAQCLcBGAs/s1600/esp32task_queue.png" /></a></div>
<pre style="line-height: 125%; margin: 0;"> </pre>
<pre style="line-height: 125%; margin: 0;"> </pre>
ArsViatorhttp://www.blogger.com/profile/05132375494512856451noreply@blogger.com0