if else commands

I’m making a piano using analog sensors as keys. I’m using if else commands to check a sensor and then play a note if the value is below a certain point. Individually the commands work, but when I use all six of them, each key produces the same note. The note produced isn’t in the program, but is close to the average of all of the notes. I’m also a new programmer so any advice on how to clean this up would be appreciated.

#define Note_C 65.41   //Hz   
#define Note_D 73.42   //Hz   
#define Note_E 82.41   //Hz
#define Note_F 87.31   //Hz
#define Note_G 98      //Hz
#define Note_A 110     //Hz
#define threshold 1000 


const int speaker=3;  
const int B_1=A0;    // pins A0-A5 have sensors attatched to them 
const int B_2=A1;    // pins 13-8 are being used to power each sensor
const int B_3=A2;     
const int B_4=A3;     
const int B_5=A4;
const int B_6=A5;
const int P_1=13;
const int P_2=12;
const int P_3=11;
const int P_4=10;
const int P_5=9;
const int P_6=8;


int val_1=0;
int val_2=0;
int val_3=0;
int val_4=0;
int val_5=0;
int val_6=0;


void setup()
{   
pinMode(P_1, OUTPUT);      
digitalWrite(P_1, HIGH);
pinMode(P_2, OUTPUT);
digitalWrite(P_2, HIGH);
pinMode(P_3, OUTPUT);
digitalWrite(P_3, HIGH);
pinMode(P_4, OUTPUT);
digitalWrite(P_4, HIGH);
pinMode(P_5, OUTPUT);
digitalWrite(P_5, HIGH);
pinMode(P_6, OUTPUT);
digitalWrite(P_6, HIGH);
}


void loop()
{
  val_1=analogRead(B_1); // checks each sensor value and stores it
  delay(1);              // each value must be checked twice with a 
  val_1=analogRead(B_1); // delay inbetween to provide consistant values
  val_2=analogRead(B_2);
  delay(1);
  val_2=analogRead(B_2);
  val_3=analogRead(B_3);
  delay(1);
  val_3=analogRead(B_3);
  val_4=analogRead(B_4);
  delay(1);
  val_4=analogRead(B_4);
  val_5=analogRead(B_5);
  delay(1);
  val_5=analogRead(B_5);
  val_6=analogRead(B_6);
  delay(1);
 val_6=analogRead(B_6);
 
 if (val_1 < threshold)     // if a value drops below the threshold
  {tone (speaker, Note_C);} // a note is played
    else noTone (speaker);                     
 if (val_2 < threshold)     
  {tone (speaker, Note_D);} 
    else noTone(speaker);                       
 if (val_3 < threshold)     
  {tone (speaker, Note_E);} 
    else noTone (speaker);
 if (val_4 < threshold) 
  {tone (speaker, Note_F);}
    else noTone (speaker);
  if (val_5 < threshold)
  {tone (speaker, Note_G);}
    else noTone (speaker);
  if (val_6 < threshold) 
   {tone (speaker, Note_A);}
    else noTone (speaker);
    noTone(speaker);
  }

What happens if you call tone function twice with two notes simultaneously? i.e. what happens if you do like the following?

void loop()
{
  tone (speaker, Note_C);
  tone (speaker, Note_E);
}

If you hear Note_E only, the problem seems to be a bit difficult.

What sort of sensors are you using and how are they wired ? What range of values do you get from your analogRead() inputs ?

Once you have got this working investigate the use of arrays and cut the length of the program by about 80%

@tasasaki it isn't a consistent note. It sounds like they keep interrupting each other.

@UKHeliBob I have bananas hooked up as sensors. each power supply runs through a resistor and then to the analog port and a banana. when the banana and a ground are touched, the voltage to the analog sensor drops. The analogRead() goes from 1023 to around 600. the exact number varies. Thanks for the arrays tip

Unconventional but possibly workable…

Not the solution to your problem, but why are you using digital pins to provide the 5V to the sensors ? Why not just connect them to 5V ?

The note produced isn’t in the program, but is close to the average of all of the notes

That does not make sense. To quote from the tone() function reference page

Only one tone can be generated at a time. If a tone is already playing on a different pin, the call to tone() will have no effect. If the tone is playing on the same pin, the call will set its frequency.

Can I suggest that you add a Serial.print() just before each tone() and noTone() so that you can track which sections of the program are being activated ?

Personally I prefer to use braces to hold blocks of code in if/else even if only one line of code is to be executed, like this

  if (val_1 < threshold)     // if a value drops below the threshold
  {
    tone (speaker, Note_C);
  } // a note is played
  else 
  {
    noTone (speaker);                     
  }

I find it much easier to visualise what is going on and if later I add other lines of code, such as I suggested above, there is no confusion as to which code will be executed.

  val_1=analogRead(B_1); // checks each sensor value and stores it
  delay(1);              // each value must be checked twice with a 
  val_1=analogRead(B_1); // delay inbetween to provide consistant values
  val_2=analogRead(B_2);
  delay(1);
  val_2=analogRead(B_2);

There is really no need to read the pin twice. It’s the delay that makes the second reading stable. Dump the first one.

@UKHeliBob: I originally had one 5v power supply for all of the sensors, but i was made to believe that the issue was because they were all wired in parallel. I don't think that's the case, but i haven't had the time to switch it back yet. I know the tone thing makes no sense, but it is happening. All of the tones being produced are identical and the tone produced sounds close to the average. I added the Serial.print() before the tone() like you suggested, and everything is activating properly and when it should.

@PaulS: Thanks for the advice

The logic for playing the tones looks wrong.

Even if you turn the tone on, it will immediately be turned off by the next if statement, won't it ?

It does, but the Arduino goes through the code so fast it isn't really perceptible. Using regular if statements instead of if else statements doesn't have a noticeable effect. There probably is a better way to do it though.

Hi, can you post a picture or CAD in jpg, png or pdf format of your circuit diagram.

I understand you are trying for polyphonic but are only getting a from of monophonic..

UKHeliBob quotes.

Only one tone can be generated at a time. If a tone is already playing on a different pin, the call to tone() will have no effect. If the tone is playing on the same pin, the call will set its frequency.

There is your problem ,you cannot play more than one tone a time, you are expecting to play more than one tone all together. That is, the generator is monophonic, one only tone source at a time. The generator cannot produce the complex waveform that two or more tones will produce. You need a DtoA and complex digital processing to accomplish this.

Tom...... :)

David_S: @tasasaki it isn't a consistent note. It sounds like they keep interrupting each other.

@UKHeliBob I have bananas hooked up as sensors. each power supply runs through a resistor and then to the analog port and a banana. when the banana and a ground are touched, the voltage to the analog sensor drops. The analogRead() goes from 1023 to around 600. the exact number varies. Thanks for the arrays tip

Try connecting the banana directly to a pin that in setup() you mode as INPUT_PULLUP.

And change those int variables that will never get outside of 0 to 255 into bytes.

Hi…use this link to see how the tone is produced.

http://arduino.cc/en/Reference/Tone

Generates a square wave of the specified frequency (and 50% duty cycle) on a pin. A duration can be specified, otherwise the wave continues until a call to noTone()

The generator is only PWM at 50%, square wave, you are not going to get any better than that out of the arduino.

Tom… :slight_smile:

@TomGeorge: I can’t upload the diagram, the website keeps breaking. I wasn’t trying to do multiple tones at one time. My intent was to have the previous tone stop before a new one is played. I only intended it to work if one key is touched at a time, so only one if else command is active at any given time. If that isn’t what my code said, could you tell me how to fix it?