How to create Virtual Analog Channels

Introduction

This chapter will cover how to create a Virtual Analog Channel (or VAC). This feature allows you to plot values - mainly while decoding - instead of simply displaying them on a channel inside boxes (decoder items). Indeed, plotting values on a graph is sometimes the best way to see meaningful information.

Keep in mind that most of the parameters (color, size…) can be changed directly in ScanaStudio, using the display settings. Thus, even if you define them using the functions below, the user is able to modify them at any time. To know more about how to use VACs in ScanaStudio, please read this page.

VAC global

VAC operation

Each protocol decoder implementing VACs should attribute a unique ID to each VAC. Internaly, ScanaStudio will automatically generate a globally unique ID compsed of the VAC ID and the Decoder ID. The main reason behind this is to allow several decoders to control their “child” VACs simultaneously.

Consequently, on a decoder script level, you can identify any number of VACs with the ID that you have aribrarly given to them, without any risks of conflict even if other protocol decoders implement the same IDs.

Ultimately, even if you duplicate the same protocol decoder several times in the same workspace (wich is perfectly legal and meaningful if you need 3 PWM decoders), there won’t be any conflicts between those instances of the same decoder.

Botom line: You only need to attribute a unique ID within the scope of your script for each individual VAC.

ScanaStudio.vac_create_channel(VAC_index,unit,color,title)

Description: This function creates a new VAC, which will display a graph.

Parameters:

  • VAC_index: VAC index (0-based, i.e. first index is 0),
  • unit: unit of values you want to plot, like m/s or Deg C,
  • color: the HTML color of your curve and your VAC. A color must be described by its hexadecimal value (6 digits/letters), for example the basics:
    • White: #FFFFFF,
    • Yellow: #FFFF00,
    • Red: #FF0000,
    • Blue: #0000FF.
  • title: the VAC’s title. That title will be displayed as the channel name.

Context: Protocol decoder.

ScanaStudio.vac_remove_channel(VAC_index)

Description: This function removes a VAC.

Parameters:

  • VAC_index: index of the VAC you want to remove (0-based, i.e. first index is 0).

Context: Protocol decoder.

ScanaStudio.vac_set_size(VAC_index, size_factor)

Description: This function sets the size of a VAC previously created.

Parameters:

  • VAC_index : VAC index (0-based, i.e. first VAC index is 0),
  • size_factor : the height of the VAC in ScanaStudio signal area, between 0 and 5.

Context: Protocol decoder.

ScanaStudio.vac_set_color(VAC_index, color)

Description: This function sets the color of a VAC previously created.

Parameters:

  • VAC_index: VAC index (0-based, i.e. first VAC index is 0),
  • color: the HTML color of your curve and your VAC. A color must be described by its hexadecimal value (6 digits/letters).

Context: Protocol decoder.

ScanaStudio.vac_set_unit(VAC_index, “unit”)

Description: This function sets the unit of a VAC previously created.

Parameters:

  • VAC_index: VAC index (0-based, i.e. first VAC index is 0),
  • unit: unit of values you want to plot,

Context: Protocol decoder.

ScanaStudio.vac_append_sample(VAC_index, sample_inex, value)

Description: This function appends samples to a VAC previously created.

Parameters:

  • VAC_index: VAC index (0-based, i.e. first VAC index is 0),
  • sample_inex: The sample index corresponding to the value to be displayed. This will set the horizontal position of the plotted point in the graph,
  • Value: the value of the samples you want to append.

Context: Protocol decoder.

Example VAC for Temperature and Humidity sensors

Purpose

In this part, we’ll look at an example VAC implementation. In this example, we’ll modify the I2C - Temperature and Humidity sensors protocol to display the temperature and the humidity obtained from a sensor with two different VACs, one for temperature, and the other for humidity. To start, you have to open the i2c-temperature-humidity.js file in your local scripts folder.

Create a VAC

First, you have to create your VACs in function on_decode_signals(resume). To quickly summarize, for the first entrance into this function, the boolean resume is false (or !resume). Thus, it’s at this moment that we can initialize the values you want to use later to decode ; in our case, this is where we will create the VACs.

Here, we want to add two VACs to display the temperature and the humidity given by an I2C frame. In this example, we will set the parameters as shown below :

function on_decode_signals (resume)
{
    if (!resume) //If resume == false, it's the first call to this function.
    {
        //...other exiting code here...
        ScanaStudio.vac_create_channel(0, "°C", "#118c8c", "Temperature");
		ScanaStudio.vac_set_size(0, 5);

		ScanaStudio.vac_create_channel(1, "%", "#1938de", "Humidity");
		ScanaStudio.vac_set_size(1, 5);
    }
    //...other exiting code here...
}

Add samples to VACs

Find where the data is created

Now it’s time to create the samples to be appended in the VACs. First, you have to understand where (and when) the I2C frame’s data are created. In our example, it’s done by calling process_i2c_item(i2c_items[i]) when a new data is decoded. Thus, the data is built in the entry-point function on_decode_signals(resume) :

function on_decode_signals(resume)
{
    //...code here hidden for simplicity
    var i2c_items = ScanaStudio.pre_decode("i2c.js",resume);
    for (i = 0; i < i2c_items.length; i++)
    {
        //...code here hidden for simplicity
        process_i2c_item(i2c_items[i]);
    }
}
Append samples to VACs

Appending samples in the VACs will therefore be done in function process_i2c_item(item), especially in I2C_FRAME.DATA_LSB. The displayed value are get_value_temperature(data_word) for temperature and get_value_rh(data_word) for humidity. The start word is item.start_sample_index.

function on_decode_signals (resume)
{
    //...code here hidden for simplicity...
    process_i2c_item(i2c_items[i]);
    //...code here hidden for simplicity...
}

function process_i2c_item(item)
{
  //...
  /*If it's a start, re-start, stop, ACK or NACK*/
  //...

  else //It's any other address or data byte
  {
    //...
    switch (frame_state)
    {
      case I2C_FRAME.ADDRESS:
          //...
      break;

      case I2C_FRAME.CMD:
          //...
      break;

      case I2C_FRAME.DATA_MSB:
          //...
      break;

      case I2C_FRAME.DATA_LSB:

          data_word = data_word | byte;
          var measure;
          var measure_type;

          //Last two LSBs define the measurement type

          if ((byte & 0x03) == 0) //Temperature
          {
              measure = get_value_temperature(data_word) + "°C";
              measure_type = "(T)";
    					ScanaStudio.vac_append_sample(0, item.start_sample_index, get_value_temperature(data_word));
  				}

          else if ((byte & 0x03) == 2) //Humidity
          {
              measure = get_value_rh(data_word) + " %";
              measure_type = "(RH)";
    					ScanaStudio.vac_append_sample(1, item.start_sample_index, get_value_rh(data_word));
          }

          //...

          break;
      case I2C_FRAME.CHKSUM:
          //...
      break;
      default: break;
    }
  }
}

Conclusion

This chapter shows how to use the Virtual Analog Channels feature of ScanaStudio. You can easily test-drive this feature either by adding the i2c-temperature-humidity script in a demo workspace or by capturing real I2C signals from an existing sensor board and adding the i2c-temperature-humidity protocol decoder.

Decoded I2C packets should generate VAC channels as shown below:

VAC global