BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

Code not working

Arduino UNO with USB; iOS 14; Blynk library 0.6.1.

Hi, I’m trying to relay a numerical input across 2 widgets. The user inputs a value into the numerical input widget, selects an option from a menu widget and the code is supposed to loop for the number of times that the user input. Currently when I run the code the loop doesn’t even run, could somebody help me with this please? My code is as follows:

#include <BlynkSimpleStream.h>
#include <SoftwareSerial.h>
SoftwareSerial SwSerial(2, 3); // RX, TX

char auth[] = "-----";

int NumTrialsInput = 10;

/*This function will be called every time Numeric Input Widget
  in Blynk app writes values to the Virtual Pin V1
*/

BLYNK_WRITE(V1)
{
  int NumTrialsInput = param.asInt(); // assigning incoming value from pin V1 to variable NumTrials

  // process received value
}

// This function will be called every time Menu Widget
// in Blynk app writes values to the Virtual Pin 0
BLYNK_WRITE(V0) {
  switch (param.asInt())
  {
    case 1: // Item 1
    SwSerial.println("Accuracy trials selected");
      void Accuracy ();
      break;
    case 2: // Item 2
    SwSerial.println("Reaction time trials selected");
      void Reactiontime ();
      break;
    default:
      SwSerial.println("Unknown item selected");
  }
}

void Accuracy() {
  for (int i = 0; i < NumTrialsInput; i++) { //loops for number of trials that coach inputs

    delay(2000); //constant delay time of 2s before next LED turns on

    int myLed = random(2, 6); //pick a random number between 2 and 6 and store it in myLed
    digitalWrite(myLed, HIGH); //turn on the LED that corresponds to the LED just picked
    delay(3000); // leave LED on for this constant no. of secs (e.g. 3s)
    digitalWrite(myLed, LOW); //turn the LED off
    delay(2000); //leave the LED off for 2s
    // note that all timing values are arbitrary, can screen through existing waterpolo trials and find average timings currently used and change accordingly.
  }
}

void Reactiontime() {
  for (int i = 0; i < NumTrialsInput; i++) { //loops for number of trials that coach inputs

    delay(random(500, 2000)); //random delay time of .5 to 2s before LED turns on again

    int myLed = random(2, 6); //pick a random number between 2 and 6 and store it in myLed
    digitalWrite(myLed, HIGH); //turn on the LED that corresponds to the LED just picked
    delay(3000); // leave LED on for this constant no. of secs (e.g. 3s)
    digitalWrite(myLed, LOW); //turn the LED off
    delay(2000); //leave the LED off for 2s
    // note that all timing values are arbitrary, can screen through existing waterpolo trials and find average timings currently used and change accordingly.
  }
}

void setup()
{
  // Debug console
  SwSerial.begin(9600);

  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);

  // Blynk will work through Serial
  // Do not read or write this serial manually in your sketch
  Serial.begin(9600);
  Blynk.begin(Serial, auth);
}

void loop()
{
  Blynk.run();
}

You should t have int before this line of code in BLYNK_WRITE(V1),
As you’ve already defined ‘NumTrialsInput‘ as a global integer at the top of your code.

Also, you should t be using delays in your code, as the block code execution until the delay has completed. This prevents the void loop from executing and therefore prevents Blynk.run from executing.
Instead, you should be using timeout timers, preferably as a lambda function.

Pete.

Thanks for your reply Pete. I changed my delays to lambda timeout functions but am not sure if I got it right, or if I included the right libraries. currently I get a “‘myLed’ is not captured” error when I compile. This is what I have at the moment:

#include <BlynkSimpleStream.h>
#include <SoftwareSerial.h>
#include <SimpleTimer.h>

SoftwareSerial SwSerial(2, 3); // RX, TX

char auth[] = "---------";

int NumTrialsInput;
int myLed;
SimpleTimer timer;

/*This function will be called every time Numeric Input Widget
  in Blynk app writes values to the Virtual Pin V1
*/
BLYNK_WRITE(V1)
{
  int NumTrialsInput = param.asInt(); // assigning incoming value from pin V1 to variable NumTrials

  // process received value
}

BLYNK_WRITE(V2) // Button Widget writes to Virtual Pin V2
{
  if (param.asInt() == 1) {    // if Button sends 1
    Accuracy();             // start the function
  }
}

BLYNK_WRITE(V3) // Button Widget writes to Virtual Pin V3
{
  if (param.asInt() == 1) {    // if Button sends 1
    Reactiontime();             // start the function
  }
}

void Accuracy() {
  for (int i = 0; i < NumTrialsInput; i++) { //loops for number of trials that coach inputs
    int myLed = random(2, 6); //pick a random number between 2 and 6 and store it in myLed
    digitalWrite(myLed, HIGH); //turn on the LED that corresponds to the LED just picked
    timer.setTimeout(3000L, []() // leave LED on for this constant no. of secs (e.g. 3s)
    {
      digitalWrite(myLed, LOW);
    });
    timer.setTimeout(4000L, []() // leave LED off for this constant no. of secs (e.g. 4s)before next LED lights up
    {
    });
    // note that all timing values are arbitrary, can screen through existing waterpolo trials and find average timings currently used and change accordingly.
  }
}

void Reactiontime() {
  for (int i = 0; i < NumTrialsInput; i++) { //loops for number of trials that coach inputs
    int myLed = random(2, 6); //pick a random number between 2 and 6 and store it in myLed
    digitalWrite(myLed, HIGH); //turn on the LED that corresponds to the LED just picked
    timer.setTimeout(3000L, []() // leave LED on for this constant no. of secs (e.g. 3s)
    {
      digitalWrite(myLed, LOW);
    }); 
    timer.setTimeout(random(2500L,4000L), []() // leave LED off for this constant no. of secs (e.g. 4s)before next LED lights up
    {
    });
    // note that all timing values are arbitrary, can screen through existing waterpolo trials and find average timings currently used and change accordingly.
  }
}

void setup()
{
  // Debug console
  SwSerial.begin(9600);

  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);

  // Blynk will work through Serial
  // Do not read or write this serial manually in your sketch
  Serial.begin(9600);
  Blynk.begin(Serial, auth);
}

void loop()
{
  Blynk.run();
}

You should read this topic…

Pete.

I have changed by code to replace the delays with setTimeout functions, but when I input the number of trials and press the button on the Blynk app to begin the trial, 4 of the 5 LEDs simply turn on and stay that way. Can’t figure out why

#include <BlynkSimpleStream.h>
#include <SoftwareSerial.h>

SoftwareSerial SwSerial(2, 3); // RX, TX

char auth[] = "--------";

int NumTrialsInput;
int myLed;

BlynkTimer timer;

/*This function will be called every time Numeric Input Widget
  in Blynk app writes values to the Virtual Pin V1
*/
BLYNK_WRITE(V1)
{
  NumTrialsInput = param.asInt(); // assigning incoming value from pin V1 to variable NumTrials
  // process received value
}

BLYNK_WRITE(V2) // Button Widget writes to Virtual Pin V2
{
  if (param.asInt() == 1) {    // if Button sends 1
    Accuracy();             // start the function
  }
}

BLYNK_WRITE(V3) // Button Widget writes to Virtual Pin V3
{
  if (param.asInt() == 1) {    // if Button sends 1
    Reactiontime();             // start the function
  }
}

void Accuracy() {
  for (int i = 0; i < NumTrialsInput; i++) { //loops for number of trials that coach inputs
    myLed = random(2, 7); //pick a random number between 2 and 6 and store it in myLed
    digitalWrite(myLed, HIGH); //turn on the LED that corresponds to the LED just picked
    timer.setTimeout(3000L, ledoff); // leave LED on for this constant no. of secs (e.g. 3s) before turning it off
    timer.setTimeout(4000L, []() // leave LED off for this constant no. of secs (e.g. 4s)before next LED lights up
    {
    });
    // note that all timing values are arbitrary, can screen through existing waterpolo trials and find average timings currently used and change accordingly.
  }
}

void Reactiontime() {
  static int randpause;
  for (int i = 0; i < NumTrialsInput; i++) { //loops for number of trials that coach inputs
    myLed = random(2, 7); //pick a random number between 2 and 6 and store it in myLed
    digitalWrite(myLed, HIGH); //turn on the LED that corresponds to the LED just picked
    timer.setTimeout(3000L, ledoff); // leave LED on for this constant no. of secs (e.g. 3s) before turning it off
    randpause = random (2500, 4000);
    timer.setTimeout(randpause, []() // leave LED off for this constant no. of secs (e.g. 4s)before next LED lights up
    {
    });
    // note that all timing values are arbitrary, can screen through existing waterpolo trials and find average timings currently used and change accordingly.
  }
}

void ledoff () {
  digitalWrite(myLed, LOW);  // Set pin low
}

void setup()
{
  // Debug console
  SwSerial.begin(9600);

  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);

  // Blynk will work through Serial
  // Do not read or write this serial manually in your sketch
  Serial.begin(9600);
  Blynk.begin(Serial, auth);
}

void loop()
{
  Blynk.run();
}
``

Your Accuracy function has flawed logic.
Let’s say 5 trials is selected.

You go through a loop 5 times, each time selecting a random LED to turn on. The LED in question is stored as myLED but this is overwritten each time the loop executes. At the end of the loop, a random number of LEDs will be lit. This might be one LED if each of the 5 repetitions produces the same random number, or five LEDs is each repetition produces a different random number. Most likely, it will be somewhere in between.

At the end of the process (after the 3 second timeout timer) myLED will equal the number of the last LED that was randomly selected, and this LED will be turned off after 3 seconds.

I’m guessing that isn’t the behaviour you were looking for (although you haven’t really explained that thoroughly).

Pete.

The code is supposed to work this way:
The user inputs a number of trials into V1, and this number NumTrials is carried over to either the accuracy function or the reaction trials function, based on the button that he selects. In the accuracy trials, the random LED selected is to stay on for 3s before turning off, and there should be a 4s delay before the next iteration of the loop and another LED turns on. So only one LED should be switched on at any point in time. The reaction time trials work the same wat, except that the delay between loop iterations is randomised.

As for your point, i dont understand why the random LED selected would stay switched on. Wouldn’t the ledoff function at the end of the 3s timer turn it off?

And in addition to that, the LEDs don’t switch off after 3s, just like you described. The 4 LEDs simply stay lit.

Thanks so much for your help once again :slight_smile:

I think you’re assuming that the timeout timers block any further code execution until they have completed, the same as a delay.
The whole reason for using these timers is that they are non-blocking and therefore allow code execution to continue - including allowing the void loop to execute Blynk.run

You really need to either move away from using the USB serial connection or obtain an FDTI adapter and connect it to your SoftwareSerial pins so that you can use the serial monitor to debug your program flow and monitor your variable values during the program execution.

Pete.

does this mean that I need to use a blocking timer instead? because I do want a pause between one iteration of the loop and the next

No, it doesn’t.
You simply need to think a little harder about how you initialise the next cycle. This could be done by using a flag to track if another timer is needed, then triggering the next timer from the function that is called when the timeout timer ends.

Pete.