This guide explains how to set up es:scope® with es:prot™. With this setup you can observe, validate, and adjust the behavior of runtime variables in your embedded device under test.
es:prot™ is a C-based middleware solution designed for use with embedded systems. It establishes a connection to the es:scope® software, managing commands, signals and data flow. It is independent of both hardware and communication interfaces.
The middleware enables you to add 'virtual probes' and 'virtual knobs' to your code, which can then be accessed via es:scope®. These enable you to send variables as real-time measurement signals at defined sampling rates, as well as receive parameters and commands for making adjustments during runtime.
Setting es:prot™ up involves three steps:

es:prot™ is available as open C code. As it is both hardware- and interface-agnostic, you can simply include it in your project. In step two it is then configured for your chosen interface.
To include it in your project:
es_prot.h in your main source file.#include "es_prot.h"
The folder structure should look like this:
es_prot.h Header file you have to include in your main application.es_prot_config.h Header file, where you can configure the protocol preferences.color_def.h Header file containing color definitions.es_prot.c Source code of the protocol.The configuration tells es:prot™ how to work within your chosen communication interface (e.g., SPI, UART, USB). Using DMA is recommended for performance optimization.
Modify es_prot_config.h with at least these settings:
N_TX_SIGNALS Number of signals to be transmitted from the embedded system to the computer.N_RX_SIGNALS: Number of signals to be transmitted from the computer to the embedded system.MAX_COMM_BUFFER_DIM: Maximum buffer size in bytes to be allocated for your communication interface.PROCESS_FREQUENCY: Frequency of the process which sends out the data, e.g. a timer-based interrupt routine.COMM_DEV_BAUDRATE: Transmission speed in baud/s of your communication interface.es:prot™ is communication interface-agnostic. To use it which your chosen interface, you must supply two functions: one to start a transfer and one to check its status.
es_start_data_transfer() → Hands transmission and reception buffer pointers to your communication driver.es_get_transfer_status() → Reports when the data transfer has finished.Recommended: Use DMA in
es_start_data_transfer()for better performance.
Example (SPI with DMA on an STM32 Microcontroller):
void es_start_data_transfer(uint32_t buffer_size, uint8_t *tx_data_buff, uint8_t *rx_data_buff) {
HAL_SPI_TransmitReceive_DMA(&hspi3, (uint8_t*) tx_data_buff, (uint8_t*) rx_data_buff, (uint16_t) buffer_size);
};
uint8_t es_get_transfer_status()
{
if (HAL_SPI_GetState(&hspi3) == HAL_SPI_STATE_READY)
return 1;
else
return 0;
};
es:prot™ does not rely on debug symbols or ELF parsing. Instead, you define signals directly in your code by name, type, and update. You can read from and write to global es:prot™ buffers from any part of your code.
Steps:
es_prot to contain these buffers.es_prot_init_struct(volatile es_prot*) in your main() setup.es_prot_set_tx_data_info().es_prot_set_rx_data_info().main() setup.At runtime, es:prot™ sends a description of all configured signals to es:scope, enabling plug-and-play setups.
Example of a setup (FTDI SPI-USB):
volatile es_prot USB_COMM; // Create a variable of type ’es_prot’. In this example it is called USB_COMM.
void es_prot_set_tx_data_info(...){...} // Your function from before
uint8_t es_get_transfer_status(){...} // Your function from before
void main {
...
// Provide your es_prot struct
es_prot_init_struct(&USB_COMM );
// Configure all the tx signals you want to use
es_prot_set_tx_data_info(&USB_COMM,0,SCALING_FACTOR_APPLIED,TYPE_FLOAT,"i_d",PLOT_NR_1,1.0,4,BLACK);
es_prot_set_tx_data_info(&USB_COMM,1,SCALING_FACTOR_APPLIED,TYPE_FLOAT,"i_q",PLOT_NR_1,1.0,4,BLUE);
// Configure all the rx signals you want to use
es_prot_set_rx_data_info(&USB_COMM,0,"gain");
// Start the communication
es_prot_init_comm(&USB_COMM);
...
}
To exchange the buffers between the middleware and the es:scope® software, you need to call the manager function. Ideally, you should call it in a dedicated timer interrupt, which should run at the frequency defined in es_prot_config.h.
These commands should respect the transmission rates you’ve defined in configuration.
es_prot_manager() → Transmit the buffers between es:scope® and es:protOnce initialized, you can use the utilty functions anywhere in your code.
The most important utilities are:
es_prot_write_tx_value() → Write a signal to the bufferes_prot_get_rx_value() → Get a parameter from the bufferuint8_t p_parameter;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
// Catch the measurements after each PWM cycle
if (htim == &htim6)
{
es_prot_write_tx_value(&USB_COMM, 0, get_i_d());
es_prot_write_tx_value(&USB_COMM, 1, get_i_q());
es_prot_manager(&USB_COMM);
p_parameter = es_prot_get_rx_value(&USB_COMM, 0);
}
}
Once es:prot™ is running on your device, es:scope® lets you connect, configure, and start introspection.
Download the installer or files (Windows/Linux) and follow the setup process. Visit the download page here.

Before using es:scope, activate your license:

In es:prot™ the signal management is preconfigured as code. But the signals can also be reconfigured in es:scope.

In the stream tab all received signals are shown (left side). They are associated with plots (right side).
The Play/ Pause button on the top left of every window controls the signal reception.
Add a plot window:
es:scope® supports signal plots X-Y plots, and FFT plots. Using these plot types is similar to using signal plots with small exceptions:
| Property | Signal plot | X-Y plot | FFT plot |
|---|---|---|---|
| Types | One | One | Amplitude, Power, Power (dB) |
| Association | Single signal | Signal pair | Single signal |
| Statistics | Yes | No | Yes |
Focus a plow window
Associate a signal to a plot window
Toggle the signal reception active