Switch Case ipv If Then

I am new here. I am using Arduino to operate a train switch. My Arduino is connected to a 8 block relay. When I'm using If statements everything works fine. But I find Switch Case more elegant. The strange thing is that digitalWrite does not work within a case. Port numbers are OK. It is very strange. I only showed case 1.

int wisselNummer;

int wissel;
int wisseloud1=1;
int wisseloud2=1;
int wisseloud3=1;
int wisseloud4=1;

int wissel1rechtPin=2;
int wissel1kromPin=3;
int wissel2rechtPin=4;
int wissel2kromPin=5;
int wissel3rechtPin=6;
int wissel3kromPin=7;
int wissel4rechtPin=8;
int wissel4kromPin=9;

int puls=15;

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
}

void loop() {
  Serial.print("wisselnummer: ");
  while(Serial.available()==0){  }
  wisselNummer=Serial.parseInt();
  Serial.print(wisselNummer);

switch (wisselNummer) {
    case 1:
      Serial.print(", wisselstand: ");
      while(Serial.available()==0){  }
      wissel=Serial.parseInt();
      Serial.println(wissel);
      if (wissel==1 && wissel!=wisseloud1){
        digitalWrite(wissel1rechtPin,LOW);
        delay (puls);
        digitalWrite(wissel1rechtPin,HIGH);
      }
      else if (wissel==0 && wissel!=wisseloud1){
        digitalWrite(wissel1kromPin,LOW);
        delay (puls);
        digitalWrite(wissel1kromPin,HIGH);
      }
    wisseloud1=wissel;
    break;
  }
}

Doe anyone knows what I'm doing wrong here?`

And what leads you to believe that digitalWrite "doesn't work" within a case? What does "doesn't work" mean precisely in this case? What undesired behavior are you actually seeing?

Nonsense. digitalWrite works perfectly fine from within a switch case.

Show some code that replicates the problem. It doesn't have to be everything, but I should be able to compile and load and test it and see your digitalWrite not working. Then I can tell you why it doesn't work.

Found the error. Very very stupid: I forgot to define the ports as OUTPUT!

Yeah none of us has ever done something so dumb. :expressionless:

a7

I know that you did not ask for this but I would suggest to make it more scalable. Every time that you start numbering variables you should think "arrays". Also, your turnouts have related information, the two pins and the old position ('oudeStand').

To start with the related information, you can consider to use a struct or a class; the below uses a struct to combine the related information in a new type. Both structs and classes are like an entry in a phonebook where a name is associated with a phone number, an address and possibly other information.

struct WISSEL
{
  const uint8_t pinRecht;
  const uint8_t pinKrom;
  int oudeStand;
};

You can now create an array of WISSEL structs for your 4 turnouts.

WISSEL wissels[] = {
  {2, 3, 1},
  {4, 5, 1},
  {6, 7, 1},
  {8, 9, 1},
};

This is easily scalable; if you ever want to increase the number of turnouts you can simply add one or more lines instead of adding 3 variables for each turnout.

You can access the fields in the WISSEL struct using a dot as shown below for setup

// macro om het aantal elementen in enig type array te berekenen
#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
// wissel pin is actief als het niveau laag is
#define ACTIVE LOW

//int wissel;
int wisselNummer;

int wisselStand;  // 1 = recht, 0 = afbuigend

struct WISSEL
{
  const uint8_t pinRecht;
  const uint8_t pinKrom;
  int oudeStand;
};

WISSEL wissels[] = {
  {2, 3, 1},
  {4, 5, 1},
  {6, 7, 1},
  {8, 9, 1},
};

int puls = 15;

void setup()
{
  Serial.begin(115200);  // aanpassen indien noodzakelijk
  Serial.print(F("Er zijn "));
  Serial.print(NUMELEMENTS(wissels));
  Serial.println(F(" wissels"));
  for (uint8_t teller = 0; teller < NUMELEMENTS(wissels); teller++)
  {
    Serial.print(F("Wissel "));
    Serial.println(teller + 1);
    Serial.print(F("  Pin krom = "));
    Serial.println(wissels[teller].pinKrom);
    Serial.print(F("  Pin recht = "));
    Serial.println(wissels[teller].pinRecht);
    Serial.print(F("  Wisselstand = "));
    Serial.println(wissels[teller].oudeStand);

    // zet wissel pinnen als uitgang
    // we zetten eerst het niveau zodat recht en krom niet actief zijn
    digitalWrite(wissels[teller].pinKrom, !ACTIVE);
    pinMode(wissels[teller].pinKrom, OUTPUT);
    digitalWrite(wissels[teller].pinRecht, !ACTIVE);
    pinMode(wissels[teller].pinRecht, OUTPUT);
  }
}

I've defined two macros at the top of the code.

You can see how you can iterate through the turnouts. Instead of if/else or switch/case, you can simply use an index (teller, later in the program the code uses wisselNummer).

There is a function (zetWissel) to set the position of a turnout.

void zetWissel()
{
  if (wisselNummer < 1 || wisselNummer > NUMELEMENTS(wissels))
  {
    // niks te doen
    return;
  }
  if (wisselStand != 0 && wisselStand != 1)
  {
    // incorrect, niks te doen
    return;
  }

  // als de positie veranderd is
  if (wisselStand != wissels[wisselNummer - 1].oudeStand)
  {
    if (wisselStand == 1)
    {
      digitalWrite(wissels[wisselNummer - 1].pinRecht, ACTIVE);
      delay(puls);
      digitalWrite(wissels[wisselNummer - 1].pinRecht, !ACTIVE);
      Serial.println(F("recht"));
    }
    else
    {
      digitalWrite(wissels[wisselNummer - 1].pinKrom, ACTIVE);
      delay(puls);
      digitalWrite(wissels[wisselNummer - 1].pinKrom, !ACTIVE);
      Serial.println(F("afbuigend"));
    }
    // onthoud laatste stand
    wissels[wisselNummer - 1].oudeStand = wisselStand;
  }
}

The function first checks if wisselNummer and wisselStand are valid; if yes, it checks if the position changed and sets the desired position. Note that the user enters a wisselNumber starting at 1 and hence one is subtrackter from the wisselNummer to get the index in the array.

And lastly your loop() function

void loop()
{
  Serial.print("wisselnummer: ");
  while (Serial.available() == 0) {}
  wisselNummer = Serial.parseInt();
  Serial.print(wisselNummer);

  Serial.print(", wisselstand: ");
  while (Serial.available() == 0) {}
  wisselStand = Serial.parseInt();
  Serial.println(wisselStand);

  zetWissel();
  wisselNummer = 0;
}

As said, this keeps it scalable. Need 20 turnouts, just add them in the array.

Some more comments.

  1. It might be easier to remember letters for the turnout position instead of numbers; e.g. 'k' instead of '0' and 'r' instead of '1'.
  2. It might be advisable to set all turnouts in a predefined position in setup().
  3. You might benefit from reading Serial Input Basics - updated.

@sterretje: thank you very much for the suggestions!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.