Plotting with Megunolink Pro

It is far easier to see the behaviour of sensors by looking at graphical data rather than looking at numbers that they spit out. Recently, I came across such a situation where I had to design and develop an Ozone sensor module for the company I work for.

Ozone sensors themselves are highly sensitive to ambient temperature and humidity. In other words their output changes quite a lot with ambient temperature and humidity in addition to Ozone levels in the air. Hence, it was necessary to plot the Ozone sensor readings at different ambient temperatures and humidity levels.By doing so will enable us to write temperature and humidity compensation routine for the Ozone sensor module.

The plotting of data can be done using programmes like Matlab; but there is much simpler way of doing it using a software called Megunolink Pro. This article explains how you can use Megunolink’s Time plot feature to plot the data spit out by your sensors.

Go ahead and download megunolink Pro from here. You can use the software for 30days for free which is plenty of time to play with it.

Megunolink_screenshot. Once you’ve installed Megunolink Pro and opened it, the welcome screen will look like the above screenshot. As you can see Megunolink Pro is a feature rich software but we are only going to use the time plot feature in this article.

For Megunolink to plot data, it will always expect data to arrive as a text string at the PCs comport with a given format. This format is given below.

{TIMEPLOT:channelName|data|seriesName:styleCommand|T|dataValue}

You insert your data to be plotted to above text sting and Megunolink Pro will happily plot it for you. So the next question is where to insert the data? Let’s consider the Ozone sensors I was working with. I got two Ozone sensors and a microcontroller which is measuring the analogue voltage value from ADC module from both of the sensors. The ADC values will have the range from 0 to 4095 (12bit).

Let’s plot data values coming from first Ozone sensor as Oz1 and from second sensor as Oz2 using Megunolink Pro. For the purpose of this article assume microcontroller reads 1200 and 1800 via the ADC module from Oz1 and Oz2 respectively. Now to plot these two values on the same plot we need to send below text strings via UART to the PC.

{TIMEPLOT:Ozone|data|Oz1: b-2n2|T|01200}  This string plot Oz1 data

{TIMEPLOT:Ozone|data|Oz2: r-2n2|T|01800} This string plot Oz2 data

As you can see we have replaced some text strings with our own ones from the given format to send data to be plotted on the Megaunolink. The replaced text is explained below one by one.

  •  channelName has been replaced by Ozone for both strings. This will create channel name Ozone. By using channel name you can plot all your data in one plot.  In our example above we have “Ozone” for both channel names in order to plot both of them in the same plot.
  • seriesName has been replaced by Oz1 and Oz2 in the first and second string respectively. This will create two labels(Oz1 and Oz2) on the same plot.
  • styleCommand has been replaced by two strings “b-2s2” and “r-2s2”. Megaunolink will use this string to determine how it will plot the data points on the plot. For an example “b-2n2” string tells Megaunolink to plot Oz1 data with blue colour with a dashed line thickness of 2 with square markers of size 2. On the other hand “r-2s2” string tells Megunolink to plot Oz2 data with red colour with a dashed line thickness of 2 with square markers of size 2.

More plotting styles are shown in the documentation section you can check them here. Some examples of plotting styles are given below.

  • r%2d2” : red colour dash dot dot line with thickness of 2 with diamond markers of size 2.
  • y:2×2” : yellow colour dotted line with thickness of 2 with cross markers of size 2.
  • b_2+2” : blue colour solid line with thickness of 2 with plus sign markers of size 2.

Now we have quite good understanding of the data strings that should be sent to the Megunolink  Pro to plot. 

Obviously the next question is how to construct the required data string in the code. Below is the technique I’ve used and is not the only technique available. We will see how to construct the two data strings discussed earlier i.e.
{TIMEPLOT:Ozone|data|Oz1: b-2n2|T|01200}
{TIMEPLOT:Ozone|data|Oz2: r-2n2|T|01800}
As you can see on both data strings we only need to change the dataValue to plot them on one graph. |T| in the data string tells the Megunolink Pro to use PCs time on X axis as the time stamp. This way of sending data is good enough for most of our work. In case if you need to send data more often than about 10Hz then time stamp should be provided in the data string itself. This method is not discussed in this article and interested readers can consult the documentation of the Megunolink Pro. So let’s get on with the source code. It is important to note here the purpose of writing this article is to show that anybody can use Megunolink Pro to plot data regardless of the microcontroller or the coding language used. Megunolink documentation focuses at using Arduino microcontroller to plot data but in my project I’ve used pic microcontroller. I will first break the source code into several parts for the sake of explanation. Then at the end of this article I will give the full source code. Firstly, define two string arrays with data strings which are not going to change. We can do this on top of the C  code where we assign variables.

unsigned char ozone1_data_array[50] = {“{TIMEPLOT:Ozone|data|Oz1:b-2n2|T|”} ;

unsigned char ozone2_data_array[50] = {“{TIMEPLOT:Ozone|data|Oz2:b-2n2|T|”} ;

We need two integers  to save raw adc value from the sensor. Lets name them  oz1_data and oz2_data respectively. We also need to convert this data to a string before appending it to the string that Megunolink Pro accepts. Assign two arrays for the strings and name them ozone1_text and ozone2_text.  You  can assign variables as follows in C code

unsigned int oz1_data;

unsigned int oz2_data;

unsigned char ozone_text1[7];

unsigned char ozone_text2[7];

 

Now in the main loop we need to do the following.

  • Read the sensor1 and sensor2 data to variables oz1_data and oz2_data  respectively.
  • Convert oz1_data and oz2_data value to a strings and save it in ozone_text1 and ozone_text2 arrays respectively.
  • Append ozone_text1 an ozone_text2  arrays to ozone1_data_array an ozone2_data_array respectively.
  • Finally append closing bracket ‘}’ to both ozone1_data_array and ozone2_data_array before sending it to pc’s comport via uart

The code to do the following is given below. Note I’ve used void WordToStr(unsigned int input, char *output) function to convert integer values to text since I am using MikroC to write my code. Readers can also use void uitoa(unsigned int, unsigned char *buffer) function with similar results.

ozone1_data = read_sensor1_adc(); //read ozone1 data from sensor 1

ozone2_data = read_sensor2_adc(); //read ozone2 data from sensor 2

WordToStr(ozone1_data,ozone_text1)//Make text string from ozone1_data WordToStr(ozone2_data,ozone_text2)//Make text string from ozone2_data

memcpy(ozone1_data_array, ozone_text1, 33);//copy ozone_text1 to ozone1_data_array

memcpy(ozone2_data_array, ozone_text2, 33); //copy ozone_text2 to ozone2_data_array

memcpy(ozone1_data_array+38,"}");//Append closing bracket to ozone1_data_array
memcpy(ozone2_data_array+38,"}");//Append closing bracket to ozone2_data_array

 

Uart1_Write_text(ozone1_data_array) //Transmits string to plot OZ1 data to PC Uart1_Write_text(ozone2_data_array)//Transmits string to plot OZ2 data to PC

 

That’s is pretty much to it.  I will put everything together and the full code is as below.


unsigned char ozone1_data_array[50] = {“{TIMEPLOT:Ozone|data|Oz1:b-2n2|T|”} ;
unsigned char ozone2_data_array[50] = {“{TIMEPLOT:Ozone|data|Oz2:b-2n2|T|”} ;
unsigned int oz1_data;
unsigned int oz2_data;
unsigned char ozone_text1[7];
unsigned char ozone_text2[7];
void main()
{
Uart1_Init(115200);//Configure 115200 baud rate.
while(1)
{

oz1_data = read_sensor1_adc();  //Read adc value from sensor1

oz2_data = read_sensor2_adc(); //Read adc value for sensor2

WordToStrWithZeros(oz1_data,ozone_text1);//Convert sensor1  value to string with padding zeroes in front

WordToStrWithZeros(oz2_data,ozone_text2);//Convert sensor2 value to string with padding zeroes in front
memcpy(ozone1_data_array+33,ozone_text1);//Append sensor1 string to ozone1_data_array
memcpy(ozone2_data_array+33,ozone_text2);//Append sensor2 string to ozone2_data_array
memcpy(ozone1_data_array+38,"}");//Append closing bracket to ozone1_data_array
memcpy(ozone2_data_array+38,"}");//Append closing bracket to ozone2_data_array
Uart1_Write_Text(ozone1_data_array); //Send oz1 string to pc to plot
Uart1_Write_Text(ozone2_data_array); //Send oz2 string to pc to plot
Delay_ms(1000);//Send data to pc every 1 second
}

}

The  example above is given for MikroC compiler hence functions like Uart1_init(), Uart1_Write_Text(char *array) and Delay_ms(unsigned int time) come from its  libraries. However they have following tasks in the code.

Uart1_Init() : Initialize uart with user specified baud rate

Uart1_Write_Text(char *array): Transmit array via Uart1

Delay_ms(unsigned int time): Delay in milliseconds

Readers may find the equivalent functions in their compiler documentation.
That’s it; download Megunolink Pro and give it try!