1

I am having some trouble getting my board to perform the function I want it to perform. This is a project I have due in a few days, and I have hit a wall I just can't seem to get past. Now, I will say the issue is definitely in the way I coded the program, but I don't really know enough about Arduino (and coding) to understand why it is not working. My board is properly hooked up to use 3LEDs, a speaker, a photoresistor, and an ultrasonic sensor (detects distances). My Arduino program takes serial input from a GUI that I created in MATLAB. I have verified the MATLAB code is good, and the serial port is communicating properly. I have made an alarm that goes off when light or motion is detected. It has 3 basic functions:

  1. Set the alarm
  2. Turn off the alarm
  3. "snooze" which just delays for 5 minutes and then the alarm goes off

The snooze and turn off alarm parts of my code are working great, but the set alarm is where I am having trouble. The snooze option sets off the yellow LED to verify it is on "snooze". The red LED comes on when the alarm is currently going off. The green LED comes on when the alarm is set. When I try to activate the "Set Alarm" function, which is case 'O' in a switch case, the light does come on, but the sensors are not picking up any input as far as I can tell. Again I have verified the pins and everything are set up correctly as I have isolated those and verified they work. I have a suspicion that the problem is because I have the sensors initialed within the switch case of the "Set Alarm" (case 'O', not 0). I don't really know how to get the sensors to run continually within that switch case until the "turn alarm off" case is activated. I need the sensors to be activated/reset by "Set Alarm" case.

**I am also new to this forum so please let me know if I am missing anything!

here is my code:

void setup() 
{
  Serial.begin(115200);
  pinMode(12,OUTPUT); //RED
  pinMode(13,OUTPUT); //GREEN
  pinMode(14,OUTPUT); //YELLOW
  pinMode(16,OUTPUT); //SPEAKER
  pinMode(4,INPUT); //Echo
  pinMode(2,OUTPUT); //Trig
}

void loop() 
{
 if(Serial.available() >0)
 {
 char b = Serial.read();

  switch(b)
  {
    //Turn Alarm off
    case 'A' : 
    {
    digitalWrite(12,LOW);//red off
    digitalWrite(13,LOW); // green off
    digitalWrite(14,LOW); //yellow off
    noTone(16);
    delay(500);
    }
    break;

    // Set alarm
    case 'O' : 
    {
      int light;
  light = analogRead(0);
  unsigned long distance;
    digitalWrite(2,LOW);
  delayMicroseconds(2);
  digitalWrite(2,HIGH);
  delayMicroseconds(10);
  digitalWrite(2,LOW);
  distance = pulseIn(4,HIGH);
  distance = distance/58; //centimeters
  delay(500);

    digitalWrite(12,LOW); //red off
    digitalWrite(14,LOW); //yellow off
    digitalWrite(13,HIGH); //green on

  if (light < 400)
    {
     digitalWrite(12,HIGH);//red on
    digitalWrite(13,LOW); // green off
    digitalWrite(14,LOW); //yellow off
    tone(16,832);
    delay(500); 
    }

  if (distance < 50)
    {
     digitalWrite(12,HIGH);//red on
    digitalWrite(13,LOW); // green off
    digitalWrite(14,LOW); //yellow off
    tone(16,832);
    delay(500); 
    }

    }
    break;

    // snooze option
    case 'Z' : 
    {
    digitalWrite(14,HIGH); //yellow on
    digitalWrite(12,LOW); //red off
    digitalWrite(13,LOW); // green off
    noTone(16);
    delay(300000UL);
    digitalWrite(12,HIGH); //red on
    digitalWrite(13,LOW); // green off
    digitalWrite(14,LOW); //yellow off
    tone(16,832);
    delay(500); 
    }
    break;
   }


  }
}

Any help would be very much appreciated!

sa_leinad
  • 3,218
  • 2
  • 23
  • 51
Geraldo
  • 13
  • 2

2 Answers2

2

The problem is that, if you enter 'O', you go thorugh the set alarm case only once. If no alarm was triggered, it just falls through the if statements and is then back in the main loop. In that main loop, you only check for your sensors, if something was entered to the serial console. That means if you do not enter anything during a loop, nothing happens.

The solution to this would be to implement a finite state machine. That means you use a state variable for the switch case. You then update your state based on the state and the external conditions. In your case you can just update the state using user input.

I changed your code a bit for a possible (but bad) implementation. I did not verify or check for errors. I recommend using a more solid implementation, if you plan to build upon this code for more complex behavior.

char state = 'A'; //initialize state in Off state
char b;          // make user input variable global
void setup()
{
  Serial.begin(115200);
  pinMode(12, OUTPUT); //RED
  pinMode(13, OUTPUT); //GREEN
  pinMode(14, OUTPUT); //YELLOW
  pinMode(16, OUTPUT); //SPEAKER
  pinMode(4, INPUT); //Echo
  pinMode(2, OUTPUT); //Trig
}

void loop() { if (Serial.available() > 0) { b = Serial.read(); } // close user input section

switch (state) // run switch case every loop { //Turn Alarm off case 'A' : { digitalWrite(12, LOW); //red off digitalWrite(13, LOW); // green off digitalWrite(14, LOW); //yellow off noTone(16);

    delay(500);
  }
  break;

// Set alarm
case 'O' :
  {
    int light;
    light = analogRead(0);
    unsigned long distance;
    digitalWrite(2, LOW);
    delayMicroseconds(2);
    digitalWrite(2, HIGH);
    delayMicroseconds(10);
    digitalWrite(2, LOW);
    distance = pulseIn(4, HIGH);
    distance = distance / 58; //centimeters
    delay(500);

    digitalWrite(12, LOW); //red off
    digitalWrite(14, LOW); //yellow off
    digitalWrite(13, HIGH); //green on

    if (light &lt; 400)
    {
      digitalWrite(12, HIGH); //red on
      digitalWrite(13, LOW); // green off
      digitalWrite(14, LOW); //yellow off
      tone(16, 832);
      delay(500);
    }

    if (distance &lt; 50)
    {
      digitalWrite(12, HIGH); //red on
      digitalWrite(13, LOW); // green off
      digitalWrite(14, LOW); //yellow off
      tone(16, 832);
      delay(500);
    }

  }
  break;

// snooze option
case 'Z' :
  {
    digitalWrite(14, HIGH); //yellow on
    digitalWrite(12, LOW); //red off
    digitalWrite(13, LOW); // green off
    noTone(16);
    delay(300000UL);
    digitalWrite(12, HIGH); //red on
    digitalWrite(13, LOW); // green off
    digitalWrite(14, LOW); //yellow off
    tone(16, 832);
    delay(500);
  }
  break;

}

state = b; // update state based on input

}

Kerbolosh
  • 86
  • 4
1

The most simplest way to troubleshoot a program is to add Serial.println(); statements everywhere. For example you could add Serial.println("Setting Alarm"); in the first line of the case for setting the alarm.

You will notice that the set alarm code only runs once through, instead of continously. You should use the case to set a mode or a state in where the sensors are checked continously.

First I would create a variable called setAlarmMode and set it to false.

setAlarmMode = false;

Then I would remove the reading of sensors from the case statement and instead set setAlarmMode to true.

// Set alarm
case 'O' :
  {
    Serial.println("Setting Alarm");
// Set the LEDs for the mode
digitalWrite(12, LOW); //red off
digitalWrite(14, LOW); //yellow off
digitalWrite(13, HIGH); //green on

setAlarmMode = true;

} break;

Now I would insert this code outside of the if (Serial.available() > 0) code block:

// Read sensors
if (setAlarmMode == true)
  {
    Serial.println("Reading sensors");
    int light;
    light = analogRead(0);
    Serial.print("Light sensor value: ");
    Serial.print(light);
unsigned long distance;

// Do trigger pulse
digitalWrite(2, LOW);
delayMicroseconds(2);
digitalWrite(2, HIGH);
delayMicroseconds(10);
digitalWrite(2, LOW);

distance = pulseIn(4, HIGH);
distance = distance / 58; //centimeters
Serial.print(&quot;   Distance sensor value: &quot;);
Serial.println(distance);

if (light &lt; 400)
{
  Serial.println(&quot;Light below threshold&quot;);
  setAlarmMode = false;
  activateAlarm();
}

if (distance &lt; 50)
{
  Serial.println(&quot;Distance below threshold&quot;);
  setAlarmMode = false;
  activateAlarm();
}

delay(500);

}

I have also created a function to hold the common code of showing the alarm:

void activateAlarm(void)
{
  digitalWrite(12, HIGH); //red on
  digitalWrite(13, LOW); // green off
  digitalWrite(14, LOW); //yellow off
  tone(16, 832);
  delay(500);
}
sa_leinad
  • 3,218
  • 2
  • 23
  • 51