2025年12月12日 星期五

會跳舞機器人奧托雙足(Otto Biped)

前一篇:OTTO 忍者機器人
奧托雙足:Otto DIY build your own robot

操作介面:



HTML腳本:



  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<title>Otto Web BLE Controller</title>
<style>
body { font-family: Arial, sans-serif; text-align:center; background:#f9f9f9; }
button{
    width:140px; height:60px; margin:10px; font-size:16px;
    border:none; border-radius:10px; background:#4CAF50; color:white;
}
button.red{ background:#d9534f; }
button.blue{ background:#0275d8;}
.container{ margin-top:30px; }
</style>
</head>
<body>

<h2>OTTO BLE 遙控器</h2>
<button id="connectBle">連線 / Connect</button>
<button id="disconnectBle" disabled>中斷連線 / Disconnect</button>
<p id="status">尚未連線</p>

<div class="container">
    <button onclick="sendMove('forward')">⬆ 前進 / Forward (forward)</button><br>
    <button onclick="sendMove('left')">⬅ 左轉 / Left (left)</button>
    <button onclick="sendMove('stop')" class="red">⏹ 停止 / Stop (stop)</button>
    <button onclick="sendMove('right')">➡ 右轉 / Right (right)</button><br>
    <button onclick="sendMove('backward')">⬇ 後退 / Backward (backward)</button>
</div>

<h3>表情與動作 / Emotions & Gestures</h3>
<!-- 第一列 -->
<button onclick="sendGesture('happy')">開心 / Happy (happy)</button>
<button onclick="sendGesture('superhappy')">超開心 / Super Happy (superhappy)</button>
<button onclick="sendGesture('sad')">難過 / Sad (sad)</button>
<button onclick="sendGesture('sleeping')">睡覺 / Sleeping (sleeping)</button><br>
<!-- 第二列 -->
<button onclick="sendGesture('confused')">困惑 / Confused (confused)</button>
<button onclick="sendGesture('fretful')">煩躁 / Fretful (fretful)</button>
<button onclick="sendGesture('love')">愛心 / Love (love)</button>
<button onclick="sendGesture('angry')">生氣 / Angry (angry)</button><br>
<!-- 第三列 -->
<button onclick="sendGesture('magic')">魔法 / Magic (magic)</button>
<button onclick="sendGesture('wave')">揮手 / Wave (wave)</button>
<button onclick="sendGesture('victory')">勝利 / Victory (victory)</button>
<button onclick="sendGesture('fail')">失敗 / Fail (fail)</button><br>
<!-- 第四列 -->
<button onclick="sendGesture('fart')">放屁 / Fart (fart)</button>
<br/>
<img src="2_01.png">
<script>
let device, server, uartService, tx;

// 速度索引 0~5,先固定 2,如果要加 slider 再改這裡
let speedIndex = 2;

const connectBtn    = document.getElementById("connectBle");
const disconnectBtn = document.getElementById("disconnectBle");
const statusEl      = document.getElementById("status");

connectBtn.onclick = async () => {
    try{
        device = await navigator.bluetooth.requestDevice({
            filters:[
                { namePrefix: "Otto" },
                { services: ["0000ffe0-0000-1000-8000-00805f9b34fb"] }
            ]
        });

        device.addEventListener("gattserverdisconnected", onDisconnected);

        server = await device.gatt.connect();
        uartService = await server.getPrimaryService("0000ffe0-0000-1000-8000-00805f9b34fb");
        tx = await uartService.getCharacteristic("0000ffe1-0000-1000-8000-00805f9b34fb");

        statusEl.innerHTML = "已連線: " + device.name;
        connectBtn.disabled = true;
        disconnectBtn.disabled = false;
    }catch(e){
        alert("連線失敗: " + e);
    }
};

disconnectBtn.onclick = () => {
    disconnect();
};

function disconnect(){
    if (device && device.gatt && device.gatt.connected){
        device.gatt.disconnect();
    } else {
        onDisconnected();
    }
}

function onDisconnected(){
    tx = null;
    uartService = null;
    server = null;
    statusEl.innerHTML = "尚未連線";
    connectBtn.disabled = false;
    disconnectBtn.disabled = true;
    console.log("藍牙已斷線");
}

function sendRaw(str){
    if(!tx) { 
        alert("請先連線 BLE"); 
        return; 
    }
    const data = new TextEncoder().encode(str);
    tx.writeValue(data);
    console.log(">>> Sent:", JSON.stringify(str));
}

// 移動 / 模式:指令 + 速度數字 + 換行
function sendMove(cmd){
    const line = cmd + String(speedIndex) + "\n";
    sendRaw(line);
}

// 表情:指令 + "0" + 換行,讓 Arduino 那邊 n 會被設成 0(合法索引)
function sendGesture(cmd){
    const line = cmd + "0\n";
    sendRaw(line);
}
</script>

</body>
</html>

Arduino程式:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
/*  
*                        
*    ______________      ____                                _____    _  _     _
*   |   __     __  |    / __ \ _________ _________   ____   |  __ \  | | \\   //  
*   |  |__|   |__| |   | |  | |___   ___ ___   ___  / __ \  | |  | | | |  \\ //  
*   |_    _________|   | |  | |   | |       | |    | |  | | | |  | | | |   | |
*   | \__/         |   | |__| |   | |       | |    | |__| | | |__| | | |   | |
*   |              |    \____/    |_|       |_|     \____/  |_____/  |_|   |_|
*   |_    _________|
*     \__/            
*
*    This Sketch was created to control Otto Starter with the Offical Web Bluetooth Controller for Otto DIY Robots.
*    For any question about this script you can contact us at education@ottodiy.com
*    By: Iván R. Artiles
*/

#include <Otto.h>
#include <EEPROM.h>

#define LEFTLEG 2
#define RIGHTLEG 3
#define LEFTFOOT 4
#define RIGHTFOOT 5
#define TRIG 8
#define ECHO 9
#define BLE_TX 11
#define BLE_RX 12
#define BUZZER 13


#if defined(ARDUINO_ARCH_ESP32)
  #include "BluetoothSerial.h"
  String device_name = "Otto BT Esp32 A21";
  BluetoothSerial bluetooth;
#else
  #include <SoftwareSerial.h>
  String device_name = "NFU-OSSR-A21";
  SoftwareSerial bluetooth(BLE_TX, BLE_RX);
#endif

int move_speed[] = {3000, 2000, 1000, 750, 500, 250};
int n = 2;
int ultrasound_threeshold = 15;
String command = "";

int v;
int ch;
int i;
int positions[] = {90, 90, 90, 90};
int8_t trims[4] = {0,0,0,0};
unsigned long sync_time = 0;

bool calibration = false;

int isavailable = 1;
  
Otto Ottobot;

long ultrasound_distance() {
   long duration, distance;
   digitalWrite(TRIG,LOW);
   delayMicroseconds(2);
   digitalWrite(TRIG, HIGH);
   delayMicroseconds(10);
   digitalWrite(TRIG, LOW);
   duration = pulseIn(ECHO, HIGH);
   distance = duration/58;
   return distance;
}

void setup() {
  Serial.begin(9600);
  Ottobot.init(LEFTLEG, RIGHTLEG, LEFTFOOT, RIGHTFOOT, true, BUZZER);
  pinMode(TRIG, OUTPUT); 
  pinMode(ECHO, INPUT);

#if defined(ARDUINO_ARCH_ESP32)
  Serial.print("ESP32");
  bluetooth.begin(device_name);
  //bluetooth.deleteAllBondedDevices(); // Uncomment this to delete paired devices; Must be called after begin
#else
  Serial.print("No ESP32");
  Serial.print(device_name);
  bluetooth.begin(9600);
  bluetooth.print("AT+NAME" + device_name+ "\r\n");
#endif
  
  Ottobot.home();
  v = 0;
}

void loop() {
  checkBluetooth();//if something is coming at us
    if (Serial.available() > 0) {
    command = Serial.readStringUntil('\n');
    command.trim(); // 去掉換行與空白
    Serial.print("Received: ");
    Serial.println(command);
  }
  if (command == "forward") {
    Forward();
  }
  else if (command == "backward") {
    Backward();
  }
  else if (command == "right") {
    Right();
  }
  else if (command == "left") {
    Left();
  }
  else if (command == "avoidance") {
    Avoidance();
  }
  else if (command == "force") {
    UseForce();
  }
}
void checkBluetooth() {
  char charBuffer[20]; // 最多讀 19 字元 + 結尾 0
  
  if (bluetooth.available() > 0) {
    isavailable = 1;

    int numberOfBytesReceived = bluetooth.readBytesUntil('\n', charBuffer, 19);
    if (numberOfBytesReceived <= 0) return;

    charBuffer[numberOfBytesReceived] = '\0'; // C 字串結尾
    Serial.print("Received by BLE: ");
    Serial.println(charBuffer);

    // 最後一個字元當作速度 index(0~9),避免不是數字時出錯可稍微檢查
    char last = charBuffer[numberOfBytesReceived - 1];
    if (last >= '0' && last <= '9') {
      n = last - '0';
      if (n < 0) n = 0;
      if (n > 5) n = 5;  // 限制在 0~5
    }

    // 前面幾個字元當作指令名稱
    if (strstr(charBuffer, "forward") == &charBuffer[0]) {
      command = "forward";
    }   
    else if (strstr(charBuffer, "backward") == &charBuffer[0]) {
      command = "backward";
    }
    else if (strstr(charBuffer, "right") == &charBuffer[0]) {
      command = "right";
    }
    else if (strstr(charBuffer, "left") == &charBuffer[0]) {
      command = "left";
    }
    else if (strstr(charBuffer, "stop") == &charBuffer[0]) {
      command = "stop";
      Stop();
    }
    else if (strstr(charBuffer, "ultrasound") == &charBuffer[0]) {
      Stop();
      bluetooth.print(ultrasound_distance());
    }
    else if (strstr(charBuffer, "avoidance") == &charBuffer[0]) {
      command = "avoidance";
    }
    else if (strstr(charBuffer, "force") == &charBuffer[0]) {
      command = "force";
    }

    // ===== 表情 / 手勢指令區 =====
    else if (strstr(charBuffer, "happy") == &charBuffer[0]) {
      command = "";
      Ottobot.playGesture(OttoHappy);
    }
    else if (strstr(charBuffer, "superhappy") == &charBuffer[0]) {
      command = "";
      Ottobot.playGesture(OttoSuperHappy);
    }
    else if (strstr(charBuffer, "sad") == &charBuffer[0]) {
      command = "";
      Ottobot.playGesture(OttoSad);
    }
    else if (strstr(charBuffer, "sleeping") == &charBuffer[0]) {
      command = "";
      Ottobot.playGesture(OttoSleeping);
    }
    else if (strstr(charBuffer, "confused") == &charBuffer[0]) {
      command = "";
      Ottobot.playGesture(OttoConfused);
    }
    else if (strstr(charBuffer, "fretful") == &charBuffer[0]) {
      command = "";
      Ottobot.playGesture(OttoFretful);
    }
    else if (strstr(charBuffer, "love") == &charBuffer[0]) {
      command = "";
      Ottobot.playGesture(OttoLove);
    }
    else if (strstr(charBuffer, "angry") == &charBuffer[0]) {
      command = "";
      Ottobot.playGesture(OttoAngry);
    }
    else if (strstr(charBuffer, "magic") == &charBuffer[0]) {
      command = "";
      Ottobot.playGesture(OttoMagic);
    }
    else if (strstr(charBuffer, "wave") == &charBuffer[0]) {
      command = "";
      Ottobot.playGesture(OttoWave);
    }
    else if (strstr(charBuffer, "victory") == &charBuffer[0]) {
      command = "";
      Ottobot.playGesture(OttoVictory);
    }
    else if (strstr(charBuffer, "fail") == &charBuffer[0]) {
      command = "";
      Ottobot.playGesture(OttoFail);
    }
    else if (strstr(charBuffer, "fart") == &charBuffer[0]) {
      command = "";
      Ottobot.playGesture(OttoFart);
    }

    // 校正與測試
    else if (strstr(charBuffer, "C") == &charBuffer[0]) {
      if (calibration == false) {
        Ottobot._moveServos(10, positions);
        calibration = true;
        delay(50);
      } 
      command = "calibration";
      Calibration(String(charBuffer));
    }
    else if (strstr(charBuffer, "walk_test") == &charBuffer[0]) {
      command = "";
      Ottobot.walk(3, 1000, FORWARD);
    }
    else if (strstr(charBuffer, "save_calibration") == &charBuffer[0]) {
      command = "";
      readChar('s');
    }
  }
  else {
    if (isavailable == 1) {
      Serial.println("No Bluetooth is available.");
      isavailable = 0;
    }
  }
}

void Forward() {
  Ottobot.walk(1, move_speed[n], FORWARD);
}

void Backward() {
  Ottobot.walk(1, move_speed[n], BACKWARD);
}

void Right() {
  Ottobot.walk(1, move_speed[n], RIGHT);
}

void Left() {
  Ottobot.walk(1, move_speed[n], LEFT);
}

void Stop() {
  Ottobot.home();
}

void Avoidance() {
  if (ultrasound_distance() <= ultrasound_threeshold) {
    Ottobot.playGesture(OttoConfused);
    for (int count=0 ; count<2 ; count++) {
      Ottobot.walk(1,move_speed[n],-1); // BACKWARD
    }
    for (int count=0 ; count<4 ; count++) {
      Ottobot.turn(1,move_speed[n],1); // LEFT
    }
  }
  Ottobot.walk(1,move_speed[n],1); // FORWARD
}

void UseForce() {
  if (ultrasound_distance() <= ultrasound_threeshold) {
      Ottobot.walk(1,move_speed[n],-1); // BACKWARD
    }
    if ((ultrasound_distance() > 10) && ( ultrasound_distance() < 15)) {
      Ottobot.home();
    }
    if ((ultrasound_distance() > 15) && ( ultrasound_distance() < 30)) {
      Ottobot.walk(1,move_speed[n],1); // FORWARD
    }
    if (ultrasound_distance() > 30) {
      Ottobot.home();
    }  
}

void Settings(String ts_ultrasound) {
  ultrasound_threeshold = ts_ultrasound.toInt();
}

void Calibration(String c) {
  if (sync_time < millis()) {
      sync_time = millis() + 50;
      for (int k = 1; k < c.length(); k++) {
        readChar((c[k]));
      }
  } 
}

void readChar(char ch) {
  switch (ch) {
  case '0'...'9':
    v = (v * 10 + ch) - 48;
    break;
   case 'a':
    trims[0] = v-90;
    setTrims();
    v = 0;
    break;
   case 'b':
    trims[1] = v-90;
    setTrims();
    v = 0;
    break;
   case 'c':
    trims[2] = v-90;
    setTrims();
    v = 0;
    break;
   case 'd':
    trims[3] = v-90;
    setTrims();
    v = 0;
    break;
   case 's':
    for (i=0 ; i<=3 ; i=i+1) {
      EEPROM.write(i,trims[i]);
    }
    delay(500);
    Ottobot.sing(S_superHappy);
    Ottobot.crusaito(1, 1000, 25, -1);
    Ottobot.crusaito(1, 1000, 25, 1);
    Ottobot.sing(S_happy_short);
    break;
  }
}

void setTrims() {
  Ottobot.setTrims(trims[0],trims[1],trims[2],trims[3]);
  Ottobot._moveServos(10, positions); 
}

2025年12月11日 星期四

OTTO 忍者機器人

 


忍者機器人:Otto Ninja Starter robot
操作介面:RemoteXY
開源程式:OttoNinja


以下文章是由Grok AI生成,提示詞:https://remotexy.com/ 設計理念和創新商模


RemoteXY 的設計理念與創新商業模式

RemoteXY 是一個專門用於微控制器(如 Arduino、ESP8266、ESP32 等)開發的遠端控制平台,允許使用者透過 Android 或 iOS 行動裝置建立圖形化使用者介面(GUI),輕鬆控制硬體裝置。它支援藍牙、Wi-Fi、以太網、USB OTG 及雲端伺服器等多種連接方式,主要針對 IoT(物聯網)、機器人及智慧家居等應用設計。以下根據官方網站、應用程式描述及相關開發資源,分析其設計理念創新商業模式

設計理念(Design Philosophy)

RemoteXY 的核心設計理念強調簡單化(Simplicity)、快速原型開發(Rapid Prototyping)使用者導向的圖形化控制(Graphical User-Centric Control),旨在降低 IoT 開發門檻,讓非專業程式設計師也能輕鬆建立互動介面。其哲學可歸納為以下幾點:

  • 無程式碼圖形化介面建置(No-Code GUI Builder):使用者透過網站編輯器(https://remotexy.com)拖拉元件(如按鈕、滑桿、圖表、聲音播放器等)來設計自訂 GUI,系統自動生成 Arduino IDE 相容的原始碼模板。這體現「民主化開發」(Democratization of Development)的理念,讓初學者或硬體工程師專注於邏輯而非介面程式碼。官方描述:「使用圖形介面編輯器,你可以製作自己的獨特 GUI 並上傳到板子上。」
  • 跨平台與多連接支援(Cross-Platform & Multi-Connectivity):支援多種硬體板卡(如 Arduino UNO/MEGA、STM32、nRF)及通訊模組(如 HC-05 藍牙、W5100 以太網),並整合雲端伺服器實現「全球隨處控制」(Internet from Anywhere)。這反映出「無縫整合」(Seamless Integration)的原則,強調裝置的靈活性與可擴展性,避免傳統開發的複雜佈線與相容性問題。創新點包括「雲端連接測試」,允許裝置從世界任何角落透過網際網路管理。
  • 創新功能導向使用者體驗(Innovative Features for Enhanced UX):如新增「線上圖表」(Online Graph)顯示即時變數變化、「聲音效果播放」(Sound Element)及滑桿自動居中等,這些設計源自使用者反饋,體現迭代式開發(Iterative Design)的理念。平台與 Arduino IDE、FLProg 等工具無縫整合,促進「快速測試與部署」(Rapid Testing & Deployment)。相較競爭對手如 MIT App Inventor,RemoteXY 更專注於硬體控制的即時性與低延遲。

總體而言,RemoteXY 的設計哲學受開源精神啟發(如 Arduino 社群),但更注重「行動端原生控制」(Mobile-Native Control),讓 IoT 從原型到產品化的流程更直觀,適合教育、DIY 愛好者及小型開發團隊。

創新商業模式(Innovative Business Model)

RemoteXY 採用Freemium 模式(免費增值)結合開源生態系統(Open-Source Ecosystem),這是其商業創新的核心,借鏡 Arduino 的「一切免費分享」哲學,但透過專業工具及雲端服務創造付費價值。該模式不僅降低進入障礙,還透過社群貢獻驅動成長。

  • Freemium 結構
    • 免費版(RemoteXY: Arduino control):基本功能免費,包括 GUI 編輯器、行動 App 下載及標準連接(如藍牙、Wi-Fi)。這吸引大量初學者與社群使用者,建立使用者基數。App 在 Google Play 上免費提供,強調「安裝 App 並遵循裝置開發者指示連接」。
    • 付費版(RemoteXY: Arduino control PRO):進階功能需付費購買 App(如 Google Play 上售價約數美元),解鎖雲端伺服器無限連接、更多元件庫及專業支援。這形成「基本免費、進階付費」的漏斗模式,轉換率依賴免費版的黏著度。
  • 開源與社群驅動(Open-Source & Community-Driven):平台提供完整程式庫(Library)給 Arduino IDE 使用,鼓勵開發者分享專案(如機器人控制、智慧家居範例)。這類似 Arduino 的商業模式:「團隊建立了一個基於免費分享的公司,發布所有設計檔案。」 創新在於與 Kickstarter 等眾籌平台合作(如 AirBoard 專案),將 RemoteXY PRO 作為 IoT 開發套件的一部分,透過後援者融資擴大曝光。
  • 擴展收入來源(Revenue Diversification):除了 App 銷售,潛在包括雲端訂閱(無限裝置管理)及合作授權(如與硬體廠商整合)。目標用戶為 DIY 發燒友、教育機構及小型 IoT 企業,模式強調「可擴展性」(Scalability),隨著使用者成長而產生網絡效應(Network Effects)。

此商業模式的創新之處在於低成本獲客 + 高價值轉換:免費工具吸引全球社群,付費解鎖專業功能,預估轉換率高於純開源模式。相較傳統軟體銷售,它更像「SaaS for Hardware」,結合雲端與行動生態。

總結與建議

RemoteXY 的設計理念以「簡單即創新」為本,商業模式則透過 Freemium 實現可持續成長,完美契合 IoT 市場的快速迭代需求。若欲深入應用,建議從官方編輯器起步,建置一個簡單的 LED 控制專案。若有特定功能需求(如整合特定硬體),可參考其部落格更新。 這不僅降低了開發成本,還開啟了無限創意可能。

無裝置程式教育:micro:bit第一堂-剪刀、石頭、布遊戲設計

本課程在虎尾鎮安慶國小試教。網址:https://www.facebook.com/share/v/17mBrum3fb/


 
學生端程



Python程式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
def on_received_number(receivedNumber):
    global select, mode
    select = 0
    mode = receivedNumber
radio.on_received_number(on_received_number)

def on_button_pressed_a():
    global mode
    if select == 0:
        if mode == 3:
            basic.show_icon(IconNames.HAPPY)
    else:
        mode = (mode + 1) % 7
        basic.show_number(mode)
input.on_button_pressed(Button.A, on_button_pressed_a)

def on_gesture_shake():
    global step, Number2
    if select == 0:
        if mode == 4:
            step += 1
            basic.show_number(step)
        elif mode == 6:
            Number2 = randint(0, 2)
            if Number2 == 0:
                basic.show_icon(IconNames.SMALL_SQUARE)
            elif Number2 == 1:
                basic.show_icon(IconNames.SQUARE)
            else:
                basic.show_icon(IconNames.SCISSORS)
input.on_gesture(Gesture.SHAKE, on_gesture_shake)

def on_logo_pressed():
    global select
    select = 1
    basic.show_icon(IconNames.ANGRY)
input.on_logo_event(TouchButtonEvent.PRESSED, on_logo_pressed)

def on_received_string(receivedString):
    global name
    name = receivedString
radio.on_received_string(on_received_string)

def on_button_pressed_b():
    global select
    if select == 0:
        if mode == 3:
            basic.show_icon(IconNames.SAD)
    else:
        select = 0
        basic.show_icon(IconNames.YES)
input.on_button_pressed(Button.B, on_button_pressed_b)

Number2 = 0
select = 0
step = 0
name = ""
mode = 0
id2 = 1
mode = 0
name = "Q-Robot AI"
step = 0
select = 0
basic.show_number(id2)
basic.pause(2000)
radio.set_group(212)

def on_forever():
    if select == 0:
        if mode == 0:
            basic.show_number(id2)
        elif mode == 1:
            basic.show_string(name)
        elif mode == 2:
            basic.show_icon(IconNames.HEART)
            basic.pause(500)
            basic.show_icon(IconNames.SMALL_HEART)
            basic.pause(500)
        elif mode == 5:
            if input.light_level() <= 10:
                basic.show_leds("""
                    # # # # #
                    # # # # #
                    # # # # #
                    # # # # #
                    # # # # #
                    """)
            else:
                basic.clear_screen()
basic.forever(on_forever)