Compare commits
135 Commits
githubacti
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
b0af4b54b2 | ||
|
5aade18a66 | ||
|
77ed2ccfb1 | ||
|
1aaedf1fa0 | ||
|
6a5d25197b | ||
|
6d4b2185b4 | ||
|
5a1ba75dc9 | ||
|
b4f625d44c | ||
|
2f7a536874 | ||
|
0e78265f35 | ||
|
c9560c7411 | ||
|
5f7a8e5301 | ||
|
32783f38ba | ||
|
fa34fe5fd2 | ||
|
5aba020bb3 | ||
|
3838b46f1d | ||
|
5188a57927 | ||
|
3fd2c31481 | ||
|
2457725e0c | ||
|
75d7bfb7c2 | ||
|
36ee2958e1 | ||
|
0b6b882b7d | ||
|
4ae3308ef2 | ||
|
4b241dd0c7 | ||
|
f8c7d0f275 | ||
|
a93febb5b7 | ||
|
3b9d90e551 | ||
|
e2b28e7847 | ||
|
63571fb12f | ||
|
ec378c5b09 | ||
|
d4214c65f2 | ||
|
4ad5c2d4a0 | ||
|
b86010f1e6 | ||
|
3e0c9b43a2 | ||
|
d0a85fd0d2 | ||
|
d8167ae9ff | ||
|
8040c1265a | ||
|
c5b86dea72 | ||
|
4ad347214d | ||
|
d47ea29d1a | ||
|
738acc328f | ||
|
ee8c698cc2 | ||
|
d624f5c04a | ||
|
800c8fb088 | ||
|
42ee472c58 | ||
|
3923944a2e | ||
|
d51b5bc1f4 | ||
|
3742cc45f2 | ||
|
b6398d35c4 | ||
|
1c2bbed2a9 | ||
|
971f0b9ee0 | ||
|
4cbd9be8b8 | ||
|
b3f09e56ce | ||
|
77675c1776 | ||
|
04c1fb49aa | ||
|
cfe95cfd21 | ||
|
9528f73140 | ||
|
6b8e57e806 | ||
|
bad64f13ee | ||
|
7b303b0fd2 | ||
|
9cfba7504a | ||
|
d57b67e52e | ||
|
79517f8a30 | ||
|
17b1953889 | ||
|
33e6fbbcb2 | ||
|
9a7bf30e80 | ||
|
c588c6178f | ||
|
11fea05486 | ||
|
f5e1e238f2 | ||
|
17b5cb71cb | ||
|
51ea620578 | ||
|
327052859c | ||
|
918af4f3ac | ||
|
98d8b2977b | ||
|
64471a53f9 | ||
|
53fae2fac5 | ||
|
736722086e | ||
|
80845a32f9 | ||
|
06b0d87e92 | ||
|
98e0421c6e | ||
|
39acf9876d | ||
|
dbf98512e8 | ||
|
c0c2e03354 | ||
|
58b6da2e55 | ||
|
e73ad03eb6 | ||
|
37ceec5332 | ||
|
75507ae433 | ||
|
322ebfbc64 | ||
|
fd98b539fd | ||
|
008ecaf1ea | ||
|
fc2fabc83f | ||
|
92eb599602 | ||
|
e4008a3a73 | ||
|
c200b042c6 | ||
|
50a11dc168 | ||
|
d4ad562722 | ||
|
2cd240b860 | ||
|
49bdbc8952 | ||
|
696bb17dda | ||
|
a4f86fb7ac | ||
|
a52fe73cb3 | ||
|
386966c542 | ||
|
3dd02576d2 | ||
|
84b310195e | ||
|
cbe120bd56 | ||
|
64161dea1b | ||
|
3fa148d35a | ||
|
8aefd3e6bc | ||
|
b4a9c98a88 | ||
|
964daade75 | ||
|
09b254671d | ||
|
766708e4ab | ||
|
85b3fdd281 | ||
|
c1480cbc8b | ||
|
ae57052452 | ||
|
b62cd1ca17 | ||
|
2a30a2dd76 | ||
|
3fcd625555 | ||
|
9392c22424 | ||
|
0720c3b8f5 | ||
|
c2d06e3444 | ||
|
2d5582dd6a | ||
|
0bad95322b | ||
|
dd63007fe7 | ||
|
c2314827c7 | ||
|
25475acd0d | ||
|
72b9716721 | ||
|
12dc012887 | ||
|
1891d440e1 | ||
|
45411fbfcd | ||
|
c639609ce5 | ||
|
9655b6c64c | ||
|
1a5555ed52 | ||
|
e5adf2029e | ||
|
dcea457cb5 |
8
.github/lock.yml
vendored
@ -30,13 +30,7 @@ lockLabel: false
|
||||
|
||||
# Comment to post before locking. Set to `false` to disable
|
||||
|
||||
lockComment: >
|
||||
|
||||
This thread has been automatically locked since there has not been
|
||||
|
||||
any recent activity after it was closed. Please open a new issue for
|
||||
|
||||
related bugs.
|
||||
lockComment: false
|
||||
|
||||
|
||||
|
||||
|
51
.github/workflows/codeql.yml
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
name: "Code scanning - action"
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '0 19 * * 0'
|
||||
|
||||
jobs:
|
||||
CodeQL-Build:
|
||||
|
||||
# CodeQL runs on ubuntu-latest and windows-latest
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: javascript
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
@ -1,8 +1,11 @@
|
||||
name: pxt-buildtarget
|
||||
name: pxt-buildmain
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: master
|
||||
branches:
|
||||
- 'master'
|
||||
- 'main'
|
||||
create:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@ -11,7 +14,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [8.x]
|
||||
node-version: [18.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
@ -34,4 +37,4 @@ jobs:
|
||||
NPM_ACCESS_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
|
||||
CHROME_BIN: chromium-browser
|
||||
DISPLAY: :99.0
|
||||
CI: true
|
||||
CI: true
|
4
.github/workflows/pxt-buildpr.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [8.x]
|
||||
node-version: [18.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
@ -28,4 +28,4 @@ jobs:
|
||||
env:
|
||||
CHROME_BIN: chromium-browser
|
||||
DISPLAY: :99.0
|
||||
CI: true
|
||||
CI: true
|
39
.github/workflows/pxt-buildpush.yml
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
name: pxt-buildpush
|
||||
|
||||
on:
|
||||
push:
|
||||
# main/master has its own build that includes the crowdin key
|
||||
branches-ignore:
|
||||
- 'main'
|
||||
- 'master'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: npm install
|
||||
run: |
|
||||
sudo apt-get install xvfb
|
||||
sudo npm install -g pxt
|
||||
npm install
|
||||
- name: pxt ci
|
||||
run: |
|
||||
pxt ci
|
||||
env:
|
||||
PXT_ACCESS_TOKEN: ${{ secrets.PXT_ACCESS_TOKEN }}
|
||||
PXT_RELEASE_REPO: ${{ secrets.PXT_RELEASE_REPO }}
|
||||
NPM_ACCESS_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
|
||||
CHROME_BIN: chromium-browser
|
||||
DISPLAY: :99.0
|
||||
CI: true
|
52
.github/workflows/testghpkgs.yml
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
name: pxt-testghpkgs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [8.x]
|
||||
branch: [stable3.0]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ matrix.branch }}
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: npm install
|
||||
run: |
|
||||
sudo npm install -g pxt
|
||||
npm install
|
||||
- name: pxt buildtarget
|
||||
run: pxt buildtarget
|
||||
- name: cache build output
|
||||
uses: actions/cache@v1
|
||||
env:
|
||||
cache-name: cache-testghpkgs
|
||||
with:
|
||||
path: temp/ghpkgs
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- name: pxt testghpkgs
|
||||
run: pxt testghpkgs
|
||||
env:
|
||||
PXT_FORCE_GITHUB_PROXY: 1
|
||||
PXT_ACCESS_TOKEN: ${{ secrets.PXT_ACCESS_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.TRAVIS_GITHUB_ACCESS_TOKEN }}
|
||||
- name: upload build log
|
||||
uses: actions/upload-artifact@v2
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: logs-${{ matrix.branch }}
|
||||
path: temp/ghpkgs/*.txt
|
7
.gitignore
vendored
@ -27,10 +27,7 @@ crowdinstats.csv
|
||||
*.db
|
||||
*.suo
|
||||
*.log
|
||||
|
||||
.DS_Store
|
||||
.idea
|
||||
*.iml
|
||||
.vscode/.BROWSE.VC.DB-shm
|
||||
.vscode/.BROWSE.VC.DB-wal
|
||||
package-lock.json
|
||||
package-lock.json
|
||||
.DS_Store
|
27
.travis.yml
@ -1,27 +0,0 @@
|
||||
language: node_js
|
||||
os: linux
|
||||
dist: trusty
|
||||
node_js:
|
||||
- "8.9.4"
|
||||
before_install:
|
||||
- export CHROME_BIN=chromium-browser
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
script:
|
||||
- "node node_modules/pxt-core/built/pxt.js travis"
|
||||
# - "(cd libs/lang-test0; node ../../node_modules/pxt-core/built/pxt.js run)"
|
||||
# - "(cd libs/lang-test1; node ../../node_modules/pxt-core/built/pxt.js run)"
|
||||
# - "(cd libs/lang-test0; node ../../node_modules/pxt-core/built/pxt.js test)"
|
||||
# - "(cd libs/lang-test1; node ../../node_modules/pxt-core/built/pxt.js test)"
|
||||
# - "node node_modules/pxt-core/built/pxt.js testdir tests"
|
||||
# - "(cd libs/hello; node ../../node_modules/pxt-core/built/pxt.js testconv http://az851932.vo.msecnd.net/files/td-converter-tests-v1.json)"
|
||||
sudo: false
|
||||
notifications:
|
||||
email:
|
||||
- touchdevelop-build@microsoft.com
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
- built/cache
|
||||
- libs/hello/built/cache
|
||||
|
1
.vscode/settings.json
vendored
@ -1,6 +1,5 @@
|
||||
// Place your settings in this file to overwrite default and user settings.
|
||||
{
|
||||
"files.autoSave": "afterDelay",
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
"**/built/**": true,
|
||||
|
19
.vscode/tasks.json
vendored
@ -1,20 +1,19 @@
|
||||
{
|
||||
"version": "0.1.0",
|
||||
"version": "2.0.0",
|
||||
// Task runner is jake
|
||||
"command": "pxt",
|
||||
// Need to be executed in shell / cmd
|
||||
"isShellCommand": true,
|
||||
"showOutput": "always",
|
||||
"tasks": [
|
||||
{
|
||||
// TS build command is local.
|
||||
"taskName": "serve",
|
||||
// Make this the default build command.
|
||||
"isBuildCommand": true,
|
||||
// Use the redefined Typescript output problem matcher.
|
||||
"label": "serve",
|
||||
"type": "shell",
|
||||
"command": "pxt",
|
||||
"args": [
|
||||
"serve"
|
||||
],
|
||||
"problemMatcher": [
|
||||
"$tsc"
|
||||
]
|
||||
],
|
||||
"group": "build"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
139
README.md
@ -1,78 +1,149 @@
|
||||
# Calliope target for Microsoft MakeCode
|
||||
|
||||
This editor is hosted at https://makecode.calliope.cc.
|
||||
# calliope target for PXT
|
||||
|
||||
|
||||
### BUILD COMMENTS
|
||||
|
||||
- build libs/core/dal.d.ts new requires some meddling, as the `#define` parser does not parse `#ifdef` and thus
|
||||
has some conflicts with double defines constants
|
||||
pxt-calliope is a [Microsoft Programming Experience Toolkit (PXT)](https://github.com/Microsoft/pxt) target that allows you to program a [Calliope mini](https://calliope.cc/en).
|
||||
|
||||
![](http://calliope.cc/content/1-ueber-mini/mini_board.png)
|
||||
|
||||
## Local server
|
||||
* [Try it live](https://makecode.calliope.cc/)
|
||||
|
||||
The local server allows to run the editor and the documentation from your computer.
|
||||
## Issue tracking
|
||||
|
||||
### Setup
|
||||
Please add an issue if you discover an (unreported) bug.
|
||||
|
||||
The following commands are a 1-time setup after synching the repo on your machine.
|
||||
## Developing new extensions
|
||||
|
||||
* See requirements for [pxt](https://github.com/Microsoft/pxt)
|
||||
* [clone this repo](https://help.github.com/articles/cloning-a-repository/) to your computer and go in the project folder
|
||||
Authoring and testing of new extensions can be done directly from the web editor. See [our documentation](https://makecode.com/blog/github-packages) on how to get started. If you want to run the editor locally, keep reading.
|
||||
|
||||
## Local server setup
|
||||
|
||||
The local server lets you to run the editor and serve the documentation from your own computer. It is meant for a single developer used and not designed to serve the editor to a large amount of users.
|
||||
|
||||
1. Install [Node.js](https://nodejs.org/) 8.9.4 or higher.
|
||||
2. Clone this repository.
|
||||
```
|
||||
git clone https://github.com/microsoft/pxt-calliope
|
||||
cd pxt-calliope
|
||||
```
|
||||
* install the PXT command line (add ``sudo`` for Mac/Linux shells).
|
||||
3. Install the PXT command line (add `sudo` for Mac/Linux shells).
|
||||
```
|
||||
npm install -g pxt
|
||||
```
|
||||
* install the dependencies
|
||||
4. Install the pxt-calliope dependencies.
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
Go to the **Running** section.
|
||||
|
||||
### Developer Setup
|
||||
|
||||
This is the typical setup used by the MakeCode team to work on the microbit.
|
||||
|
||||
1. Install [Node.js](https://nodejs.org/) 8.9.4 or higher.
|
||||
2. Install [Docker](https://www.docker.com/get-started) if you plan to build ``.cpp`` files.
|
||||
3. Clone the pxt repository.
|
||||
```
|
||||
git clone https://github.com/microsoft/pxt
|
||||
cd pxt
|
||||
```
|
||||
4. Install the dependencies of pxt and build it
|
||||
```
|
||||
npm install
|
||||
npm run build
|
||||
cd ..
|
||||
```
|
||||
5. Clone the pxt-common-packages repository
|
||||
```
|
||||
git clone https://github.com/microsoft/pxt-common-packages
|
||||
cd pxt-common-packages
|
||||
npm install
|
||||
cd ..
|
||||
```
|
||||
6. Clone this repository.
|
||||
```
|
||||
git clone https://github.com/microsoft/pxt-calliope
|
||||
cd pxt-calliope
|
||||
```
|
||||
7. Install the PXT command line (add `sudo` for Mac/Linux shells).
|
||||
```
|
||||
npm install -g pxt
|
||||
```
|
||||
8. Install the pxt-calliope dependencies.
|
||||
```
|
||||
npm install
|
||||
```
|
||||
8. Link pxt-calliope back to base pxt repo (add `sudo` for Mac/Linux shells).
|
||||
This step is only required if you intend to make changes to pxt and/or
|
||||
pxt-common-packages repos. If all you want is serve a local Makecode, you can skip
|
||||
this step.
|
||||
```
|
||||
pxt link ../pxt
|
||||
pxt link ../pxt-common-packages
|
||||
```
|
||||
Note the above command assumes the folder structure of
|
||||
```
|
||||
makecode
|
||||
|
|
||||
----------------------------------
|
||||
| | |
|
||||
pxt pxt-common-packages pxt-calliope
|
||||
```
|
||||
|
||||
### Running
|
||||
|
||||
Run this command to open a local web server (add ``sudo`` for Mac/Linux shells).
|
||||
Run this command from inside pxt-calliope to open a local web server
|
||||
```
|
||||
pxt serve
|
||||
```
|
||||
If the local server opens in the wrong browser, make sure to copy the URL containing the local token.
|
||||
Otherwise, the editor will not be able to load the projects.
|
||||
|
||||
If you need modify the `.cpp` files, turn on yotta compilation with the ``-yt`` flag (add ``sudo`` for Mac/Linux shells). On Windows, you must be running
|
||||
from the ``Run Yotta`` command prompt.
|
||||
If you need to modify the `.cpp` files (and have installed yotta), enable yotta compilation using the `--localbuild` flag:
|
||||
```
|
||||
pxt serve -yt
|
||||
pxt serve --local
|
||||
```
|
||||
|
||||
## Updates
|
||||
|
||||
To update your PXT version and make sure you're running the latest tools, run (add ``sudo`` for Mac/Linux shells)
|
||||
If you want to speed up the build, you can use the ``rebundle`` option, which skips building and simply refreshes the target information
|
||||
```
|
||||
pxt update
|
||||
pxt serve --rebundle
|
||||
```
|
||||
|
||||
More instructions at https://github.com/Microsoft/pxt#running-a-target-from-localhost
|
||||
### Cleaning
|
||||
|
||||
## Testing
|
||||
Sometimes, your built folder might be in a bad state, clean it and try again.
|
||||
```
|
||||
pxt clean
|
||||
```
|
||||
|
||||
The build automatically runs the following:
|
||||
### Updates
|
||||
|
||||
* make sure the built-in packages compile
|
||||
* `pxt run` in `libs/lang-test*` - this will run the test in command line runner;
|
||||
there is a number of asserts in both of these
|
||||
* `pxt testdir` in `tests` - this makes sure all the files compile and generates .hex files
|
||||
Make sure to pull changes from all repos regularly. More instructions are at https://github.com/Microsoft/pxt#running-a-target-from-localhost
|
||||
|
||||
To test something on the device:
|
||||
## Update playlists in markdown
|
||||
|
||||
* do a `pxt deploy` in `libs/lang-test*` - they should show `1` or `2` on the screen (and not unhappy face)
|
||||
* run `pxt testdir` in `tests` and deploy some of the hex files from `tests/built`
|
||||
Get a Google API key and store it in the ``GOOGLE_API_KEY`` environment variables (turn on data from the app).
|
||||
|
||||
The `lang-test0` source comes from the `pxt-core` package. It's also tested with `pxt run` there.
|
||||
```
|
||||
pxt downloadplaylists
|
||||
```
|
||||
|
||||
## Repos
|
||||
|
||||
The pxt-calliope target depends on several other repos. The main ones are:
|
||||
- https://github.com/Microsoft/pxt, the PXT framework
|
||||
- https://github.com/Microsoft/pxt-common-packages, common APIs accross various MakeCode editors
|
||||
- https://github.com/lancaster-university/microbit, basic wrapper around the DAL
|
||||
- https://github.com/lancaster-university/microbit-dal
|
||||
|
||||
## History
|
||||
|
||||
See the [MakeCode blog](https://makecode.com/blog).
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
## Trademarks
|
||||
|
||||
MICROSOFT, the Microsoft Logo, and MAKECODE are registered trademarks of Microsoft Corporation. They can only be used for the purposes described in and in accordance with Microsoft’s Trademark and Brand guidelines published at https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general.aspx. If the use is not covered in Microsoft’s published guidelines or you are not sure, please consult your legal counsel or MakeCode team (makecode@microsoft.com).
|
||||
|
41
SECURITY.md
Normal file
@ -0,0 +1,41 @@
|
||||
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK -->
|
||||
|
||||
## Security
|
||||
|
||||
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
||||
|
||||
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
|
||||
|
||||
## Reporting Security Issues
|
||||
|
||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||
|
||||
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
|
||||
|
||||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
|
||||
|
||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
|
||||
|
||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||
|
||||
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||
* Full paths of source file(s) related to the manifestation of the issue
|
||||
* The location of the affected source code (tag/branch/commit or direct URL)
|
||||
* Any special configuration required to reproduce the issue
|
||||
* Step-by-step instructions to reproduce the issue
|
||||
* Proof-of-concept or exploit code (if possible)
|
||||
* Impact of the issue, including how an attacker might exploit the issue
|
||||
|
||||
This information will help us triage your report more quickly.
|
||||
|
||||
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
|
||||
|
||||
## Preferred Languages
|
||||
|
||||
We prefer all communications to be in English.
|
||||
|
||||
## Policy
|
||||
|
||||
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
|
||||
|
||||
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "../pxt"
|
||||
},
|
||||
{
|
||||
"path": "../pxt-common-packages"
|
||||
},
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
]
|
||||
}
|
BIN
clients/macuploader/Graphics/appicon.sketch
Normal file
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 40 KiB |
BIN
clients/macuploader/Graphics/menubar.sketch
Normal file
131
compiler/combiner.ts
Normal file
@ -0,0 +1,131 @@
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtcompiler.d.ts"/>
|
||||
|
||||
namespace ts.pxtc.extension {
|
||||
pxtc.compilerHooks.postBinary = (program: ts.Program, opts: CompileOptions, res: CompileResult) => {
|
||||
if (!opts.target.isNative)
|
||||
return
|
||||
const mbdal = res.outfiles["mbdal-binary.hex"]
|
||||
const mbcodal = res.outfiles["mbcodal-binary.hex"]
|
||||
if (!mbdal || !mbcodal)
|
||||
return
|
||||
|
||||
let outp = ""
|
||||
|
||||
wrapHex(mbdal, 0x00, [0x99, 0x01, 0xc0, 0xde])
|
||||
wrapHex(mbcodal, 0x0D, [0x99, 0x03, 0xc0, 0xde], true)
|
||||
|
||||
outp += ":00000001FF\n"
|
||||
|
||||
res.outfiles["binary.hex"] = outp
|
||||
|
||||
function hex2str(bytes: number[]) {
|
||||
return ts.pxtc.hexfile.hexBytes([bytes.length - 3].concat(bytes)) + "\n"
|
||||
}
|
||||
|
||||
function paddingString(len: number) {
|
||||
let r = ""
|
||||
const len0 = len
|
||||
while (len >= 44) {
|
||||
r += hex2str([0x00, 0x00, 0x0C,
|
||||
0x42, 0x42, 0x42, 0x42,
|
||||
0x42, 0x42, 0x42, 0x42,
|
||||
0x42, 0x42, 0x42, 0x42,
|
||||
0x42, 0x42, 0x42, 0x42])
|
||||
len -= 44
|
||||
}
|
||||
if (len >= 12) {
|
||||
const numBytes = (len - 11) >> 1
|
||||
const bytes = [0x00, 0x00, 0x0C]
|
||||
for (let i = 0; i < numBytes; ++i) bytes.push(0x42)
|
||||
const add = hex2str(bytes)
|
||||
r += add
|
||||
len -= add.length
|
||||
}
|
||||
while (len--)
|
||||
r += "\n"
|
||||
|
||||
U.assert(r.length == len0)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
function addBlock(blk: string) {
|
||||
const leftoff = blk.length & 511
|
||||
outp += blk + paddingString(512 - leftoff)
|
||||
}
|
||||
|
||||
function wrapHex(inpHex: string, dataType: number, deviceType: number[], keepSrc = false) {
|
||||
let blk =
|
||||
hex2str([0x00, 0x00, 0x04, 0x00, 0x00])
|
||||
+ hex2str([0x00, 0x00, 0x0A].concat(deviceType))
|
||||
let upperAddr = 0
|
||||
const lines = inpHex.split(/\r?\n/)
|
||||
for (let i = 0; i < lines.length; ++i) {
|
||||
const line = lines[i]
|
||||
if (!line)
|
||||
continue
|
||||
const parsed = ts.pxtc.hexfile.parseHexRecord(line)
|
||||
|
||||
switch (parsed.type) {
|
||||
case 0x00:
|
||||
/*
|
||||
const parsed2 = parsed.len <= 16 && lines[i + 1] ?
|
||||
ts.pxtc.hexfile.parseHexRecord(lines[i + 1])
|
||||
: null
|
||||
// if this and next line can fit in 32 bytes, concat them
|
||||
if (parsed2 && parsed2.type == 0x00 &&
|
||||
parsed2.addr == parsed.addr + parsed.len &&
|
||||
parsed.len + parsed2.len <= 32) {
|
||||
parsed.data = parsed.data.concat(parsed2.data)
|
||||
parsed.len += parsed2.len
|
||||
i++
|
||||
}
|
||||
*/
|
||||
addData([parsed.addr >> 8, parsed.addr & 0xff, dataType]
|
||||
.concat(parsed.data))
|
||||
break
|
||||
|
||||
case 0x01:
|
||||
flush()
|
||||
if (keepSrc) break
|
||||
else return
|
||||
|
||||
case 0x04:
|
||||
const newUpper = ((parsed.data[0] << 8) | parsed.data[1]) << 16
|
||||
if (upperAddr != newUpper) {
|
||||
upperAddr = newUpper
|
||||
addData([0, 0, 0x04, parsed.data[0], parsed.data[1]])
|
||||
}
|
||||
break
|
||||
|
||||
case 0x03:
|
||||
case 0x05:
|
||||
// ignore
|
||||
break
|
||||
|
||||
case 0x0E:
|
||||
// src record
|
||||
addData([parsed.addr >> 8, parsed.addr & 0xff, 0x0E]
|
||||
.concat(parsed.data))
|
||||
break
|
||||
|
||||
default:
|
||||
U.oops(`unknown hex record type: ${line}`)
|
||||
break
|
||||
}
|
||||
}
|
||||
flush()
|
||||
|
||||
function addData(bytes: number[]) {
|
||||
const newData = hex2str(bytes)
|
||||
blk += newData
|
||||
}
|
||||
|
||||
function flush() {
|
||||
if (blk)
|
||||
addBlock(blk)
|
||||
blk = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
23
compiler/tsconfig.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"declaration": true,
|
||||
"moduleResolution": "node",
|
||||
"isolatedModules": false,
|
||||
"out": "../built/compiler.js",
|
||||
"rootDir": ".",
|
||||
"newLine": "LF",
|
||||
"sourceMap": false,
|
||||
"typeRoots": ["../node_modules/@types"],
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost",
|
||||
"es2017",
|
||||
"ES2018.Promise"
|
||||
]
|
||||
}
|
||||
}
|
2
docfiles/offline-app-trademarks.html
Normal file
@ -0,0 +1,2 @@
|
||||
Micro:bit and micro:bit logo are trademarks and/ or copyrights of the Micro:bit
|
||||
Educational Foundation. © Micro:bit Educational Foundation. All rights reserved.
|
103
docs/about.md
Normal file
@ -0,0 +1,103 @@
|
||||
![](/static/mb/device/calliope_website.jpg)
|
||||
|
||||
# About
|
||||
|
||||
## @description A Blocks / Javascript code editor for the Calliope mini, a pocket-size computer with 5x5 display, sensors and Bluetooth.
|
||||
|
||||
The [Calliope mini](https://calliope.cc) is a [pocket-size computer]([/device](https://calliope.cc/en/calliope-mini/tech-facts)) with a 5x5 display of 25 LEDs, Bluetooth and sensors that can be programmed by anyone.
|
||||
|
||||
The Calliope mini provides an easy and fun introduction to programming and making ??? switch on, program it to do something fun ??? wear it, customize it.
|
||||
Just like Arduino, the Calliope mini can additionally be connected to and interact with sensors, displays, and other devices.
|
||||
|
||||
* [Read the docs](/docs)
|
||||
|
||||
## [Hardware: The Device](/device)
|
||||
|
||||
The Calliope mini is packaged with sensors, radio and other goodies. Learn about the [hardware components]([/device](https://calliope.cc/en/calliope-mini/tech-facts)) of the Calliope mini to make the most of it!
|
||||
|
||||
## ~ hint
|
||||
|
||||
**Looking to buy a Calliope mini?** See the [list of resellers](https://calliope.cc/en/shops).
|
||||
|
||||
## ~
|
||||
|
||||
## Programming: [Blocks](/blocks) or [JavaScript](/javascript)
|
||||
|
||||
You can program the Calliope mini using [Blocks](/blocks) or [JavaScript](/javascript) in your web browser via the [Calliope mini APIs](/reference):
|
||||
|
||||
```block
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
basic.showString("Hi!");
|
||||
})
|
||||
```
|
||||
```typescript
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
basic.showString("Hi!");
|
||||
})
|
||||
```
|
||||
|
||||
The editor work in [most modern browsers](/browsers), work [offline](/offline) once loaded and do not require any installation.
|
||||
|
||||
## [Compile and Flash: Your Program!](/device/usb)
|
||||
|
||||
When you have your code ready, you connect your Calliope mini to a computer via a USB cable, so it appears as a mounted drive (named MINI). If you are using the Calliope mini REV2 you also see another drive (FLASH) that handels up to 25 additional programs.
|
||||
|
||||
Compilation to ARM thumb machine code from [Blocks](/blocks) or [JavaScript](/javascript) happens in the browser. You save the ARM binary
|
||||
program to a file, which you then copy to the micro:bit drive, which flashes the micro:bit device with the new program.
|
||||
|
||||
## Simulator: Test Your Code
|
||||
|
||||
You can run your code using the micro:bit simulator, all within the confines of a web browser.
|
||||
The simulator has support for the LED screen, buttons, as well as compass, accelerometer, and digital I/O pins.
|
||||
|
||||
```sim
|
||||
basic.forever(() => {
|
||||
basic.showString("Hi!");
|
||||
})
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
led.stopAnimation();
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
# . . . #
|
||||
. # # # .`);
|
||||
});
|
||||
input.onButtonEvent(Button.B, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
led.stopAnimation();
|
||||
basic.showLeds(`
|
||||
. # . # .
|
||||
# . # . #
|
||||
# . . . #
|
||||
. # . # .
|
||||
. . # . .`);
|
||||
});
|
||||
```
|
||||
|
||||
## Learn!
|
||||
|
||||
We have tons of [projects](/projects), [examples](/examples) and [courses](/courses) to get your started!
|
||||
|
||||
## C++ Runtime
|
||||
|
||||
The [C++ micro:bit runtime](http://lancaster-university.github.io/microbit-docs/), created at [Lancaster University](http://www.lancaster.ac.uk/), provides access to the hardware functions of the micro:bit,
|
||||
as well as a set of helper functions (such as displaying a number/image/string on the LED screen).
|
||||
|
||||
The [micro:bit library](/reference) mirrors the functions of the C++ library.
|
||||
When code is compiled to ARM machine code, the calls to JavaScript micro:bit functions are replaced with calls to the corresponding C++ functions.
|
||||
|
||||
## [Command Line Tools](/cli)
|
||||
|
||||
Looking to use @homeurl@ in your favorite editor? Install the [command line tools](/cli) and get rolling!
|
||||
|
||||
## [Extensions](/extensions)
|
||||
|
||||
Create, edit and distribute your own blocks and JavaScript using [extensions](/extensions). Extensions are hosted on GitHub and may be written using C++, JavaScript and/or ARM thumb.
|
||||
|
||||
## [Open Source](/open-source)
|
||||
|
||||
The code for the Calliope mini is [open source](/open-source) on GitHub. Contributors are welcome!
|
||||
|
||||
```package
|
||||
radio
|
||||
```
|
30
docs/blocks/logic/boolean.md
Normal file
@ -0,0 +1,30 @@
|
||||
# @extends
|
||||
|
||||
## #examples
|
||||
|
||||
## Example: ``AND`` operator
|
||||
|
||||
This example turns on LED `3 , 3`, if LEDs `1 , 1` and `2 , 2` are both on:
|
||||
|
||||
```blocks
|
||||
if (led.point(1,1) && led.point(2,2)) {
|
||||
led.plot(3,3)
|
||||
}
|
||||
```
|
||||
|
||||
## Example: Comparisons of numbers and strings
|
||||
|
||||
When you compare two Numbers, you get a Boolean value, such as the comparison `x < 5` in the code below:
|
||||
|
||||
```blocks
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
let x = randint(0, 5)
|
||||
if(x < 5) {
|
||||
basic.showString("low");
|
||||
} else {
|
||||
basic.showString("high");
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
See the documentation on [Numbers](/types/number) for more information on comparing two Numbers.
|
15
docs/blocks/logic/if.md
Normal file
@ -0,0 +1,15 @@
|
||||
# @extends
|
||||
|
||||
## #examples
|
||||
|
||||
## Example: adjusting screen brightness
|
||||
|
||||
If the [light level](/reference/input/light-level) is `< 100`, this code sets the brightness to `255` when the button A is pressed:
|
||||
|
||||
```blocks
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
if(input.lightLevel()<100){
|
||||
led.setBrightness(255);
|
||||
}
|
||||
})
|
||||
```
|
3
docs/blocks/loops.md
Normal file
@ -0,0 +1,3 @@
|
||||
# @extends
|
||||
|
||||
## #specific
|
20
docs/blocks/loops/for-of.md
Normal file
@ -0,0 +1,20 @@
|
||||
# @extends
|
||||
|
||||
## #examples
|
||||
|
||||
## Example: Find the highest number
|
||||
|
||||
Find the highest number in a list of numbers. Display the highest number on the screen.
|
||||
|
||||
```blocks
|
||||
let list: number[] = []
|
||||
let highest = 0
|
||||
highest = 0
|
||||
list = [5, 8, 6, 2, 4, 3, 7, 1]
|
||||
for (let value of list) {
|
||||
if (value > highest) {
|
||||
highest = value
|
||||
}
|
||||
}
|
||||
basic.showNumber(highest)
|
||||
```
|
15
docs/blocks/loops/for.md
Normal file
@ -0,0 +1,15 @@
|
||||
# @extends
|
||||
|
||||
## #examples
|
||||
|
||||
## Example: Count to 4
|
||||
|
||||
This program will show the numbers 0, 1, 2, 3, and 4 one after another on the LED screen.
|
||||
|
||||
```blocks
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
for(let i = 0; i < 5; ++i) {
|
||||
basic.showNumber(i)
|
||||
}
|
||||
})
|
||||
```
|
16
docs/blocks/loops/repeat.md
Normal file
@ -0,0 +1,16 @@
|
||||
# @extends
|
||||
|
||||
## #examples
|
||||
|
||||
## Example: Blinking heart
|
||||
|
||||
Flash the ``heart`` icon on the screen `4` times.
|
||||
|
||||
```blocks
|
||||
for (let i = 0; i < 4; i++) {
|
||||
basic.showIcon(IconNames.Heart)
|
||||
basic.pause(300)
|
||||
basic.clearScreen()
|
||||
basic.pause(300)
|
||||
}
|
||||
```
|
17
docs/blocks/loops/while.md
Normal file
@ -0,0 +1,17 @@
|
||||
# @extends
|
||||
|
||||
## #examples
|
||||
|
||||
## Example: diagonal line
|
||||
|
||||
The following example uses a while loop to make a diagonal line on the LED screen (points `0, 0`, `1, 1`, `2, 2`, `3, 3`, `4, 4`).
|
||||
|
||||
```blocks
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
let index = 4;
|
||||
while(index >= 0) {
|
||||
led.plot(index, index);
|
||||
index--;
|
||||
}
|
||||
})
|
||||
```
|
29
docs/blocks/math/random-boolean.md
Normal file
@ -0,0 +1,29 @@
|
||||
# random Boolean
|
||||
|
||||
Returns a pseudo-random boolean value that is either `true` or `false`.
|
||||
|
||||
```sig
|
||||
Math.randomBoolean()
|
||||
```
|
||||
|
||||
## Returns
|
||||
|
||||
* a pseudo-random [boolean](types/boolean) that is either `true` or `false`.
|
||||
|
||||
## Example
|
||||
|
||||
Make your @boardname@ do a coin toss when it's dropped softly. Have the LEDs show 'heads' or 'tails' as the result of the toss.
|
||||
|
||||
```blocks
|
||||
input.onGesture(Gesture.FreeFall, () => {
|
||||
if (Math.randomBoolean()) {
|
||||
basic.showIcon(IconNames.Happy)
|
||||
} else {
|
||||
basic.showIcon(IconNames.Sword)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
[random](/reference/math/random)
|
12
docs/blocks/on-start.md
Normal file
@ -0,0 +1,12 @@
|
||||
# @extends
|
||||
|
||||
## #exstart
|
||||
|
||||
In this example, ``on start`` sets a dimmer brightness on the screen and the button handler shows a string.
|
||||
|
||||
```blocks
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
basic.showString("Hello!")
|
||||
})
|
||||
led.setBrightness(50)
|
||||
```
|
36
docs/blocks/variables/assign.md
Normal file
@ -0,0 +1,36 @@
|
||||
# Assignment Operator
|
||||
|
||||
Use an equals sign to make a [variable](/blocks/variables/var) store the [number](/types/number)
|
||||
or [string](/types/string) you say.
|
||||
|
||||
When you use the equals sign to store something in a variable, the equals sign is called
|
||||
an *assignment operator*, and what you store is called a *value*.
|
||||
|
||||
## Storing numbers in variables
|
||||
|
||||
This program makes the variable `item` equal `5` and then shows it on the [LED screen](/device/screen).
|
||||
|
||||
````blocks
|
||||
let item = 5
|
||||
basic.showNumber(item)
|
||||
````
|
||||
|
||||
## Storing strings in variables
|
||||
|
||||
This program makes the variable `name` equal `Joe` and then shows it on the [LED screen](/device/screen).
|
||||
|
||||
````blocks
|
||||
let name = "Joe"
|
||||
basic.showString(name);
|
||||
````
|
||||
|
||||
## Notes
|
||||
|
||||
You can use the assignment operator with variables of
|
||||
every [type](/types). A *type* is which kind of thing
|
||||
a variable can store, like a number or string.
|
||||
|
||||
## See also
|
||||
|
||||
[variable](/blocks/variables/var), [types](/types)
|
||||
|
13
docs/blocks/variables/change.md
Normal file
@ -0,0 +1,13 @@
|
||||
# @extends
|
||||
|
||||
## #examples
|
||||
|
||||
## Example: show the value of a variable
|
||||
|
||||
Use the assignment operator to set the value of a [variable](/blocks/variables/var). Change the value of a variable from 0 to 1 using the change item block. Then display the new value of the variable on the LED screen. Like this:
|
||||
|
||||
```blocks
|
||||
let x = 0;
|
||||
x += 1;
|
||||
basic.showNumber(x);
|
||||
```
|
87
docs/blocks/variables/var.md
Normal file
@ -0,0 +1,87 @@
|
||||
# Local Variables
|
||||
|
||||
How to define and use local variables.
|
||||
|
||||
## @parent language
|
||||
|
||||
A variable is a place where you can store and retrieve data. Variables have a name, a [type](/types), and value:
|
||||
|
||||
* *name* is how you'll refer to the variable
|
||||
* *type* refers to the kind of data a variable can store
|
||||
* *value* refers to what's stored in the variable
|
||||
|
||||
## Var statement
|
||||
|
||||
Use the Block Editor variable statement to create a variable
|
||||
and the [assignment operator](/blocks/variables/assign)
|
||||
to store something in the variable.
|
||||
|
||||
For example, this code stores the number `2` in the `x` variable:
|
||||
|
||||
```blocks
|
||||
let x = 2;
|
||||
```
|
||||
Here's how to define a variable in the Block Editor:
|
||||
|
||||
1. Click `variables`.
|
||||
|
||||
2. Change the default variable name if you like.
|
||||
|
||||
3. Drag a block type on the right-side of the [assignment operator](/blocks/variables/assign) and click the down arrow to change the variable name.
|
||||
|
||||
A variable is created for the number returned by the [brightness](/reference/led/brightness) function.
|
||||
|
||||
```blocks
|
||||
let b = led.brightness();
|
||||
```
|
||||
|
||||
## Using variables
|
||||
|
||||
Once you've defined a variable, just use the variable's name whenever you need what's stored in the variable. For example, the following code shows the value stored in `counter` on the LED screen:
|
||||
|
||||
```blocks
|
||||
let counter = 1;
|
||||
basic.showNumber(counter);
|
||||
```
|
||||
|
||||
To change the contents of a variable use the assignment operator. The following code sets `counter` to 1 and then increments `counter` by 10:
|
||||
|
||||
```blocks
|
||||
let counter = 1;
|
||||
counter = counter + 10;
|
||||
basic.showNumber(counter);
|
||||
```
|
||||
|
||||
## Why use variables?
|
||||
|
||||
If you want to remember and modify data, you'll need a variable.
|
||||
A counter is a great example:
|
||||
|
||||
```blocks
|
||||
let counter = 0;
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
counter = counter + 1;
|
||||
basic.showNumber(counter);
|
||||
});
|
||||
```
|
||||
|
||||
## Local variables
|
||||
|
||||
Local variables exist only within the function or block of code where they're defined. For example:
|
||||
|
||||
```blocks
|
||||
// x does NOT exist here.
|
||||
if (led.brightness() > 128) {
|
||||
// x exists here
|
||||
let x = 0;
|
||||
}
|
||||
```
|
||||
|
||||
### Notes
|
||||
|
||||
* You can use the default variable names if you'd like, however, it's best to use descriptive variable names. To change a variable name in the editor, select the down arrow next to the variable and then click "new variable".
|
||||
|
||||
## See also
|
||||
|
||||
[types](/types), [assignment operator](/blocks/variables/assign)
|
||||
|
BIN
docs/calliope/02_Hero_CalliopEO.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
docs/calliope/03_Hero_KidsLab.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
docs/calliope/calliopeo-header.png
Normal file
After Width: | Height: | Size: 220 KiB |
@ -10,8 +10,8 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Get Ready",
|
||||
"url":"/calliope/firststeps/firstSteps",
|
||||
"description": "Find out how to start working with the Calliope mini",
|
||||
"imageUrl": "/docs/calliope/firststeps/connecting.jpg",
|
||||
"largeImageUrl": "/docs/calliope/firststeps/firstSteps.jpg",
|
||||
"imageUrl": "/calliope/firststeps/connecting.jpg",
|
||||
"largeImageUrl": "/calliope/firststeps/firstSteps.jpg",
|
||||
"cardType": "tutorial",
|
||||
"label": "Never seen a mini? Start Here!",
|
||||
"labelClass": "green small ribbon"
|
||||
@ -20,8 +20,8 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "The 5x5 LED matrix",
|
||||
"url":"/calliope/firststeps/5x5LED",
|
||||
"description": "Learn how to create and show images, numbers or letters on the LED matrix",
|
||||
"imageUrl": "/docs/calliope/firststeps/5x5LED.jpg",
|
||||
"largeImageUrl": "/docs/calliope/firststeps/5x5LED_L.jpg",
|
||||
"imageUrl": "/calliope/firststeps/5x5LED.jpg",
|
||||
"largeImageUrl": "/calliope/firststeps/5x5LED_L.jpg",
|
||||
"cardType": "tutorial",
|
||||
"label": "New? Start Here!",
|
||||
"labelClass": "yellow small ribbon"
|
||||
@ -30,8 +30,8 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Radio",
|
||||
"url":"/calliope/firststeps/Radio",
|
||||
"description": "Find out how to use the radion function and how to send messages from one Calliope mini to another one",
|
||||
"imageUrl": "/docs/calliope/firststeps/Radio.jpg",
|
||||
"largeImageUrl": "/docs/calliope/firststeps/Radio_L.jpg",
|
||||
"imageUrl": "/calliope/firststeps/Radio.jpg",
|
||||
"largeImageUrl": "/calliope/firststeps/Radio_L.jpg",
|
||||
"cardType": "tutorial",
|
||||
"label": "",
|
||||
"labelClass": "orange small ribbon"
|
||||
@ -40,8 +40,8 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Loops",
|
||||
"url":"/calliope/firststeps/Loops",
|
||||
"description": "Loops are important to be able to execute program instructions multiple times",
|
||||
"imageUrl": "/docs/calliope/firststeps/Loops.jpg",
|
||||
"largeImageUrl": "/docs/calliope/firststeps/Loops_L.jpg",
|
||||
"imageUrl": "/calliope/firststeps/Loops.jpg",
|
||||
"largeImageUrl": "/calliope/firststeps/Loops_L.jpg",
|
||||
"cardType": "tutorial",
|
||||
"label": "",
|
||||
"labelClass": "green small ribbon"
|
||||
@ -50,8 +50,8 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Mathematics",
|
||||
"url":"/calliope/firststeps/Mathematics",
|
||||
"description": "The Calliope mini can become your little math helper",
|
||||
"imageUrl": "/docs/calliope/firststeps/Mathematics.jpg",
|
||||
"largeImageUrl": "/docs/calliope/firststeps/Mathematics_L.jpg",
|
||||
"imageUrl": "/calliope/firststeps/Mathematics.jpg",
|
||||
"largeImageUrl": "/calliope/firststeps/Mathematics_L.jpg",
|
||||
"cardType": "tutorial",
|
||||
"label": "",
|
||||
"labelClass": "green small ribbon"
|
||||
@ -60,8 +60,8 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Inputs",
|
||||
"url":"/calliope/firststeps/Inputs",
|
||||
"description": "Use conditions for different actions",
|
||||
"imageUrl": "/docs/calliope/firststeps/Inputs.jpg",
|
||||
"largeImageUrl": "/docs/calliope/firststeps/Inputs_L.jpg",
|
||||
"imageUrl": "/calliope/firststeps/Inputs.jpg",
|
||||
"largeImageUrl": "/calliope/firststeps/Inputs_L.jpg",
|
||||
"cardType": "tutorial",
|
||||
"label": "",
|
||||
"labelClass": "green small ribbon"
|
||||
@ -70,8 +70,8 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Sensors",
|
||||
"url":"/calliope/firststeps/Sensors",
|
||||
"description": "Measure temperature, light and orientation",
|
||||
"imageUrl": "/docs/calliope/firststeps/Sensors.jpg",
|
||||
"largeImageUrl": "/docs/calliope/firststeps/Sensors_L.jpg",
|
||||
"imageUrl": "/calliope/firststeps/Sensors.jpg",
|
||||
"largeImageUrl": "/calliope/firststeps/Sensors_L.jpg",
|
||||
"cardType": "tutorial",
|
||||
"label": "",
|
||||
"labelClass": "green small ribbon"
|
||||
@ -80,8 +80,8 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Output",
|
||||
"url":"/calliope/firststeps/Output",
|
||||
"description": "Audio, light and motion",
|
||||
"imageUrl": "/docs/calliope/firststeps/Output.jpg",
|
||||
"largeImageUrl": "/docs/calliope/firststeps/Output_L.jpg",
|
||||
"imageUrl": "/calliope/firststeps/Output.jpg",
|
||||
"largeImageUrl": "/calliope/firststeps/Output_L.jpg",
|
||||
"cardType": "tutorial",
|
||||
"label": "",
|
||||
"labelClass": "green small ribbon"
|
||||
@ -90,8 +90,8 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Decisions",
|
||||
"url":"/calliope/firststeps/Decisions",
|
||||
"description": "If..., then it happens... or it happens...",
|
||||
"imageUrl": "/docs/calliope/firststeps/Decisions.jpg",
|
||||
"largeImageUrl": "/docs/calliope/firststeps/Decisions_L.jpg",
|
||||
"imageUrl": "/calliope/firststeps/Decisions.jpg",
|
||||
"largeImageUrl": "/calliope/firststeps/Decisions_L.jpg",
|
||||
"cardType": "tutorial",
|
||||
"label": "",
|
||||
"labelClass": "green small ribbon"
|
||||
@ -100,8 +100,8 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Variables",
|
||||
"url":"/calliope/firststeps/Variables",
|
||||
"description": "A variable is not a static value, it’s what you determine it to be.",
|
||||
"imageUrl": "/docs/calliope/firststeps/Variables.jpg",
|
||||
"largeImageUrl": "/docs/calliope/firststeps/Variables_L.jpg",
|
||||
"imageUrl": "/calliope/firststeps/Variables.jpg",
|
||||
"largeImageUrl": "/calliope/firststeps/Variables_L.jpg",
|
||||
"cardType": "tutorial",
|
||||
"label": "",
|
||||
"labelClass": "green small ribbon"
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 24 KiB |
@ -14,7 +14,7 @@ For example drag and drop some blocks and try your program on the Simulator with
|
||||
|
||||
Click the Download button in the editor. This will download a 'hex' file, which is a compact format of your program that your mini can read. Once the file has been downloaded, just copy it to your Calliope mini just like copying a file to a USB stick.
|
||||
|
||||
![Connecting Image](/docs/calliope/firststeps/connecting.jpg)
|
||||
![Connecting Image](/calliope/firststeps/connecting.jpg)
|
||||
|
||||
|
||||
## Introduction @unplugged
|
||||
@ -32,7 +32,7 @@ Be careful to insure that the ridge on the plug is facing upwards.
|
||||
|
||||
If the plug slides easily into the socket then you are attaching it correctly. Otherwise, turn the plug round and re-insert it into the socket. Slide it to "on“ and your Calliope mini is powered by the batteries.
|
||||
|
||||
![Powering Image](/docs/calliope/firststeps/powerItUp.png)
|
||||
![Powering Image](/calliope/firststeps/powerItUp.png)
|
||||
|
||||
|
||||
## Introduction @unplugged
|
||||
|
@ -10,7 +10,7 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Shop",
|
||||
"url":"https://shop.calliope.cc",
|
||||
"description": "You can get the mini at the official calliope store.",
|
||||
"imageUrl": "/docs/calliope/links/thumbnail_shop.gif",
|
||||
"imageUrl": "/calliope/links/thumbnail_shop.gif",
|
||||
"largeImageUrl": "",
|
||||
"label": "",
|
||||
"buttonLabel": "Open Calliope Shop",
|
||||
@ -19,7 +19,7 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Projects",
|
||||
"url":"https://calliope.cc/en/projekte",
|
||||
"description": "A collection of calliope mini projects",
|
||||
"imageUrl": "/docs/calliope/links/thumbnail_projects.gif",
|
||||
"imageUrl": "/calliope/links/thumbnail_projects.gif",
|
||||
"largeImageUrl": "",
|
||||
"label": "",
|
||||
"buttonLabel": "View Projects",
|
||||
@ -28,7 +28,7 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Teaching materials",
|
||||
"url":"https://calliope.cc/schulen/schulmaterial",
|
||||
"description": "",
|
||||
"imageUrl": "/docs/calliope/links/thumbnail_didactic_material.gif",
|
||||
"imageUrl": "/calliope/links/thumbnail_didactic_material.gif",
|
||||
"largeImageUrl": "",
|
||||
"label": "",
|
||||
"buttonLabel": "View",
|
||||
@ -37,7 +37,7 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Forum",
|
||||
"url":"https://forum.calliope.cc",
|
||||
"description": "Be a part of our comunity",
|
||||
"imageUrl": "/docs/calliope/links/thumbnail_community.gif",
|
||||
"imageUrl": "/calliope/links/thumbnail_community.gif",
|
||||
"largeImageUrl": "",
|
||||
"label": "",
|
||||
"buttonLabel": "Open Forum",
|
||||
|
27
docs/calliope/templates.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Projects
|
||||
|
||||
Here are some cool tutorials to get you started with your @boardname@!
|
||||
|
||||
## Basic
|
||||
|
||||
```codecard
|
||||
[
|
||||
{
|
||||
"name": "Calliope mini 2.x",
|
||||
"url":"_f7ACuxgaocvr",
|
||||
"description": "The Calliope mini 2.0 and newer has a larger memory than the previous versions. If you use this template for your project, you can make the most of all the features on your Calliope mini!",
|
||||
"imageUrl": "/calliope/templates/32KB.png",
|
||||
"largeImageUrl": "/calliope/templates/32KB_L.png",
|
||||
"cardType": "sharedExample",
|
||||
"buttonLabel": "New project"
|
||||
},{
|
||||
"name": "Calliope mini 1.x",
|
||||
"url":"_7YbU6iMhoTdR",
|
||||
"description": "This template is designed for all Calliope mini, but especially for those up to version 1.3. If you have such a Calliope mini or an earlier version, you can start directly with this template.",
|
||||
"imageUrl": "/calliope/templates/16KB.png",
|
||||
"largeImageUrl": "/calliope/templates/16KB_L.png",
|
||||
"cardType": "sharedExample",
|
||||
"buttonLabel": "New project"
|
||||
}
|
||||
]
|
||||
```
|
BIN
docs/calliope/templates/16KB.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
docs/calliope/templates/16KB_L.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
docs/calliope/templates/32KB.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
docs/calliope/templates/32KB_L.png
Normal file
After Width: | Height: | Size: 34 KiB |
@ -9,7 +9,7 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
"name": "Flashing Heart",
|
||||
"url":"/projects/flashing-heart",
|
||||
"description": "Make an animated flashing heart.",
|
||||
"imageUrl": "/docs/calliope/tutorials/01_flashing_heart.gif",
|
||||
"imageUrl": "/calliope/tutorials/01_flashing_heart.gif",
|
||||
"largeImageUrl": "",
|
||||
"cardType": "tutorial",
|
||||
"label": "",
|
||||
@ -17,57 +17,57 @@ Here are some cool tutorials to get you started with your @boardname@!
|
||||
}, {
|
||||
"name": "Name Tag",
|
||||
"description": "Scroll your name on the screen",
|
||||
"imageUrl": "/docs/calliope/tutorials/02_nametag.gif",
|
||||
"imageUrl": "/calliope/tutorials/02_nametag.gif",
|
||||
"url": "/projects/name-tag",
|
||||
"cardType": "tutorial"
|
||||
}, {
|
||||
"name": "Smiley Buttons",
|
||||
"url":"/projects/smiley-buttons",
|
||||
"description": "Show different smiley images by pressing the buttons.",
|
||||
"imageUrl": "/docs/calliope/tutorials/03_smiley_button.gif",
|
||||
"imageUrl": "/calliope/tutorials/03_smiley_button.gif",
|
||||
"largeImageUrl": "",
|
||||
"cardType": "tutorial"
|
||||
}, {
|
||||
"name": "Dice",
|
||||
"url":"/projects/dice",
|
||||
"description": "Shake the dice and see what number comes up!",
|
||||
"imageUrl": "/docs/calliope/tutorials/04_dice.gif",
|
||||
"imageUrl": "/calliope/tutorials/04_dice.gif",
|
||||
"cardType": "tutorial"
|
||||
}, {
|
||||
"name": "Love Meter",
|
||||
"url":"/projects/love-meter",
|
||||
"description": "The @boardname@ is feeling the love, see how much!",
|
||||
"imageUrl":"/docs/calliope/tutorials/05_love_meter.gif",
|
||||
"imageUrl":"/calliope/tutorials/05_love_meter.gif",
|
||||
"cardType": "tutorial"
|
||||
}, {
|
||||
"name": "Mini Chat",
|
||||
"url":"/projects/mini-chat",
|
||||
"description": "Build your own social network made of minis.",
|
||||
"imageUrl": "/docs/calliope/tutorials/06_mini_chat.gif",
|
||||
"imageUrl": "/calliope/tutorials/06_mini_chat.gif",
|
||||
"cardType": "tutorial"
|
||||
}, {
|
||||
"name": "Rock Paper Scissors",
|
||||
"url":"/projects/rock-paper-scissors",
|
||||
"description": "Make the Rock-Paper-Scissors game on your @boardname@ and challenge your friends.",
|
||||
"imageUrl":"/docs/calliope/tutorials/07_stone_paper_scissors.gif",
|
||||
"imageUrl":"/calliope/tutorials/07_stone_paper_scissors.gif",
|
||||
"cardType": "tutorial"
|
||||
}, {
|
||||
"name": "Coin Flipper",
|
||||
"url":"/projects/coin-flipper",
|
||||
"description": "Guess the coin toss and see if you're lucky.",
|
||||
"imageUrl": "/docs/calliope/tutorials/08_coin_flipper.gif",
|
||||
"imageUrl": "/calliope/tutorials/08_coin_flipper.gif",
|
||||
"cardType": "tutorial"
|
||||
}, {
|
||||
"name": "Snap the dot",
|
||||
"url": "/projects/snap-the-dot",
|
||||
"description": "Use the game blocks to create a skill game",
|
||||
"imageUrl": "/docs/calliope/tutorials/09_snap_the_dot.gif",
|
||||
"imageUrl": "/calliope/tutorials/09_snap_the_dot.gif",
|
||||
"cardType": "tutorial"
|
||||
}, {
|
||||
"name": "Multi Dice",
|
||||
"url": "/projects/multi-dice",
|
||||
"description": "Compete with multiple dices",
|
||||
"imageUrl": "/docs/calliope/tutorials/10_multi_dice.gif",
|
||||
"imageUrl": "/calliope/tutorials/10_multi_dice.gif",
|
||||
"cardType": "tutorial"
|
||||
}
|
||||
]
|
||||
|
74
docs/coding-cards.md
Normal file
@ -0,0 +1,74 @@
|
||||
# Coding Cards
|
||||
|
||||
## Math
|
||||
|
||||
```codecard
|
||||
[
|
||||
{
|
||||
"name": "Make a Digital Balance",
|
||||
"description": "Use the accelerometer to find the balance point",
|
||||
"url": "https://drive.google.com/open?id=1Tl80unLA5_Zwkymh1flSbwuZbCIqSOxQ",
|
||||
"imageUrl": "/static/coding-cards/balance-card.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Make a Digital Dice",
|
||||
"description": "Create a shakeable dice that uses the accelerometer",
|
||||
"url": "https://drive.google.com/open?id=1iW75z-7maJ3qixwv9Yuj6rA5U387qVpg",
|
||||
"imageUrl": "/static/coding-cards/dice-card.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Make a Trundle Wheel",
|
||||
"description": "Build trundle wheel that measures a distance travelled",
|
||||
"url": "https://drive.google.com/open?id=1hzpBN5aqzYMvm7s_W6RQr9u4eFx1f6LK",
|
||||
"imageUrl": "/static/coding-cards/trundlewheel-card.jpg"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Games
|
||||
|
||||
```codecard
|
||||
[
|
||||
{
|
||||
"name": "Nervous",
|
||||
"description": "Carefully move the ring but don't touch the wire!",
|
||||
"url": "https://drive.google.com/open?id=1BJCkrdMoojU-ojQcOluawecw5W6kcdnZ",
|
||||
"imageUrl": "/static/coding-cards/games-nervous.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Reaction",
|
||||
"description": "Which player has the fastest reaction time?",
|
||||
"url": "https://drive.google.com/open?id=1kfZKLflUrPoeveboo1LpubgaJSsFkDgY",
|
||||
"imageUrl": "/static/coding-cards/games-reaction.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Shake the Bottle",
|
||||
"description": "Shake the bottle until the fizz inside pops the lid",
|
||||
"url": "https://drive.google.com/open?id=1lTZbrVP5UDG7IZeY1Kod8gw4VNcldzzZ",
|
||||
"imageUrl": "/static/coding-cards/games-shake.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Sprite Based Games",
|
||||
"description": "Try this game to see how to make sprite based games",
|
||||
"url": "https://drive.google.com/open?id=1p1fm9SlFVr8NQ9ctQvhZ7H-okfxXhabW",
|
||||
"imageUrl": "/static/coding-cards/games-sprite.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Zen",
|
||||
"description": "Strike a pose but keep very still, wiggle too much and your out!",
|
||||
"url": "https://drive.google.com/open?id=14JBWsx-K489GjSgvMX4kslxaHKYfdBtj",
|
||||
"imageUrl": "/static/coding-cards/games-zen.jpg"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
[Make a Digital Balance](https://drive.google.com/open?id=1Tl80unLA5_Zwkymh1flSbwuZbCIqSOxQ),
|
||||
[Make a Digital Dice](https://drive.google.com/open?id=1iW75z-7maJ3qixwv9Yuj6rA5U387qVpg),
|
||||
[Make a Trundle Wheel](https://drive.google.com/open?id=1hzpBN5aqzYMvm7s_W6RQr9u4eFx1f6LK),
|
||||
[Nervous](https://drive.google.com/open?id=1BJCkrdMoojU-ojQcOluawecw5W6kcdnZ),
|
||||
[Reaction](https://drive.google.com/open?id=1kfZKLflUrPoeveboo1LpubgaJSsFkDgY),
|
||||
[Shake the Bottle](https://drive.google.com/open?id=1lTZbrVP5UDG7IZeY1Kod8gw4VNcldzzZ),
|
||||
[Sprite Based Games](https://drive.google.com/open?id=1p1fm9SlFVr8NQ9ctQvhZ7H-okfxXhabW),
|
||||
[Zen](https://drive.google.com/open?id=14JBWsx-K489GjSgvMX4kslxaHKYfdBtj)
|
8
docs/courses/blocks-to-javascript/SUMMARY.md
Normal file
@ -0,0 +1,8 @@
|
||||
# [Blocks to JavaScript](/courses/blocks-to-javascript)
|
||||
|
||||
* [Blocks to JavaScript](/courses/blocks-to-javascript)
|
||||
* [Hello JavaScript](/courses/blocks-to-javascript/hello-javascript)
|
||||
* [Starter Blocks](/courses/blocks-to-javascript/starter-blocks)
|
||||
* [Writing Code](/courses/blocks-to-javascript/writing-code)
|
||||
* [Conditional Loops](/courses/blocks-to-javascript/conditional-loops)
|
||||
* [Writing Functions](/courses/blocks-to-javascript/writing-functions)
|
15
docs/courses/logic-lab.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Logic Lab
|
||||
|
||||
![Logic lab header image](/static/courses/logic-lab/logic-lab-header.jpg)
|
||||
|
||||
A basic aspect of knowledge and understanding is whether something is true or not. Considering conditions around you and making a conclusion about something being true or false means that you are using logic. Computers and, in fact, all of digital electronics rely on this idea of logic to process information and give results in terms of conditions being true or false. Logic is used almost everywhere in the programs you write in places where you want decide to do one task or another.
|
||||
|
||||
## Logic topics
|
||||
|
||||
These topic sections teach you about applying logic to conditions and using Boolean algebra to express them. Also, you will see how logical operators work and how they combine to form more complex logic structures.
|
||||
|
||||
* [Logic and Expressions](/courses/logic-lab/expressions)
|
||||
* [Boolean Elements](/courses/logic-lab/elements)
|
||||
* [Logic Explorer](/courses/logic-lab/explorer)
|
||||
* [Logic Gates](/courses/logic-lab/logic-gates)
|
||||
* [Programmable Logic](/courses/logic-lab/programmable)
|
8
docs/courses/logic-lab/SUMMARY.md
Normal file
@ -0,0 +1,8 @@
|
||||
# [Logic Lab](/courses/logic-lab)
|
||||
|
||||
* [Logic Lab](/courses/logic-lab)
|
||||
* [Logic and Expressions](/courses/logic-lab/expressions)
|
||||
* [Boolean Elements](/courses/logic-lab/elements)
|
||||
* [Logic Explorer](/courses/logic-lab/explorer)
|
||||
* [Logic Gates](/courses/logic-lab/logic-gates)
|
||||
* [Programmable Logic](/courses/logic-lab/programmable)
|
207
docs/courses/logic-lab/elements.md
Normal file
@ -0,0 +1,207 @@
|
||||
# Boolean elements
|
||||
|
||||
Whether creating equations in Boolean algebra or using them in your programs, you'll form both simple and complex logical expressions that use basic operations to combine the logical conditions.
|
||||
|
||||
## Notation
|
||||
|
||||
Boolean (logical) equations are expressed in a way similar to mathmatical equations. Variables in Boolean expressions though, have only two possible values, ``true`` or ``false``. For an equation using a logical expression, the equivalant sides of the equal sign ,``=``, will be only ``true`` or ``false`` too.
|
||||
|
||||
The following list shows the basic notation elements for Boolean expressions.
|
||||
|
||||
* ``~A``: the inverse (**NOT**) of ``A``, when ``A`` is ``true``, ``~A`` is ``false``
|
||||
* ``A + B``: the value of ``A`` **OR** ``B``
|
||||
* ``A · B``: the value of ``A`` **AND** ``B``
|
||||
* ``A ⊕ B``: the value of the exclusive OR (**XOR**) of ``A`` with ``B``
|
||||
* ``Q``: equivalent result (OUTPUT) value of a logical expression
|
||||
|
||||
A resulting value, ``Q``, from a logical expression in is shown like:
|
||||
|
||||
``Q`` = ``A + B``
|
||||
|
||||
An equation to show logically equivalent expressions (where both sides have the same resulting value) can look like this:
|
||||
|
||||
``~(A + B)`` = ``~A · ~B``
|
||||
|
||||
## Logical operators
|
||||
|
||||
All Boolean expressions result from a combination of conditions and operators. These operators join individual conditons together and evaluate into a single ``true`` or ``false`` condition. The following are the basic logical operators. Their use in both Boolean algebra and in code is shown along with their truth table.
|
||||
|
||||
### Identity
|
||||
|
||||
Identity means that a result value is the same as the condition itself.
|
||||
|
||||
``Q = A``
|
||||
|
||||
```block
|
||||
let A = false
|
||||
let Q = A
|
||||
```
|
||||
|
||||
#### Example - Blink LEDs on press
|
||||
|
||||
```blocks
|
||||
let A = false
|
||||
basic.forever(function () {
|
||||
A = input.buttonIsPressed(Button.A)
|
||||
if (A) {
|
||||
basic.showIcon(IconNames.Chessboard)
|
||||
} else {
|
||||
basic.clearScreen()
|
||||
}
|
||||
basic.pause(100)
|
||||
})
|
||||
```
|
||||
|
||||
#### Truth table
|
||||
|
||||
A | A
|
||||
-|-
|
||||
F | F
|
||||
T | T
|
||||
|
||||
### NOT (Negation)
|
||||
|
||||
The NOT operator is called negation or the inverse. It takes a single logical value and makes it have the opposite value, ``true`` goes to ``false`` and ``false`` goes to ``true``.
|
||||
|
||||
``Q = ~A``
|
||||
|
||||
```block
|
||||
let A = false
|
||||
let Q = !(A)
|
||||
```
|
||||
|
||||
#### Example - Blink LEDs on not pressed
|
||||
|
||||
```blocks
|
||||
let A = false
|
||||
basic.forever(function () {
|
||||
A = input.buttonIsPressed(Button.A)
|
||||
if (!(A)) {
|
||||
basic.showIcon(IconNames.Chessboard)
|
||||
} else {
|
||||
basic.clearScreen()
|
||||
}
|
||||
basic.pause(100)
|
||||
})
|
||||
```
|
||||
|
||||
#### Truth table
|
||||
|
||||
A | ~A
|
||||
-|-
|
||||
F | T
|
||||
T | F
|
||||
|
||||
### OR (Disjunction)
|
||||
|
||||
The OR operator results in ``true`` when one or more conditions are ``true``.
|
||||
|
||||
``Q = A + B``
|
||||
|
||||
```block
|
||||
let A = false
|
||||
let B = false
|
||||
let Q = A || B
|
||||
```
|
||||
|
||||
#### Example - Blink on any press
|
||||
|
||||
```blocks
|
||||
let A = false
|
||||
let B = false
|
||||
basic.forever(function () {
|
||||
A = input.buttonIsPressed(Button.A)
|
||||
B = input.buttonIsPressed(Button.B)
|
||||
if (A || B) {
|
||||
basic.showIcon(IconNames.Chessboard)
|
||||
} else {
|
||||
basic.clearScreen()
|
||||
}
|
||||
basic.pause(100)
|
||||
})
|
||||
```
|
||||
|
||||
#### Truth table
|
||||
|
||||
A | B | A + B
|
||||
-|-|-
|
||||
F | F | F
|
||||
T | F | T
|
||||
F | T | T
|
||||
T | T | T
|
||||
|
||||
### AND (Conjunction)
|
||||
|
||||
The AND operator requires that all conditions are ``true`` for the result to be ``true``.
|
||||
|
||||
``Q = A · B``
|
||||
|
||||
```block
|
||||
let A = false
|
||||
let B = false
|
||||
let Q = A && B
|
||||
```
|
||||
|
||||
#### Example - Blink on double press only
|
||||
|
||||
```blocks
|
||||
let A = false
|
||||
let B = false
|
||||
basic.forever(function () {
|
||||
A = input.buttonIsPressed(Button.A)
|
||||
B = input.buttonIsPressed(Button.B)
|
||||
if (A && B) {
|
||||
basic.showIcon(IconNames.Chessboard)
|
||||
} else {
|
||||
basic.clearScreen()
|
||||
}
|
||||
basic.pause(100)
|
||||
})
|
||||
```
|
||||
|
||||
#### Truth table
|
||||
|
||||
A | B | A · B
|
||||
-|-|-
|
||||
F | F | F
|
||||
T | F | F
|
||||
F | T | F
|
||||
T | T | T
|
||||
|
||||
### XOR (Exclusive OR) #xor
|
||||
|
||||
Exclusive OR (XOR) means that only one or the other condition is true. Both conditions can't be true at the same time. XOR is common in Boolean algebra but it has no operator in JavaScript. Its operation can be made from combining a few simple expressions.
|
||||
|
||||
``Q = A ⊕ B``
|
||||
|
||||
```block
|
||||
let A = false
|
||||
let B = false
|
||||
let Q = (A || B) && !(A && B)
|
||||
```
|
||||
|
||||
#### Example - Blink on one press or the other
|
||||
|
||||
```blocks
|
||||
let A = false
|
||||
let B = false
|
||||
basic.forever(function () {
|
||||
A = input.buttonIsPressed(Button.A)
|
||||
B = input.buttonIsPressed(Button.B)
|
||||
if ((A || B) && !(A && B)) {
|
||||
basic.showIcon(IconNames.Chessboard)
|
||||
} else {
|
||||
basic.clearScreen()
|
||||
}
|
||||
basic.pause(100)
|
||||
})
|
||||
```
|
||||
|
||||
#### Truth table
|
||||
|
||||
A | B | A ⊕ B
|
||||
-|-|-
|
||||
F | F | F
|
||||
T | F | T
|
||||
F | T | T
|
||||
T | T | F
|
162
docs/courses/logic-lab/explorer.md
Normal file
@ -0,0 +1,162 @@
|
||||
# Logic explorer
|
||||
|
||||
As a way to see how the basic logical operators work, we'll make a program to test them with all their possible input values.
|
||||
|
||||
## Inputs and output
|
||||
|
||||
Make an array called ``||variables:inputs||`` with two values, ``false`` and ``true``, as logical inputs. Add another variable ``||variables:Q||`` to receive the resulting value of a logical expression as output.
|
||||
|
||||
```blocks
|
||||
let inputs = [false, true]
|
||||
let Q = false
|
||||
```
|
||||
|
||||
## Single input loop
|
||||
|
||||
To start with, we'll make a single input test for the variable ``||variables:A||``. The output, in variable ``||variables:Q||``, for the logical operator test will display an icon on the LEDs. A ``true`` value shows a ``t-shirt`` and ``false`` will show a ``small diamond``.
|
||||
|
||||
1. Get a ``||loops:for element||`` loop and put it in the ``||loops:on start||``. Rename the ``||variables:index||`` variable to ``||variables:A||`` and switch the ``||variables:list||`` variable to ``||variables:inputs||``.
|
||||
2. Pull a ``||variables:set Q to||`` block into the ``||loops:for element||`` loop and set the value to ``||logic:false||``.
|
||||
3. Go find the ``||logic:if then else||`` and put in below the ``||variables:set Q to||``. Pick up a ``||variables:Q||`` in ``||variables:VARIABLE||`` and drop it onto the ``||logic:false||`` to replace it.
|
||||
4. Move a ``||basic:show icon||`` inside the ``||logic:if then||`` section and change the image to a ``t-shirt``. This is our image for a ``true`` output.
|
||||
5. Move a ``||basic:show icon||`` inside the ``||logic:else||`` section and change the image to a ``small diamond``. This is our image for a ``false`` output.
|
||||
6. Just below the ``||logic:if then else||``, put in a ``||loops:pause||``, a ``||basic:clear screen||``, and another ``||basic:pause||`` block. Set the time for each ``||basic:pause||`` to ``500``.
|
||||
|
||||
```blocks
|
||||
let inputs = [false, true]
|
||||
let Q = false
|
||||
for (let A of inputs) {
|
||||
Q = false
|
||||
if (Q) {
|
||||
basic.showIcon(IconNames.TShirt)
|
||||
} else {
|
||||
basic.showIcon(IconNames.SmallDiamond)
|
||||
}
|
||||
basic.pause(500)
|
||||
basic.clearScreen()
|
||||
basic.pause(500)
|
||||
}
|
||||
```
|
||||
|
||||
## Identity test
|
||||
|
||||
The identity test is simple. It just makes the output have the same logical value as the input. Set the ``||variables:Q||`` output variable to the ``||variables:A||`` variable.
|
||||
|
||||
```block
|
||||
let A = false
|
||||
let Q = A
|
||||
```
|
||||
|
||||
### Identity truth table
|
||||
|
||||
For the Identity test, these output values will show for the inputs:
|
||||
|
||||
A | Q = A
|
||||
-|-
|
||||
**false** | ``[basic.showIcon(IconNames.SmallDiamond)]``
|
||||
**true** | ``[basic.showIcon(IconNames.TShirt)]``
|
||||
|
||||
## NOT test
|
||||
|
||||
Negation, or inversion, makes the output have the opposite value of the input. So, the output value is NOT the same as the input. Since there are only two possible values, the output is the other value that is NOT the input.
|
||||
|
||||
Replace the ``||logic:false||`` in the ``||variables:Q||`` equation with a ``||logic:not||`` operator. Pull the ``||variables:A||`` variable down from the ``||loops:for element||`` loop and drop it inside the ``||logic:not||`` operator.
|
||||
|
||||
```block
|
||||
let A = false
|
||||
let Q = !A
|
||||
```
|
||||
|
||||
### NOT truth table
|
||||
|
||||
For the NOT test, these output values will show for the inputs:
|
||||
|
||||
A | ~A
|
||||
-|-
|
||||
**false** | ``[basic.showIcon(IconNames.TShirt)]``
|
||||
**true** | ``[basic.showIcon(IconNames.SmallDiamond)]``
|
||||
|
||||
## Two input loop
|
||||
|
||||
For the rest of the operator tests, we need to have another input variable. This variable comes from a second ``||loops:for element||`` loop. With one input variable there was just two possible input values. Adding a second input variable increases the number of possible input combinations by two times. Now there will be 4 different input possibilities. This will result in the truth tables having 4 rows for the operator tests.
|
||||
|
||||
Go get another ``||loops:for element||`` loop and put it in so that it surrounds all the inside the first loop. Rename the ``||variables:index||`` variable to ``||variables:B||`` and switch the ``||variables:list||`` variable to ``||variables:inputs||``.
|
||||
|
||||
```blocks
|
||||
let inputs = [false, true]
|
||||
let Q = false
|
||||
for (let A of inputs) {
|
||||
for (let B of inputs) {
|
||||
Q = !A
|
||||
if (Q) {
|
||||
basic.showIcon(IconNames.TShirt)
|
||||
} else {
|
||||
basic.showIcon(IconNames.SmallDiamond)
|
||||
}
|
||||
basic.pause(500)
|
||||
basic.clearScreen()
|
||||
basic.pause(500)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## OR test
|
||||
|
||||
Now, grab an ``||logic:or||`` operator and replace the ``||logic:not||`` in the ``||variables:Q||`` equation with it. Pull the ``||variables:A||`` variable down from the outside ``||loops:for element||`` loop and drop it in on the left side the ``||logic:or||`` operator. Drag down the ``||variables:B||`` variable down from the inside ``||loops:for element||`` loop and drop it in on the right side the ``||logic:or||`` operator.
|
||||
|
||||
```block
|
||||
let A = false
|
||||
let B = false
|
||||
let Q = A || B
|
||||
```
|
||||
### OR truth table
|
||||
|
||||
For the OR test, these output values will show for the inputs:
|
||||
|
||||
A | B | A + B
|
||||
-|-|-
|
||||
**false** | **false** | ``[basic.showIcon(IconNames.SmallDiamond)]``
|
||||
**false** | **true** | ``[basic.showIcon(IconNames.TShirt)]``
|
||||
**true** | **false** | ``[basic.showIcon(IconNames.TShirt)]``
|
||||
**true** | **true** | ``[basic.showIcon(IconNames.TShirt)]``
|
||||
|
||||
## AND test
|
||||
|
||||
Now, switch the ``||logic:or||`` operator type in the ``||variables:Q||`` equation to the ``||logic:and||`` operator type:
|
||||
|
||||
```block
|
||||
let A = false
|
||||
let B = false
|
||||
let Q = A && B
|
||||
```
|
||||
|
||||
### AND truth table
|
||||
|
||||
For the AND test, these output values will show for the inputs:
|
||||
|
||||
A | B | A · B
|
||||
-|-|-
|
||||
**false** | **false** | ``[basic.showIcon(IconNames.SmallDiamond)]``
|
||||
**false** | **true** | ``[basic.showIcon(IconNames.SmallDiamond)]``
|
||||
**true** | **false** | ``[basic.showIcon(IconNames.SmallDiamond)]``
|
||||
**true** | **true** | ``[basic.showIcon(IconNames.TShirt)]``
|
||||
|
||||
## XOR test
|
||||
|
||||
To test XOR, we'll use the XOR expression from [Boolean elements](/courses/logic-lab/elements#xor). Drag and place the ``||logic:LOGIC||`` blocks to make the ``||variables:Q||`` equation to look like this:
|
||||
|
||||
```block
|
||||
let A = false
|
||||
let B = false
|
||||
let Q = (A || B) && !(A && B)
|
||||
```
|
||||
### XOR truth table
|
||||
|
||||
For the XOR test, these output values will show for the inputs:
|
||||
|
||||
A | B | A ⊕ B
|
||||
-|-|-
|
||||
**false** | **false** | ``[basic.showIcon(IconNames.SmallDiamond)]``
|
||||
**false** | **true** | ``[basic.showIcon(IconNames.TShirt)]``
|
||||
**true** | **false** | ``[basic.showIcon(IconNames.TShirt)]``
|
||||
**true** | **true** | ``[basic.showIcon(IconNames.SmallDiamond)]``
|
142
docs/courses/logic-lab/expressions.md
Normal file
@ -0,0 +1,142 @@
|
||||
# Logic and expressions
|
||||
|
||||
The use and study of _logic_ involves finding a new fact by analyzing whether some other facts together can prove to be true. Some facts, or conditions, when looked at together may prove another fact to be true, or maybe false.
|
||||
|
||||
If the temperature outside is below freezing and you don't have a coat, you will feel cold. If you're not sick, then you will feel well. If you can swim or ride in a boat in water, you will stay afloat. These are statements of fact that result from some condition being true.
|
||||
|
||||
## Truth statements
|
||||
|
||||
By taking some facts and putting them into a logical form, we can make an arithmetic that helps us analyze them and make a conclusion. Using the examples just mentioned, let's turn them into some logical word equations:
|
||||
|
||||
* ``Outside temperature is freezing`` **AND** ``I have no coat`` **=** ``I feel cold``
|
||||
* **NOT** ``sick`` **=** ``I feel well``
|
||||
* ``I can swim`` **OR** ``I'm in a boat`` **=** ``I'm floating``
|
||||
|
||||
You see the AND, NOT, and OR in the example word equations? These are our logical _operators_. Every day we make decisions when we think about one or more facts together using these operators. Sometimes, it's necessary for all facts to be true in order for the conclusion to be true. This is the case when the AND operator is used. When analyzing facts with the OR operator, only on fact needs to be true for the conclusion to be true also.
|
||||
|
||||
Making a decision may require more than just one or two facts. When this happens, another operator is needed to combine the facts together to make a conclusion. In the last example word equation, you actually might not be floating if just those two condtions are true. To correctly prove that you're actually floating, you need to state that you're in water too.
|
||||
|
||||
* **(**``I can swim`` **OR** ``I'm in a boat``**) AND** ``I'm in water`` **=** ``I'm floating``
|
||||
|
||||
To prove that you're floating, the two facts that you can swim or you are in a boat must be made into a single fact that is combined with the other fact that you are also in water. Otherwise, if you're able to swim but still on land, or in a boat that is on the beach, you're not not floating.
|
||||
|
||||
## Boolean algebra
|
||||
|
||||
As a way to reduce the conditions, or facts as we've called them, into a form that is more compact, an algebra was invented. George Boole made a type of arithmetic (Boolean algebra) that uses symbols for the conditions, the operators, and the result. The conditions are considered as variables that have the value of either ``true`` or ``false``. the operators like AND, OR, and NOT are single character symbols. If we want to change the statement "I'm happy when it's sunny or when I'm eating a donut" into a Boolean equation, we could start by making the conditions into variables.
|
||||
|
||||
* Variable ``A`` = ``"It's sunny"``
|
||||
* Variable ``B`` = ``"I've eaten a donut"``
|
||||
|
||||
The result then, is a variable called ``Q`` that is true when you're happy and is a value of an operation of ``A`` with ``B``. This operation is OR which is represented by the ``+`` symbol.
|
||||
|
||||
``Q`` = ``A + B``
|
||||
|
||||
The result of ``Q`` is ``true`` when either it's sunny or you've had a donut. If other things make you happy, like being on vacation, you could add that to the equation.
|
||||
|
||||
* Variable ``C`` = ``"I'm on vacation"``
|
||||
|
||||
``Q`` = ``A + B + C``
|
||||
|
||||
It could be that you're easy to please and you just have to feel well to be happy. So, you're happy when your NOT sick. We'll use the ``~`` to mean NOT in our equation.
|
||||
|
||||
* Variable ``A`` = ``"I'm sick"``
|
||||
|
||||
``Q`` = ``~A``
|
||||
|
||||
In the situation where all conditions must be true for the result to be true, the conditions use the AND operation. For the sun to shine on you, the sky must be clear and it has to be daytime. We put these two facts together with the AND symbol ``·``.
|
||||
|
||||
* Variable ``A`` = ``"The sky is clear"``
|
||||
* Variable ``B`` = ``"It's daytime"``
|
||||
* Result ``Q`` = ``"The sun is shining"``
|
||||
|
||||
``Q`` = ``A · B``
|
||||
|
||||
## Expressions
|
||||
|
||||
Sometimes different operations on the same conditions can make equivalent results. If we take the opposite case of the last example where the sun is not shining, the variables for that are:
|
||||
|
||||
* Variable ``A`` = ``"The sky is clear"``
|
||||
* Variable ``B`` = ``"It's daytime"``
|
||||
* Result ``Q`` = ``"The sun is shining"``
|
||||
* Result ``~Q`` = ``"The sun is NOT shining"``
|
||||
|
||||
To make the opposite of ``"the sun is shining"`` we negate, use the NOT symbol, on both sides of the equation.
|
||||
|
||||
``~Q`` = ``~(A · B)``
|
||||
|
||||
Now, let's think of the sun NOT shining due to negative conditions. If the sky isn't clear OR it's not daytime, then the sun isn't shining. So, the NOT symbol is put in before the variables for each condition so that ``"the sun is NOT shining"`` has another equation like this:
|
||||
|
||||
``~Q`` = ``~A + ~B``
|
||||
|
||||
We see that the side with the ``A`` and ``B`` variables in both equations are equivalent to each other since they both equate to ``~Q``:
|
||||
|
||||
``~(A · B)`` = ``~A + ~B``
|
||||
|
||||
The logic equation now doesn't include the result variable ``Q`` but instead there are two _expressions_ that are logically equivalent on each side.
|
||||
|
||||
### ~ hint
|
||||
|
||||
#### De Morgan's Thereom
|
||||
|
||||
That last equation, ``~(A · B)`` = ``~A + ~B``, demonstrates an inportant property in Boolean algebra. It's called De Morgan's Thereom which says that the inverse (NOT) of a conjunction (AND) is logically equivalent to the disjunction (OR) of two inverses (NOT). Also, the inverse (NOT) of a disjunction (OR) is logically equivalent to the conjunction (AND) of two inverses (NOT).
|
||||
|
||||
This easier understood by seeing the Boolean equations for both cases:
|
||||
|
||||
``~(A · B)`` = ``~A + ~B``
|
||||
|
||||
>-- AND --
|
||||
|
||||
``~(A + B)`` = ``~A · ~B``
|
||||
|
||||
### ~
|
||||
|
||||
## Truth tables
|
||||
|
||||
A truth table is a way to see all possible condtions for the variables in a logical expression and to chart the results. Using the truth statement about when it's freezing outside and you have no coat, here's the truth table showing the possible conditions and their results:
|
||||
|
||||
It's freezing | I have no coat | I feel cold
|
||||
-|-|-
|
||||
false | false | false
|
||||
false | true | false
|
||||
true | false | false
|
||||
true | true | true
|
||||
<br/>
|
||||
|
||||
Because you feel cold only when both conditions are true, the statement becomes an AND expression in Boolean algebra.
|
||||
|
||||
* Variable ``A`` = ``"it's freezing"``
|
||||
* Variable ``B`` = ``"I don't have a coat"``
|
||||
|
||||
``A · B`` = ``Q``
|
||||
|
||||
A truth table for the variables in the expression have the same values as the table for the truth statement (``true`` and ``false`` are abbreviated to just ``T`` and ``F``).
|
||||
|
||||
A | B | Q
|
||||
-|-|-
|
||||
F | F | F
|
||||
F | T | F
|
||||
T | F | F
|
||||
T | F | T
|
||||
<br/>
|
||||
|
||||
What would happen if we changed the condition of ``"I have no coat"`` to ``"I have a coat"``? How does that affect truth table about how cold you feel?
|
||||
|
||||
It's freezing | I have a coat | I feel cold
|
||||
-|-|-
|
||||
false | false | false
|
||||
false | true | false
|
||||
true | false | true
|
||||
true | true | false
|
||||
<br/>
|
||||
|
||||
A | B | Q
|
||||
-|-|-
|
||||
F | F | F
|
||||
F | T | F
|
||||
T | F | T
|
||||
T | F | F
|
||||
<br/>
|
||||
|
||||
To write a Boolean equation for when you feel cold, we find the condtions in the table where ``Q`` is ``true``. Here we see that you will feel cold only in one row, when condition ``A`` is ``true`` and condtion ``B`` is ``false``. The Boolean equation for these conditions is this:
|
||||
|
||||
``A · ~B`` = ``Q``
|
87
docs/courses/logic-lab/logic-gates.md
Normal file
@ -0,0 +1,87 @@
|
||||
# Logic Gates
|
||||
|
||||
![OR gate symbol](/static/courses/logic-lab/logic-gates/full-adder.png)
|
||||
|
||||
In the real world digital devices aren't the abstract logical expressions of Boolean algebra, but they are implementations of these expressions in hardware. The logical expressions are translated into device structures called _logic gates_. A logic gate is both a symbolic representation of a logical operation and, when used in digital electronics, it can is an actual circuit in hardware. A single logic gate is usually made of several transistors an shares space with many others in an integrated circuit.
|
||||
|
||||
Each of the basic operators we learned about in the [expressions](/courses/logic-lab/expressions) section have a gate symbol. The symbol takes the place of the operator and the variables are the inputs to the gate. The resulting value from the expression equation is the output of the gate. The output of a gate can be a final result or it can be connected as an input to yet another gate.
|
||||
|
||||
## Gate symbols
|
||||
|
||||
Logic gates are symbols that can directly replace an expression in Boolean arithmetic. Each one has a different shape to show its particular function. The inputs (Boolean variables) enter at the left of the symbol and the output leaves from the right. When combined together, several gates can make a complex logical evaluation system that has many inputs and outputs. Digital computers are designed by connecting thousands, or millions, of these gates to together.
|
||||
|
||||
### NOT gate
|
||||
|
||||
The NOT gate is a forward arrow with a small circle at the output. The circle part of the symbol is what says that the output is negating the input.
|
||||
|
||||
![NOT gate symbol](/static/courses/logic-lab/logic-gates/not-gate.png)
|
||||
|
||||
### OR gate
|
||||
|
||||
Th OR gate has a curved input side and a sharp pointed output.
|
||||
|
||||
![OR gate symbol](/static/courses/logic-lab/logic-gates/or-gate.png)
|
||||
|
||||
### AND gate
|
||||
|
||||
The AND gate has a flat input side and round output side.
|
||||
|
||||
![AND gate symbol](/static/courses/logic-lab/logic-gates/and-gate.png)
|
||||
|
||||
### Exclusive OR (XOR) gate
|
||||
|
||||
The exclusive or gate symbol is just like the OR gate but it has an additonal curved line crossing the inputs.
|
||||
|
||||
![XOR gate symbol](/static/courses/logic-lab/logic-gates/xor-gate.png)
|
||||
|
||||
## Combined logic
|
||||
|
||||
When you connect multiple gates together you have a combined logic system or _combinatorial logic_. To design a combined logic system we can use a truth tables to match logical outputs for out various input conditions. Boolean expressions are written from the conditions in the table. Then, we can directly convert the expression into a diagram of logic gates.
|
||||
|
||||
You might remember that back in [Boolean elements](/courses/logic-lab/elements#xor) we saw that there was no operator to use in code for XOR. It was was made up using a combination of AND, OR, and NOT operators:
|
||||
|
||||
```block
|
||||
let A = false
|
||||
let B = false
|
||||
let Q = (A || B) && !(A && B)
|
||||
```
|
||||
|
||||
Let's map the input and output conditions in a truth table for a combined logic system for XOR. We'll find all the conditions that cause a ``true`` result and create a Boolean expression for them.
|
||||
|
||||
A | B | A ⊕ B
|
||||
-|-|-
|
||||
F | F | F
|
||||
F| T | T
|
||||
T| F | T
|
||||
T | T | F
|
||||
<br/>
|
||||
|
||||
There are two conditions where the result column has ``true`` values. The first conditon is when ``A`` is ``false`` and ``B`` is ``true`` which is expressed as ``~A · B``. The second conditon is when ``A`` is ``true`` and ``B`` is ``false`` which is expressed as ``A · ~B``. Our XOR expression is ``true`` when one of these conditions are ``true`` which is written like:
|
||||
|
||||
``A ⊕ B`` = ``(~A · B) + (A · ~B)``
|
||||
|
||||
In code this expression is formed with these logic blocks:
|
||||
|
||||
```block
|
||||
let A = false
|
||||
let B = false
|
||||
let Q = (!A && B) || (A && !B)
|
||||
```
|
||||
|
||||
Coverting the equation to logic gates makes the following diagram. Notice how each gate "connects" the variables together just like the logic blocks in the code above.
|
||||
|
||||
![Combinatorial XOR first version](/static/courses/logic-lab/logic-gates/combinatorial1-xor.png)
|
||||
|
||||
However, if we take the other two unused conditions from the truth table that make the XOR operation ``false``, can make the negative equation for XOR, called a NXOR:
|
||||
|
||||
``~(A ⊕ B)`` = ``(~A · ~B) + (A · B)``
|
||||
|
||||
To get back to ``A ⊕ B`` we have to negate this negative equation. Then, with the help of [De Morgan's Thereom](/courses/logic-lab/expressions#de-morgan-s-thereom), we get a different equation for XOR but it's still logically equivalent to the original one.
|
||||
|
||||
``A ⊕ B`` = ``(A + B) · ~(A · B)``
|
||||
|
||||
When this equation is converted to logic gates, there's one fewer gate than in the first diagram.
|
||||
|
||||
![Combinatorial XOR second version](/static/courses/logic-lab/logic-gates/combinatorial2-xor.png)
|
||||
|
||||
This diagram has less complexity than the first one. Reduction in the number of gates to accomplish the same logical result is one of the primary goals for digital logic design. For electronic devices, this allows more gates to use the limited amount of space on an integrated circuit.
|
231
docs/courses/logic-lab/programmable.md
Normal file
@ -0,0 +1,231 @@
|
||||
# Programmable logic
|
||||
|
||||
Logic gates are formed by connecting transistors together on a semiconductor material to make an integrated circuit. The wafers, or chips, of semiconductor contain lots of logic gates that make up different types of devices which work together to read, store, calculate, and transmit digital information.
|
||||
|
||||
Most integrated circuits contain a specific arrangement logic gates at the time they are manufactured. Because of their physical and chemical properties, some semiconductors can let you change connections between the gates after the device is manufactured. By applying special voltages at programming pins, a custom arrangement of gates can be "programmed" into the integrated circuit. These types of semiconductors are part of a category of electronics called _Programmable Logic Devices (PLD)_. There are many different kinds. Some of them you program only once and others you can erase the original gate arrangement and program in new ones multiple times.
|
||||
|
||||
We can use the @boardname@ to create our own PLD. The digital pins are the inputs for the logic circuits. The logic gates we program are logical expressions in code that combine the digital inputs we read from the pins. The result of the expression is written to a digital output pin.
|
||||
|
||||
## Board PLD
|
||||
|
||||
The physical idea of using your board as a PLD looks like this:
|
||||
|
||||
![Board with to logic inputs and one output](/static/courses/logic-lab/pld/mbit-pld.png)
|
||||
|
||||
The logic inputs for `A` and `B` are connected to digital input pins. The resulting output `Q` is connected to a digital output pin. We can make a general representation of your board as a PLD by selecting some digital pins to use as inputs and outputs for our programmable logic.
|
||||
|
||||
![Generic PLD representation](/static/courses/logic-lab/pld/generic-pld.png)
|
||||
|
||||
By "connecting" the pins together with code, we can program virtual logic gates and make the board act like a PLD. With multiple pins and some more code, we can even create a combined logic circuit.
|
||||
|
||||
![Gates inside the PLD diagram](/static/courses/logic-lab/pld/not-and-or.png)
|
||||
|
||||
|
||||
|
||||
## Programmable NOT gate
|
||||
|
||||
The **NOT** gate takes the logic value of the input and inverts it at the output. This is a single input gate using just the **P0** pin for input.
|
||||
|
||||
![NOT gate with pin assignments](/static/courses/logic-lab/pld/not-gate-pins.png)
|
||||
|
||||
The **NOT** gate is wired using alligator test clips as shown in the following diagram. The output clip is connected to pin **P2**.
|
||||
|
||||
![NOT gate wiring diagram](/static/courses/logic-lab/pld/not-gate-pld.png)
|
||||
|
||||
The script to program the **NOT** gate is simply a logical inverse of ``||pins:digital read pin||`` written to an output pin with ``||pins:digital write pin||``.
|
||||
|
||||
```block
|
||||
if (pins.digitalReadPin(DigitalPin.P0) > 0) {
|
||||
pins.digitalWritePin(DigitalPin.P2, 0)
|
||||
} else {
|
||||
pins.digitalWritePin(DigitalPin.P2, 1)
|
||||
}
|
||||
```
|
||||
|
||||
## Programmable OR gate
|
||||
|
||||
The **OR** gate takes two inputs and makes the output ``true`` if any input is ``true``. The **P0** and **P1** pins are the inputs.
|
||||
|
||||
![OR gate with pin assignments](/static/courses/logic-lab/pld/or-gate-pins.png)
|
||||
|
||||
The **OR** gate is wired using alligator test clips as shown in this diagram. The output clip is connected to pin **P2**.
|
||||
|
||||
![OR gate wiring diagram](/static/courses/logic-lab/pld/or-gate-pld.png)
|
||||
|
||||
The script to program an **OR** gate is two ``||pins:digital read pin||`` blocks, evaluated with an ``||logic:or||``, and the result is written to an output pin with ``||pins:digital write pin||``.
|
||||
|
||||
```block
|
||||
if ((pins.digitalReadPin(DigitalPin.P0) > 0) || pins.digitalReadPin(DigitalPin.P1) > 0) {
|
||||
pins.digitalWritePin(DigitalPin.P2, 1)
|
||||
} else {
|
||||
pins.digitalWritePin(DigitalPin.P2, 0)
|
||||
}
|
||||
```
|
||||
|
||||
## Programmable AND gate
|
||||
|
||||
The **AND** gate takes two inputs and makes the output ``true`` if both inputs are ``true``. The **P0** and **P1** pins are the inputs.
|
||||
|
||||
![AND gate with pin assignments](/static/courses/logic-lab/pld/and-gate-pins.png)
|
||||
|
||||
The **AND** gate is wired using alligator test clips as shown in the next diagram. The output pin is connected to pin **A2**.
|
||||
|
||||
![AND gate wiring diagram](/static/courses/logic-lab/pld/and-gate-pld.png)
|
||||
|
||||
The script for an **AND** gate is two ``||pins:digital read pin||`` blocks, evaluated with an ``||logic:and||``, and the result is written to an output pin with ``||pins:digital write pin||``.
|
||||
|
||||
```block
|
||||
if ((pins.digitalReadPin(DigitalPin.P0) > 0) && pins.digitalReadPin(DigitalPin.P1) > 0) {
|
||||
pins.digitalWritePin(DigitalPin.P2, 1)
|
||||
} else {
|
||||
pins.digitalWritePin(DigitalPin.P2, 0)
|
||||
}
|
||||
```
|
||||
|
||||
## Combined logic
|
||||
|
||||
You can program your board to have multiple logic gates that operate on the two inputs. Just combine the three logic gate scripts from above into one ``||loops:forever||`` loop. If you have an expansion connector for your @boardname@, you could program multiple outputs for your logic system. You could also use one extra input pin as an observer pin to test the outputs of your combined logic. The different outputs feedback to the observer pin so it will see what their logic levels are. Here's a schematic for a multiple gate system.
|
||||
|
||||
![micro:bit NOT, AND, OR gate PLD](/static/courses/logic-lab/pld/not-and-or-pld.png)
|
||||
|
||||
The combined logic for our multiple gate PLD is programmed like this:
|
||||
|
||||
```blocks
|
||||
let A = false
|
||||
let B = false
|
||||
basic.forever(function () {
|
||||
A = pins.digitalReadPin(DigitalPin.P0) > 0
|
||||
B = pins.digitalReadPin(DigitalPin.P1) > 0
|
||||
|
||||
if (A) {
|
||||
pins.digitalWritePin(DigitalPin.P2, 0)
|
||||
} else {
|
||||
pins.digitalWritePin(DigitalPin.P2, 1)
|
||||
}
|
||||
if (A || B) {
|
||||
pins.digitalWritePin(DigitalPin.P3, 1)
|
||||
} else {
|
||||
pins.digitalWritePin(DigitalPin.P3, 0)
|
||||
}
|
||||
if (A && B) {
|
||||
pins.digitalWritePin(DigitalPin.C4, 1)
|
||||
} else {
|
||||
pins.digitalWritePin(DigitalPin.C4, 0)
|
||||
}
|
||||
basic.pause(100)
|
||||
})
|
||||
```
|
||||
|
||||
### Logic observer
|
||||
|
||||
As easy way to see what the outputs of our PLD are, you can use the **P6** pin as a logic observer input and display the letter ``T`` for a ``true`` output value and the letter ``F`` for ``false``.
|
||||
|
||||
```blocks
|
||||
basic.forever(function () {
|
||||
if (pins.digitalReadPin(DigitalPin.C6) > 0) {
|
||||
basic.showString("T")
|
||||
} else {
|
||||
basic.showString("F")
|
||||
}
|
||||
basic.pause(100)
|
||||
})
|
||||
```
|
||||
|
||||
### Input tests
|
||||
|
||||
You can test different input combinations by connecting the other ends of alligator clip leads on pins **P0** and **P1** to either **GND** or **3V**. The **GND** pin will make a ``false`` input value and **3V** will make a ``true`` input value.
|
||||
|
||||
If you have an expansion connector for your @boardname@, you can use the combined logic script and the logic observer code to check each ouptput. Move the other end alligator clip lead connected to the observer pin **P6** to each of the outputs **P2**, **P3**, and **P4** to see the result of the logic operation programmed for those pins.
|
||||
|
||||
If you just have the @boardname@ by itself, you can test each logic function using only the scripts for each logic gate. Just put the script inside a ``||loops:forever||`` and place a ``||basic:show string||`` block with the logic letter after each ``||pins:digital write pin||``.
|
||||
|
||||
This is the code for the **NOT** gate:
|
||||
|
||||
```blocks
|
||||
basic.forever(function() {
|
||||
if (pins.digitalReadPin(DigitalPin.P0) > 0) {
|
||||
pins.digitalWritePin(DigitalPin.P2, 0)
|
||||
basic.showString("F")
|
||||
} else {
|
||||
pins.digitalWritePin(DigitalPin.P2, 1)
|
||||
basic.showString("T")
|
||||
}
|
||||
basic.pause(100)
|
||||
})
|
||||
```
|
||||
|
||||
#### NOT truth table
|
||||
|
||||
As an example, here's the truth table with pin voltages for the **NOT** operation:
|
||||
|
||||
P0 | P2 | Display
|
||||
-|-|-
|
||||
GND | 3V | ``[basic.showString("T")]``
|
||||
3V | GND | ``[basic.showString("F")]``
|
||||
<br/>
|
||||
|
||||
Do test connections for the inputs and check the results for the **OR** and **AND** outputs.
|
||||
|
||||
#### OR truth table
|
||||
|
||||
P0 | P1 | P3 | Display
|
||||
-|-|-|-
|
||||
GND | GND | ? | ?
|
||||
GND | 3V | ? | ?
|
||||
3V | GND | ? | ?
|
||||
3V | 3V | ? | ?
|
||||
|
||||
#### AND truth table
|
||||
|
||||
P0 | P1 | P4 | Display
|
||||
-|-|-|-
|
||||
GND | GND | ? | ?
|
||||
GND | 3V | ? | ?
|
||||
3V | GND | ? | ?
|
||||
3V | 3V | ? | ?
|
||||
|
||||
### XOR device
|
||||
|
||||
As we learned earlier, the **XOR** gate operation is made up from several other gates. The result `Q` was made from this expression in code:
|
||||
|
||||
```block
|
||||
let A = false
|
||||
let B = false
|
||||
let Q = (!A && B) || (A && !B)
|
||||
```
|
||||
|
||||
We'll make an **XOR** gate by programming a combined logic device for it. This time let's say that the whole @boardname@ is a programmed **XOR** gate.
|
||||
|
||||
![XOR symbol with board image](/static/courses/logic-lab/pld/xor-mbit.png)
|
||||
|
||||
Let's use the same wiring diagram as we did for the **OR** gate using **P0** and **P1** as input pins with **P2** as the output pin.
|
||||
|
||||
![XOR gate wiring diagram](/static/courses/logic-lab/pld/xor-gate-pld.png)
|
||||
|
||||
Our logic gate script is a bit different this time. To simplify forming the expression for **XOR**, we'll assign variables to the input and output values.
|
||||
|
||||
```blocks
|
||||
let A = false
|
||||
let B = false
|
||||
basic.forever(function () {
|
||||
A = pins.digitalReadPin(DigitalPin.P0) > 0
|
||||
B = pins.digitalReadPin(DigitalPin.P1) > 0
|
||||
if (!(A) && B || A && !(B)) {
|
||||
pins.digitalWritePin(DigitalPin.P2, 1)
|
||||
basic.showString("T")
|
||||
} else {
|
||||
pins.digitalWritePin(DigitalPin.P2, 0)
|
||||
basic.showString("F")
|
||||
}
|
||||
basic.pause(100)
|
||||
})
|
||||
```
|
||||
|
||||
Connect the inputs for **P0** and **P1** according to the **XOR** truth table and see if the outputs in the table match your results.
|
||||
|
||||
P0 | P1 | P2 | Display
|
||||
-|-|-|-
|
||||
GND | GND | GND | ``[basic.showString("F")]``
|
||||
GND | 3V | 3V | ``[basic.showString("T")]``
|
||||
3V | GND | 3V | ``[basic.showString("T")]``
|
||||
3V | 3V | GND | ``[basic.showString("F")]``
|
19
docs/device/bluetooth/hf2.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Bluetooth HF2
|
||||
|
||||
The Bluetooth HF2 service implements a subset of [HF2](https://github.com/Microsoft/uf2/blob/master/hf2.md), namely the serial message logging.
|
||||
|
||||
## Service
|
||||
|
||||
### HF2 service
|
||||
|
||||
* UUID: ``b112f5e6-2679-30da-a26e-0273b6043849``
|
||||
|
||||
### TX Characteristic
|
||||
|
||||
* Optional
|
||||
* UUDI: ``b112f5e6-2679-30da-a26e-0273b604384a``
|
||||
* NOTIFY only
|
||||
|
||||
This characteristic mostly emits HF2 serial messages. The first byte contains the type of message and length in the lower 6 bits. The message contains up to 19 bytes.
|
||||
|
||||
This service is supported by the MakeCode editor to receive messages.
|
48
docs/device/crocodile-clips.md
Normal file
@ -0,0 +1,48 @@
|
||||
# Crocodile clips
|
||||
|
||||
The large holes at the bottom of the board are designed to attach alligator/crocodile clips
|
||||
to create electrical circuit with other components.
|
||||
|
||||
# ~hint
|
||||
|
||||
**No crocodile clips!?!?!** Use [wires or aluminium foil](/device/foil-circuits)!
|
||||
|
||||
# ~
|
||||
|
||||
|
||||
## Connecting crocodile clips
|
||||
|
||||
The hole for ``P0`` and ``GND`` allow to grab the board on the side which makes for a great grip.
|
||||
|
||||
![](/static/mb/device/croc-clips/crocclipsclamped.jpg)
|
||||
|
||||
Pass one jaw in the hole and grab the side of the board with the other jaw.
|
||||
|
||||
![](/static/mb/device/croc-clips/sideclamp.jpg)
|
||||
|
||||
For the center holes, ``P1`` and ``P2``, you can also grab the bottom of the board but they are a bit harder to grip.
|
||||
|
||||
You can also grip the board between the jaws. In which case, you will want to make sure to avoid overlapping the jaws
|
||||
with the other pins as it will create short-circuit in the board.
|
||||
|
||||
![](/static/mb/device/croc-clips/badclamp.jpg)
|
||||
|
||||
Adding a little tape helps keeping the crocodile clips in place.
|
||||
|
||||
![](/static/mb/device/croc-clips/frontclamp.jpg)
|
||||
|
||||
## Example: on pin pressed with random numbers
|
||||
|
||||
This example displays a random number every time the crocodile clip holds `GND` then connects and disconnects the `P0` pin.
|
||||
Each time the crocodile clip is firmly connected and disconnected from pin `P0`,
|
||||
the @boardname@ will return a random Number between 0 and the parameter limit.
|
||||
|
||||
```blocks
|
||||
input.onPinTouchEvent(TouchPin.P0, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
basic.showNumber(randint(0, 10))
|
||||
})
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
[micro:bit pins](/device/pins)
|
16
docs/device/data-analysis.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Data Analysis
|
||||
|
||||
In addition to learning programming, the @boardname@ is a fantastic tool for observing and measuring things that happen in the natural world. The sciences rely on methods of observation, information gathering, and analysis. Using the @boardname@ with MakeCode, you can use the sensors and inputs to measure and capture physical events that occur. Measurement data can then be sent for recording by other devices like another @boardname@ or a personal computer.
|
||||
|
||||
![Data graph logo](/static/mb/device/data-analysis/data-analysis.jpg)
|
||||
|
||||
The Data Viewer in the MakeCode editor allows you to stream and log data from your programs. It will do this when you write data values using the **[serial](/reference/serial)** write functions. When you try your code in the simulator or connect with USB, each value you write is saved and collected as a log for you to analyze later if you want.
|
||||
|
||||
These topics describe how to analyze your data using MakeCode with the @boardname@:
|
||||
|
||||
* [Plotting with LEDs](./data-analysis/led-plotting)
|
||||
* [Viewing your data](./data-analysis/viewing)
|
||||
* [Writing data](./data-analysis/writing)
|
||||
* [Generating data](./data-analysis/generating)
|
||||
* [Analyze](./data-analysis/analyze)
|
||||
* [Remote data collection](./data-analysis/remote)
|
110
docs/device/data-analysis/analyze.md
Normal file
@ -0,0 +1,110 @@
|
||||
# Analyze
|
||||
|
||||
When it recognizes that data in the console has a format it can show in a chart, the Data Viewer will display it along with any new values that arrive. It also creates multiple charts if it notices more than one value stream in the incoming data.
|
||||
|
||||
If you want to keep the data and work with it later, you can download it and save it to your computer or mobile device.
|
||||
|
||||
## Charting value streams
|
||||
|
||||
As an example, let's generate some data for two values. The first value `x` makes a line on the chart. The second value is the square of the first value `x**2`shifted by `5`. This second value will show a chart of a parabola.
|
||||
|
||||
```blocks
|
||||
for (let x = 0; x <= 10; x++) {
|
||||
serial.writeValue("x", x)
|
||||
serial.writeValue("y", (x - 5)**2)
|
||||
basic.pause(1000)
|
||||
}
|
||||
```
|
||||
|
||||
![Charts of line and parabola](/static/mb/device/data-analysis/line-parabola.jpg)
|
||||
|
||||
Since we used ``||serial:serial write value||`` for each value, there are two charts, one for the `x` stream and the other for the `y` stream. Also, the values shown in the console window are formatted as name value pairs:
|
||||
|
||||
```
|
||||
x:0
|
||||
y:25
|
||||
x:1
|
||||
y:16
|
||||
...
|
||||
```
|
||||
|
||||
## Charting by data lines
|
||||
|
||||
Instead of writing multiple values separately, we can combine them in an array and write them together at once. Using the last example, let's combine each line and parabola value into an array.
|
||||
|
||||
```blocks
|
||||
for (let x = 0; x <= 10; x++) {
|
||||
serial.writeNumbers([x, (x - 5) ** 2])
|
||||
basic.pause(1000)
|
||||
}
|
||||
```
|
||||
|
||||
![One chart of both line and parabola](/static/mb/device/data-analysis/line-parabola2.jpg)
|
||||
|
||||
This time both values are shown on the same chart. We used ``||serial:serial write numbers||`` to send both values at the same time. Instead of being written as name value pairs, the values are combined into one line of comma separated values (CSV). The Data Viewer recognizes the values as one stream and puts multiple data lines on the same chart. The console shows the data in CSV format:
|
||||
|
||||
```
|
||||
0,25
|
||||
1,16
|
||||
2,9
|
||||
3,4
|
||||
...
|
||||
```
|
||||
|
||||
## Raw data
|
||||
|
||||
The data in the console window appears exactly like it's written by your program. The data your program writes is called "raw" data. The Data Viewer reads the data and "cooks" it by deciding how to display it in a way that's useful to you.
|
||||
|
||||
You can select and copy the raw data from the console and paste it into another program if you want to work with it outside of the MakeCode editor. Also, there is a copy button next to the console window that let's you easily copy the raw data with one click.
|
||||
|
||||
![Copy button for console data](/static/mb/device/data-analysis/copy-button.gif)
|
||||
|
||||
## Downloading your data
|
||||
|
||||
You can download your data to save it to view in another program. Click the **Download** button above the chart view.
|
||||
|
||||
![Download button highlighted](/static/mb/device/data-analysis/download-button.jpg)
|
||||
|
||||
The data is formatted again and saved in file with a name like:
|
||||
|
||||
``microbit-data-13-20-2018-14-18-15-0700.csv``
|
||||
|
||||
The filename contains the date and time when the data was downloaded. If you open the file in an editor you can see how the Data Viewer reformatted it from how it was in the console.
|
||||
|
||||
### Download format
|
||||
|
||||
The download file will contain your data as lines of CSV. The downloaded data from the first example will look something like this:
|
||||
|
||||
```
|
||||
sep=
|
||||
time (source1) x time (source1) y
|
||||
0 0 0 25
|
||||
1.018 1 1.026 16
|
||||
2.049 2 2.045 9
|
||||
3.062 3 3.059 4
|
||||
4.064 4 4.074 1
|
||||
5.078 5 5.078 0
|
||||
6.115 6 6.112 1
|
||||
7.097 7 7.112 4
|
||||
8.131 8 8.128 9
|
||||
9.145 9 9.145 16
|
||||
10.148 10 10.16 25
|
||||
```
|
||||
|
||||
The first line says what character is used as the value separator. Characters other than a comma can be used as separators. The Data Viewer choose to use a `TAB` character. The next line contains the headings for the values. These are the names of each value when name value pairs are written to the console. Also, a time value (timestamp) is included for each value. The timestamp is the amount of time since the start of the program when the value was written.
|
||||
|
||||
The remaining lines contain the data values and their timestamps. Each line has one occurrence of each value. So, for the example data above, each new `x` and `y` value is put together on the same line.
|
||||
|
||||
### Loading into a spreadsheet
|
||||
|
||||
Each line of data is placed into a row in the spreadsheet. The separators tell the spreadsheet which column the values go into.
|
||||
|
||||
![CSV data in spreadsheet](/static/mb/device/data-analysis/spreadsheet-data.jpg)
|
||||
|
||||
### Analyze in the spreadsheet
|
||||
|
||||
Spreadsheets are powerful tools for analyzing and looking at relationships in your data. Most spreadsheet programs can do advanced charting too. Here's a chart of our example data. You'll notice that it looks similar to the chart displayed by the MakeCode editor.
|
||||
|
||||
![Spreadsheet with chart](/static/mb/device/data-analysis/spreadsheet-chart.jpg)
|
||||
|
||||
The spreadsheet knows how to take the headings from the download file and use them as labels for the individual data lines.
|
111
docs/device/data-analysis/generating.md
Normal file
@ -0,0 +1,111 @@
|
||||
# Generating data
|
||||
|
||||
## Sensor values
|
||||
|
||||
Most of the data you want to record probably comes from values measured by the sensors. The sensor values are read using ``||input:Input||`` blocks. They return to your program the current value measured by the sensor.
|
||||
|
||||
```block
|
||||
serial.writeValue("accelX", input.acceleration(Dimension.X))
|
||||
```
|
||||
|
||||
```block
|
||||
serial.writeValue("heading", input.compassHeading())
|
||||
```
|
||||
|
||||
```block
|
||||
serial.writeValue("light", input.lightLevel())
|
||||
```
|
||||
|
||||
```block
|
||||
serial.writeValue("forceX", input.magneticForce(Dimension.X))
|
||||
```
|
||||
|
||||
## Pin data
|
||||
|
||||
External sensors and devices connected to the board are read using the ``||pins:Pins||`` blocks. Here are some examples of reading the pins and reporting measurements from devices:
|
||||
|
||||
### Soil moisture
|
||||
|
||||
```block
|
||||
let moisture = pins.analogReadPin(AnalogPin.P0)
|
||||
serial.writeValue("moisture", moisture)
|
||||
```
|
||||
|
||||
### Closed door detector
|
||||
|
||||
```block
|
||||
pins.onPulsed(DigitalPin.P0, PulseValue.Low, () => {
|
||||
serial.writeValue("DoorClosed", 1)
|
||||
})
|
||||
```
|
||||
|
||||
### I2C humidity sensor
|
||||
|
||||
```block
|
||||
let humidity = pins.i2cReadNumber(61, NumberFormat.Int8LE)
|
||||
serial.writeValue("humidity", humidity)
|
||||
```
|
||||
|
||||
## Human events
|
||||
|
||||
Sometimes we want to track human interactions with a device. These events might be button presses, gestures, or pin touches.
|
||||
|
||||
### Example: Button tracker
|
||||
|
||||
Run this example in the editor and switch to the Data Viewer. Watch it plot your button presses like pulse events in the chart.
|
||||
|
||||
```blocks
|
||||
let buttonValue = 0
|
||||
basic.forever(() => {
|
||||
if (input.buttonIsPressed(Button.A)) {
|
||||
buttonValue = 1
|
||||
} else {
|
||||
buttonValue = 0;
|
||||
}
|
||||
serial.writeValue("ButtonA", buttonValue)
|
||||
basic.pause(200)
|
||||
})
|
||||
```
|
||||
|
||||
Writing an additional value creates another stream that will appear in a separate chart. Adding and event for another button press, we can plot pulses on a second chart.
|
||||
|
||||
```blocks
|
||||
let buttonValue = 0
|
||||
basic.forever(() => {
|
||||
if (input.buttonIsPressed(Button.A)) {
|
||||
buttonValue = 1
|
||||
} else {
|
||||
buttonValue = 0;
|
||||
}
|
||||
serial.writeValue("ButtonA", buttonValue)
|
||||
if (input.buttonIsPressed(Button.B)) {
|
||||
buttonValue = 1
|
||||
} else {
|
||||
buttonValue = 0;
|
||||
}
|
||||
serial.writeValue("ButtonB", buttonValue)
|
||||
basic.pause(200)
|
||||
})
|
||||
```
|
||||
|
||||
## Time and timestamps
|
||||
|
||||
A timestamp marks when you read a value or detect that an event happens. These are commonly written along with other data values as an additional data item. The data viewer will create timestamps for values it sees when you write them. If you are downloading and saving data from the Data Viewer, it creates the timestamps for you and you don't need to add them.
|
||||
|
||||
If you need your own time values, you can make them from the **running time** of the board.
|
||||
|
||||
```block
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
serial.writeValue("shaken", input.runningTime())
|
||||
})
|
||||
```
|
||||
|
||||
Also, you can write your own custom CSV with your own timestamp:
|
||||
|
||||
```blocks
|
||||
serial.writeLine("timestamp,temp,light")
|
||||
basic.forever(() => {
|
||||
serial.writeNumbers([input.runningTime(), input.temperature(), input.lightLevel()])
|
||||
basic.pause(30000)
|
||||
})
|
||||
```
|
97
docs/device/data-analysis/led-plotting.md
Normal file
@ -0,0 +1,97 @@
|
||||
# Plotting data with LEDs
|
||||
|
||||
To quickly see and record your data values, use the ``||led:plot bar graph||`` block. It will plot a value on the LED screen and write a number to console at the same time.
|
||||
|
||||
```blocks
|
||||
basic.forever(() => {
|
||||
let i = 0
|
||||
while (i < 25) {
|
||||
led.plotBarGraph(i, 25)
|
||||
i += 2
|
||||
basic.pause(1000)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Here's a plot of values from `1` to `25`:
|
||||
|
||||
```sim
|
||||
basic.forever(() => {
|
||||
let i = 0
|
||||
while (i < 25) {
|
||||
led.plotBarGraph(i, 25)
|
||||
i += 2
|
||||
basic.pause(1000)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Plot range
|
||||
|
||||
A number of LEDs will light up to show how much the value is related to the _high_ number in the second argument. The high number sets the _range_ of values to show. If the high number is set to `16` and you want to plot the value of `8`, then that value is half of the range.
|
||||
|
||||
```block
|
||||
led.plotBarGraph(8, 16)
|
||||
```
|
||||
So, about half of the LEDs will light up to represent that number.
|
||||
|
||||
```sim
|
||||
basic.forever(() => {
|
||||
basic.clearScreen()
|
||||
basic.showString("8 up to 16")
|
||||
basic.clearScreen()
|
||||
basic.pause(500)
|
||||
led.plotBarGraph(8, 16)
|
||||
basic.pause(2000)
|
||||
})
|
||||
```
|
||||
|
||||
## Autoranging
|
||||
|
||||
If you don't know what the largest number to plot will be, then you can set the high number to `0`. This lets the largest value plotted be the range value. This is called _autoranging_. To see how it works, make an array of numbers and plot them. Put a large value in the middle of the array with smaller values before and after it. Watch as the same values are plotted with fewer lights after the largest number is plotted.
|
||||
|
||||
```blocks
|
||||
let values = [4,8,12,16,50,4,8,12,16]
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
led.plotBarGraph(values[i], 0)
|
||||
basic.pause(1000)
|
||||
}
|
||||
```
|
||||
|
||||
## Recording plotted values
|
||||
|
||||
The ``||led:plot bar graph||`` also sends the number value it's plotting to the console. You can see the output in the Data Viewer. It charts the values and they appear as individual numbers in console.
|
||||
|
||||
```blocks
|
||||
input.onButtonEvent(Button.B, input.buttonEventValue(ButtonEvent.Click), () => {
|
||||
for (let i = 0; i < 25; i++) {
|
||||
if (i % 2 > 0) {
|
||||
led.plotBarGraph(0, 0)
|
||||
} else {
|
||||
led.plotBarGraph(i, 24)
|
||||
}
|
||||
basic.pause(500)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The chart for the the plotted values from the example above:
|
||||
|
||||
![Plot LEDs chart result](/static/mb/device/data-analysis/plot-bar-graph.jpg)
|
||||
|
||||
The values appear in the console as just one number per line:
|
||||
|
||||
```
|
||||
0
|
||||
2
|
||||
0
|
||||
4
|
||||
0
|
||||
6
|
||||
...
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
[plot bar graph](/reference/led/plot-bar-graph)
|
||||
|
161
docs/device/data-analysis/remote.md
Normal file
@ -0,0 +1,161 @@
|
||||
# Remote data collection
|
||||
|
||||
If you have more than one @boardname@ you can setup one of them to receive data sent by radio from other @boardname@s. Remote @boardname@s can take measurements and send them to a board that's connected by USB to a computer. The @boardname@ connected to the computer is the data recorder and writes the received data to the serial port.
|
||||
|
||||
![Remote micro:bit sending](/static/mb/device/data-analysis/radio-zap.jpg)
|
||||
|
||||
## Receiver @boardname@
|
||||
|
||||
Connect the @boardname@ to a computer with a USB cable. The data received over radio is sent to the computer with this connection using writes to the serial port. If you have the [Windows 10 MakeCode](https://www.microsoft.com/store/apps/9PJC7SV48LCX) app, you can view the received data with the [Data Viewer](./viewing) in the editor. Otherwise, you need a _serial terminal_ app or some other program that can read from the computer's serial port.
|
||||
|
||||
The receiving @boardname@ sets a radio group number on which to listen for incoming messages.
|
||||
|
||||
```block
|
||||
radio.setGroup(99)
|
||||
```
|
||||
|
||||
The receiver then waits to receive a packet (radio message) from the sender which contains the data to record. This happens inside an ``||radio:on received number||`` block. If the sending @boardname@ is measuring temperature at a remote location (somewhere else in the room maybe), the receiver will write the value received as a temperature measurement to the serial port.
|
||||
|
||||
```blocks
|
||||
radio.setGroup(99)
|
||||
radio.onReceivedNumber(function (receivedNumber) {
|
||||
basic.showNumber(receivedNumber)
|
||||
serial.writeValue("TempCelsius", receivedNumber)
|
||||
})
|
||||
```
|
||||
|
||||
## Remote sender @boardname@
|
||||
|
||||
A remote @boardname@ reads its measurement values and sends them to the same radio group as the receiver.
|
||||
|
||||
```block
|
||||
radio.setGroup(99)
|
||||
```
|
||||
A typical measurement program might read a sensor value continuously. Depending on how much the values change, the measurement program could contain the read operation in a loop with a delay interval. In the example here, the delay is one minute between each read of a temperature value. The value is sent on the current radio group with ``||radio:radio send number||``.
|
||||
|
||||
```blocks
|
||||
let temperature = 0
|
||||
radio.setGroup(99)
|
||||
basic.forever(() => {
|
||||
temperature = input.temperature()
|
||||
basic.showNumber(temperature)
|
||||
radio.sendNumber(temperature)
|
||||
basic.pause(60000)
|
||||
})
|
||||
```
|
||||
|
||||
## Sending multiple values
|
||||
|
||||
The remote @boardname@ in the previous example sent a single value which was temperature. The receiver understands that the incoming value is a temperature measurement. If you want the remote to also send the current amount of light measured, the receiver won't know that this other value isn't a temperature reading.
|
||||
|
||||
The sender code is modified to use a value packet instead of just a number message. Here's the sender program sending both temperature and light values with ``||radio:radio send value||``.
|
||||
|
||||
```blocks
|
||||
let temperature = 0
|
||||
let lightLevel = 0
|
||||
radio.setGroup(99)
|
||||
basic.forever(() => {
|
||||
temperature = input.temperature()
|
||||
radio.sendValue("temperature", temperature)
|
||||
lightLevel = input.lightLevel()
|
||||
radio.sendValue("light", lightLevel)
|
||||
basic.pause(60000)
|
||||
})
|
||||
```
|
||||
|
||||
Here's the program for the receiver to record both temperature and light:
|
||||
|
||||
```blocks
|
||||
radio.setGroup(99)
|
||||
radio.onReceivedValue(function (name: string, value: number) {
|
||||
basic.showString(name + ":")
|
||||
basic.showNumber(value)
|
||||
serial.writeValue(name, value)
|
||||
})
|
||||
```
|
||||
|
||||
The receiver program uses just one ``||radio:on received number||`` event to record the values. The ``name`` and the ``value`` are parameters for the event block so both temperature and light values are received here.
|
||||
|
||||
## Multiple remote stations
|
||||
|
||||
For more complex data recording situations, you might need to measure sensor values from multiple locations at the same time. This means that there is more than one remote @boardname@ (station) measuring data.
|
||||
|
||||
### Separate radio groups
|
||||
|
||||
You could add another receiver @boardname@ and set it to a different radio group. This way you can copy the same programs to each sender and receiver and just change the radio group number for the matched boards. This solution, though, means you need an extra receiver board and another computer to record the data from the second station.
|
||||
|
||||
### Station identifiers
|
||||
|
||||
A different solution from using more than one radio group is to still have just one receiver on one group but make the different stations send identifiers with their values.
|
||||
|
||||
This is done with ``||radio:radio set transmit serial number||`` which tells the radio to add the board's serial number to the packet it sends. The serial number is included with the ``name`` and ``value`` so the receiver can know what station it comes from.
|
||||
|
||||
```block
|
||||
radio.setTransmitSerialNumber(true)
|
||||
```
|
||||
|
||||
The sender's program with the identifier added:
|
||||
|
||||
```blocks
|
||||
let temperature = 0
|
||||
radio.setGroup(99)
|
||||
radio.setTransmitSerialNumber(true)
|
||||
basic.forever(() => {
|
||||
temperature = input.temperature()
|
||||
basic.showNumber(temperature)
|
||||
radio.sendValue("temperature", temperature)
|
||||
basic.pause(60000)
|
||||
})
|
||||
```
|
||||
|
||||
The program on the receiver board can use the serial number to make a name value pair that the [Data Viewer](./writing#name-value-pairs) can recognize:
|
||||
|
||||
```blocks
|
||||
let id = 0;
|
||||
radio.setGroup(99)
|
||||
radio.onReceivedValue(function (name: string, value: number) {
|
||||
id = radio.receivedPacket(RadioPacketProperty.SerialNumber)
|
||||
basic.showString(name + ":")
|
||||
basic.showNumber(value)
|
||||
serial.writeValue(id + "_" + name, value)
|
||||
})
|
||||
```
|
||||
|
||||
The serial number, ``id``, is used as a _prefix_ for the ``name`` to identify which station the ``value`` came from.
|
||||
|
||||
### Extended data recording
|
||||
|
||||
If you're recording data to save on a computer for analysis or other uses outside of the MakeCode editor, you can use the ``||radio:radio write received packet to serial||`` block to format it for you. This function will format the data from the received packet into a [JSON](https://en.wikipedia.org/wiki/JSON) string and write it to the serial port, all in one operation. It's used just like this:
|
||||
|
||||
```blocks
|
||||
radio.onReceivedNumber(function (receivedNumber) {
|
||||
radio.writeReceivedPacketToSerial();
|
||||
});
|
||||
```
|
||||
|
||||
The output to the serial port is a line of text with these name value pairs:
|
||||
|
||||
* **t** - time: the time when the packet was sent
|
||||
* **s** - serial: the serial number of the board that sent the packet (if enabled)
|
||||
* **n** - name: the name for the data value from the string part of the packet
|
||||
* **v** - value: the data from the number part of the packet
|
||||
|
||||
It's sent in this format to the serial port:
|
||||
|
||||
```json
|
||||
{"t":3504,"s":1951284846,"n":"temperature","v":19}
|
||||
{"t":3823,"s":1951284846,"n":"temperature","v":20}
|
||||
{"t":4143,"s":1951284846,"n":"temperature","v":20}
|
||||
{"t":4463,"s":1951284846,"n":"temperature","v":18}
|
||||
{"t":4781,"s":1951284846,"n":"temperature","v":21}
|
||||
{"t":5102,"s":1951284846,"n":"temperature","v":17}
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
[radio](/reference/radio), [serial write value](/reference/serial/write-value),
|
||||
[write received packet to serial](/reference/radio/write-received-packet-to-serial)
|
||||
|
||||
```package
|
||||
radio
|
||||
```
|
50
docs/device/data-analysis/viewing.md
Normal file
@ -0,0 +1,50 @@
|
||||
# Viewing your data
|
||||
|
||||
## Recording data
|
||||
|
||||
When your code is writing data, and the editor is recording it, the **Show data** button is displayed in the simulator under the board and simulation controls.
|
||||
|
||||
![Show data button](/static/mb/device/data-analysis/show-data.jpg)
|
||||
|
||||
## Data view window
|
||||
|
||||
If you press the **Show data** button, the editor will switch from the **Blocks** or **JavaScript** view to display a charting window and a text console.
|
||||
|
||||
![Data chart and console](/static/mb/device/data-analysis/data-view.jpg)
|
||||
|
||||
The console window under the graph will show the data in the format it was written. The chart is the visual representation of the values appearing on the console.
|
||||
|
||||
## Time scroll
|
||||
|
||||
The chart will display new data as it arrives. The chart will scroll with time to continue to display new values.
|
||||
|
||||
![Data chart time scroll](/static/mb/device/data-analysis/time-scroll.gif)
|
||||
|
||||
## Data view controls
|
||||
|
||||
The chart window shows the data view controls on top of the chart.
|
||||
|
||||
![Data view controls](/static/mb/device/data-analysis/data-view-controls.jpg)
|
||||
|
||||
Here's what the controls do:
|
||||
|
||||
**Return**: The return button switches the view back to previous code window (either Blocks or JavaScript).
|
||||
|
||||
![Return button](/static/mb/device/data-analysis/return-button.jpg)
|
||||
|
||||
|
||||
**Source**: Tells you where the data is coming from. If the code writing the data is running in the simulator, then the source is **Simulator**. If your code is running on the @boardname@ and connected by USB, the source is **@boardname@**.
|
||||
|
||||
![Source label](/static/mb/device/data-analysis/source-label.jpg)
|
||||
|
||||
**Pause**: The pause button will stop the display of new values and stop scrolling. When you resume, the chart starts again with the current value written.
|
||||
|
||||
![Pause button](/static/mb/device/data-analysis/pause-button.jpg)
|
||||
|
||||
**Resume**: The resume button will start displaying new values after the **Pause** button was pressed.
|
||||
|
||||
![Resume button](/static/mb/device/data-analysis/resume-button.jpg)
|
||||
|
||||
**Download**: The download button collects the data your code has written and downloads it to your computer as a file called something like _data-11-2018-23-00-0700.csv_. The numbers in the filename are the date and time when the file is created. The file may automatically open in an editor or spreadsheet if one of those programs is associated with _csv_ files.
|
||||
|
||||
![Download button](/static/mb/device/data-analysis/download-button.jpg)
|
187
docs/device/data-analysis/writing.md
Normal file
@ -0,0 +1,187 @@
|
||||
# Writing data
|
||||
|
||||
While you're using MakeCode, all data written by the [serial](/reference/serial) functions is recorded by the MakeCode editor. This happens when you try your code in the simulator and also when the @boardname@ is connected to a computer running the MakeCode app with USB.
|
||||
|
||||
## Data formats
|
||||
|
||||
The Data Viewer recognizes the format of your output and decides how to display it. If your data is a _stream_ of values it will plot them in the chart window and show them as text in the console. If your data is just text information, it appears only in the console window.
|
||||
|
||||
You can write data in these format types:
|
||||
|
||||
* Text ([string](/types/string)): `"Hello there!"`
|
||||
* [Numbers](/types/number): `"354"`
|
||||
* [Number arrays](/types/array): `"11,3,45,76"`
|
||||
* Name value pairs: `"accelY:956"`
|
||||
|
||||
## Text output
|
||||
|
||||
Text is formed by simply using string data. The text data is not recorded in the console until a complete "line" of text is written. A line is just a string with some special characters (ones you don't actually see printed) at the end. You can write several strings, say:
|
||||
|
||||
```block
|
||||
serial.writeString("Hello ");
|
||||
serial.writeString("from ")
|
||||
serial.writeString("micro:bit")
|
||||
```
|
||||
|
||||
This text, though, won't appear in the editor console until it becomes a complete line. If you follow the string writes with a line in your code, then the line will show up:
|
||||
|
||||
```block
|
||||
serial.writeString("Hello ")
|
||||
serial.writeString("from ")
|
||||
serial.writeString("micro:bit")
|
||||
serial.writeLine("")
|
||||
```
|
||||
|
||||
Text output is used mostly for messages since number formats have meaning when used for data analysis.
|
||||
|
||||
The blank ``||serial:serial write line||`` adds the special line ending characters and turns the previous strings into a complete line of text. The whole line could simply be written out with just one function:
|
||||
|
||||
```block
|
||||
serial.writeLine("Hello from micro:bit")
|
||||
```
|
||||
|
||||
When you're writing only text, it appears only in the console view and not in the chart window. This example writes four messages of text:
|
||||
|
||||
```block
|
||||
for (let i = 0; i < 4; i++) {
|
||||
serial.writeLine("Hello from micro:bit " + i)
|
||||
}
|
||||
```
|
||||
|
||||
The four messages appear in the console window:
|
||||
|
||||
![Console output](/static/mb/device/data-analysis/console-output.jpg)
|
||||
|
||||
## Writing numbers
|
||||
|
||||
In order for the Data Viewer to recognize a number as value and show in the chart, it has to be in a line by itself. So, numbers written individually won't be charted:
|
||||
|
||||
```block
|
||||
serial.writeNumber(1)
|
||||
serial.writeNumber(2)
|
||||
serial.writeNumber(3)
|
||||
```
|
||||
|
||||
The numbers don't show up as single values because they appear in the output as a string: `"123"`. Also, the string doesn't form a complete line so it doesn't show up in the console window either. You could add a blank line to the numbers already written. If you did this, you would have just one value charted which is `123`:
|
||||
|
||||
```block
|
||||
serial.writeNumber(1)
|
||||
serial.writeNumber(2)
|
||||
serial.writeNumber(3)
|
||||
serial.writeLine("")
|
||||
```
|
||||
|
||||
Here's a way to chart the numbers individually:
|
||||
|
||||
```block
|
||||
for (let i = 0; i < 4; i++) {
|
||||
serial.writeNumber(i)
|
||||
serial.writeLine("")
|
||||
}
|
||||
```
|
||||
|
||||
It's much better though to use a value stream by writing the numbers as [name value pairs](#name-value-pairs).
|
||||
|
||||
## Number arrays
|
||||
|
||||
Numbers in arrays are displayed on separate data lines on the same chart. You can use ``||serial:serial write numbers||`` to write several values at once. The numbers are written to the output as _comma separated values_ (CSV). The array of numbers:
|
||||
|
||||
```block
|
||||
let values = [0,1,2,3,4];
|
||||
```
|
||||
|
||||
is written to the output in the form of a CSV string as: `"0,1,2,3,4"`.
|
||||
|
||||
The Data Viewer recognizes this as an array of numbers and charts them on separate data lines:
|
||||
|
||||
```block
|
||||
let values = [0, 1, 2, 3, 4]
|
||||
basic.forever(() => {
|
||||
serial.writeNumbers(values)
|
||||
})
|
||||
```
|
||||
|
||||
Data lines are shown for each value in the array:
|
||||
|
||||
![Data lines on chart](/static/mb/device/data-analysis/data-lines.jpg)
|
||||
|
||||
Give this example a try and watch the chart make a diamond pattern from two triangle waves:
|
||||
|
||||
```blocks
|
||||
let diamond: number[] = []
|
||||
basic.forever(() => {
|
||||
for (let i = 0; i <= 10 - 1; i++) {
|
||||
if (i < 5) {
|
||||
diamond[0] = i
|
||||
diamond[1] = 5 - i
|
||||
} else {
|
||||
diamond[0] = 10 - i
|
||||
diamond[1] = i - 5
|
||||
}
|
||||
serial.writeNumbers(diamond)
|
||||
basic.pause(500)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
It will look like this:
|
||||
|
||||
![Data pattern on chart](/static/mb/device/data-analysis/diamond-chart.jpg)
|
||||
|
||||
## Name value pairs
|
||||
|
||||
A very common way to report and record data is to use a _name value pair_ (NVP). A value is given a name so you know what it's for or where it came from. The name value pair is written with the format of _name:value_. There is a name, a colon character, and the value all together on one line. The line is written to the output and the Data Viewer recognizes it as a value and charts it as part of a value stream. The value stream is based on the name so any new values received with the same name are displayed on the chart that's showing values for that name. If more than one type of name value pair is found, the Data Viewer makes another value stream and shows those values on a different chart.
|
||||
|
||||
If you want to report the values for both temperature and light, you can make separate name value pairs for them. The name value pairs are written using ``||serial:serial write value||``. This function writes the values to the output as lines in a format like this:
|
||||
|
||||
```
|
||||
temp:17
|
||||
light:118
|
||||
temp:18
|
||||
light:117
|
||||
```
|
||||
|
||||
```blocks
|
||||
basic.forever(() => {
|
||||
serial.writeValue("temp", input.temperature())
|
||||
serial.writeValue("light", input.lightLevel())
|
||||
basic.pause(5000)
|
||||
})
|
||||
```
|
||||
|
||||
Two charts display each value stream:
|
||||
|
||||
![Two charts for each value type](/static/mb/device/data-analysis/two-value-chart.jpg)
|
||||
|
||||
The console output shows the different name value pairs too:
|
||||
|
||||
![Two values in console output](/static/mb/device/data-analysis/two-value-console.jpg)
|
||||
|
||||
### Writing subvalues
|
||||
|
||||
Similar to number arrays, different name value pairs are shown on one chart by using _subvalues_. You make a subvalue by combining a first-level name and a second-level name with a `'.'`:
|
||||
|
||||
``"firstLevel.secondLevel"``
|
||||
|
||||
The first-level name is value name for the chart. The second-level name is the name for the actual value displayed.
|
||||
|
||||
If you want to show all three values of acceleration on a single chart, then use each axis as a second-level (subvalue) name, ``"acceleration.x"``.
|
||||
|
||||
```block
|
||||
serial.writeValue("acceleration.x", input.acceleration(Dimension.X))
|
||||
```
|
||||
|
||||
To show the values for each axis together:
|
||||
|
||||
```blocks
|
||||
basic.forever(() => {
|
||||
serial.writeValue("acceleration.x", input.acceleration(Dimension.X))
|
||||
serial.writeValue("acceleration.y", input.acceleration(Dimension.Y))
|
||||
serial.writeValue("acceleration.z", input.acceleration(Dimension.Z))
|
||||
basic.pause(500)
|
||||
})
|
||||
```
|
||||
|
||||
Each subvalue ``'x'``, ``'y'``, and ``'z'`` is displayed on the chart named ``"acceleration"`` in the Data Viewer.
|
||||
|
||||
![Three subvalues of acceleration in one chart](/static/mb/device/data-analysis/combined-values.jpg)
|
86
docs/device/error-codes.md
Normal file
@ -0,0 +1,86 @@
|
||||
# Error codes
|
||||
|
||||
Your @boardname@ may encounter a situation that prevents it from running your code. When this happens, a frowny face will appear on your @boardname@ screen (see picture) followed by an error number. These are called _panic_ codes.
|
||||
|
||||
```sim
|
||||
basic.forever(function() {
|
||||
basic.showLeds(`
|
||||
# . . . #
|
||||
# # . # #
|
||||
. . . . .
|
||||
. # # # .
|
||||
# . . . #
|
||||
`)
|
||||
basic.pause(1000)
|
||||
basic.clearScreen()
|
||||
basic.showString("020")
|
||||
})
|
||||
```
|
||||
|
||||
## Board system errors
|
||||
|
||||
The @boardname@ system errors range between **01** - **99**. For a full list of these codes, what they mean and what you can do to resolve them, visit the [micro:bit guide to error codes](https://support.microbit.org/en/support/solutions/articles/19000016969).
|
||||
|
||||
* **10** (`MICROBIT_I2C_LOCKUP`): the @boardname@'s I2C bus is not working
|
||||
* **20** (`MICROBIT_OOM`): there is no free memory on the @boardname@
|
||||
* **30** (`MICROBIT_HEAP_ERROR`): a problem in the heap space
|
||||
* **40** (`MICROBIT_NULL_DEREFERENCE `): there was a NULL dereference, the @boardname@ tried to manage a invalid object pointer
|
||||
* **42** (`MICROBIT_SYSTEM_ERROR`): there's an error condition in the @boardname@ system software
|
||||
* **43** (`MICROBIT_NO_RADIO`): the @boardname@ can't enable the radio
|
||||
* **50** (`MICROBIT_HARDWARE_UNAVAILABLE_ACC`): an error occurred with the micro:bit's accelerometer component
|
||||
* **51** (`MICROBIT_HARDWARE_UNAVAILABLE_MAG`): an error occurred with the micro:bit's magnetometer component
|
||||
* **90** (`MICROBIT_HARDWARE_CONFIGURATION_ERROR`): actual board hardware doesn't match the configuration description
|
||||
* **98** (`MICROBIT_ASSERTION_FAILED`): assertion failed, the condition in an [assert](/reference/control/assert) was false
|
||||
|
||||
## Memory errors
|
||||
|
||||
Memory error codes range from **800** - **909**.
|
||||
|
||||
### ~alert
|
||||
|
||||
#### Report errors!
|
||||
|
||||
If you ever see an error within the range of **800** - **909**, please report an issue at [GitHub](https://github.com/microsoft/pxt-microbit/issues) or on the [support](https://support.microbit.org/) page.
|
||||
|
||||
### ~
|
||||
|
||||
### Garbage collector errors
|
||||
|
||||
Error codes generated from the garbage collector.
|
||||
|
||||
* **840**: Allocation pointer is null or invalid
|
||||
* **841**: Garbage collection work queue error
|
||||
* **843**: VTable entry is not free
|
||||
* **844**: GC allocation failed for requested number of bytes
|
||||
* **846**: Invalid allocation thread
|
||||
* **848**: Allocation pointer beyond allocation header
|
||||
* **849**: Allocation pointer is null
|
||||
|
||||
### Program access errors
|
||||
|
||||
* **901** (`PANIC_INVALID_BINARY_HEADER`): the type header for the object is not valid
|
||||
* **902** (`PANIC_OUT_OF_BOUNDS`): the object data portion is greater than the length defined for it
|
||||
* **903** (`PANIC_REF_DELETED`): an object reference was deleted and the object is no longer valid
|
||||
* **904** (`PANIC_SIZE`): the object size doesn't match the size defined for the type
|
||||
* **905** (`PANIC_INVALID_VTABLE`): an object vtable is invalid or not initialized
|
||||
* **906** (`PANIC_INTERNAL_ERROR`): an internal resource error
|
||||
* **907** (`PANIC_NO_SUCH_CONFIG`): the specified device resource is not present
|
||||
* **909** (`PANIC_INVALID_ARGUMENT`): the argument value is out of range or the type or format is invalid
|
||||
|
||||
## JavaScript runtime codes
|
||||
|
||||
### Invalid cast codes
|
||||
|
||||
When the static type of ``x`` is a class ``C``, the dynamic type of ``x`` isn’t ``C``, and you try to access a field on ``x`` or call a method on ``x``, you will get one of the following codes, depending on dynamic type of ``x``.
|
||||
|
||||
* **980** (`PANIC_CAST_FROM_UNDEFINED`): when value of ``x`` is ``undefined``
|
||||
* **981** (`PANIC_CAST_FROM_BOOLEAN`): when value of ``x`` is ``true`` or ``false``
|
||||
* **982** (`PANIC_CAST_FROM_NUMBER`): when ``x`` is a ``number``
|
||||
* **983** (`PANIC_CAST_FROM_STRING`): when ``x`` is a ``string``
|
||||
* **984** (`PANIC_CAST_FROM_OBJECT`): when ``x`` is object of some type
|
||||
* **985** (`PANIC_CAST_FROM_FUNCTION`): when ``x`` is a function
|
||||
* **989** (`PANIC_CAST_FROM_NULL`): when ``x`` is ``null``
|
||||
|
||||
## See also
|
||||
|
||||
[panic](/reference/control/panic), [assert](/reference/control/assert)
|
11
docs/device/firmware.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Firmware
|
||||
|
||||
Occasionally, changes and improvements to the system software (firmware) on the @boardname@ are needed. Updates to the firmware are made by the [micro:bit Education Foundation](http://microbit.org/about).
|
||||
|
||||
## Do I need an update?
|
||||
|
||||
Changes to the firmware don't happen very often. You probably don't need to update it for your @boardname@ if everything is working alright. Sometimes there's a problem with a certain part of the board not working right or it has trouble connecting to your computer or other device. In those cases, a firmware update may include a fix for the problem.
|
||||
|
||||
## Getting a firmware update
|
||||
|
||||
Instructions for updating the firmware are shown on the **[firmware upgrade](https://microbit.org/guide/firmware/)** support page at microbit.org.
|
52
docs/device/foil-circuits.md
Normal file
@ -0,0 +1,52 @@
|
||||
# foil circuits
|
||||
|
||||
The large holes at the bottom of the board are designed to attach alligator/crocodile clips
|
||||
to create electrical circuit with other components.
|
||||
|
||||
If you do not have crocodile clips at hand, you can use wires or even Aluminium foil to achieve the same result.
|
||||
We will show you how to connect the @boardname@ to headphones using Aluminium foil and tape.
|
||||
|
||||
https://youtu.be/mhXYyPuvpz0
|
||||
|
||||
## Materials
|
||||
|
||||
* @boardname@ and battery pack (you can also power it via USB)
|
||||
* a small piece of cardboard
|
||||
* Aluminium foil
|
||||
* tape
|
||||
|
||||
## Assembly instructions
|
||||
|
||||
Tape the @boardname@ and battery pack to the card board. Make sure to remove the batteries while you are building your circuit.
|
||||
|
||||
![](/static/mb/device/croc-clips/microbitattached.jpg)
|
||||
|
||||
Cut the thinnest strip of foil possible and roll it into a cable. You can also try to fold, whatever works for you.
|
||||
Build two of those wires.
|
||||
|
||||
![](/static/mb/device/croc-clips/foilcut.jpg)
|
||||
|
||||
Place the foil wire on the ``GND`` pin and attach with a piece of tape. Press hard to get the best connection between
|
||||
the foil and the pin board. Make sure the foil is not overlapping with the other pins!
|
||||
|
||||
![](/static/mb/device/croc-clips/groundconnected.jpg)
|
||||
|
||||
Place the second wire on the ``P0`` pin the same way. Make sure the wire does not overlap with the other pins!
|
||||
|
||||
![](/static/mb/device/croc-clips/microbitconnect.jpg)
|
||||
|
||||
Tape the headphone jack connector to the cardboard and roll the wire coming from ``GND`` around the metal base.
|
||||
Make sure the wire does not touch the other metal rings on the jack.
|
||||
|
||||
![](/static/mb/device/croc-clips/jackground.jpg)
|
||||
|
||||
Tape the second wire on the head of the jack connector.
|
||||
|
||||
![](/static/mb/device/croc-clips/jackconnect.jpg)
|
||||
|
||||
![](/static/mb/device/croc-clips/foilcircuit.jpg)
|
||||
|
||||
|
||||
## See also
|
||||
|
||||
[@boardname@ pins](/device/pins)
|
145
docs/device/mes-events.md
Normal file
@ -0,0 +1,145 @@
|
||||
# MES events
|
||||
|
||||
Events and event values are generated in the Message Event Service (MES). Using MES events allows orderly interactions between the @boardname@ and external devices. These events are sent to and received from other wireless devices paired with the @boardname@ (phone, game pad, etc.).
|
||||
|
||||
The event source IDs represent a device feature category. The event values are actions for, or notifications about a device feature.
|
||||
|
||||
### ~hint
|
||||
|
||||
**MES system sources**
|
||||
|
||||
The MES events are defined in this source file of the **[microbit-dal](https://github.com/lancaster-university/microbit-dal)**:
|
||||
|
||||
* [MESEvents.h](https://github.com/lancaster-university/microbit-dal/blob/master/inc/bluetooth/MESEvents.h)
|
||||
|
||||
Also, you can see how the message bus works in the DAL core files:
|
||||
|
||||
* [MemberFunctionCallback.cpp](https://github.com/lancaster-university/microbit-dal/blob/master/source/core/MemberFunctionCallback.cpp)
|
||||
* [MicroBitListener.cpp](https://github.com/lancaster-university/microbit-dal/blob/master/source/core/MicroBitListener.cpp)
|
||||
|
||||
### ~
|
||||
|
||||
## Raised events
|
||||
|
||||
Events are generated, or _raised_, for by the @boardname@ for a paired device. These are raised using the [raise event](/reference/control/raise-event) function.
|
||||
|
||||
```typescript-ignore
|
||||
control.raiseEvent(
|
||||
control.eventSourceId(EventBusSource.MES_REMOTE_CONTROL_ID),
|
||||
control.eventValueId(EventBusValue.MES_REMOTE_CONTROL_EVT_VOLUMEUP)
|
||||
);
|
||||
```
|
||||
|
||||
### Remote control
|
||||
|
||||
Events for using the @boardname@ as a remote control for audio play.
|
||||
|
||||
#### MES_REMOTE_CONTROL_ID
|
||||
|
||||
* `MES_REMOTE_CONTROL_EVT_PLAY`: Play the current track
|
||||
* `MES_REMOTE_CONTROL_EVT_PAUSE`: Pause the current play in progress
|
||||
* `MES_REMOTE_CONTROL_EVT_STOP`: Stop playing and reset to the beginning of the current track
|
||||
* `MES_REMOTE_CONTROL_EVT_NEXTTRACK`: Skip to the next track
|
||||
* `MES_REMOTE_CONTROL_EVT_PREVTRACK`: Skip to the previous track
|
||||
* `MES_REMOTE_CONTROL_EVT_FORWARD`: Move forward in the current track
|
||||
* `MES_REMOTE_CONTROL_EVT_REWIND`: Move backward in the current track
|
||||
* `MES_REMOTE_CONTROL_EVT_VOLUMEUP`: Increase the play volume (audio)
|
||||
* `MES_REMOTE_CONTROL_EVT_VOLUMEDOWN`: Decrease the play volume (audio)
|
||||
|
||||
### Camera
|
||||
|
||||
Control camera actions on a paired device.
|
||||
|
||||
#### MES_CAMERA_ID
|
||||
|
||||
* `MES_CAMERA_EVT_LAUNCH_PHOTO_MODE`: Turn on or set the camera to _photo_ mode.
|
||||
* `MES_CAMERA_EVT_LAUNCH_VIDEO_MODE`: Turn on or set the camera to _video_ mode.
|
||||
* `MES_CAMERA_EVT_TAKE_PHOTO`: Capture the picture in the camera view.
|
||||
* `MES_CAMERA_EVT_START_VIDEO_CAPTURE`: Begin capturing video (start record)
|
||||
* `MES_CAMERA_EVT_STOP_VIDEO_CAPTURE`: End capturing video (stop record)
|
||||
* `MES_CAMERA_EVT_STOP_PHOTO_MODE`: Stop photo mode and return to the default mode
|
||||
* `MES_CAMERA_EVT_STOP_VIDEO_MODE`: Stop video mode and return to the default mode
|
||||
* `MES_CAMERA_EVT_TOGGLE_FRONT_REAR`: Switch from the front camera to rear camera or rear to front
|
||||
|
||||
### Alerts
|
||||
|
||||
Trigger standard alert notifications on a device.
|
||||
|
||||
#### MES_ALERTS_ID
|
||||
|
||||
* `MES_ALERT_EVT_DISPLAY_TOAST`
|
||||
* `MES_ALERT_EVT_VIBRATE`
|
||||
* `MES_ALERT_EVT_PLAY_SOUND`
|
||||
* `MES_ALERT_EVT_PLAY_RINGTONE`
|
||||
* `MES_ALERT_EVT_FIND_MY_PHONE`
|
||||
* `MES_ALERT_EVT_ALARM1`
|
||||
* `MES_ALERT_EVT_ALARM2`
|
||||
* `MES_ALERT_EVT_ALARM3`
|
||||
* `MES_ALERT_EVT_ALARM4`
|
||||
* `MES_ALERT_EVT_ALARM5`
|
||||
* `MES_ALERT_EVT_ALARM6`
|
||||
|
||||
## Received events
|
||||
|
||||
Events are received by the @boardname@ from a paired device. You capture these in an [on event](/reference/control/on-event) function.
|
||||
|
||||
```typescript-ignore
|
||||
control.onEvent(EventBusSource.MES_DEVICE_INFO_ID, EventBusValue.MES_DEVICE_INCOMING_CALL, () => {
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
### Carrier signal strength
|
||||
|
||||
Signal strength to the subscribed carrier service.
|
||||
|
||||
#### MES_SIGNAL_STRENGTH_ID
|
||||
|
||||
* `MES_SIGNAL_STRENGTH_EVT_NO_BAR`: No service available or very low signal strength
|
||||
* `MES_SIGNAL_STRENGTH_EVT_ONE_BAR`: Low signal strength
|
||||
* `MES_SIGNAL_STRENGTH_EVT_TWO_BAR`: Medium signal strength
|
||||
* `MES_SIGNAL_STRENGTH_EVT_THREE_BAR`: High signal strength
|
||||
* `MES_SIGNAL_STRENGTH_EVT_FOUR_BAR`: Full signal strength
|
||||
|
||||
### Device information
|
||||
|
||||
Information about the current status of the device
|
||||
|
||||
#### MES_DEVICE_INFO_ID
|
||||
|
||||
* `MES_DEVICE_ORIENTATION_LANDSCAPE`: Display orientation is now in landscape
|
||||
* `MES_DEVICE_ORIENTATION_PORTRAIT`: Display orientation is now in portrait
|
||||
* `MES_DEVICE_GESTURE_NONE`: No gesture detected for device activation
|
||||
* `MES_DEVICE_GESTURE_DEVICE_SHAKEN`: The device was shaken
|
||||
* `MES_DEVICE_DISPLAY_OFF`: Device display is now turned off
|
||||
* `MES_DEVICE_DISPLAY_ON`: Device display is now turned on
|
||||
* `MES_DEVICE_INCOMING_CALL`: Currently receiving an incoming call
|
||||
* `MES_DEVICE_INCOMING_MESSAGE`: A message was received (SMS or other messaging app)
|
||||
|
||||
### Game pad controller
|
||||
|
||||
Button events from a paired game pad.
|
||||
|
||||
#### MES_DPAD_CONTROLLER_ID
|
||||
|
||||
* `MES_DPAD_BUTTON_A_DOWN`: Button **A** pressed
|
||||
* `MES_DPAD_BUTTON_A_UP`: Button **A** released
|
||||
* `MES_DPAD_BUTTON_B_DOWN`: Button **B** pressed
|
||||
* `MES_DPAD_BUTTON_B_UP`: Button **B** released
|
||||
* `MES_DPAD_BUTTON_C_DOWN`: Button **C** pressed
|
||||
* `MES_DPAD_BUTTON_C_UP`: Button **C** released
|
||||
* `MES_DPAD_BUTTON_D_DOWN`: Button **D** pressed
|
||||
* `MES_DPAD_BUTTON_D_UP`: Button **D** released
|
||||
* `MES_DPAD_BUTTON_1_DOWN`: Button **1** pressed
|
||||
* `MES_DPAD_BUTTON_1_UP`: Button **1** released
|
||||
* `MES_DPAD_BUTTON_2_DOWN`: Button **2** pressed
|
||||
* `MES_DPAD_BUTTON_2_UP`: Button **2** released
|
||||
* `MES_DPAD_BUTTON_3_DOWN`: Button **3** pressed
|
||||
* `MES_DPAD_BUTTON_3_UP`: Button **3** released
|
||||
* `MES_DPAD_BUTTON_4_DOWN`: Button **4** pressed
|
||||
* `MES_DPAD_BUTTON_4_UP`: Button **4** released
|
||||
|
||||
## See also
|
||||
|
||||
[raise event](/reference/control/raise-event), [on event](/reference/control/on-event),
|
||||
[event value](/reference/control/event-value)
|
64
docs/device/pins.md
Normal file
@ -0,0 +1,64 @@
|
||||
# micro:bit pins
|
||||
|
||||
The micro:bit pins
|
||||
|
||||
![](/static/mb/device/pins-0.png)
|
||||
|
||||
The micro:bit has 25 external connections on the edge connector of the board, which we refer to as ‘pins’. The edge connector is the grey area on the right side of the figure above.
|
||||
|
||||
There are five large pins, that are also connected to holes in the board labelled: 0, 1, 2, 3V, and GND. And along the same edge, there are 20 small pins that you can use when plugging the micro:bit into an edge connector.
|
||||
|
||||
## Large pins
|
||||
|
||||
You can easily attach crocodile clips or 4mm banana plugs to the five large pins.
|
||||
|
||||
The first three, labelled 0, 1 and 2 are flexible and can be used for many different things - which means they are often called ‘general purpose input and output’ (shortened to GPIO). These three pins also have the ability to read analogue voltages using something called an analogue-to-digital converter (ADC). They all have the same function:
|
||||
|
||||
* **0**: GPIO (general purpose digital input and output) with analogue to digital convertor (ADC).
|
||||
* **1**: GPIO with ADC
|
||||
* **2**: GPIO with ADC
|
||||
|
||||
The other two large pins (3V and GND) are very different!
|
||||
|
||||
## ~hint
|
||||
|
||||
Watch out! The pins labelled 3V and GND relate to the power supply of the board, and they should NEVER be connected together.
|
||||
For details on the power, current and voltage limitations of the board, see [Power Supply](https://tech.microbit.org/hardware/powersupply/)
|
||||
|
||||
## ~
|
||||
|
||||
*power input*: If the micro:bit is powered by USB or a battery, then you can use the 3V pin as a *power output* to power peripherals with.
|
||||
|
||||
* **3V**: *3 volt power output* or *power input*. (1) *power output*: If the micro:bit is powered by USB or a battery, then you can use the 3V pin as a power output to power peripherals with; (2) *power input*: If the micro:bit is not being powered by USB or battery, you can use the 3V pin as a power input to power the micro:bit
|
||||
* **GND**: attaches to ground in order to complete a circuit (required when using the 3V pin)
|
||||
|
||||
If you hold the ‘GND’ pin with one hand, you can program the microbit to detect yourself touching the 0,1 or 2 pins with your other hand, giving you three more buttons to experiment with (you just used your body to complete an electrical circuit).
|
||||
|
||||
## Small pins
|
||||
|
||||
There are 20 small pins numbered sequentially from 3-22 (these pins are not labeled on the micro:bit, however, they are labelled in the picture above).
|
||||
|
||||
Unlike the three large pins that are dedicated to being used for external connections, some of the small pins are shared with other components on the micro:bit board. For example, pin 3 is shared with some of the LEDs on the screen of the micro:bit, so if you are using the screen to scroll messages, you can’t use this pin as well.
|
||||
|
||||
* **pin 3**: GPIO shared with LED Col 1 of the LED screen; can be used for ADC and digital I/O when the LED screen is turned off.
|
||||
* **pin 4**: GPIO shared with LED Col 2 of the LED screen; can be used for ADC and digital I/O when the LED screen is turned off.
|
||||
* **pin 5**: GPIO shared with Button A. This lets you trigger or detect a button "A" click externally. This pin has a pull-up resistor, which means that by default it is at voltage of 3V. To replace button A on the micro:bit with an external button, connect one end of the external button to pin 5 and the other end to GND. When the button is pressed, the voltage on pin 5 is pulled down to 0, which generates a button click event.
|
||||
* **pin 6**: GPIO shared with LED Col 9 of the LED screen; can be used for digital I/O when the LED screen is turned off.
|
||||
* **pin 7**: GPIO shared with LED Col 8 of the LED screen; can be used for digital I/O when the LED screen is turned off.
|
||||
* **pin 8**: Dedicated GPIO, for sending and sensing digital signals.
|
||||
* **pin 9**: GPIO shared with LED Col 7 of the LED screen; can be used for digital I/O when the LED screen is turned off.
|
||||
* **pin 10**: GPIO shared with LED Col 3 of the LED screen; can be used for ADC and digital I/O when the LED screen is turned off.
|
||||
* **pin 11**: GPIO shared with Button B. This lets you trigger or detect a button “B” click externally.
|
||||
* **pin 12**: this GPIO pin has been reserved to provide support for accessibility.
|
||||
* **pin 13**: GPIO that is conventionally used for the serial clock (SCK) signal of the 3-wire Serial Peripheral Interface (SPI) bus.
|
||||
* **pin 14**: GPIO that is conventionally used for the Master In Slave Out (MISO) signal of the SPI bus.
|
||||
* **pin 15**: GPIO that is conventionally used for the Master Out Slave In (MOSI) signal of the SPI bus.
|
||||
* **pin 16**: Dedicated GPIO (conventionally also used for SPI ‘Chip Select’ function).
|
||||
* **pins 17 and 18**: these pins are wired to the 3V supply, like the large ‘3V’ pad.
|
||||
* **pins 19 and 20**: implement the clock signal (SCL) and data line (SDA) of the I2C bus communication protocol. With I2C, several devices can be connected on the same bus and send/read messages to and from the CPU. Internally, the accelerometer and the compass are connected to i2c.
|
||||
* **pins 21 and 22**: these pins are wired to the GND pin and serve no other function
|
||||
|
||||
## Connecting to the small pins
|
||||
|
||||
It is recommended that an edge connector be acquired to connect to the small pins. More information on compatible edge connectors will be available later.
|
||||
|
172
docs/device/reactive.md
Normal file
@ -0,0 +1,172 @@
|
||||
# The micro:bit - a reactive system
|
||||
|
||||
## Computing systems
|
||||
|
||||
What sort of a *computing system* is the micro:bit?
|
||||
|
||||
## ~hint
|
||||
|
||||
There are different types of computing systems, to address different kinds of problems that arise in practice: *transaction processing systems* are used by banks to handle huge numbers of financial transactions by their customers; *distributed systems* make a set of networked computers appear as one big computer (like Google’s search engine); there are also *parallel systems*, such as graphic cards, which perform a huge number of primitive operations simultaneously, using a great number of small processing cores.
|
||||
|
||||
## ~
|
||||
|
||||
The micro:bit is a *reactive system* – it reacts continuously to external events, such as a person pressing the **A** button of the micro:bit or shaking the device. The reaction to an event may be to perform a computation, update variables, and change the display. After the device reacts to an event, it is ready to react to the next one. If this sounds like a computer game, that’s because most computer games are reactive systems too!
|
||||
|
||||
## Responsiveness
|
||||
|
||||
We want reactive systems to be responsive, which means to react in a timely manner to events. For example, when you play a computer game, it’s frustrating if you press a button to make a character jump, but it doesn’t immediately jump. A delay in reacting, or lack of responsiveness, can be the difference between life and death, both in the real and virtual worlds.
|
||||
|
||||
Let’s consider a simple example: you want to program your micro:bit to accurately count the number of times the **A** button has been pressed and continuously display the current count on the 5x5 [LED screen](/device/screen). Because the LED screen is small, we can only display one digit of a number at a time on it. The [show number](/reference/basic/show-number) function will scroll the digits of a number across the screen so you can read it.
|
||||
|
||||
Let’s say that the current count is 42 and the number 42 is scrolling across the LED screen. This means there is some code executing to perform the scroll. So, what should happen if you press the **A** button during the scroll? It would be a bad idea to ignore the button press, so some code should record the occurrence of the button press. But we just said there already is code running in order to scroll the number 42! If we wait until the code scrolling the 42 has finished to look for a button press, we will miss the button press. We want to avoid this sort of unresponsiveness.
|
||||
|
||||
## Concurrency
|
||||
|
||||
To be responsive, a reactive system needs to be able to do several things at the same time (concurrently), just like you can. But the micro:bit only has one CPU for executing your program, which means it can only execute one program instruction at a time. It can, however, execute millions of instructions in a single second. This points the way to a solution.
|
||||
|
||||
Think about how a motion picture projector works - it projects only 24 frames per second, yet this is good enough to provide the illusion of fluid motion on the screen. The micro:bit can execute millions of instructions per second, so it seems quite possible for the device to both to smoothly scroll the number 42 across the LED screen while looking for button presses and counting them.
|
||||
|
||||
Let’s think about three sequences of instructions:
|
||||
|
||||
* Sequence **S1**: contains the instructions (let’s say several hundred thousand or so) that scroll the number 42 across the LED screen.
|
||||
* Sequence **S2**: contains a few instructions to check if button **A** is pressed.
|
||||
* Sequence **S3**: contains a few instructions to increment a counter.
|
||||
|
||||
In order to be responsive, we would like to *interrupt* the execution of sequence **S1** *periodically* to execute the sequence **S2**, which will check if button **A** is pressed, which looks like:
|
||||
|
||||
![Execution sequence diagram: S1 and S2](/static/mb/device/reactive-0.png)
|
||||
|
||||
The result is that it takes sequence **S1** a little longer to complete, due to the interruptions to execute sequence **S2**, but we are checking often enough to detect a press of button **A** . When **S2** detects a press of button **A**, then the sequence **S3** can be executed before **S1** resumes:
|
||||
|
||||
![Execution sequence diagram: S1 and S2 with interrupt and one S3 slice](/static/mb/device/reactive-1.png)
|
||||
|
||||
As we’ll soon see, there are other choices for how the sequences can be ordered to achieve the desired result.
|
||||
|
||||
## The micro:bit scheduler and queuing up subprograms
|
||||
|
||||
The micro:bit’s *scheduler* provides the capability to concurrently execute different code sequences, relieving us of a lot of low-level programming. In fact, scheduling is so useful that it is a part of every *operating system*!
|
||||
|
||||
The first job of the scheduler is to allow multiple *subprograms* to be queued up for later execution. For our purposes, a subprogram is just a statement or sequence of statements in the context of a larger program. Consider the program below for counting button presses.
|
||||
|
||||
```typescript
|
||||
let count = 0
|
||||
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
count++;
|
||||
})
|
||||
|
||||
basic.forever(() => {
|
||||
basic.showNumber(count)
|
||||
})
|
||||
```
|
||||
|
||||
The program above contains three statements that execute in order from top to bottom.
|
||||
The first statement initializes the global variable `count` to zero.
|
||||
|
||||
```typescript
|
||||
// statement 1
|
||||
let count = 0
|
||||
```
|
||||
|
||||
The second statement informs the scheduler that on each and every event of the **A** button being pressed, a subprogram (called the event handler) should be queued for execution. The event handler code is contained within the braces `{...}`; it increments the global variable `count` by one.
|
||||
|
||||
```typescript
|
||||
// statement 1
|
||||
let count = 0
|
||||
// statement 2
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
count++;
|
||||
})
|
||||
```
|
||||
|
||||
The third statement queues a `forever` loop for later execution by the scheduler; the body of this loop (also inside the braces `{...}`) displays the current value of global variable `count` on the LED screen.
|
||||
|
||||
```typescript
|
||||
// statement 1
|
||||
let count = 0
|
||||
// statement 2
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
count++;
|
||||
})
|
||||
// statement 3
|
||||
basic.forever(() => {
|
||||
basic.showNumber(count)
|
||||
})
|
||||
```
|
||||
|
||||
There are no more statements after the execution of these three statements, but this is not the end of program execution! That’s because the program queued the `forever` loop for execution by the scheduler (and registered an event handler for presses of button A).
|
||||
|
||||
The second job of the scheduler is to periodically interrupt execution to read (poll) the various inputs to the micro:bit (the buttons, pins, etc.) and fire off events (such as “button A pressed”). Recall that the firing of an event causes the event handler subprogram associated with that event to be queued for later execution. The scheduler uses a timer built into the micro:bit hardware to interrupt execution every 6 milliseconds and poll the inputs, which is more than fast enough to catch the quickest press of a button.
|
||||
|
||||
## Cooperative passing of control
|
||||
|
||||
How does the `forever` loop get to start execution? Furthermore, once the `forever` loop is running, how does any other subprogram (like the event handler that increments the count) ever get a chance to execute?
|
||||
|
||||
The answer is “cooperation” and “passing”. Think of a football team doing a drill – there is one ball and each footballer gets to dribble the ball for a certain number of touches, after which they pass to another footballer. A footballer who never passes prevents all other footballers from dribbling. A cooperative footballer always passes to some other footballer after taking a few touches.
|
||||
|
||||
If you hadn’t guessed already, a footballer represents subprogram and dribbling the ball corresponds to that subprogram executing. Only one subprogram gets to execute at a time, as there is only one ball (processor). Footballer Alice passing the ball to footballer Bob corresponds to stopping execution of Alice’s subprogram (and remembering where it stopped) and starting/resuming execution of Bob’s subprogram.
|
||||
|
||||
We will call this “passing control of execution” rather than “passing the ball”. However, in the world of the micro:bit, the concurrently executing subprograms are not aware of each other, so they don’t actually pass control directly to one another. Rather they pass control of execution back to the scheduler and the scheduler determines the subprogram to pass control to next. The programmer inserts a call to the `pause` function to indicate a point in the subprogram where control of execution passes to the scheduler. Also, when a subprogram ends execution, control passes to the scheduler.
|
||||
|
||||
Let’s take a look at the implementation of the `basic.forever` function to see an example of cooperative scheduling:
|
||||
|
||||
```typescript
|
||||
function forever_(body: () => void) {
|
||||
control.inBackground(() => {
|
||||
while(true) {
|
||||
body()
|
||||
basic.pause(20)
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
The `forever` loop actually is a function that takes a subprogram (another function) as a parameter. The function uses the `control.inBackground` function of the micro:bit runtime to queue a `while true` loop for execution by the scheduler. The while loop has two statements. The first statement runs the subprogram represented by the `body` parameter. The second statement passes control to the scheduler (requesting to “sleep” for 20 milliseconds).
|
||||
|
||||
Though the `while true` loop will repeatedly execute the body subprogram, between each execution of the body it will permit the scheduler to execute other subprograms. If the while loop did not contain the call to `pause`, then once control passed into the while loop, it would never pass back to the scheduler and no other subprogram would be able to execute (unless the body subprogram contained a call to `pause` itself).
|
||||
|
||||
## Round-robin scheduling
|
||||
|
||||
Now, we come to the third and final job of the scheduler, which is to determine which subprogram to pass control to next. The scheduler uses two queues to perform this task, the sleep queue and the run queue. The sleep queue contains the subprograms that have called the pause function and still have time left to sleep. The run queue contains all the non-sleeping subprograms, such as the event handlers queued by the firing of an event.
|
||||
|
||||
The scheduler moves the subprogram that has just paused into the sleep queue and then removes the subprogram at the head of the run queue and resumes its execution. Once a subprogram’s sleep period is over, the scheduler moves it from the sleep queue to the back of the run queue.
|
||||
|
||||
The property of such round-robin scheduling is that under the assumption that every subprogram periodically enters the sleep queue, then every subprogram will periodically get a chance to execute.
|
||||
|
||||
## Putting it all together
|
||||
|
||||
Let’s go back to the `count button presses` program and revisit its execution based on what we have learned about the micro:bit scheduler. As detailed before, the program executes three steps to:
|
||||
|
||||
1. Initialize the global variable `count` to zero
|
||||
2. Set up the event handler for each press of button **A**
|
||||
3. Queue the forever loop to the run queue
|
||||
|
||||
The program then ends execution and control passes back to the scheduler. Let’s assume the user has not pressed any buttons . The scheduler finds the `forever` loop in the run queue and passes control to it. The loop first calls `basic.showNumber(0)`. In the diagram below, we use “Show 0” to refer to the execution of this function:
|
||||
|
||||
![Execution sequence diagram: display loop with increment and interrupt](/static/mb/device/reactive-3.png)
|
||||
|
||||
|
||||
While "Show 0" (the blue sequence) is running, periodic interrupts by the scheduler (every 6 milliseconds) poll for button presses and queue an event handler for each press of button **A**. Let’s say that one button press takes place during this time, as shown above. This will cause an event handler (labelled “inc”) to be queued for later execution by the scheduler. Once the "Show 0" has completed, the loop then calls `basic.pause(20)` to put the forever loop to sleep for 20 milliseconds and give the scheduler an opportunity to run any newly queued event handler. Control passes to the “inc” event handler which will increment the global variable `count` from 0 to 1 and then complete, returning control to the scheduler. At some point, the `forever` loop moves from the sleep queue to the run queue; the `forever` loop then will resume and call `basic.showNumber(1)`.
|
||||
|
||||
## Final thoughts
|
||||
|
||||
Through this example, we have seen that the micro:bit scheduler enables you to create a program that is composed of concurrent subprograms. In essence, the programmer needs to only think about the concurrent subprograms cooperatively passing control back to the scheduler, making sure no subprogram hogs control (or “dribbles the ball without passing”) for too long. While a subprogram runs, the scheduler polls the buttons and other IO peripherals at a high frequency in order to fire off events and queue event handlers for later execution, but this is invisible to the programmer.
|
||||
|
||||
As a result, you can easily add a new capability to the micro:bit by just adding a new subprogram. For example, if you want to add a reset feature to the counter program, all you need to do is add a new event handler for a press of button **B** that sets the global variable "count" to zero, as shown below:
|
||||
|
||||
```typescript
|
||||
let count = 0
|
||||
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
count = count + 1
|
||||
})
|
||||
|
||||
basic.forever(() => {
|
||||
basic.showNumber(count)
|
||||
})
|
||||
|
||||
input.onButtonEvent(Button.B, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
count = 0
|
||||
})
|
||||
```
|
||||
|
97
docs/device/screen.md
Normal file
@ -0,0 +1,97 @@
|
||||
# LED screen
|
||||
|
||||
```sim
|
||||
basic.showLeds(`
|
||||
# . # . #
|
||||
. # . # .
|
||||
# . # . #
|
||||
. # . # .
|
||||
# . # . #
|
||||
`);
|
||||
```
|
||||
|
||||
The micro:bit LED screen has 25 red LED lights arranged in a 5X5 grid (5 LEDs across by 5 LEDs down).
|
||||
In the screen above, we created a checkerboard pattern using the LEDs.
|
||||
|
||||
## Which LED?
|
||||
|
||||
You use `(x ,y)` coordinates to specify a particular LED in the grid;
|
||||
where `x` is the horizontal position (0,1,2,3,4) and `y` is the vertical position
|
||||
(0, 1, 2, 3, 4).
|
||||
|
||||
To figure out the ``x``, ``y`` coordinates, position your micro:bit horizontally, like a credit card (see picture above).
|
||||
|
||||
Here are the x, y coordinates for the LEDs in the 5X5 grid:
|
||||
|
||||
`(0,0)` `(1,0)` `(2,0)` `(3,0)` `(4,0)`
|
||||
|
||||
`(0,1)` `(1,1)` `(2,1)` `(3,1)` `(4,1)`
|
||||
|
||||
`(0,2)` `(1,2)` `(2,2)` `(3,2)` `(4,2)`
|
||||
|
||||
`(0,3)` `(1,3)` `(2,3)` `(3,3)` `(4,3)`
|
||||
|
||||
`(0,4)` `(1,4)` `(2,4)` `(3,4)` `(4,4)`
|
||||
|
||||
The x, y coordinates for the LED in the center of the grid are `(2,2)`. Starting from `(0,0)` count over 2 columns and then down 2 rows.
|
||||
|
||||
## Check your understanding
|
||||
|
||||
Which LEDs are turned on in the checkboard pattern above?
|
||||
|
||||
## Row, column - 1
|
||||
|
||||
Since the row and column numbers start at 0, an easy way to figure out the (x,y) coordinates
|
||||
is to subtract 1 from the row and column number (when counting from 1).
|
||||
In other words, to specify the LED in the 4th column 5th row, subtract 1 from each number to get coordinates `(3,4)`.
|
||||
|
||||
## Turn a LED on/off
|
||||
|
||||
Use [plot](/reference/led/plot) and [unplot](/reference/led/unplot) to turn a LED on or off
|
||||
|
||||
```blocks
|
||||
led.plot(0,0);
|
||||
led.plot(1,1);
|
||||
basic.pause(1000);
|
||||
led.unplot(0,0);
|
||||
basic.pause(1000);
|
||||
led.unplot(1,1);
|
||||
```
|
||||
|
||||
## Is a LED on/off?
|
||||
|
||||
Use the [point](/reference/led/point) function to find out if a LED is on or off.
|
||||
|
||||
```blocks
|
||||
if(led.point(0,0)) {
|
||||
}
|
||||
```
|
||||
|
||||
## Display images, strings and numbers
|
||||
|
||||
Instead of turning individual LEDs on or off, as above, you can display an [image](/reference/images/image) directly to the screen or show text and numbers on screen using the [show number](/reference/basic/show-number) and [show string](/reference/basic/show-string) functions.
|
||||
|
||||
## The display buffer
|
||||
|
||||
The micro:bit runtime keeps a representation of the state of all 25 LEDS in memory. This state is known as the "display buffer" and controls which LEDs are on and which are off. The plot, unplot, and point functions access the display buffer directly. On the other hand, the functions that show an image, number, or string overwrite the buffer completely. To illustrate this, first try running this code sequence
|
||||
|
||||
```blocks
|
||||
basic.showString("d")
|
||||
led.plot(0, 0)
|
||||
```
|
||||
|
||||
You will see the letter "d" displayed as well as the LED in position `0,0` lit up. Now try reversing the order of the two statements above:
|
||||
|
||||
```blocks
|
||||
led.plot(0, 0)
|
||||
basic.showString("d")
|
||||
```
|
||||
|
||||
You will not see the LED at position `0,0` lit up because the `show string` function overwrites the whole display buffer.
|
||||
|
||||
## Pins: P3, P4, P6, P7, P9, P10
|
||||
|
||||
These pins are coupled to the LED matrix display and also to the display's associated ambient light sensing mode.
|
||||
To disable the display driver feature (which will automatically disable the light sensing feature) use the function [led.enable](/reference/led/enable).
|
||||
|
||||
More information at http://tech.microbit.org/hardware/edgeconnector_ds/ .
|
81
docs/device/serial.md
Normal file
@ -0,0 +1,81 @@
|
||||
# Serial
|
||||
|
||||
The [serial](/reference/serial) supports [serial communication](https://en.wikipedia.org/wiki/Serial_port) between the BBC micro:bit and another computer. Basically, this allows you to send data from the micro:bit to your own computer. This is very useful for debugging purposes: you can add `write line` statements in your code and see them display on your computer as the program executes.
|
||||
|
||||
The code below shows a simple script that sends a line when the BBC micro:bit starts and another line each time the button ``A`` is pressed.
|
||||
|
||||
```blocks
|
||||
serial.writeLine("started...")
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
serial.writeLine("A pressed")
|
||||
})
|
||||
```
|
||||
|
||||
Data is also automatically streamed to serial by the ** bar graph** block
|
||||
and picked up by the editor. This data can be streamed to the cloud as well.
|
||||
|
||||
```blocks
|
||||
basic.forever(() => {
|
||||
led.plotBarGraph(input.acceleration(Dimension.X), 0);
|
||||
});
|
||||
```
|
||||
|
||||
## How to read the micro:bit's serial output from your computer
|
||||
|
||||
Unfortunately, using the serial library requires quite a bit of a setup.
|
||||
|
||||
### ~ hint
|
||||
|
||||
**Windows earlier than 10**
|
||||
|
||||
If you are running a Windows version earlier than 10, you must [install a device driver](https://os.mbed.com/docs/latest/tutorials/windows-serial-driver.html) (for the computer to recognize the serial interface of the micro:bit).
|
||||
|
||||
## ~
|
||||
Also, if you don't see the serial port as one of your computer's devices, you might need to [update the firmware](/device/firmware) on the @boardname@. Find the device name for the attached serial port in the following instructions for your operating system.
|
||||
|
||||
### Windows > Tera Term
|
||||
|
||||
* Install the terminal emulator [Tera Term](https://ttssh2.osdn.jp/index.html.en). At the time of this writing, the latest version is 4.88 and can be downloaded [from here](http://en.osdn.jp/frs/redir.php?m=jaist&f=%2Fttssh2%2F63767%2Fteraterm-4.88.exe). Follow the instructions from the installer.
|
||||
|
||||
Once both the driver and the terminal emulator are installed, plug in the micro:bit and wait until the device is fully setup. Then, open TeraTerm.
|
||||
|
||||
* Hit `File` > `New Connection`
|
||||
* Check "Serial"; in the dropdown menu, pick the COM port that says "mbed Serial Port". Hit `Ok`.
|
||||
* In the menus, hit `Setup` > `Serial Port` and set the baud rate to `115200`.
|
||||
|
||||
You should be good. Feel free to hit `Setup` > `Save Setup` in the menus to erase the default configuration file with a new one so that you don't have to type in the settings again.
|
||||
|
||||
Please note that Windows will assign you a different COM port if you plug in another micro:bit. If you're juggling between micro:bits, you'll have to change the COM port every time.
|
||||
|
||||
### Windows > Putty
|
||||
|
||||
If you prefer another terminal emulator (such as [PuTTY](http://www.putty.org/)), here are some instructions.
|
||||
|
||||
* Open Windows's [Device Manager](https://windows.microsoft.com/en-us/windows/open-device-manager); expand the section called "Ports (COM & LPT)"; write down the com number for "mbed Serial Port" (e.g. COM14)
|
||||
* Open PuTTY; on the main screen, use the following settings: Serial / COM14 / 115200. Replace COM14 with the COM port number you wrote down previously. Feel free to type in a name and hit "Save" to remember this configuration.
|
||||
|
||||
![](/static/mb/serial-library-0.png)
|
||||
|
||||
* (optional): in the "Terminal" section, check "implicit cr in every lf"
|
||||
|
||||
![](/static/mb/serial-library-1.png)
|
||||
|
||||
## Linux
|
||||
|
||||
* Install the program `screen` if it is not already installed.
|
||||
* Plug in the micro:bit.
|
||||
* Open a terminal.
|
||||
* Find which device node the micro:bit was assigned to with the command `ls /dev/ttyACM*`.
|
||||
* If it was `/dev/ttyACM0`, type the command `screen /dev/ttyACM0 115200`. If it was some other device node,
|
||||
use that one in the command instead. **Note:** You may need root access to run `screen`
|
||||
successfully. You can probably use the command `sudo` like this: `sudo screen /dev/ttyACM0 115200`.
|
||||
* To exit `screen`, type `Ctrl-A` `Ctrl-D`.
|
||||
|
||||
Alternative programs include `minicom` and so on.
|
||||
|
||||
## Mac OS
|
||||
|
||||
* Plug in the micro:bit
|
||||
* Open a terminal
|
||||
* `ls /dev/cu.*` will return to you a list of serial devices; one of them will look like `/dev/cu.usbmodem1422` (the exact number depends on your computer)
|
||||
* `screen /dev/cu.usbmodem1422 115200` will open up the micro:bit's serial output. To exit, hit `Ctrl-A` `Ctrl-D`.
|
144
docs/device/servo.md
Normal file
@ -0,0 +1,144 @@
|
||||
# Equipping a microservo with Crocodile clips
|
||||
|
||||
## ~ hint
|
||||
|
||||
If you are conducting a class or group activity, you should consider preparing all servos ahead of time.
|
||||
|
||||
## ~
|
||||
|
||||
## Using a microservo with the @boardname@
|
||||
|
||||
The @boardname@ provides just enough current to operate the SG90 microservo. This servo requires 3 connections: **GND**, **3V** and a logic **pin**. In this tutorial, we will equip the servo with crocodile clips to make it easier to use. However, you could also use a shield or crocodile clips with a male connector on one end to achieve the same result.
|
||||
|
||||
### ~ hint
|
||||
|
||||
To better understand how servos work and how they are controlled, take a few minutes to read this [Brief Guide to Servos](https://www.kitronik.co.uk/pdf/a-brief-guide-to-servos.pdf).
|
||||
|
||||
### ~
|
||||
|
||||
## The easy way: Alligator/Crocodile Clip to Male Jumpers #hintconnection
|
||||
|
||||
The easiest way to connect a servo to the @boardname@ is to use cables with an **Alligator/Crocodile clip** on one end
|
||||
and a **Male jumper (pig tail)** on the other end. You can purchase bundles these cables from various electronic resellers or easily build some as shown here.
|
||||
|
||||
https://youtu.be/XtzsydSTXEg
|
||||
|
||||
### Materials
|
||||
|
||||
* 1 Crocodile clip cable
|
||||
* 1 male (pig tail) cable
|
||||
* Cutting pliers or wire cutter
|
||||
* 1 piece of heat shrink tubing and a lighter
|
||||
|
||||
Simply cut the cables, strip them, twist the bare wires together, and cover the connection with some heat shrink tubing.
|
||||
|
||||
### ~ hint
|
||||
|
||||
It is very **important** to ensure a good connection between the 2 cables. If the connection is weak, the microservo will not receive enough current and it will not work. **If you have access to a soldering iron, we strongly recommend that you solder this connection.**
|
||||
|
||||
### ~
|
||||
|
||||
## Direct connection
|
||||
|
||||
You can also connect your crocodile clips directly to the servo.
|
||||
|
||||
### Materials
|
||||
|
||||
* Cutting pliers or wire cutter
|
||||
* Tape (masking, duct tape, and/or packing tape)
|
||||
* 3 crocodile clips, yellow, red and black.
|
||||
* 1 micro servo 9g (SG90)
|
||||
|
||||
### Step 1: Cut off the connector
|
||||
|
||||
With the cutting pliers, cut off the dark plastic connector.
|
||||
|
||||
![Cutting of the plastic connector from the servo cable](/static/mb/projects/inchworm/servo1.jpg)
|
||||
|
||||
### Step 2: Strip the ends of the cables
|
||||
|
||||
Using the pliers or a wire stripper, strip the plastic insulation from the cables.
|
||||
|
||||
![Stripping the servo cable insulation](/static/mb/projects/inchworm/servotrim.jpg)
|
||||
|
||||
### Step 3: Twist the wire strands together
|
||||
|
||||
Twist the strands of bare wire at the ends of the servo cables together.
|
||||
|
||||
![Strands of the servo wires twisted together](/static/mb/projects/inchworm/servo3.jpg)
|
||||
|
||||
### Step 4: Crocodile clip
|
||||
|
||||
Cut a crocodile cable in two and strip off the insulation. If it's possible, try to use cables with colors that match the cables on the servo!
|
||||
|
||||
![Stripping insulation of a croc cable with cutting pliers](/static/mb/projects/inchworm/servo4.jpg)
|
||||
|
||||
### Step 5: Thread the cable ends together
|
||||
|
||||
Place the cables next to each other...
|
||||
|
||||
![Bare wires place together before threading](/static/mb/projects/inchworm/servo5.jpg)
|
||||
|
||||
... and thread them together.
|
||||
|
||||
![Bare wires threaded together](/static/mb/projects/inchworm/servo6.jpg)
|
||||
|
||||
### ~ hint
|
||||
|
||||
It is very **important** to ensure that there is a good connection between the 2 cables. If the connection is weak, the microservo will not receive enough current and it will not work. **If you have access to a soldering iron, we strongly recommend soldering this connection.**
|
||||
|
||||
### ~
|
||||
|
||||
### Step 6: Protect the connection
|
||||
|
||||
Protect the connection with heat shrink tubing, electrical tape, or duct tape.
|
||||
|
||||
![Wire connection protected with electrical tape](/static/mb/projects/inchworm/servo7.jpg)
|
||||
|
||||
### Step 7: Repeat for all cables
|
||||
|
||||
Repeat the same process until all cables are connected.
|
||||
|
||||
![All three cables connected and taped](/static/mb/projects/inchworm/servo8.jpg)
|
||||
|
||||
### Step 8: Testing!
|
||||
|
||||
It's time to test and find out if your connections are all secure and that the servo will function **when the @boardname@ is powered by battery**.
|
||||
|
||||
* Connect the microservo cables to these pins on the @boardname@: black to **GND**, red to **3V**, and the remaining cable to pin **0**.
|
||||
|
||||
![Connect to the pins on the board](/static/mb/projects/inchworm/circuit1.jpg)
|
||||
|
||||
## ~ hint
|
||||
|
||||
When attaching the crocodile clips to the pins, don't be afraid to clamp on to the edge of the board with the clips.
|
||||
|
||||
![Clippiing the cables to the edge of the board](/static/mb/projects/inchworm/circuit2.jpg)
|
||||
|
||||
## ~
|
||||
|
||||
* Download the following code to your @boardname@.
|
||||
|
||||
```blocks
|
||||
basic.forever(() => {
|
||||
pins.servoWritePin(AnalogPin.P0, pins.map(
|
||||
input.acceleration(Dimension.X),
|
||||
-512,
|
||||
512,
|
||||
0,
|
||||
180
|
||||
))
|
||||
})
|
||||
```
|
||||
|
||||
* Test with both power sources and make sure that the servo moves when you tilt the board:
|
||||
>* Connected with USB.
|
||||
>* Powered by batteries **only** and not connected with USB.
|
||||
|
||||
## Calibrating
|
||||
|
||||
Use the [servo calibrator](/projects/servo-calibrator) program to determine the best angles to use for your make.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If your servo seems to stutter and remain stuck at a particular position, it means that it's not receiving enough power. This is probably due to a weak connection or low battery level. Make sure that each connection is good and check your batteries.
|
25
docs/device/simulator.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Simulator
|
||||
|
||||
The JavaScript simulator allows you to test and execute most BBC micro:bit programs in the browser.
|
||||
It allows you to emulate sensor data or user interactions.
|
||||
|
||||
```sim
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Click), () => {
|
||||
basic.showString("A");
|
||||
});
|
||||
input.onButtonEvent(Button.B, input.buttonEventValue(ButtonEvent.Click), () => {
|
||||
basic.showString("B");
|
||||
});
|
||||
input.onPinTouchEvent(TouchPin.P0, input.buttonEventValue(ButtonEvent.Click), () => {
|
||||
basic.showString("0");
|
||||
});
|
||||
input.onPinTouchEvent(TouchPin.P1, input.buttonEventValue(ButtonEvent.Click), () => {
|
||||
basic.showString("1");
|
||||
});
|
||||
input.onPinTouchEvent(TouchPin.P2, input.buttonEventValue(ButtonEvent.Click), () => {
|
||||
basic.showString("2");
|
||||
});
|
||||
input.temperature()
|
||||
input.compassHeading()
|
||||
input.lightLevel()
|
||||
```
|
36
docs/device/usb.md
Normal file
@ -0,0 +1,36 @@
|
||||
# Uploading programs to your @boardname@
|
||||
|
||||
Most of the time you'll be writing and testing your programs in the [simulator](/device/simulator). Once you've finished your program though, you can **compile** it and run it on your @boardname@. Transferring your program to the @boardname@ is as simple as saving a file to a drive on your computer.
|
||||
|
||||
When you plug your @boardname@ into USB, a new drive is created with the **@drivename@** label. This is where you'll save your program.
|
||||
|
||||
![](/static/mb/device/usb-thin.jpg)
|
||||
|
||||
The basic steps are:
|
||||
|
||||
1. Connect your @boardname@ to your computer with a USB cable.
|
||||
2. Click **Download** to download the `.hex` file.
|
||||
3. Move the `.hex` file from your computer onto the **@drivename@** drive. The next section has instructions for the browser that you're using.
|
||||
|
||||
## How to transfer the program with your browser
|
||||
|
||||
Here are instructions for different browsers on Windows and Mac computers. Choose the one you're using:
|
||||
|
||||
### Windows browsers
|
||||
|
||||
* [Microsoft Edge](/device/usb/windows-edge)
|
||||
* [Internet Explorer](/device/usb/windows-ie)
|
||||
* [Chrome](/device/usb/windows-chrome)
|
||||
* [Firefox](/device/usb/windows-firefox)
|
||||
|
||||
### Mac browsers
|
||||
|
||||
* [Safari](/device/usb/mac-safari)
|
||||
* [Chrome](/device/usb/mac-chrome)
|
||||
* [Firefox](/device/usb/mac-firefox)
|
||||
|
||||
## ~hint
|
||||
|
||||
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshoot).
|
||||
|
||||
## ~
|
69
docs/device/usb/mac-chrome.md
Normal file
@ -0,0 +1,69 @@
|
||||
# Uploading from Chrome for Mac
|
||||
|
||||
While you're writing and testing your programs, you'll mostly be [running them
|
||||
in the simulator](/device/simulator), but once you've finished your program you
|
||||
can **compile** it and run it on your micro:bit.
|
||||
|
||||
The basic steps are:
|
||||
|
||||
1. Connect your micro:bit to your computer via USB
|
||||
2. Click **Download** and download the `.hex` file
|
||||
3. Copy the `.hex` file from your computer onto the micro:bit drive
|
||||
|
||||
## Requirements
|
||||
|
||||
You need the following things to transfer and run a script on your micro:bit:
|
||||
|
||||
* A-Male to Micro USB cable to connect your computer to your micro:bit. This is
|
||||
the same cable that is commonly used to connect a smart phone to a computer.
|
||||
* A PC running Windows 7 or later, or a Mac running OS X 10.6 or later
|
||||
|
||||
## Step 1: Connect your micro:bit to your computer
|
||||
|
||||
First, connect the micro:bit:
|
||||
|
||||
1. Connect the small end of the USB cable to the micro USB port on your micro:bit.
|
||||
|
||||
2. Connect the other end of the USB cable to a USB port on your computer.
|
||||
|
||||
Your computer should recognise your micro:bit as a new drive. On computers
|
||||
running Windows, `MICROBIT` appears as a drive under Devices and drives. On a Mac
|
||||
it appears as a new drive under Devices.
|
||||
|
||||
![](/static/mb/device/usb-osx-device.png)
|
||||
|
||||
## Step 2: Download your program
|
||||
|
||||
1. Open your project on @homeurl@
|
||||
2. Click **Download**
|
||||
3. When prompted, choose to **save** the compiled file onto your computer. The
|
||||
prompt will be different depending on which browser you are using, or
|
||||
whether you are using a Windows computer or a Mac
|
||||
|
||||
When you select **Download** in Chrome, the file will appear at the bottom of
|
||||
the browser. Click on the small arrow and select **Show in Finder**. This will
|
||||
show the file in your download folder. Drag and drop the file onto your
|
||||
`MICROBIT` drive.
|
||||
|
||||
![](/static/mb/device/usb-osx-chrome.png)
|
||||
|
||||
## Step 3: Transfer the file to your micro:bit
|
||||
|
||||
* Once you've found the folder containing your `.hex` file, drag and drop it
|
||||
onto your `MICROBIT` drive
|
||||
* The LED on the back of your micro:bit flashes during the transfer (which
|
||||
should only take a few seconds).
|
||||
* Once transferred, the code will run automatically on your micro:bit. To rerun
|
||||
your program, press the reset button on the back of your micro:bit. The reset
|
||||
button automatically runs the newest file on the micro:bit.
|
||||
|
||||
By copying the script onto the `MICROBIT` drive, you have programmed it into the
|
||||
flash memory on the micro:bit, which means even after you unplug the micro:bit,
|
||||
your program will still run if the micro:bit is powered by battery.
|
||||
|
||||
|
||||
## ~hint
|
||||
|
||||
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshoot).
|
||||
|
||||
## ~
|
71
docs/device/usb/mac-firefox.md
Normal file
@ -0,0 +1,71 @@
|
||||
# Uploading from Firefox for Mac
|
||||
|
||||
While you're writing and testing your programs, you'll mostly be [running them
|
||||
in the simulator](/device/simulator), but once you've finished your program you
|
||||
can **compile** it and run it on your micro:bit.
|
||||
|
||||
The basic steps are:
|
||||
|
||||
1. Connect your micro:bit to your computer via USB
|
||||
2. Click **Download** and download the `.hex` file
|
||||
3. Copy the `.hex` file from your computer onto the micro:bit drive
|
||||
|
||||
## Requirements
|
||||
|
||||
You need the following things to transfer and run a script on your micro:bit:
|
||||
|
||||
* A-Male to Micro USB cable to connect your computer to your micro:bit. This is
|
||||
the same cable that is commonly used to connect a smart phone to a computer.
|
||||
* A PC running Windows 7 or later, or a Mac running OS X 10.6 or later
|
||||
|
||||
## Step 1: Connect your micro:bit to your computer
|
||||
|
||||
First, connect the micro:bit:
|
||||
|
||||
1. Connect the small end of the USB cable to the micro USB port on your micro:bit.
|
||||
|
||||
2. Connect the other end of the USB cable to a USB port on your computer.
|
||||
|
||||
Your computer should recognise your micro:bit as a new drive. On computers
|
||||
running Windows, `MICROBIT` appears as a drive under Devices and drives. On a Mac
|
||||
it appears as a new drive under Devices.
|
||||
|
||||
![](/static/mb/device/usb-osx-device.png)
|
||||
|
||||
## Step 2: Download your program
|
||||
|
||||
1. Open your project on @homeurl@
|
||||
2. Click **Download**
|
||||
3. When prompted, choose to **save** the compiled file onto your computer. The
|
||||
prompt will be different depending on which browser you are using, or
|
||||
whether you are using a Windows computer or a Mac
|
||||
|
||||
A dialogue box will appear, asking whether you would like to open or save your
|
||||
hex file. Select **Save file** and click **OK** and the file will then appear in
|
||||
your downloads in the top right of your browser. Right click on the file and
|
||||
click on **Show in Finder** and the file will appear in your downloads folder.
|
||||
Select the file and drag and drop it onto your `MICROBIT` drive.
|
||||
|
||||
![](/static/mb/device/usb-osx-firefox-1.jpg)
|
||||
|
||||
![](/static/mb/device/usb-osx-firefox-2.png)
|
||||
|
||||
## Step 3: Transfer the file to your micro:bit
|
||||
|
||||
* Once you've found the folder containing your `.hex` file, drag and drop it
|
||||
onto your `MICROBIT` drive
|
||||
* The LED on the back of your micro:bit flashes during the transfer (which
|
||||
should only take a few seconds).
|
||||
* Once transferred, the code will run automatically on your micro:bit. To rerun
|
||||
your program, press the reset button on the back of your micro:bit. The reset
|
||||
button automatically runs the newest file on the micro:bit.
|
||||
|
||||
By copying the script onto the `MICROBIT` drive, you have programmed it into the
|
||||
flash memory on the micro:bit, which means even after you unplug the micro:bit,
|
||||
your program will still run if the micro:bit is powered by battery.
|
||||
|
||||
## ~hint
|
||||
|
||||
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshoot).
|
||||
|
||||
## ~
|
68
docs/device/usb/mac-safari.md
Normal file
@ -0,0 +1,68 @@
|
||||
# Uploading from Safari for Mac
|
||||
|
||||
While you're writing and testing your programs, you'll mostly be [running them
|
||||
in the simulator](/device/simulator), but once you've finished your program you
|
||||
can **compile** it and run it on your micro:bit.
|
||||
|
||||
The basic steps are:
|
||||
|
||||
1. Connect your micro:bit to your computer via USB
|
||||
2. Click **Download** and download the `.hex` file
|
||||
3. Copy the `.hex` file from your computer onto the micro:bit drive
|
||||
|
||||
## Requirements
|
||||
|
||||
You need the following things to transfer and run a script on your micro:bit:
|
||||
|
||||
* A-Male to Micro USB cable to connect your computer to your micro:bit. This is
|
||||
the same cable that is commonly used to connect a smart phone to a computer.
|
||||
* A PC running Windows 7 or later, or a Mac running OS X 10.6 or later
|
||||
|
||||
## Step 1: Connect your micro:bit to your computer
|
||||
|
||||
First, connect the micro:bit:
|
||||
|
||||
1. Connect the small end of the USB cable to the micro USB port on your micro:bit.
|
||||
|
||||
2. Connect the other end of the USB cable to a USB port on your computer.
|
||||
|
||||
Your computer should recognise your micro:bit as a new drive. On computers
|
||||
running Windows, `MICROBIT` appears as a drive under Devices and drives. On a Mac
|
||||
it appears as a new drive under Devices.
|
||||
|
||||
![](/static/mb/device/usb-osx-device.png)
|
||||
|
||||
## Step 2: Download your program
|
||||
|
||||
1. Open your project on @homeurl@
|
||||
2. Click **Download**
|
||||
3. When prompted, choose to **save** the compiled file onto your computer. The
|
||||
prompt will be different depending on which browser you are using, or
|
||||
whether you are using a Windows computer or a Mac
|
||||
|
||||
When you select **Download** in Safari a file called `Unknown` will be
|
||||
downloaded into your Downloads folder. Open your Downloads folder and drag and
|
||||
drop the file onto your `MICROBIT` drive, under Devices:
|
||||
|
||||
![](/static/mb/device/usb-osx-dnd.png)
|
||||
|
||||
## Step 3: Transfer the file to your micro:bit
|
||||
|
||||
* Once you've found the folder containing your `.hex` file, drag and drop it
|
||||
onto your `MICROBIT` drive
|
||||
* The LED on the back of your micro:bit flashes during the transfer (which
|
||||
should only take a few seconds).
|
||||
* Once transferred, the code will run automatically on your micro:bit. To rerun
|
||||
your program, press the reset button on the back of your micro:bit. The reset
|
||||
button automatically runs the newest file on the micro:bit.
|
||||
|
||||
By copying the script onto the `MICROBIT` drive, you have programmed it into the
|
||||
flash memory on the micro:bit, which means even after you unplug the micro:bit,
|
||||
your program will still run if the micro:bit is powered by battery.
|
||||
|
||||
|
||||
## ~hint
|
||||
|
||||
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshoot).
|
||||
|
||||
## ~
|
24
docs/device/usb/troubleshoot.md
Normal file
@ -0,0 +1,24 @@
|
||||
# Troubleshooting Transfer
|
||||
|
||||
You can’t drag and drop more than one hex file at once onto your micro:bit. If
|
||||
you try to drag and drop a second hex file onto your micro:bit before the first
|
||||
file has finished downloading, then the second file may fail in different ways.
|
||||
|
||||
When the first program has been written to the micro:bit, the drive will
|
||||
disengage. If you drag and drop a second file at this point it may not find the
|
||||
drive and the second write will fail.
|
||||
|
||||
The errors may look like this:
|
||||
|
||||
**Windows**
|
||||
|
||||
![](/static/mb/device/usb-windows-copy-file-error.jpg)
|
||||
|
||||
**Mac**
|
||||
|
||||
![](/static/mb/device/usb-osx-copy-file-error.png)
|
||||
|
||||
Or it may appear that there are two hex files on your micro:bit so the micro:bit
|
||||
won’t be able to run multiple files. To rectify this, unplug your micro:bit and
|
||||
plug it in again. Make sure that your micro:bit appears as `MICROBIT` and not
|
||||
`MAINTENANCE`.
|
44
docs/device/usb/webusb.md
Normal file
@ -0,0 +1,44 @@
|
||||
# WebUSB
|
||||
|
||||
[WebUSB](https://wicg.github.io/webusb/) is an emerging web standard that allows to access @boardname@ from web pages.
|
||||
It allows for a **one-click download** without installing any additional app or software! It also allows to receive data from the @boardname@.
|
||||
|
||||
## Support
|
||||
|
||||
* Chrome 79+ browser for Android, Chrome OS, Linux, macOS and Windows 10.
|
||||
* Microsoft Edge 79+ browser for Android, Chrome OS, Linux, macOS and Windows 10.
|
||||
|
||||
## Prepare your @boardname@
|
||||
|
||||
Make sure that your @boardname@ is running version **0249** or above of the firmware. Upgrading is as easy as dragging a file and it takes a few seconds to get it done.
|
||||
|
||||
* [Check out the instructions to check and upgrade your @boardname@.](/device/usb/webusb/troubleshoot)
|
||||
|
||||
## Pair your @boardname@
|
||||
|
||||
Here are the steps on the supported browsers:
|
||||
|
||||
* connect your @boardname@ to your computer with the microUSB cable
|
||||
* open a project
|
||||
* click the triple dot icon on the **Download** button and click **Pair device**
|
||||
* click on the **Pair device** button and select **Calliope mini** or **DAPLink CMSIS-DAP** from the list.
|
||||
|
||||
If you don't see any devices in the list and @boardname@ has the right firmware (**0249** or above), you can create a [support ticket](https://support.microbit.org/support/tickets/new) to notify the Micro:bit Foundation of the problem. Skip the rest of these steps.
|
||||
|
||||
## Unpair your @boardname@ #unpair
|
||||
|
||||
You will need to unpair your device from the editor to disable WebUSB.
|
||||
|
||||
* Click on the **lock** icon in the address bar
|
||||
* Uncheck each **Calliope mini** or **DAPLink CMSIS-DAP** device
|
||||
* Reload the page
|
||||
|
||||
![](/static/webusb/unpair.gif)
|
||||
|
||||
## One-click Download
|
||||
|
||||
Once your @boardname@ is paired, MakeCode will use WebUSB to transfer the code without having to drag and drop. Happy coding!
|
||||
|
||||
## Console output
|
||||
|
||||
MakeCode will be able to "listen" to your @boardname@ and display the console output.
|
69
docs/device/usb/webusb/troubleshoot.md
Normal file
@ -0,0 +1,69 @@
|
||||
# Troubleshooting downloads with WebUSB
|
||||
|
||||
### ~ avatar
|
||||
|
||||
Having issues pairing your @boardname@ with [WebUSB](/device/usb/webusb)? Let's try to figure out why!
|
||||
|
||||
### ~
|
||||
|
||||
## Step 1: Check your cable
|
||||
|
||||
Make sure that your @boardname@ is connected to your computer with a micro USB cable. You should see a **MICROBIT** drive appear in Windows Explorer when it's connected.
|
||||
|
||||
![MICROBIT drive](/static/mb/device/windows-microbit-drive.png)
|
||||
|
||||
**If you can see the MICROBIT drive go to step 2**.
|
||||
|
||||
If you can't see the drive:
|
||||
* Make sure that the USB cable is working.
|
||||
>Does the cable work on another computer? If not, find a different cable to use. Some cables may only provide a power connection and don't actually transfer data.
|
||||
* Try another USB port on your computer.
|
||||
|
||||
Is the cable good but you still can't see the **MICROBIT** drive? Hmm, you might have a problem with your @boardname@. Try the additional steps described in the [fault finding](https://support.microbit.org/support/solutions/articles/19000024000-fault-finding-with-a-micro-bit) page at microbit.org. If this doesn't help, you can create a [support ticket](https://support.microbit.org/support/tickets/new) to notify the Micro:bit Foundation of the problem. **Skip the rest of these steps**.
|
||||
|
||||
## Step 2: Check your firmware version
|
||||
|
||||
It's possible that the firmware version on the @boardname@ needs an update. Let's check:
|
||||
|
||||
1. Go to the **MICROBIT** drive.
|
||||
2. Open the **DETAILS.TXT** file.<br/>
|
||||
![](/static/mb/device/mb-drive-contents.jpg)<br/>
|
||||
3. Look for a line in the file that says the version number. It should say **Version: \.\.\.**
|
||||
![](/static/mb/device/details-txt.jpg)
|
||||
or **Interface Version: \.\.\.**
|
||||
![](/static/mb/device/details-243.png)
|
||||
<br/>
|
||||
|
||||
If the version is **0234**, **0241**, **0243** you **NEED** to update the [firmware](/device/firmware) on your @boardname@. Go to **Step 3** and follow the upgrade instructions.
|
||||
|
||||
If the version is **0249**, **0250** or higher, **you have the right firmware** go to step **4**.
|
||||
|
||||
## Step 3: Upgrade the firmware
|
||||
|
||||
1. Put your @boardname@ into **MAINTENANCE Mode**. To do this, unplug the USB cable from the @boardname@ and then re-connect the USB cable while you hold down the reset button. Once you insert the cable, you can release the reset button. You should now see a **MAINTENANCE** drive instead of the **MICROBIT** drive like before. Also, a yellow LED light will stay on next to the reset button.
|
||||
![MAINTENANCE gesture](/static/mb/device/maintenance.gif)
|
||||
2. **[Download the firmware .hex file](https://microbit.org/guide/firmware/)**
|
||||
3. Drag and drop that file onto the **MAINTENANCE** drive.
|
||||
4. The yellow LED will flash while the `HEX` file is copying. When the copy finishes, the LED will go off and the @boardname@ resets. The **MAINTENANCE** drive now changes back to **MICROBIT**.
|
||||
5. The upgrade is complete! You can open the **DETAILS.TXT** file to check and see that the firmware version changed to the match the version of the `HEX` file you copied.
|
||||
|
||||
### ~hint
|
||||
|
||||
If you want to know more about connecting the board, MAINTENANCE Mode, and upgrading the firmware, read about it in the [Firmware guide](https://microbit.org/guide/firmware/).
|
||||
|
||||
### ~
|
||||
|
||||
## Step 4: Check your browser version
|
||||
|
||||
WebUSB is a fairly new feature and may require you to update your browser. Check that your browser version matches one of these:
|
||||
|
||||
* Chrome 65+ for Android, Chrome OS, Linux, macOS and Windows 10.
|
||||
|
||||
|
||||
## Step 5: Pair device
|
||||
|
||||
Once you've updated the firmware, open the **Chrome Browser**, go to the editor and click on **Pair Device** in the gearwheel menu.
|
||||
See [WebUSB](/device/usb/webusb) for pairing instructions.
|
||||
|
||||
Enjoy fast downloads!
|
||||
|
92
docs/device/usb/windows-chrome.md
Normal file
@ -0,0 +1,92 @@
|
||||
# Uploading from Chrome for Windows
|
||||
|
||||
## ~ hint
|
||||
|
||||
Starting with Chrome 65 on Windows 10,
|
||||
you can use **WebUSB** to download with one-click.
|
||||
[Learn more about WebUSB...](/device/usb/webusb).
|
||||
|
||||
## ~
|
||||
|
||||
While you're writing and testing your programs, you'll mostly be [running them
|
||||
in the simulator](/device/simulator), but once you've finished your program you
|
||||
can **compile** it and run it on your micro:bit.
|
||||
|
||||
The basic steps are:
|
||||
|
||||
1. Connect your micro:bit to your computer via USB
|
||||
2. Click **Download** and download the `.hex` file
|
||||
3. Copy the `.hex` file from your computer onto the micro:bit drive
|
||||
|
||||
## Requirements
|
||||
|
||||
You need the following things to transfer and run a script on your micro:bit:
|
||||
|
||||
* A-Male to Micro USB cable to connect your computer to your micro:bit. This is
|
||||
the same cable that is commonly used to connect a smart phone to a computer.
|
||||
* A PC running Windows 7 or later, or a Mac running OS X 10.6 or later
|
||||
|
||||
## Step 1: Connect your micro:bit to your computer
|
||||
|
||||
First, connect the micro:bit:
|
||||
|
||||
1. Connect the small end of the USB cable to the micro USB port on your micro:bit.
|
||||
|
||||
2. Connect the other end of the USB cable to a USB port on your computer.
|
||||
|
||||
Your computer should recognise your micro:bit as a new drive. On computers
|
||||
running Windows, `MICROBIT` appears as a drive under Devices and drives. On a Mac
|
||||
it appears as a new drive under Devices.
|
||||
|
||||
![](/static/mb/device/usb-windows-device.jpg)
|
||||
|
||||
## Step 2 (optional): Configure Chrome to ask where to save the file
|
||||
|
||||
You only need to do this once.
|
||||
|
||||
1. Open the **Settings** for Chrome.
|
||||
2. Click **Advanced** at the bottom of the page.
|
||||
3. Find the **Downloads** settings.
|
||||
4. Enable the setting **Ask where to save each file before downloading**.
|
||||
|
||||
## Step 3: Download your program
|
||||
|
||||
1. Open your project on @homeurl@
|
||||
2. Click **Download**
|
||||
3. If you did Step 2 above, Chrome will ask where to save the `.hex` file,
|
||||
so save it into the `MICROBIT` drive.
|
||||
Otherwise, continue with one of the options in Step 4 below.
|
||||
|
||||
## Step 4: Transfer the file to your micro:bit
|
||||
|
||||
If the file was saved onto your computer, you will need to transfer it to the micro:bit.
|
||||
|
||||
## Manual transfer
|
||||
|
||||
Your `.hex` file (created in Step 3 above) appears as a download at the bottom of the browser.
|
||||
Click on the arrow next to the name of the file and then click **Show in folder**.
|
||||
|
||||
![](/static/mb/device/usb-windows-chrome.png)
|
||||
|
||||
In File Explorer, drag and drop the `.hex` file from the download folder onto the `MICROBIT` drive.
|
||||
|
||||
Alternatively, right-click on the hex file, choose **Send to**, and then **MICROBIT**.
|
||||
|
||||
![](/static/mb/device/usb-windows-sendto.jpg)
|
||||
|
||||
## Step 5: After transferring the file
|
||||
|
||||
* The LED on the back of your micro:bit flashes during the transfer (which
|
||||
should only take a few seconds).
|
||||
* Once transferred, the code will run automatically on your micro:bit. To rerun
|
||||
your program, press the reset button on the back of your micro:bit. The reset
|
||||
button automatically runs the newest file on the micro:bit.
|
||||
* By copying the script onto the `MICROBIT` drive, you have programmed it into the
|
||||
flash memory on the micro:bit, which means even after you unplug the micro:bit,
|
||||
your program will still run if the micro:bit is powered by battery.
|
||||
|
||||
## ~hint
|
||||
|
||||
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshoot).
|
||||
|
||||
## ~
|
72
docs/device/usb/windows-edge.md
Normal file
@ -0,0 +1,72 @@
|
||||
# Uploading from Microsoft Edge on Windows
|
||||
|
||||
How to compile, transfer, and run a program on your micro:bit on **Microsoft Edge**.
|
||||
|
||||
While you're writing and testing your programs, you'll mostly be [running them
|
||||
in the simulator](/device/simulator), but once you've finished your program you
|
||||
can **compile** it and run it on your micro:bit.
|
||||
|
||||
The basic steps are:
|
||||
|
||||
1. Connect your @boardname@ to your computer via USB
|
||||
2. Click **Download** to download the `.hex` file
|
||||
3. Click the **Save As** button in the bottom bar and save the `.hex` file into the MICROBIT drive
|
||||
|
||||
## Requirements
|
||||
|
||||
You need the following things to transfer and run a script on your micro:bit:
|
||||
|
||||
* A-Male to Micro USB cable to connect your computer to your micro:bit. This is
|
||||
the same cable that is commonly used to connect a smart phone to a computer.
|
||||
* A PC running Windows 7 or later, or a Mac running OS X 10.6 or later
|
||||
|
||||
## Step 1: Connect your micro:bit to your computer
|
||||
|
||||
First, connect the micro:bit:
|
||||
|
||||
1. Connect the small end of the USB cable to the micro USB port on your micro:bit.
|
||||
|
||||
2. Connect the other end of the USB cable to a USB port on your computer.
|
||||
|
||||
Your computer should recognise your micro:bit as a new drive. On computers
|
||||
running Windows, `MICROBIT` appears as a drive under Devices and drives. On a Mac
|
||||
it appears as a new drive under Devices.
|
||||
|
||||
![](/static/mb/device/usb-windows-device.jpg)
|
||||
|
||||
## Step 2: Download your program
|
||||
|
||||
1. Open your project on @homeurl@
|
||||
2. Click **Download**
|
||||
3. When prompted, choose to **save** the compiled file onto your computer. The
|
||||
prompt will be different depending on which browser you are using, or
|
||||
whether you are using a Windows computer or a Mac
|
||||
|
||||
A message will appear at the bottom of the browser asking what you want to do
|
||||
with the file.
|
||||
|
||||
4. Click **Save As**
|
||||
|
||||
![Save download file dialog](/static/mb/device/usb/save-as-edge.gif)
|
||||
|
||||
5. Save the ``.hex`` file into the **MICROBIT** drive
|
||||
|
||||
![Save hex file to MICROBIT drive](/static/mb/device/usb/save-as-windows.png)
|
||||
|
||||
## Step 3: Transfer the file to your micro:bit
|
||||
|
||||
* The LED on the back of your micro:bit flashes during the transfer (which
|
||||
should only take a few seconds).
|
||||
* Once transferred, the code will run automatically on your @boardname@. To rerun
|
||||
your program, press the reset button on the back of your @boardname@. The reset
|
||||
button automatically runs the newest file on the micro:bit.
|
||||
|
||||
By copying the script onto the `MICROBIT` drive, you have programmed it into the
|
||||
flash memory on the micro:bit, which means even after you unplug the micro:bit,
|
||||
your program will still run if the micro:bit is powered by battery.
|
||||
|
||||
## ~hint
|
||||
|
||||
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshoot).
|
||||
|
||||
## ~
|
71
docs/device/usb/windows-firefox.md
Normal file
@ -0,0 +1,71 @@
|
||||
# Uploading from Firefox on Windows
|
||||
|
||||
How to compile, transfer, and run a program on your micro:bit on **Firefox for Windows**.
|
||||
|
||||
While you're writing and testing your programs, you'll mostly be [running them
|
||||
in the simulator](/device/simulator), but once you've finished your program you
|
||||
can **compile** it and run it on your micro:bit.
|
||||
|
||||
The basic steps are:
|
||||
|
||||
1. Connect your micro:bit to your computer via USB
|
||||
2. Click **Download** and download the `.hex` file
|
||||
3. Click the **Save As** button and save the `.hex` file into the MICROBIT drive
|
||||
|
||||
## Requirements
|
||||
|
||||
You need the following things to transfer and run a script on your micro:bit:
|
||||
|
||||
* A-Male to Micro USB cable to connect your computer to your micro:bit. This is
|
||||
the same cable that is commonly used to connect a smart phone to a computer.
|
||||
* A PC running Windows 7 or later, or a Mac running OS X 10.6 or later
|
||||
|
||||
## Step 1: Connect your micro:bit to your computer
|
||||
|
||||
First, connect the micro:bit:
|
||||
|
||||
1. Connect the small end of the USB cable to the micro USB port on your micro:bit.
|
||||
|
||||
2. Connect the other end of the USB cable to a USB port on your computer.
|
||||
|
||||
Your computer should recognise your micro:bit as a new drive. On computers
|
||||
running Windows, `MICROBIT` appears as a drive under Devices and drives. On a Mac
|
||||
it appears as a new drive under Devices.
|
||||
|
||||
![](/static/mb/device/usb-windows-device.jpg)
|
||||
|
||||
## Step 2: Download your program
|
||||
|
||||
1. Open your project on @homeurl@.
|
||||
2. Click **Download**.
|
||||
3. When prompted, choose to **save** the compiled file onto your computer. The
|
||||
prompt will be different depending on which browser you are using, or
|
||||
whether you are using a Windows computer or a Mac.
|
||||
|
||||
![Save download file dialog](/static/mb/device/usb/save-file-firefox.gif)
|
||||
|
||||
A window may appear asking whether you want to save or open the `.hex` file. If it doesn't, go click on the downloads icon at the top of the browser.
|
||||
|
||||
![Save file prompt](/static/mb/device/usb/open-file-firefox.png)
|
||||
|
||||
Click the folder icon and copy the file from the list of downloads to the **MICROBIT** drive.
|
||||
|
||||
![Move hex file to MICROBIT drive](/static/mb/device/usb/move-hex-file-firefox.png)
|
||||
|
||||
## Step 3: Transfer the file to your micro:bit
|
||||
|
||||
* The LED on the back of your micro:bit flashes during the transfer (which
|
||||
should only take a few seconds).
|
||||
* Once transferred, the code will run automatically on your @boardname@. To rerun
|
||||
your program, press the reset button on the back of your @boardname@. The reset
|
||||
button automatically runs the newest file on the micro:bit.
|
||||
|
||||
By copying the script onto the `MICROBIT` drive, you have programmed it into the
|
||||
flash memory on the micro:bit, which means even after you unplug the micro:bit,
|
||||
your program will still run if the micro:bit is powered by battery.
|
||||
|
||||
## ~hint
|
||||
|
||||
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshoot).
|
||||
|
||||
## ~
|
70
docs/device/usb/windows-ie.md
Normal file
@ -0,0 +1,70 @@
|
||||
# Uploading from Internet Explorer on Windows
|
||||
|
||||
While you're writing and testing your programs, you'll mostly be [running them
|
||||
in the simulator](/device/simulator), but once you've finished your program you
|
||||
can **compile** it and run it on your micro:bit.
|
||||
|
||||
The basic steps are:
|
||||
|
||||
1. Connect your micro:bit to your computer via USB
|
||||
2. Click **Download** and download the `.hex` file
|
||||
3. **Click the down arrow next to Save** in the bottom bar and select **Save As**.
|
||||
4. In the save dialog, save the `.hex` file into the MICROBIT drive
|
||||
|
||||
## Requirements
|
||||
|
||||
You need the following things to transfer and run a script on your micro:bit:
|
||||
|
||||
* A-Male to Micro USB cable to connect your computer to your micro:bit. This is
|
||||
the same cable that is commonly used to connect a smart phone to a computer.
|
||||
* A PC running Windows 7 or later, or a Mac running OS X 10.6 or later
|
||||
|
||||
## Step 1: Connect your micro:bit to your computer
|
||||
|
||||
First, connect the micro:bit:
|
||||
|
||||
1. Connect the small end of the USB cable to the micro USB port on your micro:bit.
|
||||
|
||||
2. Connect the other end of the USB cable to a USB port on your computer.
|
||||
|
||||
Your computer should recognise your micro:bit as a new drive. On computers
|
||||
running Windows, `MICROBIT` appears as a drive under Devices and drives. On a Mac
|
||||
it appears as a new drive under Devices.
|
||||
|
||||
![](/static/mb/device/usb-windows-device.jpg)
|
||||
|
||||
## Step 2: Download your program
|
||||
|
||||
1. Open your project on @homeurl@
|
||||
2. Click **Download**
|
||||
3. When prompted, choose to **save** the compiled file onto your computer. The
|
||||
prompt will be different depending on which browser you are using, or
|
||||
whether you are using a Windows computer or a Mac
|
||||
|
||||
A message will appear at the bottom of the browser asking what you want to do
|
||||
with the file. Click **on the arrow next to Save** and click **Save As**
|
||||
|
||||
![Save download file dialog](/static/mb/device/usb/save-as-ie.gif)
|
||||
|
||||
In the save dialog, save as the ``.hex`` file to the MICROBIT drive.
|
||||
|
||||
![Save hex file to MICROBIT drive](/static/mb/device/usb/save-as-windows.png)
|
||||
|
||||
## Step 3: Transfer the file to your micro:bit
|
||||
|
||||
* The LED on the back of your micro:bit flashes during the transfer (which
|
||||
should only take a few seconds).
|
||||
* Once transferred, the code will run automatically on your @boardname@. To rerun
|
||||
your program, press the reset button on the back of your @boardname@. The reset
|
||||
button automatically runs the newest file on the micro:bit.
|
||||
|
||||
By copying the script onto the `MICROBIT` drive, you have programmed it into the
|
||||
flash memory on the micro:bit, which means even after you unplug the micro:bit,
|
||||
your program will still run if the micro:bit is powered by battery.
|
||||
|
||||
|
||||
## ~hint
|
||||
|
||||
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshoot).
|
||||
|
||||
## ~
|
65
docs/device/windows-app/troubleshoot.md
Normal file
@ -0,0 +1,65 @@
|
||||
# Troubleshooting downloads from the Windows 10 App
|
||||
|
||||
### ~ avatar
|
||||
|
||||
Is the [Windows App](https://www.microsoft.com/store/apps/9pjc7sv48lcx) not downloading your program properly? Let's try to figure out why!
|
||||
|
||||
### ~
|
||||
|
||||
## Step 1: Check your cable
|
||||
|
||||
Make sure that your @boardname@ is connected to your computer with a micro USB cable. You should see a **MICROBIT** drive appear in Windows Explorer when it's connected.
|
||||
|
||||
![MICROBIT drive](/static/mb/device/windows-microbit-drive.png)
|
||||
|
||||
**If you can see the MICROBIT drive go to step 2**.
|
||||
|
||||
If you can't see the drive:
|
||||
* Make sure that the USB cable is working.
|
||||
>Does the cable work on another computer? If not, find a different cable to use. Some cables may only provide a power connection and don't actually transfer data.
|
||||
* Try another USB port on your computer.
|
||||
|
||||
Is the cable good but you still can't see the **MICROBIT** drive? Hmm, you might have a problem with your @boardname@. Try the additional steps described in the [fault finding](https://support.microbit.org/support/solutions/articles/19000024000-fault-finding-with-a-micro-bit) page at microbit.org. If this doesn't help, you can create a [support ticket](https://support.microbit.org/support/tickets/new) to notify the Micro:bit Foundation of the problem. **Skip the rest of these steps**.
|
||||
|
||||
## Step 2: Check your firmware version
|
||||
|
||||
It's possible that the firmware version on the @boardname@ needs an update. Let's check:
|
||||
|
||||
1. Go to the **MICROBIT** drive.
|
||||
2. Open the **DETAILS.TXT** file.<br/>
|
||||
![](/static/mb/device/mb-drive-contents.jpg)<br/>
|
||||
3. Look for a line in the file that says the version number. It should say **Version: \.\.\.**
|
||||
![](/static/mb/device/details-txt.jpg)<br/>
|
||||
|
||||
If the version is **0234**, you **NEED** to update the [firmware](/device/firmware) on your @boardname@. Go to **Step 3** and follow the upgrade instructions.
|
||||
|
||||
If the version is **0241**, **0243** or higher, **you have the right firmware**. You can create a [support ticket](https://support.microbit.org/support/tickets/new) to notify the Micro:bit Foundation of the problem. **Skip the rest of these steps**.
|
||||
|
||||
## Step 3: Upgrade the firmware
|
||||
|
||||
1. Put your @boardname@ into **MAINTENANCE Mode**. To do this, unplug the USB cable from the @boardname@ and then re-connect the USB cable while you hold down the reset button. Once you insert the cable, you can release the reset button. You should now see a **MAINTENANCE** drive instead of the **MICROBIT** drive like before. Also, a yellow LED light will stay on next to the reset button.
|
||||
![MAINTENANCE gesture](/static/mb/device/maintenance.gif)
|
||||
2. **[Download the firmware .hex file](https://microbit.org/guide/firmware/#update-firmware)**
|
||||
3. Drag and drop that file onto the **MAINTENANCE** drive.
|
||||
4. The yellow LED will flash while the `HEX` file is copying. When the copy finishes, the LED will go off and the @boardname@ resets. The **MAINTENANCE** drive now changes back to **MICROBIT**.
|
||||
5. The upgrade is complete! You can open the **DETAILS.TXT** file to check and see that the firmware version changed to the match the version of the `HEX` file you copied.
|
||||
|
||||
### ~hint
|
||||
|
||||
If you want to know more about connecting the board, MAINTENANCE Mode, and upgrading the firmware, read about it in the [micro:bit firmware guide](https://microbit.org/guide/firmware).
|
||||
|
||||
### ~
|
||||
|
||||
## Step 4: Wait for the driver updates
|
||||
|
||||
Once you've updated the firmware, Windows will detect the updated device and install the drivers necessary to enable communication with the @boardname@. This step happens in the background and may take a minute or two.
|
||||
|
||||
## Step 5: Drag and drop a fresh .hex file
|
||||
|
||||
If different editors were used with this board, it may need a reset to bring it back to a known-good state. Do this by dragging a ``.hex`` file containing a simple program onto the drive. You can use the one here. Click on the **Download** icon below the blocks, then drag and drop the file onto the @drivename@ drive.
|
||||
|
||||
```blocks
|
||||
basic.forever(function() {
|
||||
basic.showString("OK")
|
||||
})
|
||||
```
|
47
docs/examples.md
Normal file
@ -0,0 +1,47 @@
|
||||
# Examples
|
||||
|
||||
Here are some fun programs for your @boardname@!
|
||||
|
||||
## Fun stuff
|
||||
|
||||
```codecard
|
||||
[{
|
||||
"name": "Rando",
|
||||
"description": "Randomly blinking LEDs",
|
||||
"url": "/examples/rando",
|
||||
"cardType": "example"
|
||||
},
|
||||
{
|
||||
"name": "Game of Life",
|
||||
"description": "A Game of Life simulation in LEDs",
|
||||
"url": "/examples/gameofLife",
|
||||
"cardType": "example"
|
||||
},
|
||||
{
|
||||
"name": "Pi Monte Carlo",
|
||||
"description": "Approximate the number Pi",
|
||||
"url": "/examples/pi-montecarlo",
|
||||
"cardType": "example"
|
||||
}]
|
||||
```
|
||||
|
||||
## Sensors
|
||||
|
||||
```codecard
|
||||
[{
|
||||
"name": "Egg & Spoon Race",
|
||||
"description": "Balance a micro:bit like an egg and spoon race",
|
||||
"url": "/examples/egg-and-spoon",
|
||||
"cardType": "example"
|
||||
},{
|
||||
"name": "Plot Acceleration",
|
||||
"description": "Chart acceleration on the LED screen",
|
||||
"url": "/examples/plot-acceleration",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Radio Dashboard",
|
||||
"description": "A dashboard for radio clients",
|
||||
"url": "/examples/radio-dashboard",
|
||||
"cardType": "example"
|
||||
}]
|
||||
```
|
@ -22,13 +22,13 @@ Here's a program that simulates cell life in the LED matrix. Use button ``A`` fo
|
||||
let lifeChart: Image = null
|
||||
|
||||
//Use button A for the next iteration of game of life
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Click), () => {
|
||||
gameOfLife();
|
||||
show();
|
||||
})
|
||||
|
||||
//Use button B for reseting to random initial seed state
|
||||
input.onButtonPressed(Button.B, () => {
|
||||
input.onButtonEvent(Button.B, input.buttonEventValue(ButtonEvent.Click), () => {
|
||||
reset();
|
||||
show();
|
||||
})
|
||||
|
@ -50,10 +50,8 @@ This method of filling coordinate points, counting them, and using the differenc
|
||||
## Monte Carlo approximation of _pi_
|
||||
|
||||
```blocks
|
||||
let pir = 0
|
||||
let pid = 0
|
||||
let pi = 0
|
||||
let y = 0
|
||||
let pin = 0
|
||||
let x = 0
|
||||
let r2 = 0
|
||||
let r = 0
|
||||
@ -75,8 +73,8 @@ basic.forever(() => {
|
||||
inside = 0
|
||||
for (let i = 0; i < n; i++) {
|
||||
// generate a point within the square
|
||||
x = Math.randomRange(0, r + 1)
|
||||
y = Math.randomRange(0, r + 1)
|
||||
x = randint(0, r + 1)
|
||||
y = randint(0, r + 1)
|
||||
// test if the point is within the circle
|
||||
// sqrt(x**2 + y**2) < r ==> x**2 + y**2 < r**2
|
||||
if (x * x + y * y < r2) {
|
||||
@ -87,10 +85,7 @@ basic.forever(() => {
|
||||
// r * r * pi => inside / n ~= (r*r*pi) / (4*r*r) ~=
|
||||
// pi / 4 pi = inside / n * 4
|
||||
//
|
||||
pin = inside * 4
|
||||
// only integer arithmetic here...
|
||||
pid = pin / n
|
||||
pir = pin % n
|
||||
pi = (inside * 4) / n
|
||||
// show results
|
||||
basic.showLeds(`
|
||||
# # # # #
|
||||
@ -99,6 +94,6 @@ basic.forever(() => {
|
||||
. # . # .
|
||||
. # . . #
|
||||
`)
|
||||
basic.showString(" " + pid + "." + pir)
|
||||
basic.showString(" " + pi)
|
||||
})
|
||||
```
|
@ -4,6 +4,6 @@ Generate a random coordinate and display it on the LED screen.
|
||||
|
||||
```blocks
|
||||
basic.forever(() => {
|
||||
led.toggle(Math.randomRange(0, 5), Math.randomRange(0, 5))
|
||||
led.toggle(randint(0, 4), randint(0, 4))
|
||||
})
|
||||
```
|
21
docs/hero-banner.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Hero Banner
|
||||
|
||||
Here are some cool activities to get you started with your @boardname@!
|
||||
|
||||
## Intro Content
|
||||
|
||||
### ~ codecard
|
||||
* name: CalliopEO
|
||||
* description: CALLIOPEO – Taking the Calliope mini to the ISS.
|
||||
* imageUrl: /calliope/02_Hero_CalliopEO.png
|
||||
* url: https://calliope.cc/calliopeo
|
||||
* buttonLabel: Explore!
|
||||
* cardType: link
|
||||
---
|
||||
* name: The 5x5 LED matrix
|
||||
* description: KIDS LAB – play, learn and hack!
|
||||
* imageUrl: /calliope/03_Hero_KidsLab.png
|
||||
* url: https://calliope.cc/programmieren/kidslab
|
||||
* buttonLabel: Explore!
|
||||
* cardType: link
|
||||
### ~
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"appref": "v1.0.25"
|
||||
"appref": "v4.0.29"
|
||||
}
|
||||
|
63
docs/live-coding.md
Normal file
@ -0,0 +1,63 @@
|
||||
# Live coding sessions
|
||||
|
||||
Here are some videos of live tutorial sessions with the @boardname@!
|
||||
|
||||
## Fun stuff
|
||||
|
||||
```codecard
|
||||
[
|
||||
{
|
||||
"name": "Daily Coding Lessons!",
|
||||
"description": "Subscribe to our mixer.com stream. Live coding Monday through Friday at 9AM PST / Noon EST / 4PM GMT",
|
||||
"url": "https://mixer.com/MakeCode",
|
||||
"imageUrl": "/static/live-coding/live.png"
|
||||
},
|
||||
{
|
||||
"name": "Flashing Heart",
|
||||
"description": "Demonstrating the Flashing Heart tutorial, live.",
|
||||
"youTubeId": "NvEOKZ8wh9s",
|
||||
"imageUrl": "/static/live-coding/showleds.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Name Tag",
|
||||
"description": "A live illustration of the Name tag tutorial",
|
||||
"youTubeId": "xpRI5jjQ31E",
|
||||
"imageUrl": "/static/live-coding/showstring.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Smiley Button",
|
||||
"description": "Step by step live coding of the Smiley Button tutorial.",
|
||||
"youTubeId": "BgDxz3M7JIM"
|
||||
},
|
||||
{
|
||||
"name": "Dice",
|
||||
"description": "Step by step live coding of the Dice tutorial.",
|
||||
"youTubeId": "OmrmjtOm_sQ"
|
||||
},
|
||||
{
|
||||
"name": "Love Meter",
|
||||
"description": "Steps by step live coding of the Love Meter tutorial",
|
||||
"youTubeId": "1IYsy0_9n8g"
|
||||
},
|
||||
{
|
||||
"name": "Micro Chat",
|
||||
"description": "Steps by step live coding of the Micro Chat tutorial",
|
||||
"youTubeId": "5XqsGROG2fI"
|
||||
},
|
||||
{
|
||||
"name": "Rock Paper Scissor",
|
||||
"description": "Steps by step live coding of the Rock Paper Scissor tutorial",
|
||||
"youTubeId": "94lLBB3b1kU"
|
||||
},
|
||||
{
|
||||
"name": "Playlist",
|
||||
"description": "See all the previous live stream sessions",
|
||||
"url": "https://www.youtube.com/watch?v=NvEOKZ8wh9s&list=PLMMBk9hE-SepocOwueEtTDyOPI_TBE9yC",
|
||||
"imageUrl": "/static/live-coding/playlist.png"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
[YouTube Playlist](https://www.youtube.com/watch?v=NvEOKZ8wh9s&list=PLMMBk9hE-SepocOwueEtTDyOPI_TBE9yC)
|
12
docs/mini.pxt.io.md
Normal file
@ -0,0 +1,12 @@
|
||||
![](/static/mb/device/calliope_website.jpg)
|
||||
|
||||
|
||||
# MAKECODE UPDATE
|
||||
|
||||
## MakeCode Support nur noch eingeschränkt.
|
||||
|
||||
Der MakeCode Support für die erste Version des Calliope mini (IT-Gipfel) wird nun eingeschränkt.
|
||||
|
||||
Es kann zwar weiterhin die Editorversion [https://MakeCode.calliope.cc](https://MakeCode.calliope.cc) genutzt werden, allerdings ist diese nicht mehr komplett kompatibel zum Calliope mini der ersten Generation.
|
||||
|
||||
Eine Alternative stellt das [Open Roberta Lab](https://lab.open-roberta.org/) dar.
|
@ -2,27 +2,34 @@
|
||||
|
||||
```codecard
|
||||
[
|
||||
{
|
||||
"name": "New Project (iPad)",
|
||||
"url": "/calliope/templates",
|
||||
"imageUrl": "/calliope/templates/32KB.png",
|
||||
"largeImageUrl": "/calliope/templates/32KB_L.png"
|
||||
},
|
||||
{
|
||||
"name": "First Steps",
|
||||
"url": "/calliope/firststeps",
|
||||
"imageUrl": "/docs/calliope/firststeps/connecting.jpg",
|
||||
"largeImageUrl": "/docs/calliope/firststeps/firstSteps.jpg"
|
||||
"imageUrl": "/calliope/firststeps/connecting.jpg",
|
||||
"largeImageUrl": "/calliope/firststeps/firstSteps.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Tutorials",
|
||||
"url": "/calliope/tutorials",
|
||||
"imageUrl": "/docs/calliope/tutorials/01_flashing_heart.gif"
|
||||
"imageUrl": "/calliope/tutorials/01_flashing_heart.gif"
|
||||
},
|
||||
{
|
||||
"name": "Calliope Links",
|
||||
"url": "/calliope/links",
|
||||
"imageUrl": "/docs/calliope/links/thumbnail_shop.gif"
|
||||
"imageUrl": "/calliope/links/thumbnail_shop.gif"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
[New Project (iPad)](/calliope/templates),
|
||||
[First Steps](/calliope/firststeps),
|
||||
[Tutorials](/calliope/tutorials),
|
||||
[Calliope Links](/calliope/links)
|
||||
|
@ -1,5 +1,8 @@
|
||||
# Projects
|
||||
|
||||
* [New Project (iPad)](/calliope/templates)
|
||||
* [Calliope mini 2.x](_f7ACuxgaocvr)
|
||||
* [Calliope mini 1.x](_7YbU6iMhoTdR)
|
||||
* [First Steps](/calliope/firststeps)
|
||||
* [Get Ready](/calliope/firststeps/firstSteps)
|
||||
* [The 5x5 LED matrix](/calliope/firststeps/5x5LED)
|
||||
|
@ -4,14 +4,14 @@
|
||||
|
||||
Let's create a coin flipping program to simulate a real coin toss. We'll use icon images to represent a ``heads`` or ``tails`` result.
|
||||
|
||||
![Simulating coin toss](/docs/calliope/tutorials/08_coin_flipper_animation.gif)
|
||||
![Simulating coin toss](/calliope/tutorials/08_coin_flipper_animation.gif)
|
||||
|
||||
## Step 1
|
||||
|
||||
Get an ``||input:on button A pressed||`` block from the ``||input:Input||`` drawer in the toolbox. We'll put our coin flipping code in here.
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Click), () => {
|
||||
})
|
||||
```
|
||||
|
||||
@ -22,7 +22,7 @@ Grab an ``||logic:if else||`` block and set it inside ``||input:on button A pres
|
||||
The ``||Math:pick random true or false||`` returns a random ``true`` or ``false`` value which we use to determine a ``heads`` or ``tails`` result for a coin toss.
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Click), () => {
|
||||
if (Math.randomBoolean()) {
|
||||
} else {
|
||||
}
|
||||
@ -34,7 +34,7 @@ input.onButtonPressed(Button.A, () => {
|
||||
Now, put a ``||basic:show icon||`` block inside both the ``||logic:if||`` and the ``||logic:else||``. Pick images to mean ``heads`` and ``tails``.
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Click), () => {
|
||||
if (Math.randomBoolean()) {
|
||||
basic.showIcon(IconNames.Skull)
|
||||
} else {
|
||||
@ -52,7 +52,7 @@ Press button **A** in the simulator to try the coin toss code.
|
||||
You can animate the coin toss to add the feeling of suspense. Place different ``||basic:show icon||`` blocks before the ``||logic:if||`` to show that the coin is flipping.
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
input.onButtonEvent(Button.A, input.buttonEventValue(ButtonEvent.Click), () => {
|
||||
basic.showIcon(IconNames.Diamond)
|
||||
basic.showIcon(IconNames.SmallDiamond)
|
||||
basic.showIcon(IconNames.Diamond)
|
||||
|
@ -5,7 +5,7 @@
|
||||
Let's turn the @boardname@ into a dice!
|
||||
(Want to learn how the accelerometer works? [Watch this video](https://youtu.be/byngcwjO51U)).
|
||||
|
||||
![A mini dice](/docs/calliope/tutorials/04_dice_animation.gif)
|
||||
![A mini dice](/calliope/tutorials/04_dice_animation.gif)
|
||||
|
||||
## Step 1 @fullscreen
|
||||
|
||||
@ -35,7 +35,7 @@ Put a ``||Math:pick random||`` block in the ``||basic:show number||`` block to p
|
||||
|
||||
```blocks
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
basic.showNumber(Math.randomRange(0, 10))
|
||||
basic.showNumber(randint(0, 10))
|
||||
})
|
||||
```
|
||||
|
||||
@ -45,7 +45,7 @@ A typical dice shows values from `1` to `6`. So, in ``||Math:pick random||``, do
|
||||
|
||||
```blocks
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
basic.showNumber(Math.randomRange(1, 6))
|
||||
basic.showNumber(randint(1, 6))
|
||||
})
|
||||
```
|
||||
|
||||
|
18
docs/projects/escape-room.md
Normal file
@ -0,0 +1,18 @@
|
||||
# Escape Room
|
||||
|
||||
Projects used to create escape room experiences.
|
||||
|
||||
## Radio
|
||||
|
||||
```codecard
|
||||
[{
|
||||
"name": "Rotary Dial Radio",
|
||||
"url":"/projects/rotary-dial-radio",
|
||||
"description": "Turn an antique rotary dial phone into a radio transmitter",
|
||||
"imageUrl":"/static/mb/projects/rotary-dial-radio.png"
|
||||
}]
|
||||
```
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
Escape room ideas are gathered from a great discussion with [Pauline Maas](https://twitter.com/4pip) and [Peter Heldens](https://twitter.com/PeterHeldens) at https://microbit101.nl/.
|
@ -6,13 +6,13 @@ Learn how to use the LEDs and make a flashing heart!
|
||||
(Want to learn how lights work? [Watch this video](https://youtu.be/qqBmvHD5bCw)).
|
||||
|
||||
|
||||
![Heart shape in the LEDs](/docs/calliope/tutorials/01_flashing_heart_animation.gif)
|
||||
![Heart shape in the LEDs](/calliope/tutorials/01_flashing_heart_animation.gif)
|
||||
|
||||
## Step 1 @fullscreen
|
||||
|
||||
Place the ``||basic:show leds||`` block in the ``||basic:forever||`` block and draw a heart.
|
||||
|
||||
![An animation that shows how to drag a block and paint a heart](/docs/calliope/tutorials/add_show_led.gif)
|
||||
![An animation that shows how to drag a block and paint a heart](/calliope/tutorials/add_show_led.gif)
|
||||
|
||||
## Step 2 @fullscreen
|
||||
|
||||
@ -39,7 +39,7 @@ basic.forever(function() {
|
||||
|
||||
Look at the virtual @boardname@, you should see the heart and your drawing blink on the screen.
|
||||
|
||||
![Heart shape in the LEDs](/docs/calliope/tutorials/01_flashing_heart_animation.gif)
|
||||
![Heart shape in the LEDs](/calliope/tutorials/01_flashing_heart_animation.gif)
|
||||
|
||||
## Step 4 @fullscreen
|
||||
|
||||
|
@ -3,16 +3,15 @@
|
||||
## Introduction @unplugged
|
||||
|
||||
Make a love meter, how sweet! The @boardname@ is feeling the love, then sometimes not so much!
|
||||
Tell everyone who you are. Show you name on the LEDs.
|
||||
|
||||
![Love meter banner message](/docs/calliope/tutorials/05_love_meter_animation.gif)
|
||||
![Love meter banner message](/calliope/tutorials/05_love_meter_animation.gif)
|
||||
|
||||
## Step 1
|
||||
|
||||
Let's build a **LOVE METER** machine. Place an ``||input:on pin pressed||`` block to run code when pin **0** is pressed. Use ``P0`` from the list of pin inputs.
|
||||
|
||||
```blocks
|
||||
input.onPinPressed(TouchPin.P0, () => {
|
||||
input.onPinTouchEvent(TouchPin.P0, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
});
|
||||
```
|
||||
|
||||
@ -21,8 +20,8 @@ input.onPinPressed(TouchPin.P0, () => {
|
||||
Using ``||basic:show number||`` and ``||Math:pick random||`` blocks, show a random number from `0` to `100` when pin **0** is pressed.
|
||||
|
||||
```blocks
|
||||
input.onPinPressed(TouchPin.P0, () => {
|
||||
basic.showNumber(Math.randomRange(0, 100));
|
||||
input.onPinTouchEvent(TouchPin.P0, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
basic.showNumber(randint(0, 100));
|
||||
});
|
||||
```
|
||||
## Step 3
|
||||
@ -35,8 +34,8 @@ Show ``"LOVE METER"`` on the screen when the @boardname@ starts.
|
||||
|
||||
```blocks
|
||||
basic.showString("LOVE METER");
|
||||
input.onPinPressed(TouchPin.P0, () => {
|
||||
basic.showNumber(Math.randomRange(0, 100));
|
||||
input.onPinTouchEvent(TouchPin.P0, input.buttonEventValue(ButtonEvent.Down), () => {
|
||||
basic.showNumber(randint(0, 100));
|
||||
});
|
||||
```
|
||||
|
||||
|