-2

I am trying to compile a switch statement to create a combination lock of sorts from a nucleo board. At first I tried to tackle using multiple digital inputs in a switch statement by creating a bit mask and assigning integers, this seems to have gone alright however when I try to get my switch statement running it is stuck on case 0.

For a start case 0 should be no buttons pressed however it only activates once I press switch 1. My second problem is that no other cases in my statement will activate at all.

I have no access to a debugger as mbed is not compatible with my nucleo board and I cannot get Keil Studio working so I am pretty stumped. Does anyone what is wrong with my statement or if there is an alternate way to refer to my digital inputs within the switch statement that may make it easier?

I am a coding n00b and have struggled to find much reference to my problem, any sample code I have looked at seems to work no problem and I cannot see where I have deviated from that code.

Code is below:

// You are to use these ojects to read the switch inputs
DigitalIn SW1(USER_BUTTON);
DigitalIn SW2(BTN1_PIN);
DigitalIn SW3(BTN2_PIN);
DigitalInOut SW4(BTN3_PIN, PIN_INPUT, PullDown, 0);
DigitalInOut SW5(BTN4_PIN, PIN_INPUT, PullDown, 0);

// You are to use this object to control the LEDs
BusOut leds(TRAF_RED1_PIN, TRAF_YEL1_PIN, TRAF_GRN1_PIN);

// Use this to sound an error
Buzzer alarm;

int main()
{

    

    while (true)
    {
        leds = 0;

        // Beep
        alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
        wait_us(250000);
        alarm.rest();

        // Wait for the blue button using a while loop
        while (SW1==0) { };
             
            

        // For full marks, debounce the switches with suitable delays

        // This is a "combination lock" activity. Write some code to detect the following sequence of press-and-release inputs
        // SW1, SW2, SW5, SW3 and SW4, SW2 and SW3
        // If the full sequence is entered, correctly, the green LED should flash 3 times
        // If a sequence of inputs was entered incorrectly, the red LED should light and the buzzer should sound for 5 seconds
        // For full marks, debounce the switches and use flow control structures and arrays to avoid deep nesting of code

        

        // ***** MODIFY THE CODE BELOW HERE *****

        // ***** MODIFY THE CODE ABOVE HERE *****
       
       int Inputs = (SW1==0) << 0 | (SW2==1) << 1 | (SW3==1) << 2 | (SW4==1) << 3 | (SW5==1) << 4;
       int i;

       switch (Inputs) {

        case 0:
        printf("Please Enter Combination\n");

        if (false) {
            alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
        wait_us(250000);
        alarm.rest();
        leds = 4;
        wait_us(5000000);
        leds = 0;
        }

        break;
       
        case 1:
        printf("Input 1 is Correct\n");

         if (false) {
            alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
        wait_us(250000);
        alarm.rest();
        leds = 4;
        wait_us(5000000);
        leds = 0;
        }

        break;

        case 2:
        printf("Input 2 is Correct\n");

         if (false) {
            alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
        wait_us(250000);
        alarm.rest();
        leds = 4;
        wait_us(5000000);
        leds = 0;
        }

        break;
       
        case 16:
        printf("Input 3 is Correct\n");

         if (false) {
            alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
        wait_us(250000);
        alarm.rest();
        leds = 4;
        wait_us(5000000);
        leds = 0;
        }

        break;

        case 12:
        printf("Input 4 is Correct\n");

         if (false) {
            alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
        wait_us(250000);
        alarm.rest();
        leds = 4;
        wait_us(5000000);
        leds = 0;
        }

        break;

        case 6:
        printf("Combination is Correct!\n");
        for (int i = 0; i < 3; i = i +1)
        {
             leds = 1;
             wait_us(1000000);
             leds = 0;
             wait_us(1000000);
        }

         if (false) {
            alarm.playTone("A", Buzzer::HIGHER_OCTAVE);
        wait_us(250000);
        alarm.rest();
        leds = 4;
        wait_us(5000000);
        leds = 0;
        }

  • Why are you trying to make a switch statement? You don't actually care about people pressing multiple buttons at once, do you? Just figure out whatever function reads the state of the input as a 0 or 1 in your environment, then use that function inside a series of if statements, like `if (digital_read(sw1)) {...}`. – David Grayson Dec 06 '22 at 16:23
  • All the code below `MODIFY THE CODE ABOVE` is wrong and must be fixed. You should not define a variable named SW1 that hides the global variable of the same name, that is too confusing. Also, C doesn't support tuples like that, but you can use bitwise operators to construct a bit mask integer where each bit is an input. – David Grayson Dec 06 '22 at 16:28
  • Apologies, I do need SW2 and SW3 pressed at the same time, I will edit the original post accordingly. – DakarusJoe Dec 06 '22 at 16:29
  • Ok, can you get the single-button-at-a-time code working (and actually test it) and show us the working code for that? I don't want to guess how to do a digital reading in your environment and I don't want to debug your hardware, but I could show you how to adapt that code to make a switch statement. – David Grayson Dec 06 '22 at 16:34
  • Are the switches physical or are they GUI buttons? Are the switches polled or are they interrupts? Are the switches implemented as bits in an integer or are they values a different addresses? Reading them all at once is easier when they are implemented as bits in an integer. – Thomas Matthews Dec 06 '22 at 16:34
  • The switches are physical and interrupts, I believe they are at different addresses, my instinct would be to bus them but I am not allowed to do that. I have attached some code in my OP which shows some of the switches working as singles, I can use &&, || statements to write the code this way however I also want to sound an alarm if the inputs are false which is why I thought a switch case would be more efficient. I also tried placing the pins into an array but I cannot use an array as the statement in a switch case it seems? – DakarusJoe Dec 06 '22 at 17:27
  • I should also add due to my nucleo board and being restricted to mbed I also have no working debugger, sorry if these questions/answers seem a little basic, I am in a phase where I feel I don't know enough to know what I don't know with c++, thank you all for your time. – DakarusJoe Dec 06 '22 at 17:33

1 Answers1

0

You can make a bitmask integer where each bit corresponds to the state of one button like this:

unsigned int inputs = (SW1==0) << 0 | (SW2==0) << 1 | (SW3==0) << 2 | (SW4==0) << 3 | (SW5==0) << 4;

If you haven't seen those operators before, << is a left shift operator and | is a logical OR operator and you can look them up in any decent C++ book or introductory resource.

Your switch statement might look like this:

switch(inputs) {
case 0:  // No buttons pressed
  break;
case 1:  // SW1 pressed (bit 0 is 1)
  break;
case 2:  // SW2 pressed (bit 1 is 1)
  break;
case 4:  // SW3 pressed (bit 2 is 1)
  break;
case 6:  // SW2 and SW3 pressed
  break;
case 8:  // SW4 pressed (bit 4 is 1)
  break;
  // ...
case 31:  // All switches pressed
  break;
}
David Grayson
  • 84,103
  • 24
  • 152
  • 189
  • Thanks for the reply, I have attempted the switch statement with bitmasking however I cannot seem to get past case 0 which is also operating as if it is case 1, I see the question has been negatively marked so I guess I'm missing something easy here, my problem is that any research I do on c++ makes no reference to working with a nucleo board with digital outs but I would like to assure you I have looked at all the sample code I could find on arduino forums to no avail. I have edited the switch statement into the OP again so if someone has the time it would be much apprecaited. – DakarusJoe Dec 07 '22 at 16:12
  • The problem is probably your excessive use of blocking functions like `wait_us(5000000);`. You know that waits for 5 seconds right? While that is running, it is the only line of code running and you're not going to be reading any of the buttons. But let's not have an extended discussion here; if you need help engineering a non-blocking keypad system, that should be a separate question. – David Grayson Dec 08 '22 at 02:37
  • It is bad that you changed your question beyond recognition. Now my answer doesn't make sense because it looks to readers like I just copied some of the code you had in your question. – David Grayson Dec 08 '22 at 02:41
  • It's ok I'll look elsewhere, thank you for the help though, the 5 second wait was placed in an if statement to activate when the wrong button was pressed, I had the same problem with the cases when the if statements are removed, obviously I've made a hash of this in any case. I will remove this thread by the end of the day so your answers don't reflect poorly on you and will not edit the OP so extensively in future, I just thought pages of comments and text might be more confusing. Thank you again for your time. – DakarusJoe Dec 08 '22 at 09:07
  • Don't expect to make a single Stack Overflow post that solves every single problem in your entire engineering project. This is not a forum. What you do is identify a specific thing that you are stuck on, distill it down to its simplest form so we can understand where you are stuck, and then ask a question to solve that specific issue. When your problem is solved you accept an answer and move on, asking new questions if needed. – David Grayson Dec 08 '22 at 16:37