Switch, case or if/else statements for triggering behavior sets with HC SR-04

Hi guys,

I’m trying to program an Arduino to control ultrasonic sensor which functions as a base to driver a 2 channel solid state relais (low lvl trigger), piezo buzzer and a ballast. The ballast will be dimmed over a 1-10v port through PWM pin 9 (NPN transistor, capacitor, and some resistors).

The problem I’m facing is that I don’t exactly know how to program the Arduino in such a way it can cycle trough 4 different behaviors sets, accordingly to the distance that a person is away from the sensor. (Excuse my poor English) Let me clarify:

Maximum range: 224 centimeter

If is < distance between 223-170 centimeter> then

  • tone khz 1000
  • Pwm value 1 —> 30
  • SSR CH1 ON, 0,5 seconds OFF)
  • SSR CH2 ON, 0,5 seconds OFF)

If is < distance between 170-110 centimeter> then

  • tone khz 1000 —> 700
  • Pwm value 30 —> 110

If is < distance between 110-50 centimeter> then

  • tone khz 700 —> 500
  • Pwm value 110 —> 170

If is < distance between 50-1 centimeter> then

  • tone khz 500 —> 200
  • Pwm value 170 —> 224
  • PWM (flickering)
  • SSR CH1 ON, 3 seconds, OFF)
  • SSR CH2 ON, 3 seconds, OFF)

How would I program these different behavior sets? By using the case argument or will if/else statements also work? I’ve seen that I can use the map() argument to drive ranges, will I need that argument to map the range of the tones of the buzzer?

Sorry for all these questions, I hope you guys can help me out.
Greets from the netherlands!

Switch case are for discrete values - you want an if statement

You also need to think about how you want to handle the ON/OFF timing - is it OK to not check sensor while waiting?

#include <elapsedMillis.h>
elapsedMillis timeElapsed;
unsigned int interval = 6000; // one second in ms

#define trigPin 10
#define echoPin 12
#// define ledPin 13    //origineel, niet nodig

 int led = 3;     // PWM naar 1-10v
 int brightness = 1; //hoe hoog de output is
 int fadeAmount = 1; // schroef met 1 stap omhoog
const int buzzer = 5; // buzzer op arduino pin 9
int in1 = 8;
int in2 = 7;  

void setup() {
 
Serial.begin (9600);
 
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(led, OUTPUT);     // 1-10v wordt aangestuurd door pwm waarde
pinMode(buzzer, OUTPUT);  // buzzer op pin 5 is output
pinMode(in1, OUTPUT);     // 2ch SSR high (low lvl trigger)
  digitalWrite(in1, HIGH);    //ch1 off
  pinMode(in2, OUTPUT);
  digitalWrite(in2, HIGH);     //ch2 off
}
 
void loop() {
                                                // -- 1-10v dim
analogWrite(led, brightness); // stel brightness in op pwm output

brightness = brightness + fadeAmount;

if (brightness <= 0 || brightness >= 255){
  fadeAmount = - fadeAmount;
}
delay(30);
                                               // -- 1-10v dim
                                               
long duration, distance;                      //--- ultrasonic
digitalWrite(trigPin, LOW); // Added this line
delayMicroseconds(2); // Added this line
 
digitalWrite(trigPin, HIGH);
// delayMicroseconds(1000); - Removed this line
delayMicroseconds(10); // Added this line
digitalWrite(trigPin, LOW);
 
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) / 29.1;             // --- ultrasonic

if (distance >= 500 || distance <= 260){
//Serial.println("Out of range"); // heb ik niet nodig.
  analogWrite (9,1);        //pin 9, brightness 1
}

else {

Serial.print(distance); // gebruik dit om output te monitoren, 
                        // kan bij final versie weg
Serial.println(" cm");  // same
Serial.println(brightness);
 
}


if (distance <= 223 && distance >= 170){    // execute stuff_01
   analogWrite (9, 30);            
   tone(buzzer, 10000);
      while(timeElapsed < interval){    //interval is 1 sec
    digitalWrite(in1, HIGH);
    digitalWrite(in2, HIGH);
}
   
  // Serial.println(brightness); //check brightness line
 }


else if (distance <= 170 && distance >= 110){   //execute different stuff
        analogWrite(9, 110);
        tone(buzzer, 20000);
        
}

else if (distance <= 110 && distance >= 50){
         analogWrite(9, 110);
        tone(buzzer, 30000);
        

}

else if (distance <= 50 && distance >= 1){
         analogWrite(9, 110);
        tone(buzzer, 40000);
        digitalWrite(in1, LOW);
        digitalWrite(in2, LOW);
        
    while(timeElapsed < interval){    //interval is 1 sec
    digitalWrite(in1, HIGH);
    digitalWrite(in2, HIGH);
}
}

 else{                        // eindstatement ofwel buiten range,
                               // defined als 
   analogWrite(9,1);           //terug naar zachtjes aan 
   noTone(buzzer);      //uit?
 }
   
 delay(5);
}

This is something i worked on, am i understandig you correctly? I've inserted multiple if else and else if's for specifying different behaviour sets. It's important the sensor stays active during the cycles, so therefore i've tried to stay away from using big delays when it comes to dealing with the SSR i'm planning to use.

you're right, i've changed the ranges to not overlap each other. A thing that is not yet behaving correctly is the output to the pwn pin 3. I've used the standard example for fading an LED but what i actually want is to have the led go up to the value specified in the second action.

For example:

else if (distance <= 169 && distance >= 110){   //execute different stuff
        analogWrite(9, 110);
        tone(buzzer, 20000);
        
}

else if (distance <= 109 && distance >= 50){
         analogWrite(9,(110 ++ 170);
        tone(buzzer, 30000);

However the IDE reports the error: exit status 1
lvalue required as increment operand

Does this have something to do with this line of code at the top of my loop?

brightness = brightness + fadeAmount;

if (brightness <= 0 || brightness >= 255){
  fadeAmount = - fadeAmount;

i added the double plus without realizing it would only add one to my value. What i'm trying to achieve is
<start at 110> --> increment to --> <170>

But i'm not exactly sure what this command would look like or whether i'd need a formula somewhere else in the code.

Sorry for not being clear. I'd like every behaviour set to play indefinitely. When a visitor is in the hit area of the ultrasonic sensor, it keeps maintaining one behaviour set and changes when the visitor comes closer or distances his or herself from the sensor, the a different behaviour set is triggered and also plays in definitely.

By incrementing i mean that the value counts up to the value specified, so:

analogWrite(9,(110 ++ 170);

should achieve count up from 110 to 170.

Thanks for helping me out, much appreciated!

Do you mean doing something like for (byte pwm=110; pwm<=170; pwm++) analogWrite(9,pwm);this of course would run very quickly and not for ever - but is that what you mean by incrementing?

Yes, that's what i mean! Great. Is it difficult to incorporate this for loop into my code, in conjunction with the specified ranges by the ultrasonic sensor?

Many thanks!

Allrighty.

The ultrasonic sensor functions as the heart of the installation and the other components react to the values it measures.

According to the ranges of the ultrasonic, it triggers:

  • PWM pin; (the values drive the intensity of a dimmable ballast) through a NPN transistor. The ballast delivers the voltage of 1-10v. Values between 1 and 224 are used to alter the intensity of a fluorescent tube.
  • piezo (different tones)
  • 2channel 5v to 230AC SSR, low lvl trigger. Switches a 5v fan and 24v ultrasonic mist maker.

What i'm struggling with is the Arduino cycling through the different if/else and else if statements, i'm unable to walk through these different behaviour sets (ultrasonic rangefinder doesn't respond and the piezo does make 2 different sounds but the ballast doesn't play along.

That's a good tip, i'll bear that in mind to really dive in next time.
The only issue is that this code is due tomorrow for an art exhibition (i know i started way too late :confused: ), is it really that difficult to make this work? I'd hoped one of you experts could solve this in a flash.

I didn't mean to offend, i'm just looking for a nudge in the right direction (and feeling a little desperate to be honest) But thank you all for replying to this thread.

You need some sort of a state machine with the “doing multiple thing at the same time” approach using millis() you should read the post pinned at the top of the forum

The loop reads the distance from time to time, like x times per second (use the millis technic and no delay for this) and not block code for long

Based on the last read value decide what the PWM does. Same thing here - this should be based on its own timing using similar milli. remember previous animation stage and adapt to the cycle you want to see, do one step (increasing) at the right time

Same goes for the piezo or relays