Blynk 2.0 Virtual pin numbering issue

I observed the following behavior (HW Teensy4.1 with Ethernet shield):

> #define VIRTUAL_PIN_V30 V30 
> #define VIRTUAL_PIN_V31 V31 
> #define VIRTUAL_PIN_V32 32 
> #define VIRTUAL_PIN_V33 33 

up to V31 the compiler works. As soon as I try to declare

#define VIRTUAL_PIN_V32

with V32 the compiler has an error says “V32 is not declared” same happens until V39 . Starting with V40 it works again …
Any Idea ?

Seeing your entire sketch might help.

Also, when you post code to the forum please don’t use blockquotes as you have above.
Code should have triple backticks on an empty line above and below the block of code. Triple backticks look like this:



There seems to be more strange issues with virtual pins and Automations:
e.g. if I use virtual pin number >= 32 meaning (not in count but as value) e.g. V32 or 32 to V40 or 40 in the receiving datastream the values are updated via Automations (seen in the web interface datastreams) but not in the target HW. ( → Blynk_Write will be not called). Changing the values of Virtual Pins to V31 and below it works ! ( Compiler shows no error)
Receiving Target is TEENSY4.0 - BTW with TEENSY4.1 it works as expected.
( Sorry Pete I can not post the Sketch it is too large)

I think I’ve suggested to you before that when you face issues like this, you should create a cut-down version of the sketch which included all of library includes etc, and has sufficient code to demonstrate the issue.

What you’re doing here with aliases for the virtual pins makes no sense whatsoever. Why are you taking this approach?


What you’re doing here with aliases for the virtual pins makes no sense whatsoever. Why are you taking this approach?

I’m wondering about your comment, just following the many examples naming them V1 etc.

Here an abstract: VIRTUAL_PIN_V9 is called, VIRTUAL_PIN_V32 not

#define BLYNK_PRINT Serial
#define BLYNK_TEMPLATE_ID "xxx"
#define BLYNK_DEVICE_NAME "xxx"

#define BLYNK_AUTH_TOKEN "xxx"

#include <SPI.h>
#include <Ethernet2.h>
#include <BlynkSimpleEthernet2.h>

#define VIRTUAL_PIN_V0 V0   
#define VIRTUAL_PIN_V1 V1   
#define VIRTUAL_PIN_V2 V2   
#define VIRTUAL_PIN_V3 V3   
#define VIRTUAL_PIN_V4 V4   
#define VIRTUAL_PIN_V5 V5   
#define VIRTUAL_PIN_V6 V6   
#define VIRTUAL_PIN_V7 V7   
#define VIRTUAL_PIN_V8 V8   
#define VIRTUAL_PIN_V9 V9   

#define VIRTUAL_PIN_V32 V32 
#define VIRTUAL_PIN_V33 V33 
#define VIRTUAL_PIN_V34 V34 
#define VIRTUAL_PIN_V35 V35 

char auth[] = "xxx";       // Blynk IoT

void setup() {
  // put your setup code here, to run once:

void loop() {
  // put your main code here, to run repeatedly:;

  double TDS_181 = param.asDouble(); 
       Serial.print("value1 : ");   
  double TDS_281 = param.asDouble(); 
       Serial.print("value2 : ");   

I think the issue here is that the BlynkHandlers.h file in the Blynk library contains a list of virtual pin translations, and this is an extract…

#define V28 28
#define V29 29
#define V30 30
#define V31 31
#ifdef BLYNK_USE_128_VPINS
  #define V32 32
  #define V33 33
  #define V34 34
  #define V35 35

So, if #ifdef BLYNK_USE_128_VPINS is false then the maximum useable variable pin number is V31, which is why V32 is not recognised in your case.

I believe that this done to ensure that devices with lower memory aren’t bloated by the library.

I think (and I’ve not really studied this) that the BlynkDetectDevice.h library file decides which type of device should have more virtual pins, and which should have less. As far as I know, this is device detection is done with the pre-defined constants that are passed from the compiler and come from the board definition files, so will vary depending on which board type you choose in the IDE when compiling the device.

I think you can override the BlynkDetectDevice.h default for your board type by adding this line to your sketch…

#define BLYNK_USE_128_VPINS

You should probably add it after #define BLYNK_DEVICE_NAME "xxx" and before #include <BlynkSimpleEthernet2.h>

The Blynk sketch builder examples will normally use BLYNK_WRITE(V9) rather than creating an alias for V9.

Aliases can be very useful, but not the way you’ve used them.

What you’re doing here:

#define VIRTUAL_PIN_V9 V9

is creating an alias called VIRTUAL_PIN_V9 and telling the compiler that every time it sees this alias it should replace it with V9 during the compilation process.
However, there’s no benefit to doing this. The whole point of using aliases is that it:

a) Makes the code easier to read and
b) Allows a pin assignment (virtual or physical) to be changed in one “lookup table” rather than having to change every occurrence in the sketch

For example it’s common to create descriptive aliases for physical pins like this:

// Physical pins:
#define power_relay     4
#define DHT_pin        14
#define error_LED       2

With this type of arrangement, if you want to swap your relay from physical pin 4 to pin 5 on your board you just make one change, to the:
#define power_relay 4
line of code, rather than having to do a find/replace on your sketch, which isn’t easy as the number 4 may occur in may different places in the sketch, many of which will have nothing to do with your reference to a pin number.
It also makes code easier to follow when you do things like:

virtualWrite (power_relay, LOW);

and even better, if your relay is active LOW, as it’s turned-on by pulling the pin LOW, which is counter-intuitive. so, if you add aliases like:

#define on LOW
#define off HIGH

then your code could look like this:

virtualWrite (power_relay, on);

That way, switching to a different type of relay would only need you to swap your on/off aliases around to achieve the same functionality.

Adding aliases for virtual pins isn’t as common, but can be useful for the same reasons. If you created aliases like this:

// Virtual pins for widget controls:
#define on_off_switch_widget   V1
#define status_led_widget      V2
#define delay_slider_widget    V3
#define pause_button_widget    V4

The you could have code like:



Blynk.virtualWrite(status_led_widget, 1) or Blynk.virtualWrite(status_led_widget, on) with an additional alias for on

Including the virtual pin number in the alias makes no sense, as if you wanted to change the virtual pin number you’d either have to change all of the aliases too, or live with mis-matched and confusing aliases.
Which is why I said…


Thanks Pete, great explanation !
Hope you get well paid for your excellent support for all Blynkers

1 Like

That would turn this into a job, and I’m totally over the whole idea of working for a living.
Blynk do give me a free Pro subscription though, which is nice.


I tried to do so, it worked in a way that I do not have any compiler error anymore and the values of the virtual pins higher than 31 are visible in the Dashboard when changing them in the APP but whats not working is that e.g.
BLYNK_WRITE(WZ_slider_s) {...}
is called when a value has been changed

somebody any idea what can I do ?

What happens if you change your example sketch and remove all of the BLYNK_WRITE() functions and add this instead…

  Serial.println(;      // Which virtual pin
  Serial.println(param.asInt();  // Get the value from the virtual

Is it triggered when you change the value of a virtual pin >31 with a widget on the dashboard.


thanks Pete, this is a great idea and its working :slight_smile:

Okay, that’s good.
You could use the switch/case command to call the appropriate function when a certain virtual pin is triggered.