Syncing a Segmented Switch with a physical button on my breadboard

So I’m basically just in the beginning stages of the project I’m trying to build. It’s going to be an ignition switch for a vehicle but right now I’m just using a segmented switch to turn on lights on my breadboard (if I can send voltage to lights I can send voltage to various items in my car). It’s a BLE setup. I want to use the Blynk app to cycle through the 4 options (which works fine), but I also want to incorporate a push button. For an example, when I’m in the Off position and the button is pressed it will switch the button state to the On position. Then once the button is pressed again it will go to the Run position and so on.

As of now, I half way have it working. I’ve been trying a couple different methods but my latest revision (the one in this post) will do one switch. If I’m in the Off position it will switch it to the On position, but then another button press doesn’t do anything. I can’t continue pressing the button to get to the next states. I don’t think I’m writing to the virtual pin properly or I’m not looping things correctly. I’m still a little green to all this coding. I’ve been learning by reading forum.

Also, when I am able to get the one switch for like Off to On the segmented switch changes in the Blynk app from Off to On, but the light I have set up doesn’t change it stays in the off position on the bread board

I hope this made sense. Any ideas?




#define BLYNK_PRINT Serial


#include <SoftwareSerial.h>
SoftwareSerial SerialBLE(10, 11); // RX, TX

#include <BlynkSimpleSerialBLE.h>

BlynkTimer timer;

void checkPhysicalButton(); 


// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "iLrMxefNzOW0F0cx3KjX_ShR_6Tm8nmE";

const int offMode = 4;
const int onMode = 5;
const int runMode = 6;
const int startMode = 7;

const int buttonPin = 2;
int buttonState = 0;
int value;

  


BLYNK_WRITE(V1) {
  value = param.asInt();
  switch (param.asInt())
  {
    case 1: // Item 1
      Serial.println("Off selected");
      digitalWrite(offMode, HIGH);
      digitalWrite(onMode, LOW);
      digitalWrite(runMode, LOW);
      digitalWrite(startMode, LOW);
      break;
    case 2: // Item 2
      Serial.println("On selected");
      digitalWrite(offMode, LOW);
      digitalWrite(onMode, HIGH);
      digitalWrite(runMode, LOW);
      digitalWrite(startMode, LOW);
      break;
    case 3: // Item 3
      Serial.println("Run selected");
      digitalWrite(offMode, LOW);
      digitalWrite(onMode, LOW);
      digitalWrite(runMode, HIGH);
      digitalWrite(startMode, LOW);
      break;
    case 4: // Item 4
      Serial.println("Start selected");
      digitalWrite(offMode, LOW);
      digitalWrite(onMode, LOW);
      digitalWrite(runMode, LOW);
      digitalWrite(startMode, HIGH);
      break;
    default:
      Serial.println("Unknown item selected");
  }
}


void checkPhysicalButton(){

  
  buttonState = digitalRead(buttonPin);
  
  if (value == 1 && (buttonState == HIGH)){
     Blynk.virtualWrite(value,2);}

  if (value == 2 && (buttonState == HIGH)){
     Blynk.virtualWrite(value,3);}
     
  if (value == 3 && (buttonState == HIGH)){
     Blynk.virtualWrite(value,4);}

   Blynk.syncVirtual(value);   
}



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

  SerialBLE.begin(9600);
  Blynk.begin(SerialBLE, auth);

  Serial.println("Waiting for connections...");

  pinMode(offMode, OUTPUT);
  pinMode(onMode, OUTPUT);
  pinMode(runMode, OUTPUT);
  pinMode(startMode, OUTPUT);

  pinMode(buttonPin, INPUT);

  timer.setInterval(1000L, checkPhysicalButton); //timer will run every sec

}

void loop()
{
  Blynk.run();
  timer.run();        // run timer every second

}

Change value to V1 in this and the subsequent virtialWrite and sync commands.

Pete.

I had tried that in one of my revisions. It produces the same result whether ‘value’ or ‘V1’ are plugged in there.

It sounds like you’re changing lots of things without any real plan.

If you take a step back and think about this, it’s the widget attached to pin V1 that you’re trying to update,
`Blynk.virtualWrite(vPin, value)’ is the syntax for updating widgets attached to virtual pins. Normally, the virtual pin would be references with a “V” in front of it…

Blynk.vrtualWrite(V1, 2)

to update the segmented switch attached to V1 to position 2.

However, the leading “V” is optional.
In your code, you are using your value variable in the position where you specify which virtual pin is being updated, so when your value variable = 2, you are saying …

Blynk.vrtualWrite(V2, 2)

As your segmented switch isn’t attached to V2, it won’t be updated with this command.

I’d suggest that you make the change I suggested, and if it’s not working then add some debug messages that print out the variables so you can see exactly what’s happening.

If you still can’t figure it out, post your located code.

Pete.

Okay per your advice I have cleaned up the ‘value’ and ‘V1’ I had in there. I think I got that value integer from some forum that I was on. Now I realize my mistake there. However, it didn’t make much of a difference in my issues. I have posted a video on YouTube so you can visually see what I’m talking about. I have a red Led set up for off, green for on, blue for run, and yellow for run. The wiring is nothing to brag about, but like I said this my testing phase to send voltage later. When the physical button on the breadboard is pressed it will write the value, but it doesn’t continue to write the value and the light doesn’t change.

YouTube link:

Code:

#define BLYNK_PRINT Serial


#include <SoftwareSerial.h>
SoftwareSerial SerialBLE(10, 11); // RX, TX

#include <BlynkSimpleSerialBLE.h>


BlynkTimer timer;
void checkPhysicalButton();


// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "iLrMxefNzOW0F0cx3KjX_ShR_6Tm8nmE";

const int offMode = 4;
const int onMode = 5;
const int runMode = 6;
const int startMode = 7;

const int buttonPin = 2;
int buttonState = 0;
int value;

  


BLYNK_WRITE(V1) {
  switch (param.asInt())
  {
    case 1: // Item 1
      Serial.println("Off selected");
      digitalWrite(offMode, HIGH);
      digitalWrite(onMode, LOW);
      digitalWrite(runMode, LOW);
      digitalWrite(startMode, LOW);
      break;     
    case 2: // Item 2
      Serial.println("On selected");
      digitalWrite(offMode, LOW);
      digitalWrite(onMode, HIGH);
      digitalWrite(runMode, LOW);
      digitalWrite(startMode, LOW);
      break;
    case 3: // Item 3
      Serial.println("Run selected");
      digitalWrite(offMode, LOW);
      digitalWrite(onMode, LOW);
      digitalWrite(runMode, HIGH);
      digitalWrite(startMode, LOW);
      break;
    case 4: // Item 4
      Serial.println("Start selected");
      digitalWrite(offMode, LOW);
      digitalWrite(onMode, LOW);
      digitalWrite(runMode, LOW);
      digitalWrite(startMode, HIGH);
      break;
    default:
      Serial.println("Unknown item selected");
  }
}

void checkPhysicalButton(){

  Blynk.syncVirtual(V1);  

  

   buttonState = digitalRead(buttonPin);
    
   if (V1 == 1 && (buttonState == HIGH)){
     Blynk.virtualWrite(V1, 2);
     }

   if (V1 == 2 && (buttonState == HIGH)){
     Blynk.virtualWrite(V1, 3);
     }
}


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

  SerialBLE.begin(9600);
  Blynk.begin(SerialBLE, auth);

  Serial.println("Waiting for connections...");

  pinMode(offMode, OUTPUT);
  pinMode(onMode, OUTPUT);
  pinMode(runMode, OUTPUT);
  pinMode(startMode, OUTPUT);

  pinMode(buttonPin, INPUT);

 timer.setInterval(1000L, checkPhysicalButton);
  

}

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

}

Why have you moved the Blynk.syncVirtual(V1) to the start of the checkPhysicalButton() function?
What is the logic behind using this command?

Pete.

Does this code actually compile?

This makes no sense to me.
You haven’t declared a variable called V1, and you can’t reference the value of the widget attached to pin V1 in this way.

You need to store the value of the segmented switch in a global variable, so that you can reference it later. You did this in your original code, storing this in the value variable, but you’ve stripped this out of your current code.

You seem to be making random changes to the code structure without any understanding of what these changes will achieve.

Pete.

What happens if you add a global variable (before setup)

int physbuttonTrig;

Then change your check physical Button timer to like 200ms.

Then use below for your check button routine.

EDIT: THIS WOULD ONLY WORK FOR AN INTERRUPT ROUTINE!!

void checkPhysicalButton()
{
  ++physbuttonTrig;           //add to your button status every press

  if(physbuttonTrig > 4)
  {
      physbuttonTrig = 1;   //resets the counter if it is larger than the number of button segments
  }
  Blynk.virtualWrite(V2,physbuttonTrig);    //try this not sure if it will trigger the switch case in the Vbutton fucnction or not
  
}

Not sure if the virtual Write will trigger your switch case but give it a try.

And as @PeteKnight says… in each of your case statements set physbuttonTrig = 1 for case 1 etc.

PS. not the greatest variable name but you get the picture.

@PeteKnight from what I’ve read the Blynk.syncVirtual(V1) is supposed to be a reprocessing function. I added it into my code when I couldn’t get things to work. I don’t really understand exactly how it works, it just seemed like a good option try. I moved it to the beginning thinking maybe things needed to sync before? I’m just kinda at a trial and error approach by this point.

As far as if(V1 == 1 && actually compiling? Why as a matter of fact yes it does compile. Otherwise I wouldn’t have the code on my board. And that was the code that was running in my video so it was writing that way by writing directly to V1.

I understand why a variable would make more sense so I have put that back in now as a variable instead of V1, but really everything worked the same whether V1 or value was in the if functions.

You have indeed discovered my approach to these issues I’ve been having. I make changes without fully understanding what I’m doing. I’m not an expert coder by any means. I got some basic knowledge. I’m researching and doing trial and error until I can get a better grasp on things. I make changes to see what happens. Then I learn.

@daveblynk as mentioned above I’m a little green so I see where you going with your suggestion. But are you thinking I need to use this checkPhysicalButton() function that you wrote instead of mine? Or are you thinking I should add it into my function?

In other words remove your check button routine and try the one I supplied.

Not sure you’ve thought that one through Dave.

Your routine will increment the physbuttonTrig variable every time the checkPhysicalButton routine executes (every 200ms) and do a Blynk.virtualWrite as well.

The routine needs an if (digitalRead(buttonPin)) test at the beginning, so these actions only happen if the physical button has been pressed.

Time to go and get a coffee :coffee:

Pete.

Ahh!! I was thinking interrupt, I guess that is what I would have done.

1 Like
void checkPhysicalButton()
{
  buttonState = digitialRead(buttonPin);
  if(buttonState == HIGH)
  {
    ++physbuttonTrig;           //add to your button status every press

    if(physbuttonTrig > 4)
    {
      physbuttonTrig = 1;   //resets the counter if it is larger than the number of button segments
    }
    Blynk.virtualWrite(V2,physbuttonTrig);    //try this not sure if it will trigger the switch case in the Vbutton fucnction or not
   }
}

Also if you are polling every 200ms you might need a small delay in the if statement so it doesn’t catch a button press two times.

@daveblynk @PeteKnight thank you guys for your help. I’m at work so I don’t have my laptop in front of me, but I will try this when i get home tonight.

However, I had an idea half way spark last night so I used the Arduino Online Editor to put a code together in my down time here at work. Again I don’t always understand the coding logistics of having to do things a certain way. But is there any reason this wont work?

I moved the if statements to inside the BLYNK WRITE so they would change the variable switchValue that I created. I figured instead of trying to write to the app I could just control the switch differently? Then I set that variable as what will change in the actual switch with:

  switchValue = param.asInt();
  switch (switchValue)

I tried something similar to this last night, but when I changed switch (param.asInt()) to switch (switchValue) my blynk app wasn’t switching properly. I think I’m confused on how the logic works with the param.asInt(). Here’s that full section I just put together. Thoughts? Can you see what I’m trying to do?


BLYNK_WRITE(V1) {
  switchValue = param.asInt();
  switch (switchValue)
  {
    case 1: // Item 1
      Serial.println("Off selected");
      digitalWrite(offMode, HIGH);
      digitalWrite(onMode, LOW);
      digitalWrite(runMode, LOW);
      digitalWrite(startMode, LOW);
      break;     
    case 2: // Item 2
      Serial.println("On selected");
      digitalWrite(offMode, LOW);
      digitalWrite(onMode, HIGH);
      digitalWrite(runMode, LOW);
      digitalWrite(startMode, LOW);
      break;
    case 3: // Item 3
      Serial.println("Run selected");
      digitalWrite(offMode, LOW);
      digitalWrite(onMode, LOW);
      digitalWrite(runMode, HIGH);
      digitalWrite(startMode, LOW);
      break;
    case 4: // Item 4
      Serial.println("Start selected");
      digitalWrite(offMode, LOW);
      digitalWrite(onMode, LOW);
      digitalWrite(runMode, LOW);
      digitalWrite(startMode, HIGH);
      break;
    default:
      Serial.println("Unknown item selected");
  }
  
  buttonState = digitalRead(buttonPin);
    
   if (switchValue == 1 && (buttonState == HIGH)){
     switchValue = 2;
     }

   if (switchValue == 2 && (buttonState == HIGH)){
     switchValue = 3;
     }
     
  if (switchValue == 3 && (buttonState == HIGH)){
     switchValue = 4;
     }
}

BLYNK_WRITE(V1) is a special callback function that is triggered whenever the value of the widget attached to V1 changes, or when you call Blynk.syncVirtual(V1).

You can’t use this to poll your physical switch, as your code would ONLY read the physical switch when the widget attached to V1 is changed.

Stop making random changes to your code structure without having a proper plan for how the code will function, you’ll never make any progress otherwise.

Pete.

@daveblynk hey man, this worked perfectly to write to V1. When the button was pressed on the breadboard the switch on the app would cycle through all 4 options. The lights were not operational with the button pressed. They worked through the switch operation, but not the button presses. So I pulled all of the conditions out if the switch function and put them in a separate void whatToDo() function and looped it on a timer as well. Now the lights light up whether through app operation or the physical button operation. I still got a ways to go before all this is done and I’d like to try and figure the rest out on my own. I do really appreciate your patience with me. So thank you again!

Perfect :ok_hand: you could post the finished code so others can learn…




#define BLYNK_PRINT Serial


#include <SoftwareSerial.h>
SoftwareSerial SerialBLE(10, 11); // RX, TX

#include <BlynkSimpleSerialBLE.h>


BlynkTimer timer1;
void checkPhysicalButton();

BlynkTimer timer2;
void whatToDo();


// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "#######";

const int offMode = 4;
const int onMode = 5;
const int runMode = 6;
const int startMode = 7;

const int buttonPin = 2;
int buttonState = 0;
int switchState;

  


BLYNK_WRITE(V1) {
  switchState = param.asInt();
  switch (param.asInt())
  {
    case 1: // Item 1
      Serial.println("Off selected");
      break;     
    case 2: // Item 2
      Serial.println("On selected");
      break;
    case 3: // Item 3
      Serial.println("Run selected");
      break;
    case 4: // Item 4
      Serial.println("Start selected");
      break;
    default:
      Serial.println("Unknown item selected");
  }
}


void checkPhysicalButton()
{
  buttonState = digitalRead(buttonPin);
  
  if(buttonState == HIGH)
  {
    ++switchState;           //add to your button status every press

    if(switchState > 4)
    {
      switchState = 1;   //resets the counter if it is larger than the number of button segments
    }
    Blynk.virtualWrite(V1,switchState);
    Blynk.syncVirtual(V1);                //try this not sure if it will trigger the switch case in the Vbutton fucnction or not
   }
}

void whatToDo()
{

  if (switchState == 1){
      Serial.println("Off selected");
      digitalWrite(offMode, HIGH);
      digitalWrite(onMode, LOW);
      digitalWrite(runMode, LOW);
      digitalWrite(startMode, LOW);
  }
       
  if (switchState == 2){
      Serial.println("On selected");
      digitalWrite(offMode, LOW);
      digitalWrite(onMode, HIGH);
      digitalWrite(runMode, LOW);
      digitalWrite(startMode, LOW);
  }
      
  if (switchState == 3){
      Serial.println("Run selected");
      digitalWrite(offMode, LOW);
      digitalWrite(onMode, LOW);
      digitalWrite(runMode, HIGH);
      digitalWrite(startMode, LOW);
  }
      
  if (switchState == 4){
      Serial.println("Start selected");
      digitalWrite(offMode, LOW);
      digitalWrite(onMode, LOW);
      digitalWrite(runMode, LOW);
      digitalWrite(startMode, HIGH);
  }    

}


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

  SerialBLE.begin(9600);
  Blynk.begin(SerialBLE, auth);

  pinMode(offMode, OUTPUT);
  pinMode(onMode, OUTPUT);
  pinMode(runMode, OUTPUT);
  pinMode(startMode, OUTPUT);

  pinMode(buttonPin, INPUT);

 timer1.setInterval(200L, checkPhysicalButton);
 timer2.setInterval(200L, whatToDo);
  

}

void loop()
{
  
  Blynk.run();
  timer1.run();
  timer2.run();

}

You don’t need multiple Blynktimer objects.
A single timer object can support up to 16 timer instances.

Pete.

K I tried replying by mobile but the network didn’t let me.

Remove the timer for the to do function. This is writing your digital pins high or low every 200ms if they have changed or not.

In every switch case you need 2 things.
1- update the buttonState variable for switch case 1 switchCase = 1; and so on. (this will update the switchState so when the whatToDo is fired it will do the right one)
2- put whatToDo(); (this will fire the whatToDo function and write your pins to the desired position)

Also just before the Blynk.virtualWrite(V1, switchState); in your check buttonput the whatToDo(); and I think you will get better results.