Bump V3.0.22 (#110)
* change simulator svg * change radio image * Remove google fonts cdn * change color of 'advanced' button * font fix * font fix 2 * display fix * change fullsceen simulator bg * Continuous servo * handle continuous state * adding shims * update rendering for continuous servos * fixing sim * fix sig * typo * fix sim * bump pxt * bump pxt * rerun travis * Input blocks revision - add Button and Pin event types - merge onPinPressed & onPinReleased in new onPinEvent function - create new onButtonEvent function * update input blocks in docs and tests * remove device_pin_release block * Hide DAL.x behind Enum * bring back deprecated blocks, but hide them * shims and locales files * fix input.input. typing * remove buildpr * bump V3 * update simulator aspect ratio * add Loudness Block * revoke loudness block * Adds soundLevel To be replaced by pxt-common-packages when DAL is updated. * Remove P0 & P3 from AnalogPin Co-authored-by: Juri <gitkraken@juriwolf.de>
This commit is contained in:
110
docs/device/data-analysis/analyze.md
Normal file
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)
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
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)
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
## Downloading your data
|
||||
|
||||
You can download your data to save it to view in another program. Click the **Download** button above the chart view.
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
### 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.
|
||||
|
||||

|
||||
|
||||
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
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
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.onButtonPressed(Button.B, () => {
|
||||
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:
|
||||
|
||||

|
||||
|
||||
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
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.
|
||||
|
||||

|
||||
|
||||
## 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
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.
|
||||
|
||||

|
||||
|
||||
## 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.
|
||||
|
||||

|
||||
|
||||
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 view controls
|
||||
|
||||
The chart window shows the data view controls on top of the chart.
|
||||
|
||||

|
||||
|
||||
Here's what the controls do:
|
||||
|
||||
**Return**: The return button switches the view back to previous code window (either Blocks or JavaScript).
|
||||
|
||||

|
||||
|
||||
|
||||
**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@**.
|
||||
|
||||

|
||||
|
||||
**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.
|
||||
|
||||

|
||||
|
||||
**Resume**: The resume button will start displaying new values after the **Pause** button was pressed.
|
||||
|
||||

|
||||
|
||||
**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.
|
||||
|
||||

|
187
docs/device/data-analysis/writing.md
Normal file
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:
|
||||
|
||||

|
||||
|
||||
## 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:
|
||||
|
||||

|
||||
|
||||
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:
|
||||
|
||||

|
||||
|
||||
## 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:
|
||||
|
||||

|
||||
|
||||
The console output shows the different name value pairs too:
|
||||
|
||||

|
||||
|
||||
### 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.
|
||||
|
||||

|
Reference in New Issue
Block a user