Using an ultrasonic to guide a quadrotor

Hello everyone,

I am working on a project here, where I want to get values from an ultrasonic distance sensor and guide the landing of a quadrotor. I know that there are several ways of doing this but listen to what I have done.

I have successfully read the distances and the range that I use is 3cm to 100cm. I then map those values with the map() function to a new range from 1480 to 1600. Then I writeMicroseconds() to my Flight Controller but it seems that something is going wrong there. I spins a bit and it keeps spining but not steady. Each motor loop at two values, lets say 1000 and 1050. I have used my transmitter and forward the signals to the Flight Controller and it works fine. When I add the distance [0 to 100] to the signal it should mathematically add up the values. Fro example if the throttle is 1350 and the distance is 40 it should send a signal with 1390ms. It has the same effect. Instead of apllying those ms and work, it loops and dont work properly. It seems that it stuck in two values. Any ideas? :confused:

You've got 218 posts, and you post a question like this?

Seriously?

CtrlAltElite:
You've got 218 posts, and you post a question like this?

Seriously?

I can continue this conversation but your answer is useless. I posted for a reason hear to solve this problem and help everyone else who have this similar issue. I have already developed the procedure but I am against an issue here and I am out of ideas. If you have a solution post it else please dont spam.

I can continue this conversation but your answer is useless

...as is your question.

How can anyone (except you) possibly answer your question without seeing your code?

Engage brain. Post code (This is the Programming section, after all).

(Warning: There now follows a whine that "my code is over 5000 lines long, and is too big to post")

Here's an answer: You've done something wrong and/or stupid.
Happy now?

Hi xmarkx,

I am working on a project here a quadrotor.

Tell us more about this quad.

Is it autonomous?
Is it controlled through some user interface like a smart phone, or RC transmitter. If so, which one?
Did it fly stably before your modification?

my Flight Controller

Tell us more about this flight controller.

Did you make it yourself?
Is it a commercial product? If so, give us a link to it.

Then I writeMicroseconds()

Sounds like you are using a servo library to talk to the flight controller. Throttle, roll, pitch and yaw?
Are you just trying to control the throttle with this writeMicroseconds?

Instead of applying those ms and work, it loops and dont work properly

Um, I'm lost here. Take some time and think through what you expect it to do. Describe that for us in better detail.
Then describe how it actually behaves. In detail. Knowing that is doesn't work is not enough. You have to give us detail that describes the difference between expected and actual behavior.

Have you quantified the ultrasonic noise created by the props on your quadcopter? If not, you don't know if such sensors will work or not?

Paul

Hey vinceherman! Sure let me tell you some more details.

The quadcopter is using Ardupilot 2.8 which is a quite old. It is not autonomous but I am trying to make it autonomous in 1 DOF. This means that I will control with my trasmiter Aileron, Elevator, Rudder and the Throttle will be controlled by the Ultrasonic Sensor. Yes it was OK before that, more than OK. :slight_smile: I am using Turnigy 9XR Pro as my transmitter.

Ardupilot: https://www.ardupilot.co.uk/

Exactly I am trying to control the throttle. Let me post some code. I am not posting the entire file caz its a huge one with details that you dont need.

#define THROTTLE_IN_PIN 4
Servo THROTTLE_TO_FC;
unsigned long thrDuration;
const byte thrInPin = THROTTLE_IN_PIN;

I read the receiver with

 thrDuration = pulseIn(thrInPin, HIGH);

I write to the Flight Controller with:

 value = thrDuration+distance;
THROTTLE_TO_FC.writeMicroseconds(value);

My setup() function:

 pinMode(thrInPin, INPUT);
  THROTTLE_TO_FC.attach(8);

So, my algorithm is to read from the ultrasonic distance and I read correctly using this example:

#define echoPin 7 // Echo Pin
#define trigPin 8 // Trigger Pin
#define LEDPin 13 // Onboard LED

int maximumRange = 200; // Maximum range needed
int minimumRange = 0; // Minimum range needed
long duration, distance; // Duration used to calculate distance

void setup() {
 Serial.begin (9600);
 pinMode(trigPin, OUTPUT);
 pinMode(echoPin, INPUT);
 pinMode(LEDPin, OUTPUT); // Use LED indicator (if required)
}

void loop() {
/* The following trigPin/echoPin cycle is used to determine the
 distance of the nearest object by bouncing soundwaves off of it. */ 
 digitalWrite(trigPin, LOW); 
 delayMicroseconds(2); 

 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10); 
 
 digitalWrite(trigPin, LOW);
 duration = pulseIn(echoPin, HIGH);
 
 //Calculate the distance (in cm) based on the speed of sound.
 distance = duration/58.2;
 
 if (distance >= maximumRange || distance <= minimumRange){
 /* Send a negative number to computer and Turn LED ON 
 to indicate "out of range" */
 Serial.println("-1");
 digitalWrite(LEDPin, HIGH); 
 }
 else {
 /* Send the distance to the computer using Serial protocol, and
 turn LED OFF to indicate successful reading. */
 Serial.println(distance);
 digitalWrite(LEDPin, LOW); 
 }
 
 //Delay 50ms before next reading.
 delay(50);
}

Then I need to write the distance multiplied with a gain factor so I will end up in a range of 1400 to 1600. I have done this too. My last print before the writeMicroseconds outputs the correct values. The problem occur when I writeMicroseconds to the FC for some reason.

Thank you for your time.

Paul_KD7HB:
Have you quantified the ultrasonic noise created by the props on your quadcopter? If not, you don't know if such sensors will work or not?

Paul

No I did not since I did not try to fly it. I moved the ultrasonic with my hand and the motor angular velocities do not increase/decrease as I want. They do something crazy effect. For those who know programming let me describe the effect.

while(1) {
writeMicroseconds(1300);
delay(10);
writeMicroseconds(1350);
delay(10);
}

I hope you can feel the my error. Thanks.

I hope you can feel the my error

Feel?

Maybe the error is in the code you didn't post.

Yes, that seems more likely.

(Quantisation?)

CtrlAltElite:
Feel?

Maybe the error is in the code you didn't post.

Yes, that seems more likely.

(Quantisation?)

Please if you want to troll go somewhere else or go to sleep since you are under 18 with such comments. Open a facebook and chat there.

Tedious and juvenile.

Read my last post again.
Possibly (though on the basis of your recent posts, unlikely) try to understand the underlying principle, and apply it.

There is obviously something wrong with your code, besides all the stupid delay()s and blocking function calls. Since you are the only one that can see the code that reads from the ultrasonic sensors, or who can see the serial output you are printing to debug the problem, only YOU can fix the problem.

It is YOU who are trolling.

PaulS:
There is obviously something wrong with your code, besides all the stupid delay()s and blocking function calls. Since you are the only one that can see the code that reads from the ultrasonic sensors, or who can see the serial output you are printing to debug the problem, only YOU can fix the problem.

It is YOU who are trolling.

Are you joking? What exactly is going on? Its not always about the LOC. I have tested my code and change only a simple plus. I actually do not delay more, I just retrieve a value from the memory stack of the global variables. Just retrieve and nothing more.There are million other things that may go wrong. I have better things of doing that sit in front of a screen and troll with posts so please stop acting with such a low attitude. You have 85000 posts there.

I have also removed ~250 LOC and I post the rest here. Hope it helps.

#include <Servo.h>
#include <stdio.h>
#include <Wire.h>  

/*
 * Connect the receiver pins as following.
 * 
 * Throttle Pin -> Digital Pin 4
 * Switch Pin -> Digital Pin 7
 */
#define THROTTLE_IN_PIN 4
#define SWITCH_IN_PIN 7
#define echoPin 10 // Echo Pin
#define trigPin 9 // Trigger Pin

/*
 * The following constants will be used to attach output
 * pins and connect them to the Flight Controller Input pins.
 * They are defined in the setup() function.
 */
Servo THROTTLE_TO_FC;

unsigned long thrDuration;
unsigned long ailDuration;
unsigned long eleDuration;
unsigned long rudDuration;
unsigned long switchDuration;

// Input pins
const byte thrInPin = THROTTLE_IN_PIN;
const byte switchInPin = SWITCH_IN_PIN;

int maximumRange = 200; // Maximum range needed
int minimumRange = 0; // Minimum range needed
long duration, distance; // Duration used to calculate distance

/*
* This method reads RC receiver incoming signals. First 
* it read a PPM pulse and then it uses the map function 
* to change the range (optional).
*/
void readRCInput() {
  thrDuration = pulseIn(thrInPin, HIGH);
  //thrDuration = map(thrDuration, 1000, 2000, 980, 2020);

  switchDuration = pulseIn(switchInPin, HIGH);
  //switchDuration = map(switchDuration, 1000, 2000, 980, 2020);
}

/*
* This method prints all the values of the RC receiver.
*/
void printRCInput() {
  Serial.print("THROTLE: ");
  Serial.print(thrDuration);
  Serial.print("\t");
  Serial.print("SWITCH: ");
  Serial.println(switchDuration);
}

/*
 * This method forward all the values to the flight controller
 */
void writeRCOutput(int value) {
  THROTTLE_TO_FC.writeMicroseconds(value);
}


/*
 * Blinks twice the onboard led at digital pin 13 (for debug)
 */
void blinkLED(int times) {
  int i;
    for(i=0; i<=times; i++) {
      digitalWrite(LED_BUILTIN, HIGH);
      delay(50);  
      digitalWrite(LED_BUILTIN, LOW);
      delay(50);
      
      digitalWrite(LED_BUILTIN, HIGH);
      delay(50);
      digitalWrite(LED_BUILTIN, LOW);
      delay(50);  
    }
}

/*
 * Read the distance
 */
void updateDistance() {
 digitalWrite(trigPin, LOW); 
 delayMicroseconds(2); 

 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10); 
 
 digitalWrite(trigPin, LOW);
 duration = pulseIn(echoPin, HIGH);
 
 //Calculate the distance (in cm) based on the speed of sound.
 distance = duration/58.2;
}

/*
 * SETUP function that runs only once.
 */
void setup() {
 Serial.begin(9600);
 
  while (!Serial);
      
  // Define the inputs
 pinMode(thrInPin, INPUT);
 pinMode(switchInPin, INPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
 
  THROTTLE_TO_FC.attach(8);
  
  Serial.println("Arduino is ready.");
}

/*
* Dont stop the looping!
*/
void loop() {
  // Read any PPM signal from the Receiver
 readRCInput();  // THROTLE and SWITCH

  // Print the PPM signals that you have just read (optional)
  printRCInput();

  // Read the distance
  updateDistance();

  // Switch is DOWN [ACTIVATED]
  if(switchDuration > 1600) {
    int thrValue = thrDuration + distance;
    Serial.print("D: ");
    Serial.print(distance);
    Serial.print("\t T: ");
    Serial.println(thrValue);
    writeRCOutput(thrValue);
  }else {
    /*
     * In this case we write the input value that we have read before.
     */
    writeRCOutput(thrDuration);
  }
}

have also removed ~250 LOC and I post the rest here.

And the code you posted exhibits the behaviour you described?
I just want to be sure, and that this isn't another wild goose chase.

CtrlAltElite:
And the code you posted exhibits the behaviour you described?
I just want to be sure, and that this isn't another wild goose chase.

Of course. I have used more channels to read and forward but this behavior is also visible with one channel. I make it easier for you to read it. If thrDuration is the value from my receiver and dist is the value from the ultrasonic distance sensor,

writeMicroseconds(thrDuration) works.
writeMicroseconds(thrDuration+dist) DO NOT work.

This is so simple. Is there anything else to post and describe ?

unsigned long thrDuration;

long duration, distance; // Duration used to calculate distance

I do not like the idea of mixing signed and unsigned types.

    int thrValue = thrDuration + distance;

And then, you stick the result in a third type.

It is at this point that you should be printing all 3 values. At this point, they may not be what you think they are.