Coding help

I have a servo and a sensor working together in a void loop. Every time the loop resets it resets the sensor. How do I get the servo to make a sweep that will allow the sensor to take readings during the entire sweep without resetting the sensor's data.

//Digital pin 7 for reading in the pulse width from the MaxSonar device.
//This variable is a constant because the pin will not change throughout execution of this code.
#include <Servo.h>
Servo myservo;
const int pwPin = 7; 
//variables needed to store values
long pulse, mm, cm,milliseconds;
int pos = 0;



void setup() {

  //This opens up a serial connection to shoot the results back to the PC console
  myservo.attach(9);
  Serial.begin(9600);
}

void loop() {
  pinMode(pwPin, INPUT); 
  pulse = pulseIn(pwPin, HIGH);
  //1uS per mm
  mm = pulse/1;
  //change mm to m
  cm = mm/10;
  milliseconds=millis();
  Serial.print(milliseconds);
  Serial.print(",");
  Serial.print(mm);
  Serial.print(",");
  Serial.print(cm);
  Serial.print(",");
  Serial.println();
  delay(1);
  
  for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(50);                        // waits 15ms for the servo to reach the position 

  }
   for(pos = 180; pos>=0; pos-=1)     // goes from 180 degrees to 0 degrees 
   {                                
   myservo.write(pos);              // tell servo to go to position in variable 'pos' 
   delay(50);                       // waits 15ms for the servo to reach the position 
  }  
 
}

in a void loop

NO NO NO!
It is in a function called loop.
Void is just what it returns, which is nothing.

 pinMode(pwPin, INPUT);

Should be in the setup function not the loop function.

mm = pulse/1;

That line is not worth its salt is it? What do you think it does?

Every time the loop resets it resets the sensor.

What do you mean by this?
How do you know?
Exactly which MaxSonar sensor are you using, link please.

The mm = pulse/1 is the pulse divided by the scaling factor of 1 micro sec per mm. The pulse itself returns micro seconds, therefore the scaling factor cancels out the time and leaves millimeters. The issues we are having with the code is we would like to have our sensor to take a reading, move a degree, take another reading, move another degree. We would like for it to sweep 180 degrees this way. We plan on taking our data and mapping it. As for this line pinMode(pwPin, INPUT); we just followed an example code to help us make this one. The sensor being used is this: Ultrasonic Range Finder - HRLV-MaxSonar-EZ0 - SEN-11307 - SparkFun Electronics. The datasheet for it is here: HRLV-MaxSonar-EZ Datasheet – MaxBotix.

but... dividing a number by 1 doesn't do anything....

I guess the scaling factor would be useful if you were planning to use it under exotic atmospheres where the speed of sound was different? (also, is that the right scaling factor, even?)

As for this line pinMode(pwPin, INPUT); we just followed an example code to help us make this one

Then this strongly tells you that the person writing the code had little clue as to what they were doing.

So you don't say why you think it is resetting.

Have you wired a 100uF capacitor across the V+ and ground like it says in the data sheet.

Hi,

servo to make a sweep

How are you supplying power to the servo?

Servos use more current than the Arduino 5V can supply, they need an external supply, with the gnd of the servo supply connected to the Arduino gnd.

What model Arduino are you using?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks... Tom...... :slight_smile:

You are not reading from the sensor are the servo moves.

You need to move the sensor reading section to within the section the servo moves.

Here are a few more suggestions.

Change your baud to 115200. This should reduce the amount of time it takes to send data to the terminal.

Since the sensor is sending pulses at 50Hz you should need to add an additional delay between sensor reads and servo updates.

It would probably be a good idea to move the sensor reading and serial output section of the code to its own function. You could call that function with each movement of the servo.

We could help you with this if needed.

Further to the other suggestions, you could move this:-

pinMode(pwPin, INPUT);

into 'setup()'. You don't need to make the pin an input every time the loop cycles.

Another very small point. Instead of "pos += 1" and "pos -= 1", you could use "pos++" "and pos--". (Slightly less typing for the same result.)

One more minor point.
This:-

Serial.print(",");
Serial.println();

could be this:-

Serial.print(",\n");

(Faster and less typing.)

DuaneDegn:
Since the sensor is sending pulses at 50Hz

Duane, I think the sensor reads at 20Hz, not 50. "Readings can occur up to every 50mS, (20-Hz rate)" (Model-dependent maybe. I'm looking at the data for the LV‑MaxSonar‑EZ series.)

Edit:
@pts0004, the datasheet says:-

Pin 2-PW-This pin outputs a pulse width representation of range. The distance can be calculated using the scale factor of 147uS per inch.

This equates to 147/25.4uS, (5.7874uS), per mm, not 1uS per mm.
(DrAzzy, you were right to question this. :slight_smile: )

OldSteve:
Duane, I think the sensor reads at 20Hz, not 50. "Readings can occur up to every 50mS, (20-Hz rate)" (Model-dependent maybe. I'm looking at the data for the LV‑MaxSonar‑EZ series.)

I don't know where I got the 50Hz figure from. I can find several frequencies listed in the datasheet. It looks like there are more than one possible mode. I didn't see the 20Hz figure (not that I doubt it), but I did find 10Hz and 2Hz. With different rates using different filtering techniques.

OldSteve:
Edit:
@pts0004, the datasheet says:-This equates to 147/25.4uS, (5.7874uS), per mm, not 1uS per mm.

I'll try to find where it's stated in the datasheet but I think the 1mm per 1us figure is correct. I'll try to find the reference and edit this post.

Edit: Page 2 of the datasheet.

Pin 2- Pulse Width Output: This pin outputs a pulse width representation of the distance
with a scale factor of 1uS per mm. Output range is 300uS for 300-mm to 5000uS for
5000-mm. Pulse width output is +/- 1% of the serial data sent

I have one of these sensors. It's really nice. I used the serial interface with a Scribbler 2 robot. I also used it with a quadcopter once. The fight didn't last long. As soon as I enable the ultrasound altitude control the 'copter flipped and crashed.

This sensor has an analog output. It seems like an analog read would be a better idea than reading the pulse length.

DuaneDegn:
I don't know where I got the 50Hz figure from. I can find several frequencies listed in the datasheet. It looks like there are more than one possible mode. I didn't see the 20Hz figure (not that I doubt it), but I did find 10Hz and 2Hz. With different rates using different filtering techniques.

The datasheet I'm looking at says 20Hz.

I'll try to find where it's stated in the datasheet but I think the 1mm per 1us figure is correct. I'll try to find the reference and edit this post.
Edit: Page 2 of the datasheet.

We must be looking at different datasheets. This is the one I read:-
LV-MaxSonar®-EZ™Series
On Page 2, under "Pinout Description" for "Pin2-PW", it says what I quoted - 147uS per inch.

Edit: I think we might need pts0004 to clarify exactly which MaxSonar sensor he's using. We can't both be right. :slight_smile: (Sounds like maybe I'm looking at the wrong datasheet.)

OldSteve:
We must be looking at different datasheets. This is the one I read:-
LV-MaxSonar®-EZ™Series
On Page 2, under "Pinout Description" for "Pin2-PW", it says what I quoted - 147uS per inch.

Sorry, I was looking at the one the OP linked to.

Here's the product page.

I was wrong about having this same sensor. I have one of the LV type (the your datasheet is to).

The HRLV sensor looks very interesting.

DuaneDegn:
Sorry, I was looking at the one the OP linked to.

HRLV-MaxSonar-EZ Datasheet – MaxBotix

Here's the product page.

I was wrong about having this same sensor. I have one of the LV type (the your datasheet is to).

I missed his link. So I'm wrong about the 147uS bit. The sensor he's using must use internal scaling, I guess.
HRLV is very different to the LV, obviously. HR must be high-resolution.
I stand corrected. (Serves me right for not reading every post more carefully. Someone will jump on me for this. :frowning: )

OldSteve:
I missed his link. So I'm wrong about the 147uS bit. The sensor he's using must use internal scaling, I guess.
HRLV is very different to the LV, obviously. HR must be high-resolution.
I stand corrected. (Serves me right for not reading every post more carefully. Someone will jump on me for this. :frowning: )

To tell you the truth, I didn't know there were two different versions. You told me the datasheet you were reading but I just assumed it was the same one to which the OP linked.

If I had looked at the product page I would have realized it was a different sensor.

DuaneDegn:
To tell you the truth, I didn't know there were two different versions. You told me the datasheet you were reading but I just assumed it was the same one to which the OP linked.

No. I did look back at his first post, to see if he mentioned exactly which model, but didn't look at subsequent posts for a link. My bad.
And I like the look of those sensors. Much nicer than the HC-SR04 sensor that I'm using now. I'm swinging the 'head' of my robot car around quickly to take measurements, stopping for a few mS at each of 5 points, but it often misses things. I have to follow along with the IR remote and quickly switch to 'manual' every now and then to avoid collisions.
I might get a HRLV Max Sonar, if I can find one locally, and compare results.

OldSteve:
And I like the look of those sensors. Much nicer than the HC-SR04 sensor that I'm using now. I'm swinging the 'head' of my robot car around quickly to take measurements, stopping for a few mS at each of 5 points, but it often misses things. I have to follow along with the IR remote and quickly switch to 'manual' every now and then to avoid collisions.

I'm not sure how much a more expensive ultrasound would improve your robot's ability to detect obstacles. Ultrasound sensors have some severe weaknesses.

Ultrasound sensors have trouble with smooth flat surfaces when approached from shallow angles. The sound bounces off the surface and away from the sensor. The echo is never detected in these situations.

Ultrasound sensors also have trouble when the obstacle is a material which absorbs ultrasound. Fabric without a hard surface behind it can absorb the ultrasound rather than reflect it.

Fortunately the surfaces which are hard for ultrasound to detect are easily detected with inexpensive IR sensors. IR and ultrasound are complementary sensors. These sensors combined do a great job at avoiding obstacles.

The only obstacle with which my ultrasound enhanced Scribbler 2 had trouble was out living room couch. The IR sensor was too low to detect the couch and the ultrasound was absorbed by the cloth covered padding of the couch. A stall detector on the caster wheel would detect when the robot had been stopped so the robot would eventually free itself.

Sorry to the OP for the semi off topic wandering but hopefully this information about the limitations of ultrasound sensor will be helpful to the OP.

DuaneDegn:
I'm not sure how much a more expensive ultrasound would improve your robot's ability to detect obstacles.[I just thought it might have better amplification/filtering. Maybe not. One way to find out

Ultrasound sensors have some severe weaknesses.
Ultrasound sensors have trouble with smooth flat surfaces when approached from shallow angles. The sound bounces off the surface and away from the sensor. The echo is never detected in these situations.

I'm very aware of this, that's why the head swings side-to-side. It has no trouble at all with approaching a wall at an angle. Also aware of the problem with fabric absorbing the ping. The swinging head does OK in this situation too. Thin chair legs are my robot's main weakess. I thought a better quality sensor might do a better job in that respect. I have IR sensors on the way, but I'm not sure about their range. I'll see when they arrive. (I want the robot to turn when 12" from obstacles.)

Sorry about the hijack too, pts0004. Hopefully pointing out the weaknesses will also help you. :slight_smile:

Thank you guys for your responses. We are using the High Resolution Series of the lv-Ez Maxbotix sensors. I do not believe we even saw that a capacitor was needed. Could you tell us why it needs the capacitor and where this information is. Making a function is a good idea but we are also new to programming arduino. Could anybody give us an example sketch to compare to what we find? From what info I was able to gather, the pwm side is more accurate than the analog which is why we are using it. If the analog is better then we can swap to analog. The servo came with the inventors pack and can use the 5v on the arduino. We have the arduino Uno, btw. So far, we made the small change to the code involving the pinMode(pwPin, INPUT);. We are still having trouble trying to make the arduino take a reading after every degree servo moves.

pts0004:
Thank you guys for your responses. We are using the High Resolution Series of the lv-Ez Maxbotix sensors. I do not believe we even saw that a capacitor was needed. Could you tell us why it needs the capacitor and where this information is.

On page 2 of the datasheet:-

V+ Pin 6-Positive Power, Vcc:
The sensor operates on voltages from 2.5V -5.5V DC. For best operation, the sensor requires that the DC power be free from electrical noise. (For installations with known dirty electrical power, a 100uF capacitor placed at the sensor pins between V+ and GND will typically correct the electrical noise.)

As long as the servo is powered by an external power supply as it should be, and not the Arduino board, noise shouldn't be a problem. You shouldn't really power your servo directly from the UNO, however if you insist on doing so, adding that capacitor is a good idea.
I don't have an example sketch, sorry. Someone else might oblige you there.

pts0004:
Making a function is a good idea but we are also new to programming arduino. Could anybody give us an example sketch to compare to what we find?

Here's the sort of function I was thinking of.

void ReadUltrasound() {
  mm = pulseIn(pwPin, HIGH);
  //change mm to cm
  cm = mm/10;
 
  Serial.print("distance = ");
  Serial.print(mm);
  Serial.print(" mm, ");
  Serial.print(cm);
  Serial.println(" cm");
 }

Here's how you could call the function from within a for loop.

  for(pos = 0; pos <= 180; pos += SERVO_CHANGE) // goes from 0 degrees to 180 degrees 
  {                                
    ReadUltrasound();
    myservo.write(pos);              // tell servo to go to position in variable 'pos'  
  }

I think incrementing the position by one might take a long time to sweep the area so I added a constant "SERVO_CHANGE". This is of course optional.

#define SERVO_CHANGE 2

I think you want to read the ultrasound prior to command a position change so the servo has had time to move to the desired position. The data from the read would correspond to the earlier position.

I'm not positive this is the best approach but I'm pretty sure it will work better than the way you're doing it now.

The main problem with reading the sensor value from the pulse output is the pulsein command blocks the flow of code. There are other options to read pulses but I wouldn't worry about this yet.

Since the sensor reading is now in a function, you can remove that section from the main loop.

Edit: This thread has an example of reading pulse inputs without blocking the code. It's not as easy to us this other method as it is to use pulsein so I wouldn't try the other method until you're more comfortable writing code.

pts0004:
Could you tell us why it needs the capacitor and where this information is.

From page 4 of the datasheet.

The sensor requires noise free power for best operation. If the sensor is used with noise on the supplied power, the
readings may be affected. Typically adding a 100uF capacitor at the sensor between the V+ and GND pins will correct
most power related electrical noise issues.

The cap is mentioned as a way correct noise issues. I don't read the above as stating such a cap is required to use the sensor. "It's more of a guideline rather than a rule."

pts0004:
The servo came with the inventors pack and can use the 5v on the arduino.

If it's a micro servo you might get away with this but even still it's a bad idea. A link to "the inventors pack" would help us know what sort of servo it is.

A cap near the servo's power line would likely help if you're going to try to use the 5V Arduino power. You should really use a separate power source for the servo with the ground lines of the two supplies joined together.

Edit: If the kit you're using is SparkFun's Arduino Inventor's Kit then the servo is a micro servo. SparkFun seems to think it's okay to run the servo from the 5V line on the Arduino.