panweitong 4 years ago
commit
0d98d39d51
100 changed files with 2117 additions and 0 deletions
  1. 1 0
      README.md
  2. 36 0
      aikit/A0.md
  3. 263 0
      aikit/AI_1.md
  4. 292 0
      aikit/AI_2.md
  5. 179 0
      aikit/AI_3.md
  6. 366 0
      aikit/AI_4.md
  7. 1 0
      aikit/overview.md
  8. 28 0
      changelog.md
  9. 445 0
      colorpicker.js
  10. 7 0
      docsify-themeable
  11. 0 0
      docsify.min.js
  12. 69 0
      extension/EX_01.md
  13. 173 0
      extension/EX_02.md
  14. 46 0
      extension/EX_03.md
  15. 1 0
      extension/overview.md
  16. 6 0
      faq.md
  17. 1 0
      getting-started.md
  18. 172 0
      index.html
  19. 18 0
      index.md
  20. 13 0
      lightbox-plus-jquery.min.js
  21. 0 0
      lightbox.min.css
  22. BIN
      media/EX/001.jpg
  23. BIN
      media/EX/002.jpg
  24. BIN
      media/EX/003.jpg
  25. BIN
      media/EX/003.png
  26. BIN
      media/EX/004.jpg
  27. BIN
      media/EX/005.jpg
  28. BIN
      media/EX/005.png
  29. BIN
      media/EX/006.jpg
  30. BIN
      media/EX/007.jpg
  31. BIN
      media/EX/008.jpg
  32. BIN
      media/EX/009.jpg
  33. BIN
      media/EX/010.jpg
  34. BIN
      media/EX/011.png
  35. BIN
      media/EX/012.jpg
  36. BIN
      media/EX/015.png
  37. BIN
      media/EX/016.png
  38. BIN
      media/EX/017.png
  39. BIN
      media/EX/018.jpg
  40. BIN
      media/EX/019.jpg
  41. BIN
      media/EX/019.png
  42. BIN
      media/EX/020.png
  43. BIN
      media/EX/021.png
  44. BIN
      media/EX/022.png
  45. BIN
      media/EX/023.png
  46. BIN
      media/EX/024.png
  47. BIN
      media/EX/025.png
  48. BIN
      media/EX/026.jpg
  49. BIN
      media/EX/027.png
  50. BIN
      media/EX/028.png
  51. BIN
      media/EX/029.png
  52. BIN
      media/EX/030.png
  53. BIN
      media/EX/031.png
  54. BIN
      media/EX/032.png
  55. BIN
      media/EX/033.png
  56. BIN
      media/EX/034.png
  57. BIN
      media/EX/035.png
  58. BIN
      media/EX/036.jpg
  59. BIN
      media/EX/037.png
  60. BIN
      media/EX/038.jpg
  61. BIN
      media/EX/039.png
  62. BIN
      media/EX/040.gif
  63. BIN
      media/EX/041.gif
  64. BIN
      media/EX/041.png
  65. BIN
      media/EX/042.gif
  66. BIN
      media/EX/043.jpg
  67. BIN
      media/EX/044.png
  68. BIN
      media/EX/045.png
  69. BIN
      media/EX/046.png
  70. BIN
      media/EX/047.png
  71. BIN
      media/EX/048.png
  72. BIN
      media/EX/049.jpg
  73. BIN
      media/EX/050.png
  74. BIN
      media/EX/051.png
  75. BIN
      media/EX/052.jpg
  76. BIN
      media/EX/053.png
  77. BIN
      media/EX/054.png
  78. BIN
      media/EX/055.png
  79. BIN
      media/EX/056.jpg
  80. BIN
      media/EX/056.png
  81. BIN
      media/EX/057.png
  82. BIN
      media/EX/058.png
  83. BIN
      media/EX/059.png
  84. BIN
      media/EX/060.png
  85. BIN
      media/EX/061.png
  86. BIN
      media/EX/062.png
  87. BIN
      media/EX/063.png
  88. BIN
      media/EX/064.png
  89. BIN
      media/EX/065.png
  90. BIN
      media/EX/w1.png
  91. BIN
      media/EX/w2.png
  92. BIN
      media/EX/w3.png
  93. BIN
      media/ai/AI_E1.png
  94. BIN
      media/ai/AI_E2.png
  95. BIN
      media/ai/AI_E3.png
  96. BIN
      media/ai/AI_I1.png
  97. BIN
      media/ai/AI_I10.png
  98. BIN
      media/ai/AI_I11.png
  99. BIN
      media/ai/AI_I12.png
  100. BIN
      media/ai/AI_I13.png

+ 1 - 0
README.md

@@ -0,0 +1 @@
+To be edited.

+ 36 - 0
aikit/A0.md

@@ -0,0 +1,36 @@
+# <b>Uploader常見錯誤處理</b>
+### 1.	關鍵字:name 'xxxx' isn't defined
+描述:這個意思是有變量未定義,這種情況都是代碼錯誤了。
+
+解決辦法:和上傳插件無關,看看積木是否搭建有問題。
+### 2.	關鍵字:'/private/tmp/PKInstallSandbox.rELsyx/tmp/python'
+描述:這個只有mac版本才有問題,意思是無法訪問python,發生在用戶安裝的時候沒有輸入密碼給軟件絕對權限安裝。
+
+解決辦法:重啟uploader即可。
+### 3.	關鍵字:Sipeed_M1 with kendryte-k210
+描述:攝像頭沒有插好或者壞了。
+
+解決辦法:插好攝像頭或者換壹個攝像頭。
+### 4.	關鍵字:could not open port 'xxx': PermissionError
+問題:usb接口給其他程序占用了,通常有兩種情況,一種是因為真的打開其他程序占用了,第二種就是重復點擊上傳按鈕。
+
+解決辦法:拔掉模塊重新插入,重新打開uploader。
+### 5.	關鍵字:Timeout
+描述:模塊還在連接中或者是啟動中或者模塊的串口芯片壞了。
+
+解決辦法:等壹下再上傳,或者是換新的模塊。
+### 6.	關鍵字:file “<stadin>” line xx in <module>
+描述:代碼運行錯誤。
+
+解決辦法:固件是舊版本的,導致有些函數不支持,更新壹下固件,或者是代碼寫錯了,修改代碼積木。
+
+### 7.	上傳一直卡在77%的問題
+描述:windows電腦有多個版本的python。
+
+解決辦法:卸載電腦所有的python版本,然後重新安裝uploader如下图:<br>
+1、點擊控制面板<br>
+ <img src="/media/EX/w1.png" width="400"/><br>
+2、點擊程序裏面的卸載程序<br>
+  <img src="/media/EX/w2.png"/><br>
+3、找到所有的python,全部右鍵卸載<br>
+   <img src="/media/EX/w3.png"/><br>

+ 263 - 0
aikit/AI_1.md

@@ -0,0 +1,263 @@
+# 認識CocoBlockly X編程環境
+---
+## A.	認識AI模組及應用
+
+## 模組簡介
+
+CocoRobo AI模組是CocoRobo為了推廣人工智能教育而研發的「即插即用式」的可編程電子模組。AI模組套裝是由AI推理模組、AI攝影鏡頭模組及AI螢幕模組三部份組成。
+
+## AI模組
+
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%"><img src="/media/ai/AI_zhengmian.png" width="350"/></td>
+		<td width="50%"><img src="/media/ai/AI_fanmian.png" width="350"/></td>
+	</tr>
+	<tr>
+		<td>正面</td>
+		<td>反面</td>
+	</tr>
+</table>
+
+AI 模組作爲人工智能相關應用的主控模組,擁有基礎計算機視覺識別功能和機器學習模型的推理功能,可幫助老師實現入門和進階級別的 AI 應用。
+<br>
+#### 功能組成及應用:
+1. 自帶WIFI功能,可聯網發送或者接收數據
+2. 支援Micro SD卡存取影像、視訊、機器學習模型、音樂等資料
+3. 集成攝影鏡頭模塊的插座,供後置拍攝使用
+
+## 攝影鏡頭模組
+
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%"><img src="/media/ai/AI_photozheng.png" width="350"/></td>
+		<td width="50%"><img src="/media/ai/AI_photofan.png" width="350"/></td>
+	</tr>
+	<tr>
+		<td>正面</td>
+		<td>反面</td>
+	</tr>
+</table>
+
+200w像素攝影鏡頭,可分別插在螢幕模組或者 AI 模組上,前拍後拍都可以。並且攝影鏡頭的影像尺寸有320 x 240 px及160 x 120 px兩款,使用時可自行選擇。
+
+## 螢幕模組
+
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%"><img src="/media/ai/AI_screenzheng.png" width="350"/></td>
+		<td width="50%"><img src="/media/ai/AI_screenfan.png" width="350"/></td>
+	</tr>
+	<tr>
+		<td>正面</td>
+		<td>反面</td>
+	</tr>
+</table>
+
+#### 功能組成及應用:
+1. 集成攝影鏡頭模組插座,供前置拍照使用;
+2. 1.54 寸 LCD 全彩螢幕,繪製JPG, BMP等格式圖片;
+3. 可用於外接的 3.5mm 音頻介面;
+4. 板載功放晶片及揚聲器,支援播放WAV格式的音訊檔案;
+
+## 模組連接及使用
+1)連接AI模組、攝影鏡頭模組和螢幕模組三部分,按照如下圖所示的位置進行連接
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%"><img src="/media/ai/AI_anzhuang_1.png" width="350"/></td>
+		<td width="20%"><img src="/media/ai/AI_anzhuang_3.png" width="350"/></td>
+    <td width="30%"><img src="/media/ai/AI_anzhuang_2.png" width="350"/></td>
+	</tr>
+</table>
+
+2)使用Micro USB數據線連接AI模組和電腦
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%"><img src="/media/ai/AI_usb_1.png" width="350"/></td>
+		<td width="50%"><img src="/media/ai/AI_usb_2.png" width="350"/></td>
+	</tr>
+	<tr>
+		<td>Micro USB數據線連接電子模組</td>
+		<td>Micro USB數據線連接電腦</td>
+	</tr>
+</table>
+
+連接完成後,便可看到初始介面,按如下圖所示的步驟即可體驗AI模組的功能樣例。<br>
+<img src="/media/ai/AI_connectfinish.png" width="350"/>
+<br>STEP 1:將模組通過數據線連接到電腦的USB端口,啟動AI模組;
+<br>STEP 2:模組頂部左側按鈕左移,右側按鈕右移,按右側按鈕右移到Try Demos,按底部左邊按鈕確認,即可進入AI樣例體驗選單;
+<br>STEP 3:在AI體驗列表介面,按右側按鈕可實現翻頁操作,再按底部確定按鈕即可進行體驗。
+
+---
+## B.	CocoBlockly X
+CocoBlockly X圖形化編程工具,是可用於學習Python基礎以及AI模組的在綫編程環境。通過這款工具可以給IoT模組和AI推理模組編寫程式及上傳程式。<br>
+在Chrome瀏覽器輸入網址 http://x.cocorobo.hk ,即可開始在CocoBlockly X編程。<br>
+<img src="/media/ai/AI_coco1.png" width="350"/>
+1. 文檔存取區:程式項目命名、保存(保存為.xml檔)、刪除所有積木及所有積木一鍵截圖
+2. 模式切換區:樣例加載、模式切換(主機板模組與 AI 模組)<br>
+<img src="/media/ai/AI_coco2.png" width="350"/>
+3. 輔助區:學習資料、項目檔導入及導出、語言設置、以及用戶登入
+<br>其中,學習資料按鈕,可以跳轉至EDU或者AI HUB學習平臺:<br>
+<img src="/media/ai/AI_coco3.png" width="350"/>
+<img src="/media/ai/AI_coco4.png" width="350"/>
+4.	積木指令區:除基礎積木以外(由「邏輯」至「序列埠通訊」),不同模式下擁有不同的擴展積木
+5.	積木編程區:將積木拖入此區域中以進行程式編寫
+6.	Python編程區:當用戶將積木拖入積木編程區以後,此處將會生成對應的Python源代碼,支持用戶對代碼進行編輯、複製、下載及上傳,下載後綴為 .py格式的python文檔<br>
+<img src="/media/ai/AI_coco5.png" width="350"/>
+7.	上傳區:用戶可選擇使用有線或者無線上傳模式
+
+---
+## C.	CocoBlockly Uploader
+CocoBlockly Uploader是一款跨平臺的上傳插件,安裝後可以使CocoBlockly X實現瀏覽器、IoT模組和AI推理模組間的通訊,將編寫完成的程式上傳到相關模組。安裝方法如下:
+1. 進入CocoBlockly X編程平臺,http://x.cocorobo.hk <br>
+<img src="/media/ai/AI_uploader1.png" width="350"/>
+2.	將滑鼠移向右下方「上傳區域」的「下載」圖示位置,點按「Windows」下載Uploader,如果是Mac系統,則點按「Mac」進行下載。<br>
+<img src="/media/ai/AI_uploader2.png" width="350"/>
+
+#### Windows系統下的安裝:
+1. 下載完成後執行安裝檔,點按「安裝」按鈕,進行安裝<br>
+<img src="/media/ai/AI_upload1.png" width="210"/>
+<img src="/media/ai/AI_upload2.png" width="210"/>
+<br><br><B>注意,已安裝其它版本Python的用戶請先卸載Python。</B><br><br>
+2. 安裝程式會啟動Python安裝視窗,在選單中點按「Repair」,開始進行Python安裝程式<br>
+<img src="/media/ai/AI_upload3.png" width="210"/>
+<img src="/media/ai/AI_upload4.png" width="210"/>
+3. 安裝完成後點按「Close」按鈕<br>
+<img src="/media/ai/AI_upload5.png" width="210"/>
+4. 繼續安裝Uploader,按照安裝程式執行<br>
+<img src="/media/ai/AI_upload6.png" width="210"/>
+<img src="/media/ai/AI_upload7.png" width="210"/>
+<img src="/media/ai/AI_upload8.png" width="210"/><br>
+5. 最後,點按「完成」結束Uploader安裝程式 <br>
+<img src="/media/ai/AI_upload9.png" width="210"/>
+<img src="/media/ai/AI_upload10.png" width="210"/><br>
+6. 點擊GO TO COCOBLOCKLY X即可進入積木編程頁面
+
+#### Mac系統下的安裝:
+1)「Mac」用戶右鍵點擊安裝檔案,選擇“安裝程式(預設值)”進行安裝<br>
+<img src="/media/ai/AI_macupload1.png" width="210"/><br>
+2) 進入安裝頁面,點擊“繼續”,之後點擊“安裝“
+<img src="/media/ai/AI_macupload2.png" width="210"/>
+<img src="/media/ai/AI_macupload3.png" width="210"/><br>
+3) 驗證你的密碼,然後點擊“安裝軟件”進入正在安裝頁面,等待即可<br>
+<img src="/media/ai/AI_macupload4.png" width="210"/>
+<img src="/media/ai/AI_macupload5.png" width="210"/><br>
+4) 出現下圖“已成功安裝“頁面,則表示uploader已成功安裝,即可看到程式圖標<br>
+<img src="/media/ai/AI_macupload6.png" width="210"/>
+<img src="/media/ai/AI_macupload7.png" width="210"/><br>
+
+---
+## D.	上傳程式
+將IoT模組或AI推理模組,通過USB接駁線與電腦連接。打開CocoBlockly X編程工具。
+1.	進入CocoBlockly X編程平臺,http://x.cocorobo.hk
+<br>
+<img src="/media/ai/AI_shangchuan1.png" width="350"/><br>
+2.	在上方「切換區域」選擇AI模組:
+<br>
+<img src="/media/ai/AI_shangchuan2.png" width="350"/><br>
+3.	在右下方「上傳區域」檢查以下設定:
+<br>
+<img src="/media/ai/AI_shangchuan3.png" width="350"/><br>
+4.	在「上傳區域」點按如下圖所示中,左下角位置的「運行」按鈕上傳程式到AI模組中。
+<br>
+<img src="/media/ai/AI_shangchuan4.png" width="350"/><br>
+
+上傳失敗或出現其他錯誤,請參閲:[Uploader常見錯誤處理](/aikit/A0.md)。
+
+##### 注意:
+
+1)上圖中左下角第一個按鈕為「運行程式」按鈕,即運行當前blockly中的程式,斷開連接後,再次接通,不會繼續運行當前程式,而是顯示初始化菜單介面:
+<br>
+<img src="/media/ai/AI_shangchuan5.png" width="300"/><br>
+且選擇「Run Last」選項,也不會運行之前的程式,如果想要再次運行,需要再次點擊運行按鈕
+<br>
+2)左下角第二個按鈕為「上傳程式」按鈕,將程式上傳到AI模組中,便會存儲在模組中,斷開連接,再次接通後,選擇「Run Last」選項,即可運行上次的程式。
+<br>
+3)如果上傳出現問題,或者加載AI模組的插件出現問題,則可以點擊右下角「重啟設備」按鈕,嘗試解決。
+
+---
+## E.	串口互動窗
+串口互動窗用於顯示或查看AI模組上的數據,是測試數據(感應器、網路請求)的好幫手。在「代碼區」點按「串口互動窗」。在積木指令區點按「序列埠通訊」,在積木編程區放置【打印】指令<img src="/media/ai/AI_E1.png" width="250"/>。然後在「上傳區域」點按「運行代碼」按鈕,當顯示「上載成功!100%」後在「代碼區」點按「串口互動窗」,會顯示「Hello World!」<br>
+Windows系統:
+<br>
+<img src="/media/ai/AI_E2.png" width="300"/><br>
+Mac系統:
+<br>
+<img src="/media/ai/AI_E3.png" width="300"/><br>
+
+---
+## F.	CocoBlockly X編程體驗
+##### 1.	在螢幕模組顯示Hello World !
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%">在積木指令區點按以下指令,並依次放在積木編程區:<br>
+1)AI模組|圖像處理:「螢幕初始化」、「創建空白畫布」、「設定畫布坐標」<br><br>
+2)循環:「重複執行」<br><br>
+3)AI模組|圖像處理:「螢幕文字」並輸入「Hello World!」<br><br>
+(其中「文字大小」可通過修改數字改變;顏色可選擇,此處選為紅色)
+</td>
+		<td width="50%"><img src="/media/ai/AI_f1.png" width="350"/><img src="/media/ai/AI_f2.png" width="350"/></td>
+	</tr>
+	<tr>
+		<td colspan=2>完成編程後,在「上傳區域」點按「運行代碼」,觀察AI螢幕模組的變化。<br>
+運行結果:
+<br>
+<img src="/media/ai/AI_f3.png" width="250"/><br>
+</td>
+	</tr>
+</table>
+
+##### 2.	在螢幕中心顯示Hello World !
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%">
+1)AI模組|圖像處理:「螢幕初始化」、「創建空白畫布」、「設定畫布坐標」<br><br>
+2)循環:「重複執行」<br><br>
+3)AI模組|圖像處理:「螢幕文字」並輸入「Hello World!」<br><br>
+4)修改座標的X值及Y值,使「Hello World!放置螢幕正中心位置。
+</td>
+		<td width="50%"><img src="/media/ai/AI_f4.png" width="350"/><img src="/media/ai/AI_f5.png" width="350"/></td>
+	</tr>
+	<tr>
+		<td colspan=2>完成編程後,在「上傳區域」點按「運行代碼」,觀察AI螢幕模組的變化。<br>
+運行結果:
+<br>
+<img src="/media/ai/AI_f6.png" width="250"/><br>
+</td>
+	</tr>
+</table>
+
+##### 3.	按鈕控制
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%">在積木指令區點按以下指令,並依次放在積木編程區:<br>
+1)1.	AI模組|圖像處理:「螢幕初始化」、「創建空白畫布」、「設定畫布坐標」<br><br>
+2)循環:「重複執行」<br><br>
+3)邏輯:「邏輯判斷」<br><br>
+4)AI模組|基礎:「按鈕狀態」<br><br>
+5)AI模組|圖像處理:「螢幕文字」(顏色為白色)
+</td>
+		<td width="50%"><img src="/media/ai/AI_f7.png" width="350"/><img src="/media/ai/AI_f8.png" width="350"/></td>
+	</tr>
+	<tr>
+		<td colspan=2>運行結果:當按鈕A按下,顯示Hello World!,否則不顯示任何文字。<br>
+未按鍵:
+<img src="/media/ai/AI_f9.png" width="150"/>
+按A鍵:
+<img src="/media/ai/AI_f10.png" width="150"/>
+</td>
+	</tr>
+</table>
+
+
+##### 補充:
+上面第三步「邏輯判斷」積木塊的實現方式如下:<br>
+1)選擇:
+<br>
+<img src="/media/ai/AI_f11.png" width="250"/><br>
+2)點擊左上角圖標,顯示如下:
+<br>
+<img src="/media/ai/AI_f12.png" width="250"/><br>
+3)拖拽「否則」積木塊到右側,放到「如果」下麵,即可顯示出「否則」部分:
+<br>
+<img src="/media/ai/AI_f13.png" width="250"/><br>

+ 292 - 0
aikit/AI_2.md

@@ -0,0 +1,292 @@
+# 認識螢幕模組
+---
+
+## 	A.螢幕模組
+模組連接一個LCD彩色螢幕顯示器,螢幕解析度爲240 x 240 px (像素),可顯示JPG, BMP 等格式圖片。像素,組成點陣數位影像的最小方塊單位,每個方塊都有一個明確的位置和被分配的色彩數值,小方格顏色和位置就決定該圖像所呈現出來的樣子。如下圖所示:
+<br>
+<img src="/media/ai/AI_g1.png" width="300"/><br>
+我們以坐標系(X, Y)標明方塊的位置,X代表水準方向(X軸),Y代表垂直方向(Y軸),列螢幕的左上角為起始點(0, 0)(代表第一行,第一列),最大值為(239, 239)。<br>
+例如方塊(4, 3),指方塊的位置由左而右第5列,由上至下第4行(因為X、Y座標均從0開始)。
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%"><img src="/media/ai/AI_g2.png" width="350"/></td>
+		<td width="50%"><img src="/media/ai/AI_g3.png" width="350"/></td>
+	</tr>
+	<tr >
+		<td colspan=2>活動:列出方格A及方格B的座標系:A __________ B __________</td>
+	</tr>
+</table>
+
+---
+## 	B.螢幕模組介紹
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%">積木</td>
+		<td width="20%">指令</td>
+    <td width="30%">說明</td>
+	</tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h1.png" width="200"/></td>
+    <td width="20%">初始化</td>
+    <td width="30%">初始化螢幕</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h2.png" width="200"/><img src="/media/ai/AI_h3.png" width="200"/></td>
+    <td width="20%">改變螢幕狀態</td>
+    <td width="30%">旋轉螢幕方向、螢幕鏡面翻轉<img src="/media/ai/AI_h4.png" width="200"/></td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h5.png" width="200"/></td>
+    <td width="20%">改變螢幕顏色</td>
+    <td width="30%">填充螢幕顏色:<img src="/media/ai/AI_h6.png" width="200"/></td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h7.png" width="200"/></td>
+    <td width="20%">自定義螢幕顏色</td>
+    <td width="30%">填入不同的RGB(紅綠藍)值,達到自定義顏色的效果</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h8.png" width="200"/></td>
+    <td width="20%">清除螢幕</td>
+    <td width="30%">清除螢幕</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h9.png" width="200"/><img src="/media/ai/AI_h10.png" width="200"/><img src="/media/ai/AI_h11.png" width="200"/></td>
+    <td width="20%">參數調節</td>
+    <td width="30%">改變RGB值、XY坐標值和寬高值</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h12.png" width="200"/></td>
+    <td width="20%">建立畫布</td>
+    <td width="30%">建立畫布並定義畫布的大小</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h13.png" width="200"/></td>
+    <td width="20%">自定畫布幕顏色</td>
+    <td width="30%">填入不同的RGB(紅綠藍)值,達到自定義顏色的效果</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h24.png" width="200"/></td>
+    <td width="20%">建立畫布</td>
+    <td width="30%">建立並儲存畫布在SD記憶卡</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h14.png" width="200"/></td>
+    <td width="20%">顯示畫布</td>
+    <td width="30%">定義畫布在螢幕上的起始位置</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h15.png" width="200"/></td>
+    <td width="20%">繪製文字</td>
+    <td width="30%">螢幕可以同時顯示文字及圖形,特別適合用作圖像識別。必須同時使用「建立畫布」及「顯示畫布」指令。</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h16.png" width="200"/></td>
+    <td width="20%">繪製直線</td>
+    <td width="30%">在畫布上繪畫直線,輸入起點及終點坐標。可以選擇線條顏色及厚度。</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h17.png" width="200"/></td>
+    <td width="20%">繪製矩形</td>
+    <td width="30%">在畫布上繪畫矩形,可以是實心或空心,輸入起點坐標及尺寸。可以選擇線條顏色及厚度。</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h18.png" width="200"/></td>
+    <td width="20%">繪製圓形</td>
+    <td width="30%">在畫布上繪畫圓形,可以是實心或空心,輸入圓心的坐標及半徑。可以選擇線條顏色及厚度。</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h19.png" width="200"/></td>
+    <td width="20%">繪製十字標</td>
+    <td width="30%">在畫布上繪畫十字標,輸入中心坐標。可以選擇線條延伸長度、厚度及顏色。</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h20.png" width="200"/></td>
+    <td width="20%">繪製箭頭</td>
+    <td width="30%">在畫布上繪畫箭頭,輸入起點及終點坐標。可以選擇線條顏色及厚度。</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h21.png" width="200"/></td>
+    <td width="20%">繪製圖片</td>
+    <td width="30%">在畫布上繪畫圖片,圖片從SD卡的檔路徑中選取,輸入起點坐標及縮放比例。</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h22.png" width="200"/></td>
+    <td width="20%">顯示畫布</td>
+    <td width="30%">顯示指定畫布,畫布名可修改</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_h23.png" width="200"/></td>
+    <td width="20%">清除畫布</td>
+    <td width="30%">清除所選畫布中的所有內容</td>
+  </tr>
+</table>
+
+---
+## I.	基礎編程
+##### 活動一:在螢幕上顯示矩形圖案,設定坐標系(0,0)
+<table style="margin-top:20px;">
+<tr>
+  <td>1)AI模組|圖像處理:「螢幕初始化」、「創建空白畫布」、「設定畫布坐標」<br><br>
+2)循環:「重複執行」<br><br>
+3)AI模組|圖像處理:「繪製矩形」<br><br>
+4)AI模組|圖像處理:「顯示畫布」
+</td>
+  <td><img src="/media/ai/AI_I1.png" width="350"/><img src="/media/ai/AI_I2.png" width="350"/></td>
+</tr>
+</table>
+以上活動首先會建立一幅空白畫布並命名為「canvas」,畫布的大小設定為240 x 240。接著輸入「重複執行」指令,使螢幕不斷顯示矩形圖案,如果沒有使用該指令,矩形圖案只會顯示一次就消失。在「重複執行」指令中加入「繪製矩形」及「顯示畫布」指令並輸入參數如下:
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%">繪製矩形</td>
+		<td width="50%">矩形樣式:實心<br>
+起始座標:X=0, Y=0<br>
+尺寸:寛=1, 高=1<br>
+顏色:紅色<br>
+厚度:1<br>
+</td>
+	</tr>
+	<tr>
+		<td>顯示畫布</td>
+		<td>起始座標:X=0, Y=0</td>
+	</tr>
+</table>
+注:「建立畫布」是指建立圖像變數,將獲取的影像存放在變數中,作進一步使用。<br>
+運行結果:
+<img src="/media/ai/AI_I3.png" width="200"/>
+
+##### 活動二:修改活動一程式,在螢幕上顯示延長橫線
+<table style="margin-top:20px;">
+<tr>
+  <td>1)循環:「計次」<br>
+將指令並合在「重複執行」指令內,範圍設定為0-239,間隔=1<br>
+2)變數:「i」<br>
+將變數「i」放在「繪製矩形」座標參數中的X值處
+</td>
+  <td><img src="/media/ai/AI_I4.png" width="350"/><img src="/media/ai/AI_I5.png" width="350"/></td>
+</tr>
+<tr><td colspan=2>點按「運行」後觀察螢幕的變化,並簡短描述如下:<br><img src="/media/ai/AI_I8.png" width="350"/></td></tr><tr>
+<td colspan=2>運行結果:不斷延長的直線<br><img src="/media/ai/AI_I6.png" width="200"/><img src="/media/ai/AI_I7.png" width="200"/> </td></tr>
+</table>
+
+##### 挑戰一:
+<table style="margin-top:20px;">
+<tr>
+  <td colspan=2>修改活動二的程式,在螢幕上顯示一個紅色方塊,由左向右移動,每次移動一格。<br>
+提示:嘗試運用以下積木<br>
+<img src="/media/ai/AI_I9.png" width="350"/>
+</td>
+</tr>
+<tr>
+<td colspan=2>參考程式:<br><img src="/media/ai/AI_I10.png" width="200"/><img src="/media/ai/AI_I11.png" width="200"/> </td>
+</tr>
+<tr >
+<td colspan=2>運行結果:<br><img src="/media/ai/AI_I12.png" width="200"/><img src="/media/ai/AI_I13.png" width="200"/> </td>
+</tr>
+</table>
+
+##### 活動三:建立畫布顯示矩形圖案
+<table style="margin-top:20px;">
+<tr>
+  <td >在積木指令區點按以下指令,並依次放在積木編程區:<br>
+1)AI模組|圖像處理:「螢幕初始化」<br>
+2)AI模組|圖像處理:「建立畫布」、「設定畫布起始坐標」<br>
+3)循環:「重複執行」<br>
+4)AI模組|圖像處理:「繪製矩形」<br>
+5)AI模組|圖像處理:「顯示畫布」
+</td><td>
+<img src="/media/ai/AI_I14.png" width="350"/>
+</td>
+</tr>
+<tr >
+<td colspan=2>運行結果:<br><img src="/media/ai/AI_I15.png" width="200"/></td>
+</tr>
+</table>
+此活動目標為理解路徑的概念:<br>
+從SD卡檔夾中讀取圖像,使用該圖像作為畫布,顯示在熒幕上,然後在此畫布上畫白色的矩形塊,學生可自行修改矩形塊位置、大小及顏色。
+
+##### 活動四:建立畫布顯示方框文字
+<table style="margin-top:20px;">
+<tr>
+  <td >在積木指令區點按以下指令,並依次放在積木編程區:<br>
+1)重複活動一的程式<br>
+2)AI模組|圖像處理:「繪製文本」放在「繪製矩形」指令之下<br>
+3)AI模組|圖像處理:「顯示畫布」(必要積木,否則不會顯示任何訊息)
+</td><td>
+<img src="/media/ai/AI_I21.png" width="350"/><img src="/media/ai/AI_I17.png" width="350"/>
+</td>
+</tr>
+<tr>
+<td  colspan=2>運行結果:<br><img src="/media/ai/AI_I18.png" width="200"/></td>
+</tr>
+</table>
+
+##### 挑戰二:
+<table style="margin-top:20px;">
+<tr>
+  <td colspan=2>編寫程式,在螢幕正中心位置顯示白色方框,框內打印你的英文名。如下圖所示:<br>
+<img src="/media/ai/AI_I19.png" width="350"/><br>
+提示:需要計算文字及方框的尺寸,對應螢幕的面積尺寸,修改文字及方框的座標位置,使二者能顯示在螢幕的正中心位置。
+</td>
+</tr>
+<tr colspan=2>
+<td>參考程式:<br><img src="/media/ai/AI_I20.png" width="200"/></td>
+</tr>
+</table>
+
+---
+## C.	專題學習
+硬體設備:AI推理模組、螢幕模組<br>
+任務目標:運用「變數」及「循環」,用【線條】指令製作一個萬花筒動畫<br>
+基本流程/步驟:<br>
+<img src="/media/ai/AI_j1.png" width="200"/><br>
+第一步:模組初始化<br>
+<table style="margin-top:20px;">
+<tr>
+  <td >在積木指令區點按以下指令,並依次放在積木編程區:<br>
+1)AI模組|圖像處理:「螢幕初始化」、「建立畫布」、「設定畫布起始坐標」<br>
+2)循環:「重複執行」<br>
+3)AI模組|圖像處理:「清除畫布」
+</td><td>
+<img src="/media/ai/AI_j2.png" width="350"/>
+</td></tr>
+</table>
+
+第二步:繪畫直線萬花筒<br>
+放置【For循環】,設定變數i:由0-240,每次循環自動增加數值5,即i = 0, 5, 10, 15, ……, 240,目的是利用數值變化改變繪畫直線的座標位置,使其形成萬花筒效果。<br>
+<table style="margin-top:20px;">
+<tr>
+  <td >在步驟3【清除畫布】積木指令下,放置下列積木指令:<br>
+4)循環:【For循環】<br>
+5)AI模組|圖像處理:【繪製直線】<br>
+6)AI模組|圖像處理:【顯示畫布】<br>
+7)時間:【等待】
+</td><td>
+<img src="/media/ai/AI_j3.png" width="350"/>
+</td>
+</table>
+觀察結果:<br>
+<table style="margin-top:20px;">
+<tr>
+  <td ><img src="/media/ai/AI_j4.png" width="350"/>
+</td><td>
+<img src="/media/ai/AI_j5.png" width="350"/>
+</td><td>
+<img src="/media/ai/AI_j6.png" width="350"/>
+</td></tr>
+<tr>
+<td colspan=3>參考程式:<br><img src="/media/ai/AI_j7.png" width="350"/><img src="/media/ai/AI_j11.png" width="350"/>
+</td>
+</tr>
+</table>
+
+##### 挑戰題:
+<table style="margin-top:20px;">
+<tr>
+  <td >如何透過【For循環】方法,延續上面繪畫的直線,在餘下的空間位置繪畫直線,如下圖所示:<img src="/media/ai/AI_j8.png" width="350"/>
+</td></tr>
+<tr>
+<td >參考程式:<br><img src="/media/ai/AI_j9.png" width="350"/><img src="/media/ai/AI_j10.png" width="350"/>
+</td>
+</tr>
+</table>

+ 179 - 0
aikit/AI_3.md

@@ -0,0 +1,179 @@
+# 認識攝影鏡頭模組
+---
+
+## A.	攝影鏡頭模組
+詳情參見[認識CocoBlockly X編程環境](/aikit/AI_1.md)中“A.認識AI模組及應用”部分。
+
+---
+## B.	相機積木介紹
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%">積木</td>
+		<td width="20%">指令</td>
+    <td width="30%">說明</td>
+	</tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_l1.png" width="200"/></td>
+    <td width="20%">初始化</td>
+    <td width="30%">匯入相機的程式庫,可設定以下兩項屬性:<br>
+影像尺寸:320x240及160x120<br>
+影像色彩:彩色 及 黑白
+</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_l2.png" width="200"/></td>
+    <td width="20%">影像尺寸</td>
+    <td width="30%">設定影像的顯示尺寸,最大尺寸可輸入:寬240 高240
+</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_l3.png" width="200"/></td>
+    <td width="20%">獲取影像</td>
+    <td width="30%">獲取從攝影鏡頭拍攝的影像
+</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_l4.png" width="200"/></td>
+    <td width="20%">校正圖像</td>
+    <td width="30%">對廣角鏡頭獲取的圖片進行校正
+</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_l5.png" width="200"/></td>
+    <td width="20%">屬性設定</td>
+    <td width="30%">設定「啟用」或「停用」以下五個屬性:<img src="/media/ai/AI_l6.png" width="200"/>
+</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_l7.png" width="200"/></td>
+    <td width="20%">屬性設定</td>
+    <td width="30%">設定影像的對比度、亮度及色彩飽和度等數值屬性,範圍定為-3至3
+</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_l8.png" width="200"/></td>
+    <td width="20%">錄製影片</td>
+    <td width="30%">設定影片錄製參數,包括儲存路徑、影片寬度及高度
+</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_l9.png" width="200"/></td>
+    <td width="20%">畫布錄製</td>
+    <td width="30%">錄製影片
+</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_l10.png" width="200"/></td>
+    <td width="20%">停止錄影</td>
+    <td width="30%">停止錄影
+</td>
+  </tr>
+</table>
+
+---
+## C.	基礎編程
+##### 活動一:啟用AI攝影鏡頭
+<table style="margin-top:20px;">
+<tr>
+  <td>1.	AI模組|圖像處理:【螢幕初始化】、【創建空白畫布】、【設定起始點坐標】<br>
+2.	AI模組|相機:【相機初始化】<br>
+3.	AI模組|相機:【影像尺寸】<br>
+4.	循環:【重複執行】<br>
+5.	變數:建立變數命名為【canvas】<br>
+6.	AI模組|相機:【獲取影像】<br>
+7.	AI模組|圖像處理:【顯示畫布】<br>
+</td>
+  <td><img src="/media/ai/AI_m1.png" width="350"/></td>
+</tr>
+<tr><td colspan=2>運行結果:啟用AI攝影鏡頭並在螢幕上出現畫面<br><img src="/media/ai/AI_m2.png" width="350"/></td></tr>
+</table>
+
+##### 活動二:每隔1秒拍照並儲存相片
+<table style="margin-top:20px;">
+<tr>
+  <td>重複活動一的程式,在步驟5及7中間加入以下積木指令:<br>
+1.	AI模組|圖像處理:【儲存影像】,
+位置:/sd/user/saved.jpg
+在步驟6之後加入以下積木指令:<br>
+2.	時間:【等候】設定為1000毫秒<br>
+
+</td>
+  <td><img src="/media/ai/AI_m3.png" width="350"/></td>
+</tr>
+<tr><td colspan=2>運行結果:每隔1秒會自動拍照1次,影像顯示在螢幕上並儲存在SD記憶卡中。從AI推理模組取出SD記憶卡,透過電腦打開影像檔案:user/saved.jpg<br><img src="/media/ai/AI_m4.png" width="350"/></td></tr>
+</table>
+思考問題:上面程式運行一段時間後,為什麼SD記憶卡仍只有一幅影像檔案?
+<br><img src="/media/ai/AI_s9.png" width="350"/>
+
+##### 挑戰一:
+<table style="margin-top:20px;">
+<tr>
+  <td >修改上面程式,每次拍照並儲存圖像時均會將新的圖像存進SD卡。<br>
+提示:嘗試運用以下的積木<br>
+<img src="/media/ai/AI_m5.png" width="200"/>
+<img src="/media/ai/AI_m6.png" width="200"/>
+</td></tr>
+<tr><td >參考程式:<br><img src="/media/ai/AI_m7.png" width="350"/></td></tr>
+</table>
+
+##### 活動三:透過按動按鈕拍照並儲存相片
+<table style="margin-top:20px;">
+<tr>
+  <td>使用活動一程式,在步驟5及7之間加入以下程式:<br>
+1.	邏輯:【邏輯判斷】<br>
+2.	AI模組|基礎:【按鈕狀態】<br>
+3.	AI模組|圖像處理:【儲存影像】<br>
+4.	AI模組|圖像處理:【顯示畫布】<br>
+5.	時間:【等候】設定為1000毫秒<br>
+</td>
+  <td><img src="/media/ai/AI_m8.png" width="350"/></td>
+</tr>
+<tr><td colspan=2>運行結果:即時影像顯示在螢幕上,當按鈕B按下時,會將即時影像儲存在SD記憶卡並在螢幕上停頓顯示1秒,隨後再次顯示即時影像。</td></tr>
+</table>
+
+##### 活動四:錄製影片
+<table style="margin-top:20px;">
+<tr>
+  <td>1.	AI模組|圖像處理:【螢幕初始化】、【創建空白畫布】、【設定起始點坐標】<br>
+2.	AI模組|相機:【相機初始化】<br>
+3.	AI模組|相機:【影像尺寸】<br>
+4.	AI模組|視訊處理:【錄製影片】<br>
+5.	循環:【重複執行】<br>
+6.	變數:建立變數命名為【camera】<br>
+7.	AI模組|相機:【獲取影像】<br>
+8.	AI模組|視訊處理:【畫布錄製】<br>
+9.	螢幕|圖像處理:【顯示畫布】<br>
+10.	AI模組|視訊處理:【停止錄製】<br>
+
+</td>
+  <td><img src="/media/ai/AI_m9.png" width="350"/></td>
+</tr>
+<tr><td colspan=2><img src="/media/ai/AI_m10.png" width="350"/></td></tr>
+<tr><td colspan=2>運行結果:從AI模組取出SD記憶卡,在電腦開啟影片檔案(路徑:/sd/user/record.avi)查看影片是否錄製成功。</td></tr>
+</table>
+
+
+##### 活動五:透過按鈕錄製影片
+<table style="margin-top:20px;">
+<tr>
+  <td>1.	AI模組|圖像處理:【螢幕初始化】、【創建空白畫布】、【設定起始點坐標】<br>
+2.	AI模組|相機:【相機初始化】<br>
+3.	AI模組|相機:【影像尺寸】<br>
+4.	AI模組|視訊處理:【錄製影片】<br>
+5.	循環:【重複執行】<br>
+6.	變數:建立變數命名為【camera】<br>
+7.	AI模組|相機:【獲取影像】<br>
+8.	螢幕|圖像處理:【顯示畫布】<br>
+9.	邏輯:【邏輯判斷】<br>
+10.	AI模組|基礎:【按鈕狀態】<br>
+11.	如按鈕A按下:AI模組|視訊處理:【畫布錄製】<br>
+如按鈕A鬆開:AI模組|視訊處理:【停止錄製】
+
+</td>
+  <td><img src="/media/ai/AI_m11.png" width="350"/></td>
+</tr>
+<tr><td colspan=2>參考程式:<img src="/media/ai/AI_m12.png" width="350"/></td></tr>
+<tr><td colspan=2>運行結果:即時影像顯示在螢幕上並錄製。<br>
+當按鈕A按下時,開始錄像並會將即時影像儲存在SD記憶卡中,不按則只顯示即時畫面不錄影。
+</td></tr>
+</table>

+ 366 - 0
aikit/AI_4.md

@@ -0,0 +1,366 @@
+# 認識物體識別
+---
+
+##  A.	圖像識別與計算機視覺
+#####  1.	圖像識別
+在學習物體識別前,我們先來認識下圖像識別。<br>
+圖像識別,簡單地來說,就是一個將圖像與特定的詞語對應起來的過程。從技術上來看,是利用電腦對圖像進行處理、分析和理解,以識別各種不同模式的目標和對象的過程。圖像識別的發展經歷了三個階段:文字識別、數字圖像處理與識別、物體識別。<br>
+文字識別的研究是從 1950年開始的,一般是識別字母、數字和符號,從印刷文字識別到手寫文字識別,應用非常廣泛。<br>
+<img src="/media/ai/AI_n1.png" width="300"/><img src="/media/ai/AI_n2.png" width="350"/><br>
+數字圖像處理和識別的研究開始於1965年。數字圖像與模擬圖像相比具有存儲、傳輸方便可壓縮、傳輸過程中不易失真、處理方便等巨大優勢,這些都為圖像識別技術的發展提供了強大的動力。
+<br><img src="/media/ai/AI_n3.png" width="350"/><br>
+物體識別主要指對三維世界的物體及環境的感知和認識,屬於高級的計算機視覺範疇。它是以數字圖像處理與識別為基礎的結合人工智能、系統學等學科的研究方向,其研究成果被廣泛應用在各種工業及機器人中。
+<br><img src="/media/ai/AI_n4.png" width="350"/><br>
+瞭解了這些知識,我們再來看下面這四幅圖,第一張圖片是手寫數字,可以看到電腦將它正確地識別為了425,後三張圖片則分別分類為貓、人和車。
+<br><img src="/media/ai/AI_n5.png" width="350"/><br>
+這就是文字識別和物體識別的一些應用,電腦可通過深度學習算法,對輸入的圖像進行識別,並給出每幅圖片的識別結果。<br>
+在人工智能領域,識別問題又可以歸類為分類問題,所以物體識別,也可以稱之為物體分類。<br>
+
+
+#####  2.	計算機視覺
+我們前面提到了,圖像識別就是電腦獲取,處理和分析圖像數據的過程,這個過程其實也就是計算機視覺的實現過程。簡而言之,計算機視覺使得電腦能夠“看”事物——甚至包括人類無法看到的事物。然而,要想讓電腦做到人類無法做到的事情,我們必須首先使電腦能夠做到人類可以做的事情:看到並標記物體和生物。這是圖像識別的主要功能。<br>
+我們先來看下下面這四幅貓的圖片,我們可以很輕鬆地分辨出這四張圖片都是貓,即使它們外形長相完全不同,且體態各異,即使它只露出了一截尾巴,但我們仍然可以分辨的出來。<br>
+但這對電腦來說卻十分困難,因為電腦並沒有像我們人類大腦這樣複雜的系統。
+<br><img src="/media/ai/AI_n6.png" width="350"/><br>
+那麼,到底電腦是如何識別圖片的呢?我們來看下一節內容。<br>
+
+---
+##  B.	神經網路與深度學習
+電腦想要正確分類圖片,就需要像我們人類一樣去學習,知道圖片中大量的資訊。目前,最有可能讓電腦實現“看”的能力的技術叫做深度學習(Deep Learning,簡稱DL),它是一種讓電腦從圖片中學習的方法。學習的過程稱為訓練,識別的過程稱為推理(測試)。
+<br><img src="/media/ai/AI_n7.png" width="350"/><br>
+電腦要識別圖片,前提便是需要大量的圖片數據作為輸入,傳入電腦以供其學習。<br>
+我們以識別貓為例,前期需要先準備大量的各種品類的貓,並且打上標籤,告訴電腦:這些是貓,也就是這些圖片的分類,然後電腦將這些數據輸入網路,執行訓練,通過不斷地迭代進行學習,達到正確認識這些貓的目的。<br>
+然後,我們輸入電腦一張新的貓的圖片,進行測試,電腦執行測試演算法,便可給出輸入圖片的正確分類。<br>
+這個過程就是電腦“看”事物(學習),並給出答案(識別)的過程。<br>
+###### 我們再來看一下學術的解釋:
+深度學習就是一種機器學習框架,通過模仿人類的神經元系統,為電腦提供自主學習能力。因此,電腦可以自動識別與發掘圖像數據的特徵,準確識別圖片中的內容,而無需根據指令或手動編碼來實現(但它需要大量的數據),並大大提高了計算精度及識別準確率。<br>
+而模仿人類神經元系統的方法,在人工智能領域被稱為神經網路(Neural Networks)。<br>
+下面,我們以圖像識別的入門級應用:MNIST手寫數字識別為例,來認識神經網路與深度學習的原理。其中,MNIST是一個手寫數字的圖片數據集。<br>
+
+---
+## C.	MNIST手寫數字識別
+手寫識別是常見的圖像識別任務。電腦通過手寫體圖片來識別出圖片中的字,與印刷字體不同的是,不同人的手寫體風格迥異,大小不一, 造成了電腦對手寫識別任務的一些困難。 <br>
+在研究過程中,數字手寫體識別由於其有限的類別(0~9共10個數字)成為了相對簡單的手寫識別任務。所以,我們從簡單的手寫數字識別入手,來認識實現圖像識別的演算法。<br>
+##### 1.	人類學習和認識數字的過程
+前面已經提到,電腦需要像人一樣思考學習,才能識別出圖像,我們不妨反推一下,想一想我們小時候是怎樣學習數字的,大家總結回想一下,我們學習數字的思維過程。為什麼我們可以看到各式各樣形狀的數字,依舊可以知道它們分別是多少呢?
+<br><img src="/media/ai/AI_p1.png" width="350"/><br>
+這個過程也就是電腦要模仿的,我們把這個學習步驟寫出來。
+<br><img src="/media/ai/AI_p2.png" width="350"/><br>
+這個就是人類學習和認知的過程,也就是機器要模仿的,現在我們將人的學習方式類比到電腦中,就會知道電腦學習並識別數字的過程了。
+##### 2.	電腦學習並認識數字的過程
+###### 1)	圖像在電腦中的樣子
+我們向電腦輸入正確的帶有標籤的圖像數據,電腦看到的並不是像我們人類看到的那樣,如下圖左邊的圖片,而是下圖右邊數字矩陣的樣子。電腦中處理圖像,處理的是圖像中每一個像素(像素是電腦螢幕上所能顯示的最小單位,是用來表示圖像的單位)。
+<br><img src="/media/ai/AI_p3.png" width="350"/><br>
+上一節我們提到了,深度學習需要大量的數據作為輸入,在手寫數字識別系統中,數據來自於MNIST數據集,它包含60000個訓練集和10000測試數據集。分為圖片和標籤,圖片是28*28的像素矩陣,標籤為0~9共10個數字。
+###### 2)	模型訓練——神經網路
+有了數據集,下一步,便是將數據輸入到深度學習網路中,也就是神經網路中(這裏採用的是LeNet-5卷積神經網路模型,卷積神經網路是深度學習神經網路中最常見的一種),進行自動的特徵提取及學習,這個過程就是前面提到過的訓練過程。<br>
+我們知道,人類大腦的神經網路是由神經元和突觸組成,它們協同工作,完成對外界資訊的處理與傳遞。
+<br><img src="/media/ai/AI_p4.png" width="350"/><img src="/media/ai/AI_p5.png" width="350"/><br>
+那麼,人腦的神經網路對比到深度學習中,就是如下圖所示的網路。
+<br><img src="/media/ai/AI_p6.png" width="350"/><br>
+大量的手寫數字圖像就是輸入數據,作為第一層:輸入層(一般情況下,輸入層不在網路結構中體現,而在後面訓練開始時給出),因為每張圖像的像素是28x28,所以每張圖像一共有784個像素,電腦中的索引一般從0開始,所以輸入x即為x0-x783。 <br>
+中間部分稱為隱藏層,在LeNet-5網路中,主要採用的是:卷積層Convolutional Layer(啟動層為ReLu Layer)、池化層Pooling Layer以及全連接層Fully Connected Layer。<br>
+全連接層中加入啟動函數:Softmax,這是一個回歸模型,用於分類過程,可解決多分類問題。這裏的手寫數字識別就是一個多分類問題,0-9共10類,所以最後的輸出層y的結果為y0-y9。
+<br><img src="/media/ai/AI_p7.png" width="350"/><br>
+並且Softmax也是一個概率函數,它可以給出輸入圖像識別為不同類別的概率,以此來讓使用者判斷輸入圖像中的數字更像哪一個識別結果。<br>
+這部分就是神經網路的網路結構,是深度學習演算法實現圖像處理及學習的根本。
+###### 3)	人類學習過程和電腦學習過程的對比
+前面我們給出了人類學習和認識數字的過程,也就是下圖左邊的部分,通過上一節的學習,我們知道了電腦學習並認識數字的過程,那麼總結起來,就是下圖右邊所示的步驟。
+<br><img src="/media/ai/AI_p8.png" width="350"/><br>
+###### 4)	手寫數字識別的實現演示
+我們知道了手寫數字識別的原理,那麼,現在就來看看實際電腦中是如何實現圖像識別的吧。
+打開網址:https://ai-blockly.cocorobo.hk/ ,進入AI blockly頁面。<br>
+進入後,首先選擇Examples選項。
+<br><img src="/media/ai/AI_p9.png" width="350"/><br>
+然後,繼續選擇Tensor Flow選項,然後選擇Digit Recognition選項,並選擇OK。
+<br><img src="/media/ai/AI_p10.png" width="350"/><img src="/media/ai/AI_p11.png" width="350"/><br>
+然後,就會出現如下圖所示的積木程式塊。
+<br><img src="/media/ai/AI_p12.png" width="350"/><br>
+繼續點擊右下角區域中的RUN按鈕,即可開始訓練。
+<br><img src="/media/ai/AI_p13.png" width="350"/><br>
+訓練的迭代過程中,會產生如下圖所示的函數曲線圖及網路結構資訊(Model Architecture),可通過觀察曲線圖的變化,來判斷訓練執行的狀態及模型的訓練效果。
+<br><img src="/media/ai/AI_p14.png" width="350"/><br>
+如上圖所示,是演示的最終效果,左邊是曲線圖,第一副圖是訓練集(loss)和驗證集(val_loss)的loss變化曲線,loss是損失函數,即模型預測出的結果與標籤標注的真實值的差值。這個差值是隨著訓練輪數Epoch的增加而逐漸減小的。<br>
+第二幅圖是訓練集(acc)和驗證集(val_acc)的準確率變化曲線,準確率為識別正確的圖像個數除以總的圖像數的比值,該值隨著Epoch的增加而逐漸增大。<br>
+右側為推理測試區,在畫布中寫出你要測試的數字,點擊Detect,即可得到最終的識別結果。<br>
+其結果將打印顯示在右上方區域的Console中。
+<br><img src="/media/ai/AI_p15.png" width="350"/><img src="/media/ai/AI_p16.png" width="350"/><br>
+手寫數字識別的整個實現過程到這裏就結束了。<br>
+接下來,我們來學習今天最重要的部分——物體識別。
+
+---
+## D.	物體識別與YOLO演算法
+物體識別(Object Recognition)是計算機視覺中的一個應用,目的是讓電腦去分析一張圖片或者一段影片中的物體,並標注出其中物體所屬的類別。
+<br><img src="/media/ai/AI_q1.png" width="350"/><br>
+###### YOLO演算法介紹:
+<br><img src="/media/ai/AI_q2.png" width="350"/><br>
+YOLO是目前應用非常廣泛的一種物體識別演算法。YOLO的意思是You only look once,也就是你只看一眼,就能認出這是什麼物體,體現YOLO演算法識別的精度和速度。<br>
+YOLO是基於Pascal VOC2012數據集的目標檢測系統。它能夠檢測到20種Pascal的目標類別,包括:<br>
+- 人
+- 鳥,貓,牛,狗,馬,羊
+- 飛機,自行車,船,汽車,摩托車,火車
+- 瓶子,椅子,桌子,盆栽植物,沙發,電視或者顯示器<br>
+YOLO演算法目前最新的已經迭代到了v4版本,各個版本的應用場景都是相同的,區別只在於識別精度及速度。這裏,視頻中展示的是YOLOv3的應用及識別結果,但這並不影響學習,我們這裏主要講的是入門級的YOLOv1的原理。<br>
+YOLO演算法的識別過程分為兩個部分,這也基本是所有視覺領域內的深度學習演算法的實現過程。<br>
+1.  訓練圖像數據,迭代過程優化參數,獲得最終模型;
+2.  輸入新的圖像數據,調用模型,實現推理(inference)過程,也稱為測試過程。
+我們先來看下第一步的原理:<br>
+訓練就需要有網路,YOLO的網路結構如下圖所示,整個檢測網路包括24個卷積層和2個全連接層。其中,卷積層用來提取圖像特徵,全連接層用來預測圖像位置和類別概率值。
+<br><img src="/media/ai/AI_q3.png" width="350"/><br>
+第二步:推理過程:
+<br><img src="/media/ai/AI_q4.png" width="350"/><br>
+加載網路模型後,其推理的計算流程如圖所示,我們可以將最終識別結果之前的步驟都看做一個函數計算,通過這個計算過程,就可以得到最後的物體識別結果了。<br>
+那麼,YOLO具體是如何實現物體識別的呢?我們來深入地學習一下它的內部原理。
+<br><img src="/media/ai/AI_q5.png" width="350"/><br>
+如上圖所示,YOLO演算法將輸入圖片劃分成7x7=49個網格(即上圖中左邊第一副圖,S=7),如果一個物體的中心落在某網格(cell)內,則相應網格負責檢測該物體。<br>
+每個網格預測兩個邊界框(Bounding boxes),一共預測49x2=98個邊界框(上圖中位於上面的那副圖)。可以近似理解為在輸入圖片上粗略的選取98個候選區,這98個候選區覆蓋了圖片的整個區域,進而用回歸預測這98個候選框對應的邊界框。<br>
+除了給出邊界框,也就是圖像的位置資訊外,還會給出對應的置信度(confidence)和分類結果(categories)。其中,置信度代表了所預測的 box 中含有 object 的置信度(概率)和這個 box 預測目標位置的準確度這兩重資訊。<br>
+最後,網路就給出了圖像的最終識別結果,如下圖所示。
+<br><img src="/media/ai/AI_q6.png" width="350"/><br>
+
+---
+## E.	AI模型積木說明
+在學習瞭解了深度學習與物體識別的原理之後,我們開始積木程式塊的學習,將理論與實踐相結合,才能更好地學習並認識物體識別。
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%">積木</td>
+		<td width="20%">指令</td>
+    <td width="30%">說明</td>
+	</tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_r1.png" width="300"/></td>
+    <td width="20%">載入模型</td>
+    <td width="30%">載入人工智能模型,可以從選單中選擇常用識別模型<img src="/media/ai/AI_r2.png" width="300"/></td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_r3.png" width="300"/></td>
+    <td width="20%">獲取識別結果</td>
+    <td width="30%">獲取當前結果,可選擇數字識別的結果或者識別為某個數字的置信度<img src="/media/ai/AI_r4.png" width="300"/></td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_r5.png" width="300"/></td>
+    <td width="20%">物體識別</td>
+    <td width="30%">獲取物體識別真假值,如果識別到物體會返回「真」值,否則返回「假」值</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_r6.png" width="300"/></td>
+    <td width="20%">物體識別結果的參數</td>
+    <td width="30%">獲取識別到的每個物體的各項參數,包括:<img src="/media/ai/AI_r7.png" width="300"/></td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_r8.png" width="300"/></td>
+    <td width="20%">人臉識別</td>
+    <td width="30%">獲取人臉識別真假值,如果識別到人臉會返回「真」值,否則返回「假」值</td>
+  </tr>
+  <tr>
+    <td width="50%"><img src="/media/ai/AI_r9.png" width="300"/></td>
+    <td width="20%">人臉識別結果的參數</td>
+    <td width="30%">獲取識別到的每個人臉的各項參數,包括:<img src="/media/ai/AI_r10.png" width="300"/></td>
+  </tr>
+<tr>
+    <td width="50%"><img src="/media/ai/AI_r11.png" width="300"/></td>
+    <td width="20%">加載客制化模型</td>
+    <td width="30%">從指定路徑加載用戶預訓練好的客制化模型:/sd/user/mymodel.kmodel
+並根據要識別的物體種類來設定客制化物體的類別名稱:Object Name
+</td>
+  </tr>
+<tr>
+    <td width="50%"><img src="/media/ai/AI_r12.png" width="300"/></td>
+    <td width="20%">客制化的物體識別</td>
+    <td width="30%">獲取客制化物體識別真假值,如果識別到客制化物體會返回「真」值,否則返回「假」值</td>
+  </tr>
+<tr>
+    <td width="50%"><img src="/media/ai/AI_r13.png" width="300"/></td>
+    <td width="20%">客制化物體識別結果的參數</td>
+    <td width="30%">獲取識別到的每個客制化物體的各項參數,包括:<img src="/media/ai/AI_r14.png" width="300"/></td>
+  </tr>
+</table>
+
+---
+## F.	基礎編程
+##### 活動一:物體檢測並顯示識別結果在「串口互動窗」
+<table style="margin-top:20px;">
+<tr>
+  <td colspan=2>在積木指令區點按以下指令,並依次放在積木編程區:<br>
+1.	AI模組|圖像處理:【相機初始化】<br>
+2.	循環:【一直重複執行】<br>
+3.	AI模組|AI模型:【加載預設模型】
+選擇:模型:「常見物體檢測模型」  圖像:「img_objectrecognition」<br>
+4.	變數:【設定變數】img_objectrecognition<br>
+5.	AI模組|相機:【獲取相機捕捉的圖像】<br>
+6.	邏輯:【邏輯判斷】<br>
+7.	AI模組|模型:【識別到了任意常見物體】<br>
+8.	序列埠通訊|打印:【打印文字】
+識別到物體則顯示「Object Detected」,否則「Nothing Detected」<br>
+</td>
+</tr>
+<tr >
+<td><img src="/media/ai/AI_s1.png" width="300"/></td>
+<td>注意:步驟4必須使用內建變數「img_objectrecognition」,所以首先要在步驟3使用「加載預設模型」指令,然後才進行步驟4及步驟5。</td>
+</tr>
+<tr >
+<td><img src="/media/ai/AI_s2.png" width="300"/></td>
+<td><img src="/media/ai/AI_s3.png" width="300"/></td>
+</tr>
+<tr >
+<td>測試結果:在「代碼區」點按「串口互動窗」,將模組向四周掃描,並觀察顯示的結果如下,當檢測到有物體時會顯示「Object Found」,否則會顯示「Nothing」</td>
+<td><img src="/media/ai/AI_s4.png" width="300"/></td>
+</tr>
+</table>
+
+##### 活動二:物體檢測並顯示物體名稱
+<table style="margin-top:20px;">
+<tr>
+  <td colspan=2>重複活動一的程式,在步驟8「顯示文字」指令修改如下:<br>
+1.	循環:【For循環】<br>
+2.	AI模組|模型:【識別到了任意常見物體】<br>
+3.	序列埠通訊:【打印】<br>
+4.	AI模組|模型:【獲取物體參數】選擇「物體名稱」<br>
+</td>
+</tr>
+<tr >
+<td colspan=2><img src="/media/ai/AI_s5.png" width="300"/></td>
+</tr>
+<tr >
+<td><img src="/media/ai/AI_s6.png" width="300"/></td>
+<td><img src="/media/ai/AI_s7.png" width="300"/></td>
+</tr>
+<tr >
+<td>測試結果:點按「串口互動窗」,將模組向四周掃描,並觀察顯示的結果如下,當檢測到有物體時會顯示「物體名稱」,否則會顯示「Nothing」</td>
+<td><img src="/media/ai/AI_s8.png" width="300"/></td>
+</tr>
+</table>
+思考問題:活動二的程式運用「物體檢測模型」,判斷攝影鏡頭拍攝到的圖像,並輸出物體名稱,此名稱是如何決定?「物體檢測模型」是否能夠判斷所有物體,輸出正確名稱?
+<br><img src="/media/ai/AI_s9.png" width="300"/>
+
+---
+## G.	專題學習
+硬體設備:AI推理模組、螢幕模組、攝像頭模組<br>
+任務目標:利用攝影鏡頭將影像顯示在螢幕模組上,載入物體識別模型,將識別到的物體在螢幕上標示出來。<br>
+基本流程/步驟:
+<br><img src="/media/ai/AI_t1.png" width="350"/><br>
+
+###### 第一步:模組初始化
+<table style="margin-top:20px;">
+<tr >
+<td>在積木指令區點按以下指令,並依次放在積木編程區:<br>
+1.	AI模組|螢幕:【初始化】<br>
+2.	AI模組|相機:【初始化】<br>
+3.	循環:【重複執行】<br>
+</td>
+<td><img src="/media/ai/AI_t2.png" width="300"/></td>
+</tr>
+</table>
+
+###### 第二步:獲取影像,載入物體識別模型,進行物體識別
+<table style="margin-top:20px;">
+<tr>
+  <td colspan=2>在【重複執行】積木指令內,放置下列積木指令:<br>
+4.	AI模組|AI模型:【加載模型】
+(模型:常見物體識別模型 圖像:img_objectrecognition)<br>
+5.	變數:【賦值】(名稱:img_objectrecognition)<br>
+6.	AI模組|相機:【獲取影像】<br>
+7.	變數:【建立變數】(名稱:img_display)<br>
+8.	AI模組|圖像處理:【調整畫布尺寸】<br>
+9.	AI模組|圖像處理:【圖像轉換】<br>
+</td>
+</tr>
+<tr >
+<td colspan=2><img src="/media/ai/AI_t3.png" width="300"/></td>
+</tr>
+<tr >
+<td><img src="/media/ai/AI_t4.png" width="300"/></td>
+<td><img src="/media/ai/AI_t5.png" width="300"/></td>
+</tr>
+</table>
+
+###### 第三步:獲取影像,載入物體識別模型,進行物體識別
+<table style="margin-top:20px;">
+<tr>
+  <td colspan=2>在【圖像轉換】積木指令之後,放置下列積木指令:<br>
+10.	邏輯:【邏輯判斷】<br>
+11.	AI模組|AI模型:【物體識別】<br>
+12.	循環:【For循環】<br>
+13.	AI模組|AI模型:【物體識別】<br>
+14.	AI模組|圖像處理:【螢幕文字】,並修改座標的X值及Y值,使「物體名稱」顯示在螢幕左上角的適宜位置<br>
+15.	文字:【建立字串使用】<br>
+16.	AI模組|模型:【獲取物體參數】選擇「物體名稱」<br>
+17.	AI模組|圖像處理:【螢幕文字】並輸入「Nothing Detected.」,並修改座標的X值及Y值<br>
+
+</td>
+</tr>
+<tr >
+<td colspan=2><img src="/media/ai/AI_t6.png" width="300"/></td>
+</tr>
+<tr >
+<td colspan=2><img src="/media/ai/AI_t7.png" width="300"/></td>
+</tr>
+</table>
+
+###### 第四步:在螢幕上顯示影像
+<table style="margin-top:20px;">
+<tr>
+  <td colspan=2>在步驟10【邏輯判斷】積木指令之後,放置下列積木指令:<br>
+18.	AI模組|螢幕:【設定起始點坐標】、【顯示畫布】(名稱:img_display  起始座標X:8   Y值:36)
+</td>
+</tr>
+<tr >
+<td colspan=2><img src="/media/ai/AI_t8.png" width="300"/></td>
+</tr>
+</table>
+
+###### 完整程式:
+<table style="margin-top:20px;">
+<tr>
+ <td ><img src="/media/ai/AI_t9.png" width="300"/>
+</td>
+</tr>
+<tr >
+<td><img src="/media/ai/AI_t10.png" width="200"/></td>
+</tr>
+</table>
+
+---
+## H.	專題學習進階
+將上面專題中的第三步改為以下內容:在螢幕中顯示識別到的物體位置並以檢測框的形式標註出來。
+<table style="margin-top:20px;">
+<tr>
+  <td >在【圖像轉換】積木指令之後,放置下列積木指令:<br>
+10. 邏輯:【邏輯判斷】<br>
+11. AI模組|AI模型:【物體識別】<br>
+12. 循環:【For循環】<br>
+13. AI模組|AI模型:【物體識別】<br>
+14. AI模組|螢幕:【繪製矩形】(畫布:img_display  矩形:空心  顏色:白色  厚度:2)
+起始座標:X值,Y值   尺寸:寬度,高度<br>
+a.	數學運算:【int】轉換整數<br>
+b.	數學運算:【四則運算】,物體識別數值 / 1.42<br>
+c.	AI模組|AI模型:【物體識別屬性】<br>
+18. AI模組|螢幕:【繪製實心圓形】放置在屏幕中間<br>
+</td>
+</tr>
+<tr >
+<td><img src="/media/ai/AI_u1.png" width="200"/></td>
+</tr>
+</table>
+
+###### 第四步:在螢幕上顯示影像
+
+<table style="margin-top:20px;">
+<tr>
+  <td >在步驟10【邏輯判斷】積木指令之後,放置下列積木指令:<br>
+19. AI模組|螢幕:【顯示畫布】(名稱:img_display  起始座標X:8   Y值:36)<br>
+</td>
+</tr>
+<tr >
+<td> <img src="/media/ai/AI_u2.png" width="200"/></td>
+</tr>
+<tr >
+<td> 完整Python代碼:<img src="/media/ai/AI_u3.png" width="200"/></td>
+</tr>
+<tr >
+<td> 完整程式:<img src="/media/ai/AI_u4.png" width="200"/></td>
+</tr>
+<tr >
+<td> 運行結果:<img src="/media/ai/AI_u5.png" width="200"/><img src="/media/ai/AI_u6.png" width="200"/></td>
+</tr>
+</table>

+ 1 - 0
aikit/overview.md

@@ -0,0 +1 @@
+overview.md

+ 28 - 0
changelog.md

@@ -0,0 +1,28 @@
+## 版本日誌 Changelog
+- - -
+
+### v1.0.7 (20200810)
+
+- 功能相關
+  - 修復環境檢測中點擊開始檢測一直在刷新的問題
+  - 修復上傳插件下載鏈接出錯的問題
+  - 修復頁面右邊工具欄最後一項文字不隨語言的變化而變化,點擊無反應的問題
+  - 新增頁面右邊工具欄最後一項文字點擊添加對應的積木,中間會有加載提示
+  - 頁面彈窗新增右上角關閉按鈕
+  - 修復頁面右邊工具欄雲端Python模式以及JavaScript模式跳轉鏈接錯誤的問題
+  - 人臉辨識物體分類器路徑修改
+- 積木相關:
+  - 新增IoT模組屏幕欄目以及相關積木,將其放入IoT模組擴展模塊中
+  - 將IoT模組中的基礎欄目,Wi-Fi欄目,Web欄目,物聯網欄目的積木進行歸類
+  - 將AI模組中的人工智能下基礎欄目,音頻處理欄目,AI模型欄目的積木進行歸類
+  - 調整IoT模組中的基礎欄目積木的顏色,使其與AI模組中的人工智能下基礎欄目的積木顏色相同
+  - 將二代 blockly 中ai模組屏幕欄目的初始化積木中的 lcd.init(type=1 中的 1 改爲 2)
+- 界面相關:
+  - 新增右上角個人信息過長,當超過元素寬度,只顯示一部分字符,後面的字符以「...」替代
+  - 修復blockly編輯代碼區域數字排序區域樣式問題
+  - 修改版權信息
+
+---
+
+
+如有任何疑問,請郵件聯繫:support-hk@cocorobo.cc 感謝。

+ 445 - 0
colorpicker.js

@@ -0,0 +1,445 @@
+/**
+ * ColorPicker - pure JavaScript color picker without using images, external CSS or 1px divs.
+ * Copyright © 2011 David Durman, All rights reserved.
+ */
+(function(window, document, undefined) {
+
+    var type = (window.SVGAngle || document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML"),
+        picker, slide, hueOffset = 15, svgNS = 'http://www.w3.org/2000/svg';
+
+    // This HTML snippet is inserted into the innerHTML property of the passed color picker element
+    // when the no-hassle call to ColorPicker() is used, i.e. ColorPicker(function(hex, hsv, rgb) { ... });
+    
+    var colorpickerHTMLSnippet = [
+        
+        '<div class="picker-wrapper">',
+                '<div class="picker"></div>',
+                '<div class="picker-indicator"></div>',
+        '</div>',
+        '<div class="slide-wrapper">',
+                '<div class="slide"></div>',
+                '<div class="slide-indicator"></div>',
+        '</div>'
+        
+    ].join('');
+
+    /**
+     * Return mouse position relative to the element el.
+     */
+    function mousePosition(evt) {
+        // IE:
+        if (window.event && window.event.contentOverflow !== undefined) {
+            return { x: window.event.offsetX, y: window.event.offsetY };
+        }
+        // Webkit:
+        if (evt.offsetX !== undefined && evt.offsetY !== undefined) {
+            return { x: evt.offsetX, y: evt.offsetY };
+        }
+        // Firefox:
+        var wrapper = evt.target.parentNode.parentNode;
+        return { x: evt.layerX - wrapper.offsetLeft, y: evt.layerY - wrapper.offsetTop };
+    }
+
+    /**
+     * Create SVG element.
+     */
+    function $(el, attrs, children) {
+        el = document.createElementNS(svgNS, el);
+        for (var key in attrs)
+            el.setAttribute(key, attrs[key]);
+        if (Object.prototype.toString.call(children) != '[object Array]') children = [children];
+        var i = 0, len = (children[0] && children.length) || 0;
+        for (; i < len; i++)
+            el.appendChild(children[i]);
+        return el;
+    }
+
+    /**
+     * Create slide and picker markup depending on the supported technology.
+     */
+    if (type == 'SVG') {
+
+        slide = $('svg', { xmlns: 'http://www.w3.org/2000/svg', version: '1.1', width: '100%', height: '100%' },
+                  [
+                      $('defs', {},
+                        $('linearGradient', { id: 'gradient-hsv', x1: '0%', y1: '100%', x2: '0%', y2: '0%'},
+                          [
+                              $('stop', { offset: '0%', 'stop-color': '#FF0000', 'stop-opacity': '1' }),
+                              $('stop', { offset: '13%', 'stop-color': '#FF00FF', 'stop-opacity': '1' }),
+                              $('stop', { offset: '25%', 'stop-color': '#8000FF', 'stop-opacity': '1' }),
+                              $('stop', { offset: '38%', 'stop-color': '#0040FF', 'stop-opacity': '1' }),
+                              $('stop', { offset: '50%', 'stop-color': '#00FFFF', 'stop-opacity': '1' }),
+                              $('stop', { offset: '63%', 'stop-color': '#00FF40', 'stop-opacity': '1' }),
+                              $('stop', { offset: '75%', 'stop-color': '#0BED00', 'stop-opacity': '1' }),
+                              $('stop', { offset: '88%', 'stop-color': '#FFFF00', 'stop-opacity': '1' }),
+                              $('stop', { offset: '100%', 'stop-color': '#FF0000', 'stop-opacity': '1' })
+                          ]
+                         )
+                       ),
+                      $('rect', { x: '0', y: '0', width: '100%', height: '100%', fill: 'url(#gradient-hsv)'})
+                  ]
+                 );
+
+        picker = $('svg', { xmlns: 'http://www.w3.org/2000/svg', version: '1.1', width: '100%', height: '100%' },
+                   [
+                       $('defs', {},
+                         [
+                             $('linearGradient', { id: 'gradient-black', x1: '0%', y1: '100%', x2: '0%', y2: '0%'},
+                               [
+                                   $('stop', { offset: '0%', 'stop-color': '#000000', 'stop-opacity': '1' }),
+                                   $('stop', { offset: '100%', 'stop-color': '#CC9A81', 'stop-opacity': '0' })
+                               ]
+                              ),
+                             $('linearGradient', { id: 'gradient-white', x1: '0%', y1: '100%', x2: '100%', y2: '100%'},
+                               [
+                                   $('stop', { offset: '0%', 'stop-color': '#FFFFFF', 'stop-opacity': '1' }),
+                                   $('stop', { offset: '100%', 'stop-color': '#CC9A81', 'stop-opacity': '0' })
+                               ]
+                              )
+                         ]
+                        ),
+                       $('rect', { x: '0', y: '0', width: '100%', height: '100%', fill: 'url(#gradient-white)'}),
+                       $('rect', { x: '0', y: '0', width: '100%', height: '100%', fill: 'url(#gradient-black)'})
+                   ]
+                  );
+
+    } else if (type == 'VML') {
+        slide = [
+            '<DIV style="position: relative; width: 100%; height: 100%">',
+            '<v:rect style="position: absolute; top: 0; left: 0; width: 100%; height: 100%" stroked="f" filled="t">',
+            '<v:fill type="gradient" method="none" angle="0" color="red" color2="red" colors="8519f fuchsia;.25 #8000ff;24903f #0040ff;.5 aqua;41287f #00ff40;.75 #0bed00;57671f yellow"></v:fill>',
+            '</v:rect>',
+            '</DIV>'
+        ].join('');
+
+        picker = [
+            '<DIV style="position: relative; width: 100%; height: 100%">',
+            '<v:rect style="position: absolute; left: -1px; top: -1px; width: 101%; height: 101%" stroked="f" filled="t">',
+            '<v:fill type="gradient" method="none" angle="270" color="#FFFFFF" opacity="100%" color2="#CC9A81" o:opacity2="0%"></v:fill>',
+            '</v:rect>',
+            '<v:rect style="position: absolute; left: 0px; top: 0px; width: 100%; height: 101%" stroked="f" filled="t">',
+            '<v:fill type="gradient" method="none" angle="0" color="#000000" opacity="100%" color2="#CC9A81" o:opacity2="0%"></v:fill>',
+            '</v:rect>',
+            '</DIV>'
+        ].join('');
+        
+        if (!document.namespaces['v'])
+            document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', '#default#VML');
+    }
+
+    /**
+     * Convert HSV representation to RGB HEX string.
+     * Credits to http://www.raphaeljs.com
+     */
+    function hsv2rgb(hsv) {
+        var R, G, B, X, C;
+        var h = (hsv.h % 360) / 60;
+        
+        C = hsv.v * hsv.s;
+        X = C * (1 - Math.abs(h % 2 - 1));
+        R = G = B = hsv.v - C;
+
+        h = ~~h;
+        R += [C, X, 0, 0, X, C][h];
+        G += [X, C, C, X, 0, 0][h];
+        B += [0, 0, X, C, C, X][h];
+
+        var r = Math.floor(R * 255);
+        var g = Math.floor(G * 255);
+        var b = Math.floor(B * 255);
+        return { r: r, g: g, b: b, hex: "#" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1) };
+    }
+
+    /**
+     * Convert RGB representation to HSV.
+     * r, g, b can be either in <0,1> range or <0,255> range.
+     * Credits to http://www.raphaeljs.com
+     */
+    function rgb2hsv(rgb) {
+
+        var r = rgb.r;
+        var g = rgb.g;
+        var b = rgb.b;
+        
+        if (rgb.r > 1 || rgb.g > 1 || rgb.b > 1) {
+            r /= 255;
+            g /= 255;
+            b /= 255;
+        }
+
+        var H, S, V, C;
+        V = Math.max(r, g, b);
+        C = V - Math.min(r, g, b);
+        H = (C == 0 ? null :
+             V == r ? (g - b) / C + (g < b ? 6 : 0) :
+             V == g ? (b - r) / C + 2 :
+                      (r - g) / C + 4);
+        H = (H % 6) * 60;
+        S = C == 0 ? 0 : C / V;
+        return { h: H, s: S, v: V };
+    }
+
+    /**
+     * Return click event handler for the slider.
+     * Sets picker background color and calls ctx.callback if provided.
+     */  
+    function slideListener(ctx, slideElement, pickerElement) {
+        return function(evt) {
+            evt = evt || window.event;
+            var mouse = mousePosition(evt);
+            ctx.h = mouse.y / slideElement.offsetHeight * 360 + hueOffset;
+            var pickerColor = hsv2rgb({ h: ctx.h, s: 1, v: 1 });
+            var c = hsv2rgb({ h: ctx.h, s: ctx.s, v: ctx.v });
+            pickerElement.style.backgroundColor = pickerColor.hex;
+            ctx.callback && ctx.callback(c.hex, { h: ctx.h - hueOffset, s: ctx.s, v: ctx.v }, { r: c.r, g: c.g, b: c.b }, undefined, mouse);
+        }
+    };
+
+    /**
+     * Return click event handler for the picker.
+     * Calls ctx.callback if provided.
+     */  
+    function pickerListener(ctx, pickerElement) {
+        return function(evt) {
+            evt = evt || window.event;
+            var mouse = mousePosition(evt),
+                width = pickerElement.offsetWidth,            
+                height = pickerElement.offsetHeight;
+
+            ctx.s = mouse.x / width;
+            ctx.v = (height - mouse.y) / height;
+            var c = hsv2rgb(ctx);
+            ctx.callback && ctx.callback(c.hex, { h: ctx.h - hueOffset, s: ctx.s, v: ctx.v }, { r: c.r, g: c.g, b: c.b }, mouse);
+        }
+    };
+
+    var uniqID = 0;
+    
+    /**
+     * ColorPicker.
+     * @param {DOMElement} slideElement HSV slide element.
+     * @param {DOMElement} pickerElement HSV picker element.
+     * @param {Function} callback Called whenever the color is changed provided chosen color in RGB HEX format as the only argument.
+     */
+    function ColorPicker(slideElement, pickerElement, callback) {
+        
+        if (!(this instanceof ColorPicker)) return new ColorPicker(slideElement, pickerElement, callback);
+
+        this.h = 0;
+        this.s = 1;
+        this.v = 1;
+
+        if (!callback) {
+            // call of the form ColorPicker(element, funtion(hex, hsv, rgb) { ... }), i.e. the no-hassle call.
+
+            var element = slideElement;
+            element.innerHTML = colorpickerHTMLSnippet;
+            
+            this.slideElement = element.getElementsByClassName('slide')[0];
+            this.pickerElement = element.getElementsByClassName('picker')[0];
+            var slideIndicator = element.getElementsByClassName('slide-indicator')[0];
+            var pickerIndicator = element.getElementsByClassName('picker-indicator')[0];
+            
+            ColorPicker.fixIndicators(slideIndicator, pickerIndicator);
+
+            this.callback = function(hex, hsv, rgb, pickerCoordinate, slideCoordinate) {
+
+                ColorPicker.positionIndicators(slideIndicator, pickerIndicator, slideCoordinate, pickerCoordinate);
+                
+                pickerElement(hex, hsv, rgb);
+            };
+            
+        } else {
+        
+            this.callback = callback;
+            this.pickerElement = pickerElement;
+            this.slideElement = slideElement;
+        }
+
+        if (type == 'SVG') {
+
+            // Generate uniq IDs for linearGradients so that we don't have the same IDs within one document.
+            // Then reference those gradients in the associated rectangles.
+
+            var slideClone = slide.cloneNode(true);
+            var pickerClone = picker.cloneNode(true);
+            
+            var hsvGradient = slideClone.getElementsByTagName('linearGradient')[0];
+            
+            var hsvRect = slideClone.getElementsByTagName('rect')[0];
+            
+            hsvGradient.id = 'gradient-hsv-' + uniqID;
+            hsvRect.setAttribute('fill', 'url(#' + hsvGradient.id + ')');
+
+            var blackAndWhiteGradients = [pickerClone.getElementsByTagName('linearGradient')[0], pickerClone.getElementsByTagName('linearGradient')[1]];
+            var whiteAndBlackRects = pickerClone.getElementsByTagName('rect');
+            
+            blackAndWhiteGradients[0].id = 'gradient-black-' + uniqID;
+            blackAndWhiteGradients[1].id = 'gradient-white-' + uniqID;
+            
+            whiteAndBlackRects[0].setAttribute('fill', 'url(#' + blackAndWhiteGradients[1].id + ')');
+            whiteAndBlackRects[1].setAttribute('fill', 'url(#' + blackAndWhiteGradients[0].id + ')');
+
+            this.slideElement.appendChild(slideClone);
+            this.pickerElement.appendChild(pickerClone);
+
+            uniqID++;
+            
+        } else {
+            
+            this.slideElement.innerHTML = slide;
+            this.pickerElement.innerHTML = picker;            
+        }
+
+        addEventListener(this.slideElement, 'click', slideListener(this, this.slideElement, this.pickerElement));
+        addEventListener(this.pickerElement, 'click', pickerListener(this, this.pickerElement));
+
+        enableDragging(this, this.slideElement, slideListener(this, this.slideElement, this.pickerElement));
+        enableDragging(this, this.pickerElement, pickerListener(this, this.pickerElement));
+    };
+
+    function addEventListener(element, event, listener) {
+
+        if (element.attachEvent) {
+            
+            element.attachEvent('on' + event, listener);
+            
+        } else if (element.addEventListener) {
+
+            element.addEventListener(event, listener, false);
+        }
+    }
+
+   /**
+    * Enable drag&drop color selection.
+    * @param {object} ctx ColorPicker instance.
+    * @param {DOMElement} element HSV slide element or HSV picker element.
+    * @param {Function} listener Function that will be called whenever mouse is dragged over the element with event object as argument.
+    */
+    function enableDragging(ctx, element, listener) {
+        
+        var mousedown = false;
+
+        addEventListener(element, 'mousedown', function(evt) { mousedown = true;  });
+        addEventListener(element, 'mouseup',   function(evt) { mousedown = false;  });
+        addEventListener(element, 'mouseout',  function(evt) { mousedown = false;  });
+        addEventListener(element, 'mousemove', function(evt) {
+
+            if (mousedown) {
+                
+                listener(evt);
+            }
+        });
+    }
+
+
+    ColorPicker.hsv2rgb = function(hsv) {
+        var rgbHex = hsv2rgb(hsv);
+        delete rgbHex.hex;
+        return rgbHex;
+    };
+    
+    ColorPicker.hsv2hex = function(hsv) {
+        return hsv2rgb(hsv).hex;
+    };
+    
+    ColorPicker.rgb2hsv = rgb2hsv;
+
+    ColorPicker.rgb2hex = function(rgb) {
+        return hsv2rgb(rgb2hsv(rgb)).hex;
+    };
+    
+    ColorPicker.hex2hsv = function(hex) {
+        return rgb2hsv(ColorPicker.hex2rgb(hex));
+    };
+    
+    ColorPicker.hex2rgb = function(hex) {
+        return { r: parseInt(hex.substr(1, 2), 16), g: parseInt(hex.substr(3, 2), 16), b: parseInt(hex.substr(5, 2), 16) };
+    };
+
+    /**
+     * Sets color of the picker in hsv/rgb/hex format.
+     * @param {object} ctx ColorPicker instance.
+     * @param {object} hsv Object of the form: { h: <hue>, s: <saturation>, v: <value> }.
+     * @param {object} rgb Object of the form: { r: <red>, g: <green>, b: <blue> }.
+     * @param {string} hex String of the form: #RRGGBB.
+     */
+     function setColor(ctx, hsv, rgb, hex) {
+         ctx.h = hsv.h % 360;
+         ctx.s = hsv.s;
+         ctx.v = hsv.v;
+         
+         var c = hsv2rgb(ctx);
+         
+         var mouseSlide = {
+             y: (ctx.h * ctx.slideElement.offsetHeight) / 360,
+             x: 0    // not important
+         };
+         
+         var pickerHeight = ctx.pickerElement.offsetHeight;
+         
+         var mousePicker = {
+             x: ctx.s * ctx.pickerElement.offsetWidth,
+             y: pickerHeight - ctx.v * pickerHeight
+         };
+         
+         ctx.pickerElement.style.backgroundColor = hsv2rgb({ h: ctx.h, s: 1, v: 1 }).hex;
+         ctx.callback && ctx.callback(hex || c.hex, { h: ctx.h, s: ctx.s, v: ctx.v }, rgb || { r: c.r, g: c.g, b: c.b }, mousePicker, mouseSlide);
+         
+         return ctx;
+    };
+
+    /**
+     * Sets color of the picker in hsv format.
+     * @param {object} hsv Object of the form: { h: <hue>, s: <saturation>, v: <value> }.
+     */
+    ColorPicker.prototype.setHsv = function(hsv) {
+        return setColor(this, hsv);
+    };
+    
+    /**
+     * Sets color of the picker in rgb format.
+     * @param {object} rgb Object of the form: { r: <red>, g: <green>, b: <blue> }.
+     */
+    ColorPicker.prototype.setRgb = function(rgb) {
+        return setColor(this, rgb2hsv(rgb), rgb);
+    };
+
+    /**
+     * Sets color of the picker in hex format.
+     * @param {string} hex Hex color format #RRGGBB.
+     */
+    ColorPicker.prototype.setHex = function(hex) {
+        return setColor(this, ColorPicker.hex2hsv(hex), undefined, hex);
+    };
+
+    /**
+     * Helper to position indicators.
+     * @param {HTMLElement} slideIndicator DOM element representing the indicator of the slide area.
+     * @param {HTMLElement} pickerIndicator DOM element representing the indicator of the picker area.
+     * @param {object} mouseSlide Coordinates of the mouse cursor in the slide area.
+     * @param {object} mousePicker Coordinates of the mouse cursor in the picker area.
+     */
+    ColorPicker.positionIndicators = function(slideIndicator, pickerIndicator, mouseSlide, mousePicker) {
+        
+        if (mouseSlide) {
+            slideIndicator.style.top = (mouseSlide.y - slideIndicator.offsetHeight/2) + 'px';
+        }
+        if (mousePicker) {
+            pickerIndicator.style.top = (mousePicker.y - pickerIndicator.offsetHeight/2) + 'px';
+            pickerIndicator.style.left = (mousePicker.x - pickerIndicator.offsetWidth/2) + 'px';
+        } 
+    };
+
+    /**
+     * Helper to fix indicators - this is recommended (and needed) for dragable color selection (see enabledDragging()).
+     */
+    ColorPicker.fixIndicators = function(slideIndicator, pickerIndicator) {
+
+        pickerIndicator.style.pointerEvents = 'none';
+        slideIndicator.style.pointerEvents = 'none';
+    };
+
+    window.ColorPicker = ColorPicker;
+
+})(window, window.document);

File diff suppressed because it is too large
+ 7 - 0
docsify-themeable


File diff suppressed because it is too large
+ 0 - 0
docsify.min.js


+ 69 - 0
extension/EX_01.md

@@ -0,0 +1,69 @@
+# <b>擴展轉接模組 基礎篇</b>
+
+## A. 認識擴展轉接模組
+
+擴展轉接模組上嵌有多組接口,包含AI 和 IoT兩大類,分別配合 AI 模組和 IoT 模組使用,用於外接多種第三方感應器或電子元器件,如紅外線感應器和超聲波感應器等,通過「輸入/輸出」類積木指令編程控制。
+<table style="margin-top:20px;">
+ <tr>
+   <td width="50%"><img src="/media/ai/AI_tuozhan1.png" width="350"/></td>
+   <td width="50%"><img src="/media/ai/AI_tuozhan2.png" width="350"/></td>
+ </tr>
+ <tr>
+   <td>正面</td>
+   <td>反面</td>
+ </tr>
+</table>
+
+1. 每組接口由正極(+)、負極(-)、訊號接口(Digital和Analog均適用)組成;
+2. 每個訊號接口均對應一個數字編號;
+3. 可使用外接供電(鋰電池、電池盒等),由切換開關控制,USB側為模組供電, EXT側為外接電源供電;
+4. 白色接口供連外接電源使用。
+
+
+## B.	使用擴展轉接模組(配合AI模组)
+效果展示:使用按鈕開關控制發光二極管亮和滅。<br><br>
+<img src="/media/EX/001.jpg" width="400"/><br>
+效果分析:獲取按鈕開關的狀態(輸入)以控制二極管的亮和滅(輸出),按鈕的按下與鬆開兩種狀態、二極管的亮和滅兩種狀態,分別與高電平、低電平或者0和1對應。
+
+所需材料:AI模组、擴展轉接模組、杜邦線(母-母)、二極管、按鈕開關。<br>
+<img src="/media/EX/002.jpg" width="400"/><br>
+
+### 步驟一:連接
+連接方式如下:<br>
+<img src="/media/EX/003.png" width="600"/><br>
+連接效果:<br>
+<img src="/media/EX/004.jpg" width="500"/><br>
+
+### 步驟二:編寫程式並上傳
+
+1. 所需擴展轉接模組「輸入/輸出」類積木指令:
+
+ <img src="/media/EX/005.png" width="400"/><br>
+
+2. 編寫程式示範:<br>
+
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%">在積木指令區點按以下指令,並依次放在積木編程區:<br>
+1.循環:「重複執行」<br>
+2.邏輯:「如果...執行」、「判斷」<br>
+3.輸入/輸出:選擇AI模組獲取引腳、設定引腳<br>
+4.引腳編號務必與轉接模組上實際連接的接口編號保持一致<br>
+5.數學運算:<img src="/media/EX/007.jpg"/>
+
+</td>
+		<td width="50%"><img src="/media/EX/006.jpg" width="350"/>
+	</tr>
+	<tr>
+		<td colspan=2>運行結果:
+當按下按鈕時,二極管發光,當鬆開按鈕時,二極管熄滅。
+</td>
+	</tr>
+</table>
+
+3. 補充<br>
+上面第2步「邏輯」積木指令的實現方式如下:<br>
+1)選擇:<br><img src="/media/EX/008.jpg" /><br>
+2)點擊左上角圖標,顯示如下:<br><img src="/media/EX/009.jpg" width="300"/><br>
+3)拖拽「否則」積木指令到右側,放到「如果」下麵,即可顯示出「否則」部分:<br>
+<img src="/media/EX/010.jpg" width="300"/><br>

+ 173 - 0
extension/EX_02.md

@@ -0,0 +1,173 @@
+# <b>擴展轉接模組 應用篇</b>
+
+## A. 感應器
+<b>感應器與擴展轉接模組的連接方法:</b><br>
+<img src="/media/EX/011.png" width="500"/><br>
+
+⚠️注意:
+1. 若感應器同時有DO和AO接口,則說明此感應器支持數碼訊號和模擬訊號輸入/輸出;<br>
+若感應器僅有DO接口,則說明此感應器僅支持數碼訊號輸入/輸出;<br>
+若感應器僅有AO接口,則說明此感應器僅支持模擬訊號輸入/輸出。<br>
+2. 擴展轉接模組上接口0、1為預留接口,供其他功能使用,建議連接感應器時,選擇其他接口。
+
+<b>擴展轉接模組可以配合多種感應器的使用,比如:</b>
+
+- ### 光照感應器
+探測光源処是一個光敏電阻,光敏電阻是用硫化鎘或硒化鎘等半導體材料製成的特殊電阻器,其工作原理是基於内光電效應。隨著光照强度的升高,電阻值迅速降低,由於光照產生的載流子都參與導電,在外加電場的作用下作漂移運動,電子奔向電源的正極,空穴奔向電源的負極,從而使光敏電阻器的組織迅速下降。其在無光照時,幾乎呈高阻狀態,暗電阻很大。
+該光照感應器對環境光線最敏感,一般用來檢測周圍環境的光線的亮度,觸發單片機或繼電器模組等。
+<img src="/media/EX/012.jpg" width="500"/><br>
+<br>
+使用「序列埠互動窗」打印光照感應器「數碼訊號數值」:<br><br>
+① 連接方法:<br>
+<img src="/media/EX/015.png" width="500"/><br>
+<img src="/media/EX/016.png" width="500"/><br>
+② 程式:<br>
+<img src="/media/EX/017.png" width="500"/><br>
+③ 效果:未遮擋感應器時顯示“0”;遮擋感應器時顯示“1”。<br>
+<img src="/media/EX/018.jpg" width="500"/><br>
+
+- ### 紅外避障感應器
+紅外避障感應器具有一對紅外訊號發射與接收二極管,發射管發射一定頻率的紅外訊號,接收管接受這種頻率的紅外訊號,儅傳感器的檢測方向遇到障礙物(反射面)時,紅外訊號反射回來被接收管接收,經過比較器電路處理之後,輸出指示処的綠色指示燈將被點亮,同時數碼端口持續輸出低電平訊號。<br><br>
+<img src="/media/EX/056.jpg" width="300"/><br>
+<br>
+使用「序列埠互動窗」打印紅外避障感應器「數碼訊號數值」:<br><br>
+① 連接方法:<br>
+<img src="/media/EX/019.png" width="500"/><br>
+② 程式:<br>
+<img src="/media/EX/020.png" width="500"/><br>
+③ 效果:<br>
+<img src="/media/EX/019.jpg" width="500"/><br>
+
+- ### 雨滴感應器
+可用於不同天氣狀況的監測,並轉換成數碼訊號或模擬訊號;使用時,感應板上沒有水滴時,數碼輸出爲高電平,開關指示燈滅,感應版越乾燥,讀取的模擬接口的數值越大,滴上一滴水,數碼輸出爲低電平,開關指示燈亮,水滴越多,讀取的模擬接口的數值越小。
+支持:數碼訊號、模擬訊號輸入<br>
+參數:5.0*4.0cm<br><br>
+<img src="/media/EX/021.png" width="500"/><br><br>
+使用「序列埠互動窗」打印光照感應器「數碼訊號數值」:<br><br>
+① 連接方法:<br>
+<img src="/media/EX/015.png" width="500"/><br>
+② 程式:<br>
+<img src="/media/EX/017.png" width="500"/><br>
+③ 效果:無雨時顯示“1”;有雨時顯示“0”。<br>
+<img src="/media/EX/022.png" width="500"/><br>
+提示:此處使用濕紙巾模擬雨滴效果。
+
+
+- ### 土壤濕度感應器
+土壤濕度感應器采用FDR頻域反射原理。FDR(Frequency Domain Reflectometry)頻域反射儀是一種用於測量土壤水分的儀器,它利用電磁脈衝原理、根據電磁波在介質中傳播頻率來測量土壤的表現介電常數,從而得到土壤相對含水量。
+將感應器插入土壤中,通過模擬/數碼轉換電壓訊號,即可檢測土壤水分,土壤越乾燥,輸出電壓越小,讀取的模擬接口的數值則越大,相反,越濕潤輸出電壓越大(數值越小),讀取的模擬接口的數值則越小。<br>
+支持:數碼訊號、模擬訊號<br>
+注意:高電平數碼輸出為1,低電平數碼輸出為0;<br><br>
+<img src="/media/EX/023.png" width="500"/><br><br>
+使用「序列埠互動窗」打印光照感應器「數碼訊號數值」:<br><br>
+① 連接方法:<br>
+<img src="/media/EX/024.png" width="500"/><br>
+② 程式:<br>
+<img src="/media/EX/025.png" width="500"/><br>
+③ 效果:無雨時顯示“1”;有雨時顯示“0”。<br>
+<img src="/media/EX/026.jpg" width="500"/><br>
+
+
+- ### 煙霧感應器
+當感應器所處環境中存在可燃性氣體時,感應器的電導率隨空氣中可燃性氣體濃度的增加而增大,模擬訊號對應的輸出電壓隨濃度越高電壓越高。<br><br>
+<img src="/media/EX/027.png" width="500"/><br><br>
+使用「序列埠互動窗」打印煙霧感應器「數碼訊號數值」:<br><br>
+① 連接方法:<br>
+<img src="/media/EX/047.png" width="500"/><br>
+② 程式:<br>
+<img src="/media/EX/048.png" width="500"/><br>
+③ 效果:<br>
+<img src="/media/EX/049.jpg" width="500"/><br>
+
+- ### 火焰感應器
+火焰是由各種燃燒生成物、中間物、高溫氣體、碳氫物質以及無機物質為主題的高溫固體微粒構成的。火焰的熱輻射具有離散光譜的氣體輻射和連續光譜的固體輻射。不同燃燒物的火焰輻射强度、波長分佈有所差異,但總體來説,其對應火焰溫度的近紅外波長域及紫外光域具有很大的輻射强度,根據這種特性可製成火焰傳感器。<br>
+可監測火焰或者波長在 760nm-1100nm 範圍內的光源,打火機測試火焰距離爲80cm,與火焰的距離越大,測試距離越遠。<br><br>
+<img src="/media/EX/028.png" width="500"/><br>
+使用「序列埠互動窗」打印火焰感應器「數碼訊號數值」:<br><br>
+① 連接方法:<br>
+<img src="/media/EX/050.png" width="500"/><br>
+② 程式:<br>
+<img src="/media/EX/051.png" width="500"/><br>
+③ 效果:<br>
+<img src="/media/EX/052.jpg" width="500"/><br>
+
+- ### 震動感應器
+震動感應器的作用主要是將機械量接收下來,並轉換為與之成比例的電量。它並不是直接將原始要測的機械量轉變爲電量,而是將原始要測的機械量作爲震動感應器的輸入量,然後由機械接收部分加以接收,形成另一個適合于變換的機械量,最後由機電變換部分再變換為電量。因此一個感應器的工作性能是由機械接收部分和機電變換部分的工作性能來決定的。<br>
+震動感應器用於各種震動觸發作用,不震動時,震動開關呈閉合導通狀態,輸出端輸出低電平訊號,綠色指示燈亮。<br><br>
+<img src="/media/EX/029.png" width="500"/><br>
+使用「序列埠互動窗」打印火焰感應器「數碼訊號數值」:<br><br>
+① 連接方法:<br>
+<img src="/media/EX/053.png" width="500"/><br>
+② 程式:<br>
+<img src="/media/EX/054.png" width="500"/><br>
+③ 效果:晃動震動感應器時,顯示“1”;保持靜止時,顯示“0”。 <br>
+<img src="/media/EX/055.png" width="600"/><br>
+
+- ### 超聲波距離感應器
+超聲波感應器是將超聲波信號轉換成其他能量訊號(通常是電訊號)的感應器。超聲波是震動頻率高於20kHZ的機械波。它具有頻率高、波長短、繞射現象小,特別是方向性好、能夠成爲射綫而定向傳播等特點。超聲波對液體、固體的穿透泵零很大,尤其是在陽光不透明的固體中。超聲波碰到雜質或分界面會產生顯著反射形成反射回波,碰到活動物體能產生多普勒效應。<br>
+該感應器利用超聲波測距離,多應用於機器人避開障礙物或其他距離測量的項目。<br><br>
+<img src="/media/EX/056.png" width="500"/><br>
+使用「序列埠互動窗」打印超聲波距離感應器「數值」:<br><br>
+① 連接方法:<br>
+<img src="/media/EX/057.png" width="500"/><br>
+② 程式:<br>
+<img src="/media/EX/058.png" width="500"/><br>
+<img src="/media/EX/059.png" width="500"/><br>
+③ 效果:用手感應不同距離。 <br>
+<img src="/media/EX/060.png" width="600"/><br>
+
+## B. 伺服馬達
+伺服馬達(Servomotor)是對用於使用伺服機構的馬達總稱。指依照命令動作的意義。所謂伺服系統,就是依照指示命令動作所構成的控制裝置,應用於馬達的伺服控制,將感測器裝在馬達與控制對象機器上,偵測結果會返回伺服放大器與指令值做比較。<br><br>
+<img src="/media/EX/030.png" width="400"/><br><br>
+設定伺服馬達轉動<br><br>
+① 連接方法:<br>
+<img src="/media/EX/031.png" width="500"/><br>
+<img src="/media/EX/032.png" width="400"/><br>
+② 程式:<br>
+<img src="/media/EX/033.png" width="500"/><br>
+
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%">在積木指令區點按以下指令,並依次放在積木編程區:<br>
+1. 伺服馬達:「初始化」<br>
+2. 循環:「一直重複執行」<br>
+3. 伺服馬達:設定伺服馬達轉動角度<br>
+4. 引腳編號務必與轉接模組上實際連接的接口編號保持一致<br>
+5. 時間:「等待」<br>
+</td>
+		<td width="50%"><img src="/media/EX/034.png" width="350"/>
+	</tr>
+	<tr>
+		<td colspan=2>運行效果:伺服馬達的舵臂會先轉動至90度,再返回起始位置,一直重複
+</td>
+	</tr>
+</table>
+
+## C. LED燈帶
+發光二極管(英語:Light-emitting diode,縮寫為LED)是一種能發光的半導體電子元件。LED燈帶是指把LED組裝在帶狀的FPC(柔性綫路板)或PCB硬板上,因其産品形狀象一條帶子一樣而得名。因爲使用壽命長(一般正常壽命在8~10萬小時),又非常節能和綠色環保而逐漸在各種裝飾行業中嶄露頭角。<br><br>
+<img src="/media/EX/061.png" width="400"/><br><br>
+設定LED燈帶亮起<br><br>
+① 觀察燈帶,認識標識。(推荐型号WS2812。不同規格燈帶,標識可能會有差別。)<br>
+<img src="/media/EX/062.png" width="500"/><br><br>
+② 連接LED燈帶(使用杜邦缐連接,對應燈帶標識和擴展板接口。)<br>
+<img src="/media/EX/063.png" width="400"/><br>
+③程式:<br>
+<img src="/media/EX/064.png" width="500"/><br>
+
+<table style="margin-top:20px;">
+	<tr>
+		<td width="50%">
+		在積木指令區點按以下指令,並依次放在積木編程區:<br>
+		1. LED燈帶:「初始化」選擇AI模組。<br>
+		2. 設置燈帶引脚和燈的數量。<br>
+		3. 循環:「從範圍1到15」<br>
+		4. LED燈帶:設定燈的序號和顔色。<br>
+		5. 顯示燈帶效果。<br>
+</td>
+		<td width="50%"><img src="/media/EX/065.png" width="350"/>
+	</tr>
+	<tr>
+		<td colspan=2>運行效果:15個LED鄧全部亮起紅色
+</td>
+	</tr>
+</table>

+ 46 - 0
extension/EX_03.md

@@ -0,0 +1,46 @@
+# <b>擴展轉接模組 通訊篇</b>
+
+## A. Micro:bit
+Micro:bit是由英國BBC公司推出的面向青少年編程教育的微型計算機,別看它身材不大,但麻雀雖小五臟俱全,一塊小板子上集成了加速度傳感器,磁力傳感器,兩個可編程按鈕,25個單色LED,藍牙等常用感测器設備,采用Micro usb口供電,可外接電池盒,在底部還有多個環孔連接器,可用于控制外接設備。<br>
+學習使用Micro:bit請參閲:
+Micro:bit快速入門 https://archive.microbit.org/hk/guide/quick/<br>
+<img src="/media/EX/038.jpg" width="400"/><br><br>
+cocorobo的AI模組可以通過擴展版模組與Micro:bit通訊。<br>
+### 1. 擴展轉接模組與Micro:bit通訊
+①  連接方法<br>
+Micro:bit與擴展轉接模組的PIN口:<br>
+<img src="/media/EX/043.jpg" width="700"/><br><br>
+使用鰐魚夾連接Micro:bit與擴展轉接模組:<br>
+<img src="/media/EX/045.png" width="500"/><br><br>
+<img src="/media/EX/044.png" width="500"/><br><br>
+連接效果如下:<br>
+<img src="/media/EX/046.png" width="500"/><br><br>
+② :Micro:bit程式設計<br>
+程式設計平臺:https://makecode.microbit.org/<br>
+編寫下圖程式接收序列埠通訊文字:<br>
+<img src="/media/EX/035.png" width="500"/><br><br>
+③:AI模組程式設計<br>
+程式設計平臺:https://x.cocorobo.hk<br>
+<img src="/media/EX/039.png" width="500"/><br><br>
+④ 運行程式后查看Micro:bit的效果<br>
+<img src="/media/EX/040.gif" width="400"/><br><br>
+
+### 2. AI模組控制Micro:bit
+①  連接方法同上。<br>
+② :Micro:bit程式設計<br>
+編寫下圖程式接收序列埠通訊文字並做出不同指令:<br>
+<img src="/media/EX/037.png" width="500"/><br><br>
+③:AI模組程式設計<br>
+編寫下圖程式按下按鍵發送不同文字:<br>
+<img src="/media/EX/041.png" width="500"/><br><br>
+④ 運行程式后查看Micro:bit的效果<br>
+<img src="/media/EX/042.gif" width="400"/><br><br>
+
+## B. Arduino
+更多功能持續更新中。
+
+## C. mBot
+更多功能持續更新中。
+
+## D. LEGO
+更多功能持續更新中。

+ 1 - 0
extension/overview.md

@@ -0,0 +1 @@
+overview

+ 6 - 0
faq.md

@@ -0,0 +1,6 @@
+<div class="headerInProgress">
+	本部分內容仍在更新中,帶來的不便,請您諒解。
+</div>
+
+# 常見問題解答 FAQ
+---

+ 1 - 0
getting-started.md

@@ -0,0 +1 @@
+to be edited.

+ 172 - 0
index.html

@@ -0,0 +1,172 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <title>CocoBlockly X 幫助文檔</title>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+    <meta name="description" content="Description">
+    <meta name="viewport"
+        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <!--<link rel="stylesheet" href="https://unpkg.com/docsify-themeable/dist/css/theme-simple.css">-->
+    <link rel="stylesheet" href="vue.css">
+    <meta name="theme-color" content="#2C4FCD">
+    <link rel="apple-touch-icon" sizes="57x57" href="http://cocorobo.hk/cocoblockly/dev/img/apple-icon-57x57.png">
+    <link rel="apple-touch-icon" sizes="60x60" href="http://cocorobo.hk/cocoblockly/dev/img/apple-icon-60x60.png">
+    <link rel="apple-touch-icon" sizes="72x72" href="http://cocorobo.hk/cocoblockly/dev/img/apple-icon-72x72.png">
+    <link rel="apple-touch-icon" sizes="76x76" href="http://cocorobo.hk/cocoblockly/dev/img/apple-icon-76x76.png">
+    <link rel="apple-touch-icon" sizes="114x114" href="http://cocorobo.hk/cocoblockly/dev/img/apple-icon-114x114.png">
+    <link rel="apple-touch-icon" sizes="120x120" href="http://cocorobo.hk/cocoblockly/dev/img/apple-icon-120x120.png">
+    <link rel="apple-touch-icon" sizes="144x144" href="http://cocorobo.hk/cocoblockly/dev/img/apple-icon-144x144.png">
+    <link rel="apple-touch-icon" sizes="152x152" href="http://cocorobo.hk/cocoblockly/dev/img/apple-icon-152x152.png">
+    <link rel="apple-touch-icon" sizes="180x180" href="http://cocorobo.hk/cocoblockly/dev/img/apple-icon-180x180.png">
+    <link rel="icon" type="image/png" sizes="192x192"
+        href="http://cocorobo.hk/cocoblockly/dev/img/android-icon-192x192.png">
+    <link rel="icon" type="image/png" sizes="32x32" href="http://cocorobo.hk/cocoblockly/dev/img/favicon-32x32.png">
+    <link rel="icon" type="image/png" sizes="96x96" href="http://cocorobo.hk/cocoblockly/dev/img/favicon-96x96.png">
+    <link rel="icon" type="image/png" sizes="16x16" href="http://cocorobo.hk/cocoblockly/dev/img/favicon-16x16.png">
+    <link rel="manifest" href="http://cocorobo.hk/cocoblockly/dev/img/manifest.json">
+    <meta name="msapplication-TileColor" content="#ffffff">
+    <meta name="msapplication-TileImage" content="http://cocorobo.hk/cocoblockly/dev/img/ms-icon-144x144.png">
+    <script type="text/javascript" src="colorpicker.js"></script>
+    <link href="./lightbox.min.css" rel="stylesheet" />
+    <style type="text/css">
+        #picker {
+            width: 200px;
+            height: 200px
+        }
+
+        #slide {
+            width: 30px;
+            height: 200px
+        }
+
+        .headerInProgress {
+            font-weight: bold;
+            background-color: rgba(247, 114, 16, .9);
+            color: white;
+            padding: 16px 18px;
+            margin-bottom: 40px;
+            border-radius: 10px;
+            border-left: 5px solid rgba(238, 91, 10, 1.0);
+        }
+    </style>
+</head>
+
+<body>
+    <nav class="body-nav">
+        <a href="#/" id="hk" class="active">繁</a>
+        <a href="#/" id="cn">简</a>
+        <!-- <a href="#/" id="aa">EN</a> -->
+    </nav>
+    <div id="app">Please wait...</div>
+    <script>
+        window.$docsify = {
+            name: 'CocoBlockly X Help',
+            // repo: '',
+            logo: '/media/help-logo.png',
+            themeColor: '#225dd5',
+            homepage: 'index.md',
+            auto2top: true,
+
+            loadSidebar: true,
+            loadSidebar: 'summary.md',
+            maxLevel: 1,
+            subMaxLevel: 1,
+
+            // Search feature
+
+            search: 'auto', // default
+            search: [
+                '/index.md',
+                '/EX_01.md',
+                '/EX_02.md',
+                '/EX_03.md',
+            ],
+
+            // complete configuration parameters
+            search: {
+                maxAge: 86400000, // Expiration time, the default one day
+                paths: 'auto', // or 'auto'
+                placeholder: '點此處搜尋內容',
+
+                // Localization
+                placeholder: {
+                    '/': '點此處搜尋內容'
+                },
+
+                noData: '沒有搜尋到結果',
+
+                // Localization
+                noData: {
+                    '/': '沒有搜尋到結果'
+                },
+
+                // Headline depth, 1 - 6
+                depth: 6
+            },
+
+            ga: 'UA-110081781-1'
+        }
+    </script>
+    <script>
+        var hash = window.location.hash;
+        if (window.addEventListener) {
+            window.addEventListener("hashchange", myFunction, false);
+        } else if (window.attachEvent) {
+            window.attachEvent("hashchange", myFunction);
+        }
+        // window.onhashchange(function () {
+
+        // console.log(myFunction())
+        // })
+        function myFunction() {
+            hash = window.location.hash;
+            setTimeout(() => { imgload(); }, 500)
+        }
+        document.getElementById('cn').onclick = function () {
+            window.location.href = `http://x-help.cocorobo.cn/${hash}`
+        }
+        // document.getElementById('aa').onclick = function () {
+        //     window.location.href = `http://x-help.cocorobo.hk/${hash}`
+        // }
+    </script>
+    <!-- docsify -->
+    <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/docsify/4.9.4/docsify.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/docsify/4.9.4/plugins/search.min.js"></script> -->
+    <script src="docsify.min.js"></script>
+    <script src="search.min.js"></script>
+    <!-- docsify-themeable -->
+    <!-- <script src="//unpkg.com/docsify-themeable"></script>-->
+    <script type="text/javascript" src="lightbox-plus-jquery.min.js"></script>
+    <script>
+        window.onload = imgload = function () {
+            let imgs = document.getElementsByTagName('img')
+            for (let i = 0; i < imgs.length - 1; i++) {
+                imgs[i].onclick = function () {
+                    let parent = imgs[i].parentNode;
+                    let num = 0
+                    for (let j = 0; j < parent.children.length; j++) {
+                        let parentStr = decodeURI(parent.children[j] && parent.children[j].src) || '';
+                        let imgSrc = imgs[i].src
+                        if ((parentStr && parentStr.slice(parentStr.lastIndexOf('/') + 1, parentStr.lastIndexOf('.'))) === imgSrc.slice(imgSrc.lastIndexOf('/') + 1, imgSrc.lastIndexOf('.'))) {
+                            num = j;
+                            console.log(num)
+                        }
+                    }
+                    if (parent.tagName !== "A") {
+                        imgs[i].style.marginRight = 5 + 'px';
+                        let A = document.createElement('a')
+                        A.href = imgs[i].src;
+                        A.setAttribute('data-lightbox', imgs[i].src);
+                        A.appendChild(imgs[i]);
+                        parent.insertBefore(A, parent.children[num]);
+                        A.addEventListener('click', function () { })
+                    }
+                }
+            }
+        }
+    </script>
+</body>
+
+</html>

+ 18 - 0
index.md

@@ -0,0 +1,18 @@
+# CocoBlockly X 在線幫助文檔
+<img src="/media/blockly.png" width="650"/>
+
+## AI Kit
+
+* [認識CocoBlockly X編程環境](/aikit/AI_1.md)
+* [認識螢幕模組](/aikit/AI_2.md)
+* [認識攝影鏡頭模組](/aikit/AI_3.md)
+* [認識物體識別](/aikit/AI_4.md)
+
+## 拓展轉接模組
+
+* [基礎篇](/extension/EX_01.md)
+* [應用篇](/extension/EX_02.md)
+* [通訊篇](/extension/EX_03.md)
+
+## [Uploader常見錯誤處理](/aikit/A0.md)
+<!-- ## [版本更新日誌](changelog) -->

File diff suppressed because it is too large
+ 13 - 0
lightbox-plus-jquery.min.js


File diff suppressed because it is too large
+ 0 - 0
lightbox.min.css


BIN
media/EX/001.jpg


BIN
media/EX/002.jpg


BIN
media/EX/003.jpg


BIN
media/EX/003.png


BIN
media/EX/004.jpg


BIN
media/EX/005.jpg


BIN
media/EX/005.png


BIN
media/EX/006.jpg


BIN
media/EX/007.jpg


BIN
media/EX/008.jpg


BIN
media/EX/009.jpg


BIN
media/EX/010.jpg


BIN
media/EX/011.png


BIN
media/EX/012.jpg


BIN
media/EX/015.png


BIN
media/EX/016.png


BIN
media/EX/017.png


BIN
media/EX/018.jpg


BIN
media/EX/019.jpg


BIN
media/EX/019.png


BIN
media/EX/020.png


BIN
media/EX/021.png


BIN
media/EX/022.png


BIN
media/EX/023.png


BIN
media/EX/024.png


BIN
media/EX/025.png


BIN
media/EX/026.jpg


BIN
media/EX/027.png


BIN
media/EX/028.png


BIN
media/EX/029.png


BIN
media/EX/030.png


BIN
media/EX/031.png


BIN
media/EX/032.png


BIN
media/EX/033.png


BIN
media/EX/034.png


BIN
media/EX/035.png


BIN
media/EX/036.jpg


BIN
media/EX/037.png


BIN
media/EX/038.jpg


BIN
media/EX/039.png


BIN
media/EX/040.gif


BIN
media/EX/041.gif


BIN
media/EX/041.png


BIN
media/EX/042.gif


BIN
media/EX/043.jpg


BIN
media/EX/044.png


BIN
media/EX/045.png


BIN
media/EX/046.png


BIN
media/EX/047.png


BIN
media/EX/048.png


BIN
media/EX/049.jpg


BIN
media/EX/050.png


BIN
media/EX/051.png


BIN
media/EX/052.jpg


BIN
media/EX/053.png


BIN
media/EX/054.png


BIN
media/EX/055.png


BIN
media/EX/056.jpg


BIN
media/EX/056.png


BIN
media/EX/057.png


BIN
media/EX/058.png


BIN
media/EX/059.png


BIN
media/EX/060.png


BIN
media/EX/061.png


BIN
media/EX/062.png


BIN
media/EX/063.png


BIN
media/EX/064.png


BIN
media/EX/065.png


BIN
media/EX/w1.png


BIN
media/EX/w2.png


BIN
media/EX/w3.png


BIN
media/ai/AI_E1.png


BIN
media/ai/AI_E2.png


BIN
media/ai/AI_E3.png


BIN
media/ai/AI_I1.png


BIN
media/ai/AI_I10.png


BIN
media/ai/AI_I11.png


BIN
media/ai/AI_I12.png


BIN
media/ai/AI_I13.png


Some files were not shown because too many files changed in this diff