Orangutan library PulseIn problem: storing,start(),stop()

Hello everyone

This sensor I’m using is the Parallax Ultrasonic Ping sensor.
I have created a class in AVR studio 5.1 for the ping sensor and I having trouble at the point of pulse in the library start and then storing in a function to use later. But my can’t get the pulse to be stored.

List:

  • I’m understanding this reference correctly, that this line OrangutanPulseIn::getLastHighPulse(0); will return a time in .4microseconds?
  • what type should the storing function should be (unsigned long
    LastHighPulseMicroseconds =…,unsigned char LastHighPulseMicroseconds=…)?
  • I the stop() necessary for the ping sensor?
  • call function in my class functoin unsigned char PingPulseIn1(unsigned char pin2){
    should this be long, void,or can I leave it as char?

this code below is how i trying to store the pulse

OrangutanPulseIn::start((unsigned char[]){pin2},1);
unsigned long LastHighPulseMicroseconds = OrangutanPulseIn::getLastHighPulse(0);

Hello.

The OrangutanPulseIn class is documented in the “Orangutan Pulse/PWM Inputs” in the Pololu AVR C/C++ Library Command Reference.

Yes, getLastHighPulse returns a number in units of 0.4 microseconds.

If you look in the command reference, you can see that the return value of getLastHighPulse is an unsigned long (32-bit unsigned integer), so if you are going to be storing that value in your own variable you should probably use the same type: unsigned long. If you use a larger type then you are wasting memory and if you use a smaller type then you might accidentally change the value when those upper bits get chopped off.

I’m not sure. If you don’t call OrangutanPulseIn::stop() then the library will probably detect the ping pulse that you are sending from the AVR to the PING))) sensor and you will need to be a little careful so that your program doesn’t misinterpret that pulse.

I can’t tell you what return types your functions should have unless you tell me what the function does and what information you are trying to return from it. Once you decide what the function does and what information it is going to return, it should be pretty obvious what the return type needs to be.

–David

Thank you for answer my question
Now I have pulse_width
this is where I’m having my problem

struct PulseInputStruct
{
  volatile unsigned char* pinRegister;
  unsigned char bitmask;
  volatile unsigned long lastPCTime;
  volatile unsigned char inputState;
  volatile unsigned long lastHighPulse;
  volatile unsigned long lastLowPulse;
  volatile unsigned char newPulse;
};

How do i use the PinRegister and bitmask in my code? I’m almost positive that if i someone can tell me how to use PinRegister will complete my code. :smiley:
i called the structure

struct PulseInputStruct=pulseInfo;
pulse_width =ticks()-pulseInfo.lastLowPulse;

Hello.

What are you actually trying to accomplish with the pinRegister and bitmask? You can see plenty of examples of them being used if you look in the source code of OrangutanPulseIn:

github.com/pololu/libpololu-avr … ulseIn.cpp

–David

I’m trying to read a signal from parallax ultrasonic ping sensor. So i was hope that if i used pinRegister it will fix my input problem. I got i the idea from Lertulo’s post

his code help me understand a little bit of the pulsein library.
http://pomprocker.blogspot.com/2009/01/adding-parallax-ping-to-avr-using-c.html

information on the Ping sensor

i have a good reading from the echo but baby orangutan B 328 is not receiving the echo pulse. that why i think i need the pinRegister to get the ping’s echo to be read by my Orangutan or should i post my code?

pulse_width=get_ticks()-pulseInfo.lastPCTime;
pulse_width=get_ticks()-pulseInfo.lastLowPulse;
pulse_width=get_ticks()-pulseInfo.lastHighPulse;

I would like my AVR Ping sensor program to work just like the program in Arduino 1.0 example ping Sensor.
I got the trigger pulse to work. But the hard part is to capture the echo pulse after the trigger. because I need to read the echo width and turn it into distance(cm,inches). I don’t know how to do that and i hope the infromation in bold will help you understand what I’m talking about.

sorry about this, I know my question are frustrating and confusing :confused:
ping.h (8.08 KB)

I used Microsoft visual studios 2010
the problem lines are between Line 165-Line 215
you might of notice that my pulseWidth and state is the only two that I’m using from the libraries

The only thing the pinRegister really lets you do is read the input value of the pin, and we already have other functions in the library for doing that (see OrangutanDigital). I don’t think that the pinRegister will really help you measure echo pulse. The OrangutanPulseIn library should be measuring the echo pulse. If you want further help, please simplify your code to the simplest thing that should work but does not, and post it here. Simplifying the code means you should get rid of all the “#ifdef” lines, put all your code in one file, and you should get rid of the class you defined. If it makes the code simpler, please try to put all the code in main() and do not define any other functions. Also, please post your entire Atmel/AVR Studio project so I can see if it is configured correctly.

–David

OK, thank you
Sorry, I don’t to send a zip file, but i post all that i have in my project folder.

like this?
ping sesnor


#include <avr/io.h>

#include <pololu/orangutan>
#include <pololu/orangutan.h>
#include <pololu/OrangutanDigital/OrangutanDigital.h>
#include <pololu/OrangutanPulseIn/OrangutanPulseIn.h>
unsigned char pin2=IO_C3;
unsigned char channel=0;
unsigned long pulse_width;
unsigned char state;
unsigned long cm;

int main(){
		while(1){
                      OrangutanDigital::setOutput(pin2,LOW);
			
			OrangutanTime::delayMicroseconds(2);//2 Microseconds 
			OrangutanDigital::setOutput(pin2,HIGH);
			
			OrangutanTime::delayMicroseconds(5);//5Microseconds 
			OrangutanDigital::setOutput(pin2,LOW);
		
			//delayMicroseconds(2);//2 microseconds
			delay_ms(150);//100ms
			struct PulseInputStruct pulseInfo;
			OrangutanDigital::setInput(pin2,HIGH_IMPEDANCE);
			
			pulse_width=get_ticks()-pulseInfo.lastPCTime;
			state=pulseInfo.inputState;
			pulseInfo.lastLowPulse;
				
			OrangutanPulseIn::start((unsigned char[]){pin2},1);
			
			                            
			unsigned long LastHighPulseMicroseconds=OrangutanPulseIn::toMicroseconds(pulse_width);
			
			cm=LastHighPulseMicroseconds/14.5;						
			}				
			}				

this compiles in AVR.
here the basic of my program

I don’t know how to post .atsln file



ping.h (8.14 KB)
Dog_Follower.cpp (1.81 KB)

Thank you for simplifying your code to one file. Now how do you expect that code to behave and how is it actually behaving when you load it onto your controller? I don’t see you using any form of output, so I don’t know how you will be able to tell if the code is working.

–David

sorry I forgotten that i had to put my new hex file in avr programming. so i had to edit this post :blush:

I would expect the pulse program to wait until the trigger. then read the echo


#include <avr/io.h>

#include <pololu/orangutan>
#include <pololu/orangutan.h>
#include <pololu/OrangutanDigital/OrangutanDigital.h>
#include <pololu/OrangutanPulseIn/OrangutanPulseIn.h>
const unsigned char pin2=IO_C3;
unsigned char channel=0;
unsigned long pulse_width;
unsigned char state;
unsigned long cm;


int main(){
		while(1){
			
			OrangutanDigital::setOutput(pin2,LOW);
			
			//delay_us(100); // !!!!
			OrangutanTime::delayMicroseconds(2);//2 Microseconds 
			OrangutanDigital::setOutput(pin2,HIGH);
			//delay_us(2000); // !!!!
			OrangutanTime::delayMicroseconds(5);//5Microseconds 
			OrangutanDigital::setOutput(pin2,LOW);
					
			//delayMicroseconds(2);//2 microseconds
			delay_ms(150);//100ms
			struct PulseInputStruct pulseInfo;
			OrangutanDigital::setInput(pin2,HIGH_IMPEDANCE);
			
			pulse_width=get_ticks()-pulseInfo.lastHighPulse;
			state=pulseInfo.inputState;
			pulseInfo.lastLowPulse;
				
			OrangutanPulseIn::start((unsigned char[]){pin2},1);
			
			                            
			unsigned long LastHighPulseMicroseconds=OrangutanPulseIn::toMicroseconds(pulse_width);
			
			cm=LastHighPulseMicroseconds/37.;	
			
			delay(18);	
				
			OrangutanPulseIn::stop();	
			
						
			}				
			}

I have found a problem in my code. I noticed that pulse_width is just going up and up. so I need some kind of extra code to receive the echo last pulse goes high.

I was wondering if i need the lastPulseLow? because the echo pulse changes width do to distance between the object and the Parallax Ultrasonic Ping sensor.

Details voltage of the echo:
when there is a object 3cm in front of the Ping sensor the voltage is about 3.3V. then the voltage increase do to the increase of the distance between the object and the Ping Sensor.

Should i use the Library the read voltage and if yes, How would i do that?
Because my Multimeter can’t read it, so how would i program my baby Orangutan b 328 if my multimeter can’t read. But I can read it on my oscilloscope. so I need help with code to read the voltage of the echo pulse.
Any advice would be Appreciated

I think you are wrong about the voltage of the echo pulse. According to the PING))) documentation which can be found in the resources tab for that product, the voltage of the echo pulse is always 5 V. The important thing about the echo pulse is its duration, so that’s why you are trying to use OrangutanPulseIn to measure the length of the pulse. What sensor model are you using and where did you read about the voltage of the echo pulse?

I noticed something very bad in your latest code: you are reading pulseInfo.lastHighPulse before you even start the library, so all you are doing is reading an uninitalized variable. This results in undefined behavior, and the value you get will be meaningless.

You said “I would expect the pulse program to wait until the trigger.” but how can you actually tell if your program is behaving that way? I don’t see any output mechanism for your code except the pulse you are sending on PC3. If you are looking at PC3 with an oscilloscope you should say so.

–David

sorry using cellphone that might be why I have so many returns.
Sorry ,I thought I did in my last post. that my bad I misread my oscilloscope. the voltage is 5v on trigger and echo pulse.
I change the code recently. I moved the 100 Ms delay to the end of my code. everything is still the same otherwise .
so should what pulseInfo.lastHighpulse be?
I need the code to read the second pulse. so how my current code reads my trigger.

I don’t understand this question. Did you understand the paragraph in my last post about how you are reading an uninitialized variable when you read pulseInfo.lastHighpulse? Does that make sense?

I think your basic strategy, in pseudocode, should be like this:

main() {
  start OrangutanPulseIn
  delay 100 ms  # maybe not necessary
  while(1) {
    send the ping pulse
    delay long enough so that by the time we are done delaying, the echo pulse has been received (e.g. delay for 1000 ms)
    read the length of the last high pulse from the library
  }
}

This is not ideal but it is a good first step.

–David

I think I know what about you are talking about uninitialized variable.

I will change the code to format you given me.

this is the only code that i wrote, that actually does something. :frowning:
I got PD1 to sync with the led on the Ping sensor and that about it.

#include <avr/io.h>

#include <pololu/orangutan>
#include <pololu/orangutan.h>
#include <pololu/OrangutanDigital/OrangutanDigital.h>
#include <pololu/OrangutanPulseIn/OrangutanPulseIn.h>
#include <avr/interrupt.h>
const unsigned char pin2=IO_C3;
unsigned char channel=0;
unsigned long pulse_width;
unsigned char state;
long double cm;



int main(){
		
		while(1){
			
			
			
			OrangutanDigital::setOutput(pin2,LOW);
			
			OrangutanTime::delayMicroseconds(2);//2 Microseconds 
			OrangutanDigital::setOutput(pin2,HIGH);
		
			OrangutanTime::delayMicroseconds(5);//5Microseconds 
			OrangutanDigital::setOutput(pin2,LOW);
			
			OrangutanPulseIn::start((unsigned char[]){pin2},1);
			OrangutanDigital::setInput(pin2,HIGH_IMPEDANCE);
			struct PulseInputStruct pulseInfo;
			pulseInfo.lastPCTime;
					                            
			unsigned long LastHighPulseMicroseconds=OrangutanPulseIn::toMicroseconds(pulseInfo.lastHighPulse);
			
			cm=LastHighPulseMicroseconds/37.;	
			if (LastHighPulseMicroseconds>=300)
			{
				OrangutanDigital::setOutput(IO_D1,HIGH);
				delay_us(LastHighPulseMicroseconds);
				OrangutanDigital::setOutput(IO_D1,LOW);
			}
			
			
						
			//delay(18);	
			
			delay_ms(100);//100ms
			
				
			
			}			
			}									

what should i do to fix PD1 the sync to the echo?
Is there anything like this http://arduino.cc/en/Reference/PulseIn in Orangutan libraries?
because that what i think i need for my AVR program




Thank you for the oscilloscope traces. It still looks like your code is wrong because you are reading uninitialized variables. Here are three lines from your code:

         struct PulseInputStruct pulseInfo;
         pulseInfo.lastPCTime;
                                           
         unsigned long LastHighPulseMicroseconds=OrangutanPulseIn::toMicroseconds(pulseInfo.lastHighPulse);

The first line makes a struct; good. The second line does nothing and can be removed. The third line reads an uninitialized variable from the struct, resulting in undefined behavior. Does this make sense? You need to call OrangutanPulseIn::getPulseInfo to actually populate the struct with some useful data. Until then, you should not read from the struct.

–David

would this code below fix the uninitialized variables?

#include <avr/io.h>

#include <pololu/orangutan>
#include <pololu/orangutan.h>
#include <pololu/OrangutanDigital/OrangutanDigital.h>
#include <pololu/OrangutanPulseIn/OrangutanPulseIn.h>
#include <avr/interrupt.h>

const unsigned char pin2=IO_C3;
unsigned char channel=0;
unsigned long pulse_width;
unsigned char state;
long double cm;



int main(){
		
		while(1){
			
			
			
			OrangutanDigital::setOutput(pin2,LOW);
			
		
			OrangutanTime::delayMicroseconds(2);//2 Microseconds 
			OrangutanDigital::setOutput(pin2,HIGH);
			
			OrangutanTime::delayMicroseconds(5);//5Microseconds 
			OrangutanDigital::setOutput(pin2,LOW);
			
			OrangutanPulseIn::start((unsigned char[]){pin2},1);
			OrangutanDigital::setInput(pin2,HIGH_IMPEDANCE);
			
			struct PulseInputStruct pulseInfo;
			
			OrangutanPulseIn::getPulseInfo(1,&pulseInfo);
		   
			
			unsigned long LastHighPulseMicroseconds=OrangutanPulseIn::toMicroseconds(OrangutanPulseIn::getLastHighPulse(0));
			
			OrangutanPulseIn::stop();
			
			cm=LastHighPulseMicroseconds/37.;	
			if (LastHighPulseMicroseconds>=300)
			{
				OrangutanDigital::setOutput(IO_D1,HIGH);
				delay_us(LastHighPulseMicroseconds);
				OrangutanDigital::setOutput(IO_D1,LOW);
			}
			
			
						
			//delay(18);	
			
			delay_ms(100);//100ms
			
			
			
			}			
			}				
							

  

I still confuse what you mean “uninitialized variables”

 unsigned long LastHighPulseMicroseconds=OrangutanPulseIn::toMicroseconds(pulseInfo.lastHighPulse);

You can read about uninitalized variables here: en.wikipedia.org/wiki/Uninitialized_variable

The first argument to getPulseInfo should be 0, not 1. However, I see that you are not actually reading any data from the pulseInfo struct anywhere, so you could get rid of the line that makes the struct and get rid of the call to getPulseInfo if you wanted. In general, you should keep trying to simplify your code. That means removing commented lines and getting rid of unused variables like “cm”.

–David

I’m new at programming robots and still confused.

this code is the minimum that i could do, the only thing that is left is the trigger and pulse in.

i initialized variables like this right long LastHighPulseMicroseconds=0;
how do initialize the echo pulse into a variable to use in my code? because I know my current code doesn’t do anything.
Can you tall me how OrangutanPulseIn::Lasthighpulse(0); works to store information into the pin?
I’m Initialize the Pins right?
is this my situation “but this can cause situations where you fail to detect when an ISR has changed that variable’s value.”?
How am I going to turn OrangutanPulseIn::getLastHighPulse(0) into width? what else do i need to make it work?

#include <avr/io.h>
#include <pololu/orangutan>
#include <pololu/orangutan.h>
#include <pololu/OrangutanDigital/OrangutanDigital.h>
#include <pololu/OrangutanPulseIn/OrangutanPulseIn.h>
const unsigned char pin2=IO_C3;
long LastHighPulseMicroseconds=0;
int main(){
		
		while(1){
			OrangutanDigital::setOutput(pin2,LOW);
			OrangutanTime::delayMicroseconds(2);
			OrangutanDigital::setOutput(pin2,HIGH);
			OrangutanTime::delayMicroseconds(5);
			OrangutanDigital::setOutput(pin2,LOW);
			OrangutanPulseIn::start((unsigned char[]){pin2},1);
			OrangutanDigital::setInput(pin2,HIGH_IMPEDANCE);
			LastHighPulseMicroseconds=OrangutanPulseIn::toMicroseconds(OrangutanPulseIn::getLastHighPulse(0));
			delay_ms(100);
		}			
	}				
					

i deleted PD1 code from the code a above

Your code is looking pretty good now, except you forgot to delay before calling getLastHighPulse. You are essentially asking the library for the pulse width of the echo pulse a couple microseconds after you sent the ping pulse, so you are asking for a pulse width before the pulse has even happened. Try delaying for 1000 ms before calling getLastHighPulse(0). This is one of the steps in the pseudocode I posted a while back.

–David