|
1 |
| -Data logging **V2** |
| 1 | +Data Logging **V2** |
2 | 2 | *******************
|
3 | 3 |
|
4 | 4 | .. py:module:: log
|
5 | 5 |
|
6 |
| -This module lets you log data to a ``MY_DATA`` file saved on a |
7 |
| -micro:bit **V2**. |
| 6 | +This module lets you log data to a ``MY_DATA`` file saved on a micro:bit |
| 7 | +**V2** ``MICROBIT`` USB drive. |
8 | 8 |
|
9 |
| -Further guidance on the feature can be found on the |
10 |
| -`data logging page of the microbit.org website <https://microbit.org/get-started/user-guide/data-logging/>`_. |
| 9 | +.. image:: log-my_data.png |
| 10 | + |
| 11 | +The data is structured in a table format and it can be viewed and plotted with |
| 12 | +a browser. |
| 13 | + |
| 14 | +.. image:: log-html-view.jpeg |
| 15 | + |
| 16 | +Further guidance on this feature can be found on the |
| 17 | +`data logging page of the microbit.org website |
| 18 | +<https://microbit.org/get-started/user-guide/data-logging/>`_. |
11 | 19 |
|
12 | 20 | Functions
|
13 | 21 | =========
|
14 | 22 |
|
15 |
| -.. py:function:: set_labels(value, timestamp=log.MILLISECONDS) |
| 23 | +.. py:function:: set_labels(*labels, timestamp=log.SECONDS) |
| 24 | +
|
| 25 | + Set up the log file header. |
16 | 26 |
|
17 |
| - Set up the log file header. |
| 27 | + This function accepts any number of positional arguments, each creates |
| 28 | + a column header, e.g. ``log.set_labels("X", "Y", "Z")``. |
18 | 29 |
|
19 |
| - Each call to this function with positional arguments will generate a new |
20 |
| - header entry into the log file. |
| 30 | + Ideally this function should be called a single time, before any data is |
| 31 | + logged, to configure the data table header once. |
21 | 32 |
|
22 |
| - If the programme starts and a log file already exists it will compare the |
23 |
| - labels setup by this function call to the last headers declared in the |
24 |
| - file. If the headers are different it will add a new header entry at the |
25 |
| - end of the file. |
| 33 | + If a log file already exists when the programme starts, or if this function |
| 34 | + is called multiple times, it will check the labels already defined in the |
| 35 | + log file. |
| 36 | + If this function call contains any new labels not already present, it will |
| 37 | + generate a new header row with the additional columns. |
26 | 38 |
|
27 |
| -* **value**: Positional arguments used to generate the log headers, |
28 |
| - which go on the first line of the CSV file. For example, ``set_labels("A","B","C")`` |
29 |
| - will create three column headers titled ``A``, ``B`` and ``C`` in that order. |
30 |
| -* **timestamp**: Select the timestamp unit that will be automatically |
31 |
| - added as the first column in every row. Timestamp values can be one of |
32 |
| - ``MILLISECONDS``, ``SECONDS``, ``MINUTES``, ``HOURS``, ``DAYS`` or ``None`` to |
33 |
| - disable the timestamp. |
| 39 | + By default the first column contains a time stamp for each row. The time |
| 40 | + unit can be selected via the ``timestamp`` argument, e.g. |
| 41 | + ``log.set_labels("temp", timestamp=log.MINUTES)`` |
34 | 42 |
|
35 |
| -.. py:function:: set_mirroring(value) |
| 43 | + :param \*labels: Any number of positional arguments, each corresponding to |
| 44 | + an entry in the log header. |
| 45 | + :param timestamp: Select the timestamp unit that will be automatically |
| 46 | + added as the first column in every row. Timestamp values can be one of |
| 47 | + ``log.MILLISECONDS``, ``log.SECONDS``, ``log.MINUTES``, ``log.HOURS``, |
| 48 | + ``log.DAYS`` or ``None`` to disable the timestamp. The default value |
| 49 | + is ``log.SECONDS``. |
36 | 50 |
|
37 |
| - Mirrors the datalogging activity to the serial output. |
38 |
| - Serial mirroring is off by default. |
| 51 | +.. py:function:: set_mirroring(serial) |
39 | 52 |
|
40 |
| -* **value**: Boolean. ``True`` will enable mirroring data to the serial output. |
| 53 | + Configure mirroring of the data logging activity to the serial output. |
| 54 | + |
| 55 | + Serial mirroring is disabled by default. When enabled, it will print to |
| 56 | + serial each row logged into the log file. |
| 57 | + |
| 58 | + :param serial: ``True`` enables mirroring data to the serial output. |
41 | 59 |
|
42 | 60 | .. py:function:: delete(full=False)
|
43 | 61 |
|
44 |
| - Deletes the contents of the log, including headers. |
45 |
| - To add the log headers the ``set_labels`` function has to be called again |
46 |
| - after this. |
| 62 | + Delete the contents of the log, including headers. |
| 63 | + |
| 64 | + To add the log headers again the ``set_labels`` function should to be |
| 65 | + called after this function. |
47 | 66 |
|
48 |
| -* **full**: Selects a "full" erase format that removes the data from the |
49 |
| - flash storage. If set to ``False`` it uses a "fast" method, |
50 |
| - which invalidates the data instead of performing a slower |
51 |
| - full erase. |
| 67 | + There are two erase modes; "full" completely removes the data from the |
| 68 | + physical storage, and "fast" invalidates the data without removing it. |
52 | 69 |
|
53 |
| -.. py:function:: add({key:value}) |
54 |
| - add(key=value) |
55 |
| - |
56 |
| - There are two ways to add a data row into the log: |
| 70 | + :param full: ``True`` selects a "full" erase and ``False`` selects the |
| 71 | + "fast" erase method. |
57 | 72 |
|
58 |
| - 1. From a positional argument dictionary (key == label) |
59 |
| - - e.g. log.add({ 'temp': microbit.temperature() }) |
| 73 | +.. py:function:: add( data_dictionary, /, *, **kwargs) |
60 | 74 |
|
61 |
| - 2. From keyword arguments (argument name == label) |
62 |
| - - e.g. log.add(temp=microbit.temperature()) |
| 75 | + Add a data row to the log. |
63 | 76 |
|
64 |
| - Each call to this function adds a row to the log. |
| 77 | + There are two ways to log data with this function: |
65 | 78 |
|
66 |
| - New data labels (dictionary keys or keyword arguments) not already |
67 |
| - specified via the `set_labels` function, or by a previous call to this |
68 |
| - function, will trigger a new header entry to be added to the log with |
69 |
| - the extra label. |
| 79 | + #. Via keyword arguments, each argument name representing a label. |
70 | 80 |
|
71 |
| - Labels previously specified and not present in this function call will be |
72 |
| - skipped with an empty value in the log row. |
| 81 | + * e.g. ``log.add(X=compass.get_x(), Y=compass.get_y())`` |
73 | 82 |
|
74 |
| -Example |
75 |
| -======= |
| 83 | + #. Via a dictionary, each dictionary key representing a label. |
76 | 84 |
|
77 |
| -An example that runs through some of the functions of the log module API:: |
| 85 | + * e.g. ``log.add({ "X": compass.get_x(), "Y": compass.get_y() })`` |
| 86 | + |
| 87 | + The keyword argument option can be easier to use, and the dictionary option |
| 88 | + allows the use of spaces (and other special characters), that could not be |
| 89 | + used with the keyword arguments. |
| 90 | + |
| 91 | + New labels not previously specified via the ``set_labels`` function, or by |
| 92 | + a previous call to this function, will trigger a new header entry to be |
| 93 | + added to the log with the extra labels. |
| 94 | + |
| 95 | + Labels previously specified and not present in a call to this function will |
| 96 | + be skipped with an empty value in the log row. |
| 97 | + |
| 98 | +Examples |
| 99 | +======== |
| 100 | + |
| 101 | +A minimal example:: |
78 | 102 |
|
79 | 103 | from microbit import *
|
80 | 104 | import log
|
81 | 105 |
|
82 |
| - # Creates a new "log" file with the given "headers", timestamp added by default |
83 |
| - log.set_labels('temperature', 'brightness') |
84 |
| - |
85 |
| - # Configuring a different time unit for the timestamp |
86 |
| - log.set_labels('temperature', 'brightness', timestamp=log.SECONDS) |
87 |
| - |
88 |
| - # Enables the serial mirroring |
89 |
| - log.set_mirroring(True) |
90 |
| - |
91 |
| - # Set the timer to log data every 1h20m30s50ms |
92 |
| - run_every(h=1, min=20, s=30, ms=50) |
93 |
| - |
94 |
| - while True: |
95 |
| - if button_a.is_pressed() and button_b.is_pressed(): |
96 |
| - log.delete(full=True) |
97 |
| - elif button_a.is_pressed(): |
98 |
| - # Records the temperature & brightness every 00:01:20:30:50 (dd:hh:mm:ss:ms). |
99 |
| - log.add({ |
100 |
| - "temperature": temperature(), |
101 |
| - "brightness": display.read_light_level() |
102 |
| - }) |
103 |
| - display.show(Image.HAPPY) |
104 |
| - sleep(500) |
105 |
| - else: |
106 |
| - display.show(Image.CONFUSED) |
| 106 | + # Set the timer to log data every 5 seconds |
| 107 | + @run_every(s=5) |
| 108 | + def log_temp(): |
| 109 | + log.add(temp=temperature()) |
| 110 | + |
| 111 | +An example that runs through all of the functions of the log module API: |
| 112 | + |
| 113 | +.. include:: ../examples/data-logging.py |
| 114 | + :code: python |
0 commit comments