-
Notifications
You must be signed in to change notification settings - Fork 953
Project Editor
The Project Editor in Serial Studio allows you to create and customize JSON Project Files that define your dashboard's layout and data mapping. It provides a graphical interface to easily manage groups, datasets, actions, and frame parsing logic.
The Project Editor consists of the following key elements:
- Tree View: Displays the structure of your project, including groups, datasets, and actions. Clicking on an item will bring up its specific view in the right panel.
- Toolbar: Provides buttons to create a new project, open an existing project, save your project, and add various widgets and components to the project.
- Detail Views: The main area where the details of the selected tree item are displayed and configured. Depending on the selection in the tree view, different views will be shown (e.g., project view, group view, dataset view, action view, or frame parser function).
The Toolbar in the Project Editor allows you to quickly add new components to your project:
- New: Start a new project from scratch.
- Open: Open an existing JSON Project File.
- Save: Save the current project to a JSON file.
- Add Action: Add a button to the dashboard that sends specific data to the device when clicked.
- Add Data Grid: Add a data grid widget to the dashboard (used for displaying datasets in a table format).
- Add Multiple Plots: Add a group with multiple plots for visualizing datasets.
- Add Accelerometer: Add an accelerometer widget to the dashboard for displaying X, Y, Z axis data.
- Add Gyroscope: Add a gyroscope widget to the dashboard for displaying rotational data.
- Add Map: Add a map widget for GPS-based datasets (latitude, longitude, altitude).
- Add Container: Add a container group to organize datasets without displaying a specific widget.
The Tree View on the left side of the Project Editor shows the hierarchical structure of your project. It consists of:
- The Project Root (which represents the entire dashboard project).
- Groups: These are collections of datasets that will be displayed together in a widget.
- Datasets: Individual data values within a group that are mapped to incoming sensor data. Each dataset item in the tree view also displays an [IDX n] label to the right, where n is the index of the dataset value, starting from 1.
- Actions: Buttons that trigger specific commands when clicked by the user.
Clicking on any of these items will load the corresponding view in the main panel, where you can configure its parameters.
Clicking on an item in the Tree View opens a specific view in the detail panel. These views allow you to configure different aspects of your project.
The Project View allows you to set general properties of the project, such as:
- Project Title: A name for the project.
-
Frame Detection: Define the frame detection method to use, includes Start + End Delimiter, End Delimiter Only and No Delimiters.
-
End Delimiter Only: Ideal for scenarios where only an end delimiter (e.g.,
\n) is needed to process frames. - Start & End Delimiter: Useful for projects that require both delimiters for more precise frame handling.
- No Delimiters: Handle data as-it-comes and feed it directly to the frame parser function. Ideal for custom communication protocols.
-
End Delimiter Only: Ideal for scenarios where only an end delimiter (e.g.,
- Frame Delimiters: If applicable, define the start delimiter and end delimiter to identify and separate frames of data received from the device.
-
Conversion Method: Choose how the data inside the frame delimiters should be processed. The available methods are:
- Normal (UTF8): Default text-based data processing.
- Hexadecimal: This option is useful if your device sends binary data in hex format. Combined with a custom frame parser function, this can allow you to interpret and display binary data on the dashboard.
- Base64: Use this method to encode incoming data in Base64 before passing it to the frame parser function.
- Thunderforest API Key: Optional key for using Thunderforest map services in your project.
- MapTiler API Key: Optional key for using MapTiler map services in your project.
These options give you control over how the incoming data is handled, allowing you to customize your setup for more complex requirements such as binary data processing (example), key/value frames (example) and interacting with external map services.
When you select a group in the Tree View, the Group View is displayed, allowing you to:
- Title: Set the title for the group.
- Widget: Choose the widget that will represent this group (e.g., multiple plots, accelerometer, data grid, etc.).
A secondary toolbar is available when viewing a group. This toolbar allows you to add datasets to the group, duplicate the group or delete it.
When you select a dataset in the Tree View, the Dataset View is displayed, allowing you to configure individual datasets:
- Title: The label that will be displayed for this dataset.
- Units: The measurement units for the dataset (e.g., °C, %, etc.).
- Index: The position of the dataset in the incoming frame (this value tells the software which part of the data frame maps to this dataset).
- Min/Max Values: Set the range for widgets like gauges and bars.
- Widget Type: Choose how this dataset will be visualized (e.g., plot, gauge, bar).
A secondary toolbar is available in the Dataset View to toggle dataset parameters. Here, you can configure the plotting options & easily set the widget used to display the dataset. As with the group view, you can also duplicate the dataset and/or delete it.
The Frame Parser Function View allows you to customize how incoming data frames are parsed. This view contains a JavaScript editor where you can write or modify the function that processes the incoming data based on your project’s needs.
Frames are parsed according to the frame detection method, start delimiter and end delimiter that are configured in the project settings (in the Project View). The input passed to the frame parser function is only the data contained inside the frame, and the function is charge of transforming the frame data into an array that can later populate the values for each dataset in your project.
You can read more about this in the Data Flow in Serial Studio page.
$1023,512,850,300,45;
In this example:
-
Start Delimiter:
$ -
End Delimiter:
;
The data inside the delimiters is: 1023,512,850,300,45.
This string (1023,512,850,300,45) will be passed to the frame parser function and split using the comma as a separator, resulting in the following array:
["1023", "512", "850", "300", "45"]The frame parser function will return this array to Serial Studio, which later uses it to update the dashboard model.
You can declare global variables outside the frame parser function, allowing them to persist between function calls. This is useful for maintaining state or configuration across multiple frames. By using global variables, you can customize the behavior of the frame parser for more complex projects, such as when you need to handle multiple frame types or formats within a single project.
function parse(frame) {
return frame.split(',');
}This default parser simply splits the incoming data frame into individual elements using a comma (,) as a separator. However, you can modify this function to handle more advanced parsing needs, such as binary data processing, custom frame formats, or pre-processing the incoming data.
parse(frame), changing the function name or adding/removing arguments will result in a runtime error.
To help debug your Frame Parser Function, you can use the console.log() function to print messages to the terminal. This allows you to monitor the execution of your parser function and inspect the values of variables or the structure of the data being processed. Debugging with console.log() is especially useful when customizing the frame parser for more complex data formats.
function parse(frame) {
// Log the received frame and separator to the terminal
console.log("Received frame: " + frame);
console.log("Using separator: " + ',');
// Split the frame based on the separator and log the result
let parsedValues = frame.split(',');
console.log("Parsed values: " + JSON.stringify(parsedValues));
// Return the parsed values
return parsedValues;
}In this example:
- The
console.log()function prints the raw frame data, the separator being used, and the parsed values as an array. - This helps you debug the function by observing the data flow and ensuring that the function behaves as expected.
The Action View is where you configure actions, which are buttons displayed on the dashboard. These buttons can be used to send specific commands or data to your device when clicked by the user. Each action is fully customizable, from its label and icon to the data it sends.
- Title: The label displayed on the button.
- Icon: The icon that will be displayed on the button.
- Data to Send: The specific data or command that will be sent to the device when the button is clicked.
-
EOL Character: The End-of-Line (EOL) character appended to the data. This can be useful for commands that require a specific ending (e.g., newline
\n, carriage return\r, etc.).
Imagine you have an embedded system where sending the string RESET\n to the device will trigger a device reboot. You could create an action button for this:
- Title: Reset Device
- Icon: (choose any icon representing a reset action)
-
Data to Send:
RESET -
EOL Character:
\n(newline)
When this action button is clicked on the dashboard, it sends the command RESET\n to the device.
Once you have finished setting up your project:
- Click Save on the toolbar to save the project to a JSON file.
- This file can then be loaded by Serial Studio to visualize data according to your project's configuration.
In this tutorial, we will walk you through how to use Serial Studio to visualize analog sensor data from an Arduino using the Project Editor and a custom frame parser.
- Arduino (with at least 6 analog input ports, e.g., Arduino Uno)
- Serial Studio
- USB cable to connect the Arduino to your computer
First, upload the following code to your Arduino. This sketch reads values from the six analog pins (A0 to A5) and sends the values as a comma-separated string over serial, wrapped with start and end delimiters.
void setup() {
// Initialize serial communication at 115200 baud
Serial.begin(115200);
}
void loop() {
// Read analog values from all ADC ports (A0 to A5 on most Arduinos)
int sensorValue1 = analogRead(A0);
int sensorValue2 = analogRead(A1);
int sensorValue3 = analogRead(A2);
int sensorValue4 = analogRead(A3);
int sensorValue5 = analogRead(A4);
int sensorValue6 = analogRead(A5);
// Send start delimiter
Serial.print("/*");
// Send the values as a comma-separated string
Serial.print(sensorValue1);
Serial.print(",");
Serial.print(sensorValue2);
Serial.print(",");
Serial.print(sensorValue3);
Serial.print(",");
Serial.print(sensorValue4);
Serial.print(",");
Serial.print(sensorValue5);
Serial.print(",");
Serial.print(sensorValue6);
// Send end delimiter
Serial.print("*/");
Serial.print("\n");
// Small delay between readings
delay(1);
}- Download and install Serial Studio (if you haven’t already) from the releases page.
- Connect your Arduino to your computer via USB.
- Open Serial Studio.
- In Serial Studio, open the Project Editor by clicking on the Project Editor button in the toolbar.
- Click New to create a new project.
- Set a Project Title (e.g., "Arduino Sensor Data").
- Set the Frame Detection to Start + End Delimiters.
- Configure the Frame Delimiters:
-
Start Delimiter:
/* -
End Delimiter:
*/
-
Start Delimiter:
- Add a new Group by clicking the Add Multiple Plots button in the toolbar.
- For each analog input (A0 to A5), add a dataset:
- Click the Add Dataset button in the Group View.
- Set the Title to something descriptive (e.g., "Sensor 1", "Sensor 2", etc.).
- Set the Index value:
- A0 -> Index 1
- A1 -> Index 2
- A2 -> Index 3
- A3 -> Index 4
- A4 -> Index 5
- A5 -> Index 6
- Choose the plot type (e.g., FFT Plot).
If you want to customize the frame parser function, go to the Frame Parser Function View. By default, the function will split the data using the comma character (,) as a separator, but you can add custom logic if needed.
Here’s the default function:
/**
* Splits a data frame into an array of elements using a comma separator.
*
* Use this function to break a string (like "value1,value2,value3") into
* individual pieces, which can then be displayed or processed in your project.
*
* @param[in] frame A string containing the data frame.
* Example: "value1,value2,value3"
* @return An array of strings with the split elements.
* Example: ["value1", "value2", "value3"]
*
* @note You can declare global variables outside this function if needed
* for storing settings or keeping state between calls.
*/
function parse(frame) {
return frame.split(',');
}- Go back to the Setup Panel in Serial Studio.
- Select the Serial input method.
- Choose the correct serial port (the one your Arduino is connected to).
- Set the baud rate to 115200 (to match the baud rate in the Arduino code).
- Click Connect.
Once connected, the data will start streaming in real time, and the dashboard will display the sensor readings for each analog input. You should see the values changing as you adjust the inputs (e.g., by connecting different sensors or adjusting the input voltage).
- Upload the provided Arduino code to your board.
- Open Serial Studio and create a new project.
- Set the frame delimiters and separator.
- Add datasets for each analog input (A0 to A5).
- Optionally, customize the frame parser function.
- Connect to your Arduino and start visualizing the sensor data.
This tutorial gives you a simple way to visualize real-time data from your Arduino using Serial Studio. You can expand on this by adding more sensors or customizing the dashboard further.
Choosing the right widget for your data is important for effective visualization. Here's a quick reference:
For continuous values changing over time:
- Plot - Line graph showing trends over time
- Multiple Plots (group widget) - Compare multiple values on same timeline
For bounded values (0-100%, 0-255, etc.):
- Bar - Horizontal progress bar
- Gauge - Circular speedometer-style display
- Level - Vertical thermometer-style display
For position/orientation data:
- GPS Map (group) - Latitude/longitude on interactive map (requires 2-3 datasets: lat, lon, optional alt)
- Accelerometer (group) - 3D visualization of X, Y, Z acceleration (requires exactly 3 datasets)
- Gyroscope (group) - 3D visualization of rotation rates (requires exactly 3 datasets)
- Compass - Heading/bearing display (0-360°)
For frequency analysis:
- FFT Plot - Frequency spectrum (automatically performs FFT on incoming data)
For status indicators:
- LED Panel (group) - Color-coded status lights for multiple binary/status values
- Data Grid (group) - Table showing all values with titles and units
For advanced visualization (Pro):
- 3D Plot - X, Y, Z coordinates in 3D space (requires exactly 3 datasets)
- XY Plot - Y vs X correlation/phase diagrams (requires exactly 2 datasets)
Need more details? See the complete Widget Reference for requirements, examples, and use cases for all widgets.
Problem: Widget shows "0" or wrong data
Cause: Dataset indices don't match the parser function's return array positions
Solution:
- Dataset with index 1 = array position 0
- Dataset with index 2 = array position 1
- etc.
Example:
function parse(frame) {
return ["temp", "humidity", "pressure"];
// index 1 index 2 index 3
}Problem: Console shows "undefined" or parsing errors
Cause: JavaScript syntax errors or incorrect return value
Solution:
- Check console for error messages (red text)
- Add
console.log()to debug:
function parse(frame) {
console.log("Input:", frame);
let result = frame.split(',');
console.log("Output:", result);
return result;
}- Ensure you always return an array (not string, object, or undefined)
Problem: Frames not being detected or split incorrectly
Cause: Delimiters don't match what device actually sends
Solution:
- Check raw console output to see actual delimiters
- Common delimiters:
-
\n(newline) - Most common -
\r\n(Windows line ending) - Custom characters (e.g.,
$for start,#for end)
-
- Use hex view in console to see hidden characters
Problem: Widget doesn't display data properly
Cause: Widget type doesn't match data characteristics
Solution:
- Don't use Gauge for text data
- Don't use Bar for unbounded values
- Don't use Accelerometer unless you have exactly 3 datasets (X, Y, Z)
- See Widget Selection Guide above
Problem: Group widget shows error or doesn't appear
Cause: Widget requires specific number of datasets
Solution:
- GPS Map: Needs 2-3 datasets (lat, lon, optional alt)
- Accelerometer/Gyroscope: Need exactly 3 datasets (X, Y, Z)
- 3D Plot (Pro): Needs exactly 3 datasets (X, Y, Z)
- XY Plot (Pro): Needs exactly 2 datasets (X, Y)
Problem: 3D widgets don't work or show errors
Cause: Graphics card doesn't support OpenGL or drivers are outdated
Solution:
- Update graphics drivers
- Check if running in virtual machine (VMs often don't support OpenGL)
- Use 2D widget alternatives if OpenGL not available
✅ Good: "Temperature (°C)", "Battery Voltage (V)", "Motor RPM"
❌ Bad: "Dataset 1", "Value", "Data"
// If temperature range is 0-50°C
Min: 0
Max: 50
// Don't leave auto-scale - it wastes the gauge's range- Record a session with real data
- Export to CSV
- Use CSV Player to test your project without hardware connected
- Iterate on your dashboard design
// Parse custom binary protocol
// Format: [temp_high, temp_low, hum_high, hum_low]
function parse(frame) {
let temp = (frame[0] << 8) | frame[1]; // Combine bytes
let humidity = (frame[2] << 8) | frame[3];
return [temp / 10.0, humidity / 10.0]; // Convert to actual values
}- Widget Reference - Complete guide to all widget types
- JavaScript API Reference - Full parser function documentation
- Data Flow - Understanding how data flows through Serial Studio
- Operation Modes - Different ways to use Serial Studio
- Troubleshooting Guide - Solutions to common problems
- Examples - Real-world project examples
Need help? Check the Troubleshooting Guide or ask on GitHub Discussions!
If you find Serial Studio helpful, please consider supporting the project:
Your support helps keep the project growing, maintained, and continuously improved.