problem with conditional statement

hi there!
i'm new to C and would love it someone could help me out by taking a look at this code snippet:

void test() {
  intVal = analogRead(intPin);
  Serial.println(intVal);
  if (intVal < 301) {
    ...do something...
  }
  // if i remove the following conditional statement, the code runs ok!
  else if (intVal > 300 && intVal < 701) {
    ...do something else...
  }
  else if (intVal > 700) {
    ...do another thing...
  }
}

this code works ok if i run it with only the first and last conditions, but as soon as i add (intVal > 300 && intVal < 701) to the mix, the whole thing gets stuck and crashes.

i'm hoping this will be a really obvious error to someone and i'd be so grateful of any help! even if the code above looks fine, please let me know and i'll go further with debugging. :slight_smile:

Hi,

the preference of && is higher than > or <. Change your code as follows:

void test() {
  intVal = analogRead(intPin);
  Serial.println(intVal);
  if (intVal < 301) {
    ...do something...
  }
  // if i remove the following conditional statement, the code runs ok!
  else if ((intVal > 300) && (intVal < 701)) {
    ...do something else...
  }
  else if (intVal > 700) {
    ...do another thing...
  }
}

Mike

Hi,

sorry, I'm wrong (preference is different is Pascal but not in C), the code seemd to be ok. Try the following (i do not know. how the compiler optimates the code, maybe there is the problem:

void test() {
  intVal = analogRead(intPin);
  Serial.println(intVal);
  if (intVal <= 300) {
    ...do something...
  }
  // if i remove the following conditional statement, the code runs ok!
  else if (intVal > 300 && intVal <= 700) {
    ...do something else...
  }
  else  {
    ...do another thing...
  }
}

Mike

thanks for your help, mike_pa!

i tried those adjustments, but the code still jams. so then i tried it with a different function than the one i'm calling (where i've written "...do something...") and it seems to work ok.

so i guess it's not a problem with the conditional statements after all. i'll do some more debugging - thanks! :slight_smile:

How do you declare intval?

Have you put in other println statements in each branch of the cascading if .. else statement to try to track it down?

What is the exact nature of the crash?

It might be helpful for you to post the entire program, plus the exact crash information. (E.g., does the println of the data just before the crash look ok?)

It might be helpful for you to post the entire program, plus the exact crash information. (E.g., does the println of the data just before the crash look ok?)

the program prints the following two lines before crashing:
1
885
the first number is the position of the swtich and the second number is the reading from the potentiometer.

here's my code (some explanation below):

#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"

SdReader card;
FatVolume vol;
FatReader root;
FatReader f;
uint8_t dirLevel; // indent level for file/dir names
dir_t dirBuf;     // buffer for directory reads
WaveHC wave;      // only one!

int ledPin = 13;              // LED
int inputPin = 14;           // on/off switch
int val = 0;                    // variable for reading the pin status

// debounce stuff
int state = HIGH;          // the current state of the output pin
int reading;                  // the current reading from the input pin
int previous = LOW;     // the previous reading from the input pin
long time = 0;             // the last time the output pin was toggled
long debounce = 200;  // the debounce time, increase if the output flickers

// potentiometer
int intPin = 3;
int intVal = 0;

// play recursively - possible stack overflow if subdirectories too nested
void play(FatReader &dir)
{
  FatReader file;
  while (dir.readDir(dirBuf) > 0) {

    // skip . and .. directories
    if (dirBuf.name[0] == '.') continue;
    Serial.println();
    for (uint8_t i = 0; i < dirLevel; i++) Serial.print(' ');
    if (!file.open(vol, dirBuf)) {
      Serial.println("file.open failed");
      while(1); 
    }

    if (file.isDir()) {
      putstring("Subdir: ");
      dirLevel += 2;
      // play files in subdirectory
      play(file);
      dirLevel -= 2;    
    }
    else {
      putstring("Playing ");
      if (!wave.create(file)) {
        putstring(" Not a valid WAV");
      }
      else {
        Serial.println();
        wave.play();

        while (wave.isplaying) {
          putstring(".");
          delay(100);
        }
      }
    }
  }
}

void setup() {
  // set up serial port
  Serial.begin(9600);

  // set up waveshield pins 
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);

  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(inputPin, INPUT);     // declare switch as input
  digitalWrite(inputPin, HIGH);

  if (!card.init()) {//play with 8 MHz spi 
    putstring_nl("Card init. failed!");
    while(1);
  }
  // enable optimize read - some cards may timeout
  card.partialBlockRead(true);

  uint8_t part;
  for (part = 0; part < 5; part++) {
    if (vol.init(card, part)) break;
  }
  if (part == 5) {
    putstring_nl("No valid FAT partition!");
    while(1);
  }

  if (!root.openRoot(vol)) {
    putstring_nl("Can't open root dir!"); 
    while(1);
  }

  dirLevel = 0;
}

void test() {
  intVal = analogRead(intPin);
  Serial.println(intVal);
  if (intVal <= 300) {
    playcomplete("SOUND1.WAV");
  }
  else if (intVal > 300 && intVal <= 700) {
    playcomplete("SOUND2.WAV");
  }
  else if (intVal > 700) {
    playcomplete("SOUND3.WAV");
  }
}

void loop(){
  reading = digitalRead(inputPin);
  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    // ... invert the output
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

    // ... and remember when the last button press was
    time = millis();    
  }

  Serial.println(reading);

  if (previous != reading) {
    digitalWrite(ledPin, HIGH); // turn LED ON
    test();
  }
  previous = reading;

}

void playcomplete(char *name) {
  playfile(name);
  while (wave.isplaying);
}

void playfile(char *name) {
  if (wave.isplaying) {// already playing something, so stop it!
    wave.stop(); // stop it
  }
  if (!f.open(root, name)) {
    putstring("Couldn't open file "); 
    Serial.print(name); 
    return;
  }
  if (!wave.create(f)) {
    putstring_nl("Not a valid WAV"); 
    return;
  }
  // ok time to play!
  wave.play();
}

this code is for lady ada's wave shield using the WaveHC library. i've been coaxing this code into doing new things for me, step-by-step, so i'm pretty sure the error is of my own doing.

in case it helps, or anyone is interested here is the original code to generate a sound when a button is pressed.

what i'm trying to do is generate a sound when a switch is flipped, the sound will be different depending on the value of the potentiometer.

specifically, the software problem seems to be with the test() function, however, i also had problems when using a switch statement instead of conditionals, so if there's nothing really wrong with my code, maybe it's to do with the heaviness of the wav files?

I don't have any experience with the wave code, but if you suspect that test routine, I would do something like this:

void test() {
  intVal = analogRead(intPin);
  Serial.println(intVal);
  if (intVal <= 300) {
    Serial.print ("val < 300 found: ");
    Serial.println (intval);
    playcomplete("SOUND1.WAV");
  }
  else if (intVal > 300 && intVal <= 700) {
    Serial.print ("val between 300 and 700 found: ");
    Serial.println (intval);    
    playcomplete("SOUND2.WAV");
  }
  else if (intVal > 700) {
    Serial.print ("val > 700 found: ");
    Serial.println (intval);    
    playcomplete("SOUND3.WAV");
  }
  else {
    Serial.print ("val ???: ");
    Serial.println (intval);    
  }
}

and see what happens.

I'd be wondering about memory usage also for a failure like what you described, but again, I'm not familiar with the details of the application.

Drop the else .. if .. else .. construct you have it wrong. The difficulty is knowing what if the else belongs to

As you have it the testing is wrong because for example if the first if fails then intVal has to be greater than 300 so there is no need to test it again. in the second if.

Just use a separate if for each condition and keep the comparisons very much as they are only put brackets round each >
if ((intVal > 300) && (intVal <= 700) )

Here's how I would write it:

void test() {
  intVal = analogRead(intPin);
  Serial.println(intVal);
  if (intVal <= 300) {
    playcomplete("SOUND1.WAV");
  }
  else if (intVal <= 700) {      /* 301 - 700 */
    playcomplete("SOUND2.WAV");
  }
  else {                               /* > 700 */
    playcomplete("SOUND3.WAV");
  }
}

-Mike

thanks for all the suggestions!

mike and grumpy_mike, i tried your adjustments, but still got the same error...

andy, i tried you code and something curious came up. when clicked "verify", i got the following error:
In function 'void test()':
error: 'intval' was not declared in this scope

the first occurrence of this line is highlighted by the program:
Serial.println (intval);

You spelled "intVal" wrong?

doh!

ok, if i run that code with the playcomplete("SOUND1.WAV"); function calls in, i don't get any feedback whatsoever...

when i comment out the three calls to playcomplete, this happens:

1
1
1í1
215
val < 300 found: 215
1
1
1
1
1
...etc, etc, looping intVal...

...until i adjust the pot and flip the switch...
1
1
0
204
val < 300 found: 214
0
0

so i guess it is a problem with calling the wav files. how frustrating! these file play fine if used with a simple switch statement and three separate buttons, but as soon as i use a potentiometer it all turns to custard. i'm going to run some tests with switches instead of a pot...

This is why it's called debugging!

Fun, huh?

:frowning:

pure joy. :slight_smile:

I actually greatly enjoy the software debugging process; there is a very real satisfaction from figuring things out and unraveling mysteries.

Good luck!

Might this be a problem with running out of RAM, rather than a problem with your code? (that seems to be the usual answer when otherwise inoffensive code clobbers your application)

the RAM theory is interesting. i went back to my original code with the switch case for three buttons. works fine. as soon as i wrap the switch case in a conditional statement (perhaps heresy in the c world, i'm used the the squishy reality of javascript) the board chokes again.

at the moment i'm using a lilypad but for my final project i'll be using a mini 328 which has a whopping 2KB of RAM - i'll post back here if it works!

thanks everyone for the help! i've learnt so much in this thread! :smiley:

just in case anyone is searching for the solution to a similar problem, this was solved by using a board with more RAM! :slight_smile: