Go Down

Topic: problem with conditional statement (Read 2 times) previous topic - next topic

meg

Sep 21, 2009, 06:02 pm Last Edit: Sep 21, 2009, 06:04 pm by meg Reason: 1
hi there!
i'm new to C and would love it someone could help me out by taking a look at this code snippet:

Code: [Select]

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.  :)

mike_pa

Hi,

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

Code: [Select]
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

mike_pa

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:

Code: [Select]
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

meg

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! :)

ahdavidson

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?)
.andy

meg

Quote
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):

Code: [Select]

#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?

ahdavidson

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

Code: [Select]
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.
.andy

Grumpy_Mike

#7
Sep 22, 2009, 01:34 am Last Edit: Sep 22, 2009, 01:35 am by Grumpy_Mike Reason: 1
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) )

Mike Murdock

Here's how I would write it:
Code: [Select]
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

meg

#9
Sep 22, 2009, 11:17 am Last Edit: Sep 22, 2009, 11:20 am by meg Reason: 1
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:
[glow]Serial.println (intval);[/glow]

AWOL

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

meg

#11
Sep 22, 2009, 11:23 am Last Edit: Sep 22, 2009, 11:36 am by meg Reason: 1
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...

ahdavidson

This is why it's called debugging!

Fun, huh?

>:(
.andy

meg


ahdavidson

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

Good luck!
.andy

Go Up