How to use Virtual Pins on RaspberryPi

Continuing the discussion from Howto for Raspberry Pi:

I will try, but it will not be a short story. It is not complex, but you need to know a few things. First of all, virtual ports are defined from the widgets point of view. You have widgets you can read from, and widgets you can write to. If you want to read from a widget then the RPi device needs to supply some data. And if you write to a widget (i.e. pushing a button or moving a slider) then your RPi device receives some data (i.e button pressed or slider at position 120) it should act upon. For real pins this interaction is out-of-the-box (the blynk box). For virtual pins to work you need to program them yourself. You need to add program code to the main.cpp file in the RPi ~/blynk-library/linux directory.

But let’s try an example first with the original main.cpp file. First of all in your blynk app, create a new project or use an existing project. Add a slider to your project canvas and connect the output to Virtual pin V1. Start blynk on your RPi the usual way, and run your project on your tablet or smartphone. Wait until everything is connected and then move the slider. In the terminal window of your RPi you should see something like:

    [12475] Got a value: 121
    [12588] Got a value: 130
    [12695] Got a value: 139
    [12805] Got a value: 141

This is caused by data received from your slider. This is working because in the standard main.cpp file there is some simple code:

    BLYNK_WRITE(V1)
    {
       BLYNK_LOG("Got a value: %s", param[0].asStr());
    }

And this code couples the widget write to pin V1 to some action on the RPi. The function is called BLYNK_WRITE(V1) because a widget write to V1 automatically calls this function. Knowing this, you can make an educated guess of when the function BLYNK_WITE(V4) will be executed. See also the part over Virtual Pins and their datatypes and built-in conversion functions in https://github.com/blynkkk/blynk-library/blob/master/docs/Basics.md

Another blynk “built-in” function is the BLYNK_READ(Vx) function. Guess what this function is intended for. Yes, it will be called if and when a widget wants to READ some data. Another example can make this clear.

First of all add the Gauge widget to your project. Connect it with Virtual input pin V5. Set the reading frequency to 5 sec.
Then add the next code to your main.cpp (you could backup the original file if you wants):

#include <sys/times.h>    //don't forget this include file!!
BLYNK_READ(V5)
{
	time_t ticks;
	
	ticks = ((times( NULL)/10))%1024;
	BLYNK_LOG("Got a request at %d", ticks);
	Blynk.virtualWrite(V5, ticks);
}

We do know now that this function is executed if and when a widget is requesting (reading) data from virtual pin V5. And we know that the Gauge widget will do that every 5 sec. The function then reads the number of clock ticks that have passed since a fixed point in time. This is a steadily increasing number. It is then divided by 10 and calc modulo 1024, so the number stays in the range 0-1023 of the Gauge widget. We know what the BLYNK_LOG function does. The crucial statement is the Blynk.virtualWrite() function call. This is the function that will send the value of the second argument to the Virtual pin in the first argument. This is crucial for communicating values from the RPi to the widget.

Now you need to rebuild the blynk program on your RPi with the command: make clean all target=raspberry Make sure you execute this command while in the ~/blynk-library/linux directory. Start blynk the usual way on your RPi, and run the blynk project on your tablet or smartphone. Now just look at the value the Gauge is displaying. It should increment every 5 sec. You should also see the requests in the terminal window of your RPi.

Notice that it is not your RPi but the Gauge widget that determines the update frequency. So, usually it is the widget that is asking for a new value. And it is the responsibility of the RPi to deliver that value. This however is not always the case. Let us expand this last example a bit more.

In your app project, add the Value Display widget, connect the input to V6 and set the reading frequency to PUSH. This means that this widget will not ask for new values, but instead wait until the RPi pushes a new value to its virtual pin. Also add a LED to your project and connect its input to pin V2. Notice that although a LED is also a “read” widget, you cannot set its update frequency. It always works in the PUSH mode.
Then replace the BLYNK_READ(V5) function code with the following code:

#include <sys/times.h>
BLYNK_READ(V5)
{
	time_t ticks;
	
	ticks = ((times( NULL)/10))%1024;
	BLYNK_LOG("Got a request at %d", ticks);
	Blynk.virtualWrite(V5, ticks);
	Blynk.virtualWrite(V6, ticks);
	if( ticks > 511) 
		Blynk.virtualWrite(V2,255);
	else
		Blynk.virtualWrite(V2,0);
}

Again you need to rebuild the blynk program using make clean all target=raspberry Then start the program and run your project. Now you will see a few extra things. You will see the number of ticks also displayed in the Value widget. And then notice that the LED widget will light up when the tick value is above 511. Notice that we still have a BLYNK_READ() function that is executed if and when the virtual pin V5 is read from. But as response we also send value updates to virtual pins V6 and V2.

A warning: when using a “read” device in PUSH mode, make sure that you do not send updates with a to high frequency. You should use some mechanism to limit the number of pushes per second to an acceptable value. In the example I use the reading frequency of the Gauge widget coupled to virtual pin V5 to make sure that I update the value and led widgets only once per 5 seconds.

I think for now, these examples shows you how to use the virtual pins in the standard RPi environment. The rest is up to you and your imagination.

7 Likes

2 posts were split to a new topic: Need help using ACS712 on Rpi