{
  "appVersion": "0.6.3",
  "savedAt": "2026-09-17T07:33:28.910Z",
  "workspace": {
    "blocks": {
      "languageVersion": 0,
      "blocks": [
        {
          "type": "apm_mini_rpm",
          "id": "5n^1oMEsi=BTb5@%kiJr",
          "x": 132,
          "y": 132,
          "inputs": {
            "LEFT": {
              "shadow": {
                "type": "math_number",
                "id": ":cBZGvM]Iex]dH[o[iqS",
                "fields": {
                  "NUM": 30
                }
              }
            },
            "RIGHT": {
              "shadow": {
                "type": "math_number",
                "id": "o|.mR^Ja{JKd+/FA?%_,",
                "fields": {
                  "NUM": 30
                }
              }
            }
          },
          "next": {
            "block": {
              "type": "apm_mini_wait",
              "id": "l+Cp0tD[n~)f/p[B^]OC",
              "inputs": {
                "MS": {
                  "shadow": {
                    "type": "math_number",
                    "id": "XRY=LYvLjvyG29]0?^1x",
                    "fields": {
                      "NUM": 2000
                    }
                  }
                }
              },
              "next": {
                "block": {
                  "type": "apm_mini_stop",
                  "id": "d,Rg_YF=tp%~Q~Yd/!45",
                  "fields": {
                    "MOTOR": "0"
                  }
                }
              }
            }
          }
        }
      ]
    }
  },
  "python": "# APM mini car: stop motors on completion or interruption\nimport drive as _mini_safety_drive\n_mini_resources = []\n_mini_safety_drive.stop_rpm(0)\ntry:\n    import drive as _mini_drive_api\n    import time as _mini_time\n    \n    def _mini_number(value, low, high, label):\n        value = float(value)\n        if not low <= value <= high:\n            raise ValueError(label + ' out of range')\n        return value\n    \n    def _mini_motor(channel):\n        if channel not in (1, 2):\n            raise ValueError('Motor must be 1 or 2')\n        return channel\n    \n    def _mini_power(channel, power, brake=False):\n        channel = _mini_motor(channel)\n        power = int(_mini_number(power, -100, 100, 'Power'))\n        _mini_drive_api.stop_rpm(channel)\n        # This firmware treats soft_break=True as braking even at nonzero power.\n        _mini_drive_api.control_motor(channel, power, soft_break=bool(brake) and power == 0)\n    \n    def _mini_differential(power, steering):\n        power = _mini_number(power, -100, 100, 'Power')\n        steering = _mini_number(steering, -100, 100, 'Steering')\n        _mini_drive_api.stop_rpm(0)\n        _mini_drive_api.drive(power, steering)\n    \n    def _mini_rpm(left, right):\n        left = _mini_number(left, -300, 300, 'Left RPM')\n        right = _mini_number(right, -300, 300, 'Right RPM')\n        _mini_drive_api.drive_rpm(left, right)\n    \n    def _mini_single_rpm(channel, rpm):\n        _mini_drive_api.set_rpm(_mini_motor(channel), _mini_number(rpm, -300, 300, 'RPM'))\n    \n    def _mini_wait(milliseconds):\n        _mini_time.sleep_ms(int(_mini_number(milliseconds, 0, 60000, 'Delay')))\n    \n    def _mini_resource(obj, method):\n        _mini_resources.append((obj, method))\n        return obj\n    \n    def _mini_remote_drive(mode, maximum, deadzone):\n        import remote_controller as rc\n        maximum = _mini_number(maximum, 0, 150, 'Maximum RPM')\n        deadzone = _mini_number(deadzone, 0, 50, 'Joystick deadzone')\n        rc.scan()\n        if not rc.is_connected():\n            _mini_drive_api.stop_rpm(0)\n            return False\n        def axis(key):\n            value = rc.get_axis(key)\n            return 0 if abs(value) < deadzone else value * maximum / 100\n        if mode == 'tank':\n            left, right = axis(rc.LEFT_Y), axis(rc.RIGHT_Y)\n        else:\n            throttle, steering = axis(rc.LEFT_Y), axis(rc.LEFT_X)\n            left, right = throttle + steering, throttle - steering\n        scale = max(1, max(abs(left), abs(right)) / max(1, maximum))\n        _mini_rpm(left / scale, right / scale)\n        return True\n    \n    \n    _mini_rpm(30, 30)\n    _mini_wait(2000)\n    _mini_drive_api.stop_rpm(0)\nfinally:\n    _mini_safety_drive.stop_rpm(0)\n    for _mini_obj, _mini_method in _mini_resources:\n        try:\n            getattr(_mini_obj, _mini_method)()\n        except Exception as _mini_error:\n            print(\"Cleanup:\", _mini_error)\n    _mini_safety_drive.stop_rpm(0)\n",
  "programmingMode": "blocks"
}