4
\$\begingroup\$

I am brand new to C++ and am working with the Arduino micro controller. The project I've been working on for my university requires me to write code to do the following:

  • If the ultrasonic sensor detects a distance within a certain range, output HIGH to activate an electric motor

  • If the sensor detects distance outside this range, outputs LOW to deactivate the motor

  • I hope to create an array that will average the readings from the ultrasonic sensor over a .5 sec - 1 second interval and then output that average.

  • I started with a rangefinder script that went along with a tutorial provided on Arduino's website, so my goal is to modify that script to fit into my goals to output HIGH or LOW based on the code that I've tested and already works well to test for distance.

I am looking for any tips to create an array to average the distance from the sensor, then using a for loop to test whether it is in the interval and output HIGH or LOW.

Any help and direction would be appreciated!

const int TriggerPin = 8;  //sensor trigger pin
const int EchoPin = 9;    //sensor echo pin
const int MotorPin = 7;  //motor out pin
long Duration = 0;

void setup(){
  pinMode(TriggerPin,OUTPUT);  //sets trigger as output
  pinMode(EchoPin,INPUT);      //sets echo as input
  pinMode(MotorPin,OUTPUT);    //sets motor as output
  Serial.begin(9600);          //displays to serial monitor 
}

void loop(){
 digitalWrite(TriggerPin,LOW);  //trigger pin to 0V
 delayMicroseconds(2);          //waits 2 us
 digitalWrite(TriggerPin,HIGH); //trigger pin to 5V
 delayMicroseconds(10);         //10 us delay to recieve ping
 digitalWrite(TriggerPin,LOW);

Duration = pulseIn(EchoPin,HIGH);  //waits for echo pin to get high
//pulseIn returns the Duration in microseconds 
long Distance_mm = Distance(Duration);  //uses function to calc. distance

delay(100);  //delay half second, do next measurement
}

long Distance(long time);
{

long DistanceCalc;  //calculation variable
DistanceCalc = ((time /2.9) / 2);

//want to average this DistanceCalc reading over 10 readings, then use this value to    compare to the desired range

void loop(){
  if  (dist_avg < 600 && dist_avg > 400);
  digitalWrite(MotorPin,HIGH);
  else
  digitalWrite(MotorPin,LOW);
}
//if average distance is within .4-.6 meter range, output HIGH; turns motor on
//if avergae distance is outside .4-.6 meter range, outut LOW; turns motor off
\$\endgroup\$
5
  • \$\begingroup\$ what kind of average do you want? there is the running average: this reading + next reading / 2, or it's the framed average: sum of last x readings / x - these will prbably be the most reasonable as you want to adopt to change, not actually find the total average of all readings \$\endgroup\$ Feb 7 '14 at 17:14
  • \$\begingroup\$ The framed average: Like you said I would like to respond and adopt to the average reading. It was suggested to me that taking the average of a few readings would help reduce the risk of a outlier value to be taken into account and causing the response when it wasn't desired. I'm writing this to control a greenhouse harvest cart, and desire the cart to react to the presence of a harvester: if he is in the correct range, the cart will move continuously as he picks fruit, and if he is outside the range, the motor turns off. \$\endgroup\$
    – holmyd23
    Feb 7 '14 at 17:49
  • \$\begingroup\$ right I see, you should first refactor your loop that genereates the duration and your Distance function into one function. Then you can call that x times in a row and store the values in an array, before you then get an average. Beware that you have a bug here 'if (dist_avg < 600 && dist_avg > 400);' the if will never trigger the following code block, becuase you terminate the statement with ; \$\endgroup\$ Feb 7 '14 at 17:54
  • \$\begingroup\$ I'm very novice with coding so I am confused as to how I would combine the duration and Distance into one function. To clarify, you suggest letting the distance function run x times in a row, store these values in an array, and then average that set. I removed the ; to allow the code to continue to run if the condition isn't met on the first 'if'. If you could provide an example of how to combine the function and also to create the array to be averaged, that would be enormously helpful! And thank you in the first place for the help so far \$\endgroup\$
    – holmyd23
    Feb 7 '14 at 18:16
  • \$\begingroup\$ How exactly are HIGH and LOW defined? With the way they're named, I assume they're macros. \$\endgroup\$
    – Jamal
    Feb 8 '14 at 22:06
3
\$\begingroup\$
  • As per C++ naming convention, only user-defined types and macros in C++ are capitalized. Your constants, global variable, and functions should start with a lowercase letter.

  • Since your constants are similar, you can group them into an enum instead:

    enum Pin { Motor=7, Trigger, Echo };
    

    With the first one set to 7, the following ones will be set to 8 and 9 respectively.

    This could also help with code maintenance. If you ever need to add another Pin, you just need to insert it into the enum appropriately, as opposed to creating another constant.

  • Duration is only used in loop(), so just initialize and use it there. Having it as a global variable could invite bugs, and is otherwise bad practice. This applies to global variables in general because they're accessible throughout the entire program, meaning they can be changed anywhere.

  • You're using "magic numbers" (hard-coded numbers) in places. You should either make them variables or constants, or provide comments to specify their meaning.

  • Your indentation is quite inconsistent. You indent a different number of spaces in different functions, but you should stick to one (most common is four spaces). You especially should have indentation within functions, otherwise it may appear that the code isn't contained within that function.

  • This isn't syntactically correct:

    if  (dist_avg < 600 && dist_avg > 400);
    digitalWrite(MotorPin,HIGH);
    else
    digitalWrite(MotorPin,LOW);
    

    There shouldn't be a semicolon after the if condition, otherwise the following statements won't work with it. The second and fourth lines should also be indented.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.