go_away

Author Topic: $50 robot using PING))) Ultrasonic Sensor  (Read 12302 times)

0 Members and 1 Guest are viewing this topic.

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
$50 robot using PING))) Ultrasonic Sensor
« on: July 08, 2008, 05:34:54 PM »
I have the (not so $50) $50 robot with all the upgrades, and now I want to add this PING))) sensor I bought, but looking at the Fuzzy robot code, it looks to be for a sonar where you have to manually deal with it. From what I read about PING))) since it only has one signal line, and you have to change it from input to output somehow. I can't seem to mentally grasp the concept here. Can someone help me figure out how to write code for this sensor for my robot using an ATmega8(for now, soon to be ATMega168)

Thanks


Edit: Now using an ATmega168
« Last Edit: July 15, 2008, 03:27:42 PM by pomprocker »

Offline Scheda

  • Jr. Member
  • **
  • Posts: 24
  • Helpful? 0
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #1 on: July 08, 2008, 07:14:45 PM »
This is somewhat off topic, but how much did you pay for your PING sensor? My Radio Shack doesn't have the price for it out.

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #2 on: July 08, 2008, 08:03:15 PM »
Fry's Electronics carries parallax products. I picked one up for about $29.

Offline Brandon121233

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 320
  • Helpful? 0
  • "Genius is %1 inspiration and %99 perspiration"
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #3 on: July 08, 2008, 08:19:56 PM »
Definitely use the MAXBotics EZ1 Ultrasonic sensor instead, its a lot better (in my biased opinion of course) and easier to use cause there is basically no programming nor timing because it is all handled on the sensor itself, it outputs the information about distance in serial, analog or PWM formats. Plus I can help you out with any code help you need. Hope that helps you make your decision.
Hell, there are no rules here—we're
   trying to accomplish something.

                                                                              —Thomas Edison

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #4 on: July 09, 2008, 10:27:53 AM »
Here is some code for the BS2, that I need to convert to C for the $50 robot...

Code: [Select]
' -----[ Revision History ]------------------------------------------------





' -----[ I/O Definitions ]-------------------------------------------------



Ping            PIN     15





' -----[ Constants ]-------------------------------------------------------



#SELECT $STAMP

  #CASE BS2, BS2E

    Trigger     CON     5                       ' trigger pulse = 10 uS

    Scale       CON     $200                    ' raw x 2.00 = uS

  #CASE BS2SX, BS2P, BS2PX

    Trigger     CON     13

    Scale       CON     $0CD                    ' raw x 0.80 = uS

  #CASE BS2PE

    Trigger     CON     5

    Scale       CON     $1E1                    ' raw x 1.88 = uS

#ENDSELECT



RawToIn         CON     889                     ' 1 / 73.746 (with **)

RawToCm         CON     2257                    ' 1 / 29.034 (with **)



IsHigh          CON     1                       ' for PULSOUT

IsLow           CON     0





' -----[ Variables ]-------------------------------------------------------



rawDist         VAR     Word                    ' raw measurement

inches          VAR     Word

cm              VAR     Word





' -----[ EEPROM Data ]-----------------------------------------------------





' -----[ Initialization ]--------------------------------------------------



Reset:

  DEBUG CLS,                                    ' setup report screen

        "Parallax Ping Sonar  ", CR,

        "=====================", CR,

        CR,

        "Time (uS).....       ", CR,

        "Inches........       ", CR,

        "Centimeters...       "





' -----[ Program Code ]----------------------------------------------------



Main:

  DO

    GOSUB Get_Sonar                             ' get sensor value

    inches = rawDist ** RawToIn                 ' convert to inches

    cm = rawDist ** RawToCm                     ' convert to centimeters



    DEBUG CRSRXY, 15, 3,                        ' update report screen

          DEC rawDist, CLREOL,

          CRSRXY, 15, 4,

          DEC inches, CLREOL,

          CRSRXY, 15, 5,

          DEC cm, CLREOL



    PAUSE 100

  LOOP

  END





' -----[ Subroutines ]-----------------------------------------------------



' This subroutine triggers the Ping sonar sensor and measures

' the echo pulse.  The raw value from the sensor is converted to

' microseconds based on the Stamp module in use.  This value is

' divided by two to remove the return trip -- the result value is

' the distance from the sensor to the target in microseconds.



Get_Sonar:

  Ping = IsLow                                  ' make trigger 0-1-0

  PULSOUT Ping, Trigger                         ' activate sensor

  PULSIN  Ping, IsHigh, rawDist                 ' measure echo pulse

  rawDist = rawDist */ Scale                    ' convert to uS

  rawDist = rawDist / 2                         ' remove return trip

  RETURN

Code: [Select]
' {$STAMP BS2}

' {$PBASIC 2.5}



' Conversion constants for room temperature measurements.

CmConstant    CON   2260

InConstant    CON   890



cmDistance  VAR   Word

inDistance  VAR   Word

time        VAR   Word



DO

  PULSOUT 15, 5

  PULSIN 15, 1, time



  cmDistance = cmConstant ** time

  inDistance = inConstant ** time



  DEBUG HOME, DEC3 cmDistance, " cm"

  DEBUG CR, DEC3 inDistance, " in"



  PAUSE 100

LOOP



Code: [Select]

' -----[ Program Description ]---------------------------------------------



' This programs demonstrates roaming with the Parallax PING))) Mounting

' Bracket, which allows you to pan-scan with your Parallax PING))) sensor.

'

' This program assumes you have already set your BOE-Bot up for roaming

' with IR sensors.  You must also have the PING))) Mounting bracket

' installed as per the instructions, with the servo connected to P14 and

' the PING))) sensor connected to P15.

'

' Due to the way the PING))) bracket mounts you may have to trim your IR

' detectors down so that they don't stick up in the way of the moving

' PING))) bracket as it rotates.  It's best to angle them off at 45

' degree angles so that the BOE-Bot doesn't run into anything while

' moving along a wall at a narrow angle.

'

' The BOE-Bot will now roam around and when it senses an object, it will

' scan within a 180 degree field of view for the clearest path, which it

' will then navigate scanning for an object again.  The IR Sensors prevent

' hitting a wall when coming at it from a narrow angle where the PING)))

' might have trouble seeing it due to the lack of reflection of sound.

'

' Calibration is important to this code working properly.  If you do not

' have the correct values for your servos then you may get strange results

' from your BOE-Bot.  The necessary calibration information is listed in

' each section of the code where it is required.



' -----[ Revision History ]------------------------------------------------



' This code is basically a modified version of the Roaming With IR code

' from the Robotics With The BOE-Bot Manual, written by Andy Lindsay.

' Much of the original code was left untouched so you can see how it was

' altered.





' -----[ I/O Definitions ]-------------------------------------------------



Piezo           PIN     4               ' Piezo Speaker

RightServo      PIN     12              ' Right Servo

LeftServo       PIN     13              ' Left Servo

PingServo       PIN     14              ' PING))) Servo

Ping            PIN     15              ' PING))) Sensor





' -----[ Variables ]-------------------------------------------------------



irDetectLeft    VAR     Bit             ' Variable For Left IR Input

irDetectRight   VAR     Bit             ' Variable For Right IR Input

pulseCount      VAR     Byte            ' Used For Measuring Turns

distance        VAR     Word            ' Current Distance Of Object

oldDistance     VAR     Word            ' Old Distance Value

counter         VAR     Word            ' PING))) Cycle Counter

task            VAR     Nib             ' Current Task





' -----[ Initialization ]--------------------------------------------------



FREQOUT Piezo, 2000, 3000               ' Signal Program Start/Reset





' -----[ Program Code ]----------------------------------------------------



Main:

DO



  FREQOUT 8, 1, 38500                   ' Emit 38.5 kHz IR To Left

  irDetectLeft = IN9                    ' Store IR Detection Values



  FREQOUT 2, 1, 38500                   ' Emit 38.5 kHz IR To Right

  irDetectRight = IN0                   ' Store IR Detection Values



  IF (irDetectLeft = 0) AND (irDetectRight = 0) THEN

    GOSUB Ping_Around                   ' Object Detected via IR Forward

  ELSEIF (irDetectLeft = 0) THEN

    GOSUB Ping_Around                   ' Object Detected via IR Left

  ELSEIF (irDetectRight = 0) THEN

    GOSUB Ping_Around                   ' Object Detected via IR Right

  ENDIF



  counter = counter + 1                 ' Increment Passive Counter



  IF counter > 10 THEN                  ' Wait For 10 Servo Pulses

    GOSUB Ping_Out                      ' Activate PING)))

  ENDIF



  IF (distance > 30) THEN               ' Is Object Farther Than 30 cm?

    GOSUB Forward_Pulse                 ' If Yes Go Forward

  ELSE

    GOSUB Ping_Around                   ' Otherwise Scan For Clear Path

  ENDIF



LOOP





' -----[ Subroutines ]-----------------------------------------------------



' *************************************************************************

' * USE THE APPROPRIATE PULSOUT VALUES TO MAKE YOUR BOE-BOT MOVE FORWARD  *

' * WHILE THE PING))) IS FACING FORWARD.                                  *

' *************************************************************************



Forward_Pulse:                          ' Send A Single Forward Pulse

  PULSOUT PingServo, 750                ' Ping Servo Forward Pulse Value

  PULSOUT LeftServo, 850                ' Left Servo Forward Pulse Value

  PULSOUT RightServo, 650               ' Right Servo Forward Pulse Value

  PAUSE 20                              ' Refresh Delay

  RETURN



' *************************************************************************

' * USE THE APPROPRIATE PULSOUT VALUES TO MAKE YOUR BOE-BOT TURN LEFT 90  *

' * DEGREES.  USE THE SAME VALUE AS ABOVE FOR THE PING))) BRACKET SERVO.  *

' *************************************************************************



Turn_Left:                              ' Left Turn, About 45 Degrees

  FOR pulseCount = 0 TO 7               ' Number Of Pulses To Turn

    PULSOUT PingServo, 750              ' Ping Servo Forward Pulse Value

    PULSOUT LeftServo, 650              ' Left Servo Left Pulse Value

    PULSOUT RightServo, 650             ' Right Servo Left Pulse Value

    PAUSE 20                            ' Refresh Delay

  NEXT

  RETURN



' *************************************************************************

' * USE THE APPROPRIATE PULSOUT VALUES TO MAKE YOUR BOE-BOT TURN RIGHT 90 *

' * DEGREES.  USE THE SAME VALUE AS ABOVE FOR THE PING))) BRACKET SERVO.  *

' *************************************************************************



Turn_Right:                             ' Right Turn, About 45 Degrees

  FOR pulseCount = 0 TO 7               ' Number Of Pulses To Turn

    PULSOUT PingServo, 750              ' Ping Servo Forward Pulse Value

    PULSOUT LeftServo, 850              ' Left Servo Right Pulse Value

    PULSOUT RightServo, 850             ' Right Servo Right Pulse Value

    PAUSE 20                            ' Refresh Delay

  NEXT

  RETURN



' *************************************************************************

' * USE THE APPROPRIATE PULSOUT VALUES TO MAKE YOUR BOE-BOT MOVE BACKWARD *

' * WHILE THE PING))) IS FACING FORWARD.                                  *

' *************************************************************************



Back_Up:                                ' Back Up

  FOR pulseCount = 0 TO 40              ' Number Of Pulses To Backup

    PULSOUT PingServo, 750              ' Ping Servo Forward Pulse Value

    PULSOUT LeftServo, 650              ' Left Servo Backup Pulse Value

    PULSOUT RightServo, 850             ' Right Servo Backup Pulse Value

    PAUSE 20                            ' Refresh Delay

  NEXT

  RETURN



Ping_Out:                               ' PING)))

  counter = 0                           ' Reset Passive Delay Counter

  LOW Ping                              ' Force PING))) Line Low

  PULSOUT Ping, 5                       ' Activate PING))) Pulse

  PULSIN  Ping, 1, distance             ' Receive Return Pulse

  distance = distance ** 2257           ' Calculate Distance

  RETURN



Ping_Around:                            ' Start 180 Degree Pan-Scan

  counter = 0                           ' Reset Passive Delay Counter

  oldDistance = 30                      ' Current Old Distance Values

  task = 0                              ' Current Task Priority



' *************************************************************************

' * USE THE APPROPRIATE PULSOUT VALUE TO MAKE YOUR PING)))                *

' * TURN 90 DEGREES LEFT.                                                 *

' *************************************************************************



  FOR pulseCount = 0 TO 20              ' Number Of Pulses To Spin

    LOW Ping                            ' Force PING))) Line Low

    PULSOUT PingServo, 1085             ' Ping Servo 90 Left Pulse Value

    PULSOUT Ping, 5                     ' Activate PING)))

    PULSIN  Ping, 1, distance           ' Receive Distance Value

    PAUSE 20                            ' Refresh Delay

  NEXT



  distance = distance ** 2257           ' Calculate Distance In cm

  IF distance > oldDistance THEN        ' Is distance > Last Clear Path

    oldDistance = distance              ' Update oldDistance Value

    task = 1

  ENDIF



' *************************************************************************

' * USE THE APPROPRIATE PULSOUT VALUE TO MAKE YOUR PING)))                *

' * TURN 45 DEGREES LEFT.                                                 *

' *************************************************************************



  FOR pulseCount = 0 TO 20              ' Number Of Pulses To Spin

    LOW Ping                            ' Force PING))) Line Low

    PULSOUT PingServo, 850              ' Ping Servo 45 Left Pulse Value

    PULSOUT Ping, 5                     ' Activate PING)))

    PULSIN  Ping, 1, distance           ' Receive Distance Value

    PAUSE 20                            ' Refresh Delay

  NEXT



  distance = distance ** 2257           ' Calculate Distance In cm

  IF distance > oldDistance THEN        ' Is distance > Last Clear Path

    oldDistance = distance              ' Update oldDistance Value

    task = 2

  ENDIF



' *************************************************************************

' * USE THE APPROPRIATE PULSOUT VALUE TO MAKE YOUR PING)))                *

' * TURN 45 DEGREES RIGHT.                                                *

' *************************************************************************



  FOR pulseCount = 0 TO 20              ' Number Of Pulses To Spin

    LOW Ping                            ' Force PING))) Line Low

    PULSOUT PingServo, 400              ' Ping Servo 45 Right Pulse Value

    PULSOUT Ping, 5                     ' Activate PING)))

    PULSIN  Ping, 1, distance           ' Receive Distance Value

    PAUSE 20                            ' Refresh Delay

  NEXT



  distance = distance ** 2257           ' Calculate Distance In cm

  IF distance > oldDistance THEN        ' Is distance > Last Clear Path

    oldDistance = distance              ' Update oldDistance Value

    task = 3

  ENDIF



' *************************************************************************

' * USE THE APPROPRIATE PULSOUT VALUE TO MAKE YOUR PING)))                *

' * TURN 90 DEGREES RIGHT.                                                *

' *************************************************************************



  FOR pulseCount = 0 TO 20              ' Number Of Pulses To Spin

    LOW Ping                            ' Force PING))) Line Low

    PULSOUT PingServo, 225              ' Ping Servo 90 Right Pulse Value

    PULSOUT Ping, 5                     ' Activate PING)))

    PULSIN  Ping, 1, distance           ' Receive Distance Value

    PAUSE 20                            ' Refresh Delay

  NEXT



  distance = distance ** 2257           ' Calculate Distance In cm

  IF distance > oldDistance THEN        ' Is distance > Last Clear Path

    oldDistance = distance              ' Update oldDistance Value

    task = 4

  ENDIF



  ON task GOSUB Task0, Task1, Task2, Task3, Task4



  distance = 50                         ' Prevent Scan From Looping



  RETURN



Task0:                                  ' Forward Was Clearest Path

  GOSUB Turn_Right                      ' This Could Mean Narrow Path

  GOSUB Turn_Right                      ' So We'll Turn Around

  GOSUB Turn_Right                      ' You Can Change The Behavior

  GOSUB Turn_Right                      ' Of Any Of The Tasks

  RETURN



Task1:                                  ' 90 Degrees Left Was Clearest

  GOSUB Turn_Left

  GOSUB Turn_Left

  RETURN



Task2:                                  ' 45 Degrees Left Was Clearest

  GOSUB Turn_Left

  RETURN



Task3:                                  ' 45 Degrees Right Was Clearest

  GOSUB Turn_Right

  RETURN



Task4:                                  ' 90 Degrees Right Was Clearest

  GOSUB Turn_Right

  GOSUB Turn_Right

  RETURN





Offline airman00

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 3,653
  • Helpful? 21
  • narobo.com
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #5 on: July 09, 2008, 10:42:56 AM »
truthfully you need only translate one part of the code

this is the following part
Code: [Select]
PULSOUT Ping, Trigger                         ' activate sensor
PULSIN  Ping, IsHigh, rawDist                 ' measure echo pulse

I know how to translate the PULSOUT into C but the PULSIN I'm not sure about , it might need an interrupt or something.

In case you cant translate the above code , just take the easy way out and use this guy's code
http://www.chiefdelphi.com/forums/showthread.php?p=650374&highlight=ping#post650374

Also,
when you do figure it out , please post a C translation for the code I quoted above.

,Eric
Check out the Roboduino, Arduino-compatible board!


Link: http://curiousinventor.com/kits/roboduino

www.Narobo.com

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #6 on: July 09, 2008, 05:30:34 PM »
PULSOUT

To send a PWM signal, you need to specify the port and the amount of time. For example, to send a pulse on port 10 with a length of 4 μs, we would write:

PULSOUT 10, 2

Length Between Pulses

The PAUSE function, as we have seen before, can be used to delay operation of the next command. When using PAUSE to insert a delay between PWM pulses, keep in mind that it uses milliseconds, not 2 μs. Remember that PAUSE 1 takes the same amount of time as PULSOUT 12, 500.

PULSIN


In a similar manner to sending a PWM signal, we can also read a PWM signal from an external device. We must specify which port we are reading from, and we must also provide a variable to receive the length of the pulse. For instance, if we wanted to read a PWM pulse on port 5, we could write:

MyByte VAR Byte
PULSIN 5, MyByte

Like with PULSOUT, the units of time are 2 μs.

One common device that uses PWM input like this is the Parallax ultrasonic sensor. These sensors return a pulse for a length of time equal to the amount of time it takes sound waves to travel to an object and bounce back. Using some simple arithmetic, if we know the speed of sound and if we know the amount of time, we can calculate the distance of the object.
« Last Edit: July 09, 2008, 05:31:39 PM by pomprocker »

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #7 on: July 09, 2008, 05:33:21 PM »
I think that is basically saying, talk to it like a servo, then wait, and then listen to it like a sensor.

Offline airman00

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 3,653
  • Helpful? 21
  • narobo.com
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #8 on: July 09, 2008, 05:42:54 PM »
I think that is basically saying, talk to it like a servo, then wait, and then listen to it like a sensor.

exactly , but its not an analog sensor
Check out the Roboduino, Arduino-compatible board!


Link: http://curiousinventor.com/kits/roboduino

www.Narobo.com

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #9 on: July 09, 2008, 05:46:25 PM »
So can one remove the sensor pins they would be using on the $50 robot board from the ADC and just read it as digital?

Offline paulstreats

  • Supreme Robot
  • *****
  • Posts: 1,381
  • Helpful? 21
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #10 on: July 09, 2008, 06:45:02 PM »
The ping sensor works like this:

 You send a pulse (or pull a pin low then high then low again). You then let the pin float in input mode. The ping sensor then holds this pin high sends out its ping and waits for it to bounce back. Once the echo is detected it then pulls the pin back low.

So a simple bit of inefficient psuedocode will go:

Code: [Select]
(
set timer 0 to 0 here
set portd.o to output here)
portd.0 = 0;       //set portd.0 low
portd.0 = 1;       //set portd.0 high
portd.0 = 0;       //set portd.0 low again. This triggers the ping
set portd.0 to input here
enable timer0 here
wait 200ms (this is how long it takes for the sensor to send its ping. Remember for an accurate reading to account for changeing the prot state and enabling the timer)
while(portd.0 == 1){           //while the port is pulled high by the ping
//do nothing
}
ping reading = timer0;         the ping sensor has received an echo and pulled the line back low
//now you just have to do the math

There are many other ways to accomplish this more efficiently probably using the capture module but the code above is to give a better understanding about how to use the ping))).

I personally use the SRF02 which is a single transducer that performs both the send and receive aspect, its i2c and serial capable, can be operated a  ping sounder, an echo listener or both at once. It autocalibrates and can actually sense up to 6 metres. It cost £11.25 (about $22.50). Because its only 1 transducer it means that its half the footprint of a normal sonar type sensor. New firmware upgrades for the newer odel mean that it can intelligently pull its minimum detection ring right up to the transducer ring down.

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #11 on: July 09, 2008, 09:10:46 PM »
In the $50 robot code,

how would one change one of the sensor side ports to output and then to input?

   DDRC = 0x00;  //configure all C ports for input
   PORTC = 0x00; //make sure pull-up resistors are turned off
   DDRD = 0xFF;  //configure all D ports for output


I wouldn't want to configure ALL the C ports for output, just one pin. and then send PWM to it.
Then switch it back to input. so I can read its PWM?

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #12 on: July 10, 2008, 12:10:30 AM »
Port Registers

Port registers allow for lower-level and faster manipulation of the i/o pins of the microcontroller on an Arduino board. The chips used on the Arduino board (the ATmega8 and ATmega168) have three ports:

B (digital pin 8 to 13)
C (analog input pins)
D (digital pins 0 to 7)
Each port is controlled by three registers, which are also defined variables in the arduino language. The DDR register, determines whether the pin is an INPUT or OUTPUT. The PORT register controls whether the pin is HIGH or LOW, and the PIN register reads the state of INPUT pins set to input with pinMode(). The maps of the ATmega8 and ATmega168 chips show the ports.

DDR and PORT registers may be both written to, and read. PIN registers correspond to the state of inputs and may only be read.

PORTD maps to Arduino digital pins 0 to 7

DDRD – The Port D Data Direction Register
PORTD – The Port D Data Register
PIND – The Port D Input Pins Register - read only
PORTB maps to Arduino digital pins 8 to 13 The two high bits (6 & 7) map to the crystal pins and are not usable

DDRB – The Port B Data Direction Register
PORTB – The Port B Data Register
PINB – The Port B Input Pins Register - read only
PORTC maps to Arduino analog pins 0 to 5. Pins 6 & 7 are only accessible on the Arduino Mini

DDRC – The Port C Data Direction Register
PORTC – The Port C Data Register
PINC – The Port C Input Pins Register
Each bit of these registers corresponds to a single pin; e.g. the low bit of DDRB, PORTB, and PINB refers to pin PB0 (digital pin 8). For a complete mapping of Arduino pin numbers to ports and bits, see the diagram for your chip: ATmega8, ATmega168. (Note that some bits of a port may be used for things other than i/o; be careful not to change the values of the register bits corresponding to them.)

Examples

Referring to the pin map above, the PortD registers control Arduino digital pins 0 – 7.

You should note, however, that pins 0 & 1 are used for serial communications for programming and debugging the Arduino, so changing these pins should usually be avoided unless needed for serial input or output functions. Be aware that this can interfere with program download or debugging.

DDRD is the direction register for Port D (Arduino digital pins 0-7). The bits in this register control whether the pins in PORTD are configured as inputs or outputs so, for example:

DDRD = B11111110;  // sets Arduino pins 1 – 7 as outputs, pin 0 as input
DDRD = DDRD | B11111100;  // this is safer – it sets pins 2 to 7 as outputs
                     // without changing the value of pins 0 & 1, which are RX & TX
//See the bitwise operators reference pages and The Bitmath Tutorial in the Playground

PORTB is the register for the state of the outputs. For example;

PORTD = B10101000; // sets digital pins 7,5,3 HIGH

You will only see 5 volts on these pins however if the pins have been set as outputs using the DDRD register or with pinMode().

PINB is the input register variable – it will read all of the digital input pins at the same time.

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #13 on: July 11, 2008, 09:25:54 PM »
Working out some code here with the help from Admin's Fuzzy source code, Paulstreats pseudocode above, and the specs of the Parallax Ping.


input trigger - positive ttl pulse 5 microseconds

echo pulse - pos ttl pulse 115microsecs to 18.5 millisecs

echo hold on - 750microseconds from fall of trigger pulse


Code:


int PingPin = 1;          // assign a pin to the Ping Sensor
int PingVal = 0;          // initialize and assign Ping Sensor Reading Value

PORT_ON(DDRC, PingPin);   // Switch PingPin to OUPUT

// ------Trigger Pulse--------------

PORT_OFF(PORTC, PingPin);   // Bring PingPin low before starting trigger pulse
delay_us(2);        //  Wait for 2 microseconds
PORT_ON(PORTC, PingPin);    // Bring PingPin High for 5us according to spec sheet.
delay_us(5);       // Wait for 5 microseconds
PORT_OFF(PORTC, PingPin);; //  Bring PingPin Low and standby

//--------End Trigger Pulse---------------------

FLIP_PORT(DDRC, PingPin);   // Switch PingPin to INPUT

loop_until_bit_is_set(PINC, PingPin);     // Loop until the the PingPin goes high  (macro found in sfr_def.h)

//clears timer, reset overflow counter
reset_timer_0();       //reset timer 0

loop_until_bit_is_clear(PINC, PingPin);     // Loop until the the PingPin goes low  (macro found in sfr_def.h)

//read timer0's overflow counter
//255 is count before overflow, dependent on clock
int elapsed_time=timer0GetOverflowCount()*255+TCNT0;

//   The PING))) returns a pulse width of 29.033 uS per centimeter
PingVal = elapsed_time;
« Last Edit: July 16, 2008, 08:12:39 PM by pomprocker »

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #14 on: July 11, 2008, 09:30:38 PM »
Could someone help explain these to me in technical terms please?

#define PORT_ON( port_letter, number )         port_letter |= (1<<number)
#define PORT_OFF( port_letter, number )         port_letter &= ~(1<<number)
#define PORT_ALL_ON( port_letter, number )      port_letter |= (number)
#define PORT_ALL_OFF( port_letter, number )      port_letter &= ~(number)
#define FLIP_PORT( port_letter, number )      port_letter ^= (1<<number)
#define PORT_IS_ON( port_letter, number )      ( port_letter & (1<<number) )
#define PORT_IS_OFF( port_letter, number )      !( port_letter & (1<<number) )


edit:   figured it out on my own  :P

« Last Edit: July 14, 2008, 12:46:10 PM by pomprocker »

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #15 on: July 11, 2008, 09:35:03 PM »
how do I make sure Pin whatever on port C is set to digital mode?

I read that the C ports are set to digital I/O by default is this correct?

I've only used analog sensors on the C ports, digital sensors work too?
« Last Edit: July 14, 2008, 12:46:53 PM by pomprocker »

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #16 on: July 14, 2008, 07:23:10 PM »
hmmm it doesnt seem like this thread is posted as new unread to people when I modify only when I post a new reply.


Can someone look at the code I've been developing above?

Offline Commanderbob

  • Robot Overlord
  • ****
  • Posts: 146
  • Helpful? 2
  • Embeddedmicro.com
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #17 on: July 15, 2008, 05:13:53 PM »
Here is the code that WORKS PERFECTLY for the ATmega128 using the ICP1 pin.
robot.c
Code: [Select]
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include "hardware.h"

void init_hardware (void);
void USART_Transmit( unsigned char data );
uint16_t a2d_10( uint8_t Channel );
uint8_t a2d_8( uint8_t Channel );
uint16_t ultra_sonic (void);

void init_hardware (void)
{
    PORTA=0;
    DDRA=0;

    PORTB=YELLOW_LED_MASK;
    DDRB=YELLOW_LED_MASK;

    PORTC=0;
    DDRC=0;

    PORTD=0;
    DDRD=0;

    PORTE=0;
    DDRE=MOTOR_MASK|SERVO_WHEEL_MASK|SERVO_IR_MASK;

    PORTF=0;
    DDRF=0;

    PORTG=BLUE_LED_MASK|RED_LED_MASK;
    DDRG=BLUE_LED_MASK|RED_LED_MASK;

    TCCR3A=0b10101010;
    TCCR3B=0b00011010;
    ICR3=40000;
    OCR3A=3000;
    OCR3B=3000;
    OCR3C=3000;

    TCCR1A=0;
    TCCR1B=2;


    ADCSR = (( 1 << ADEN ) | ( 1 << ADSC ) | ADC_PRESCALAR_128 );
    ADMUX = (( 0 << REFS1 ) | ( 1 << REFS0 ));

    if (((( 1 << ADEN ) | ( 1 << ADSC ) | ADC_PRESCALAR_128 ) & ADCSR ) != 0 )
    {
        // Wait for the initial conversion to complete. This initializes
        // the ADC.

        while (ADCSR & ( 1 << ADSC) )
            ;
    }

    UBRR0H = UBRR0_INIT >> 8;
    UBRR0L = UBRR0_INIT & 0xFF;

    UCSR0A = UCSR0A_INIT;
    UCSR0B = UCSR0B_INIT;
    UCSR0C = UCSR0C_INIT;

}

void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) );
/* Put data into buffer, sends the data */
UDR0 = data;
}

uint16_t a2d_10( uint8_t Channel )
{
    // Select the channel in a manner which leaves REFS0 and REFS1 un touched.

    ADMUX = ( ADMUX & (( 1 << REFS1 ) | ( 1 << REFS0 ))) | Channel;

    // Start the conversion
    ADCSR = ADCSR | ( 1 << ADSC );

    // Wait for it to complete
    while ( ADCSR & ( 1 << ADSC ));

    return ADC;

} // a2d_10

uint8_t a2d_8( uint8_t Channel )
{
    // Select the channel in a manner which leaves REFS0 and REFS1 un touched.

    ADMUX = ( ADMUX & (( 1 << REFS1 ) | ( 1 << REFS0 ))) | ( 1 << ADLAR ) | Channel;

    // Start the conversion
    ADCSR = ADCSR | ( 1 << ADSC );

    // Wait for it to complete
    while ( ADCSR & ( 1 << ADSC ));

    // We only need the top 8 bits (left-adjusted)
    return ADCH;

} // a2d _8

uint16_t ultra_sonic (void)
{
    uint16_t fcap=0,scap=0;
    ULTRA_SONIC_OUT;
    ULTRA_SONIC_SET;
    _delay_us (10);
    ULTRA_SONIC_RESET;
    ULTRA_SONIC_IN;
    Clear_ICF1;
    TCNT1=0;
    ULTRA_SONIC_CAP_RISING;
    while (ICF1_Empty);//wait for capture
    Clear_ICF1;
    fcap=ICR1;
    ULTRA_SONIC_CAP_FALLING;
    while (ICF1_Empty);//wait for capture
    Clear_ICF1;
    scap=ICR1;
    return scap-fcap;
}


int main (void)
{
    uint16_t ac=0;
    char txt[]="      ";
    init_hardware();
    _delay_ms(100);
    while (1)
    {
        ac=ultra_sonic();
        sprintf(txt,"%u     ",ac);
        USART_Transmit(txt[0]);
        USART_Transmit(txt[1]);
        USART_Transmit(txt[2]);
        USART_Transmit(txt[3]);
        USART_Transmit(txt[4]);
        USART_Transmit('\n');
        USART_Transmit('\r');
        _delay_ms(500);
    }
}
hardware.h
Code: [Select]
#define RED_LED_PIN     4
#define RED_LED_MASK    ( 1 << RED_LED_PIN )
#define RED_LED_DDR     DDRG
#define RED_LED_PORT    PORTG

#define BLUE_LED_PIN    3
#define BLUE_LED_MASK   ( 1 << BLUE_LED_PIN )
#define BLUE_LED_DDR    DDRG
#define BLUE_LED_PORT   PORTG

#define YELLOW_LED_PIN  4
#define YELLOW_LED_MASK ( 1 << YELLOW_LED_PIN )
#define YELLOW_LED_DDR  DDRB
#define YELLOW_LED_PORT PORTB

#define LED_ON( color )     color ## _LED_PORT &= ~color ## _LED_MASK;
#define LED_OFF( color )    color ## _LED_PORT |=  color ## _LED_MASK;

#define MOTOR_MASK ( 1 << 3)
#define SERVO_WHEEL_MASK ( 1 << 4)
#define SERVO_IR_MASK ( 1 << 5)
#define ULTRA_SONIC_MASK (1<<4)

#define ULTRA_SONIC_OUT (DDRD|=ULTRA_SONIC_MASK)
#define ULTRA_SONIC_IN (DDRD&=~ULTRA_SONIC_MASK)
#define ULTRA_SONIC_SET (PORTD|=ULTRA_SONIC_MASK)
#define ULTRA_SONIC_RESET (PORTD&=~ULTRA_SONIC_MASK)
#define ULTRA_SONIC_CAP_RISING (TCCR1B|=(1<<ICES1))
#define ULTRA_SONIC_CAP_FALLING (TCCR1B&=~(1<<ICES1))

#define Clear_ICF1 TIFR|=(1<<5)
#define ICF1_Empty !(TIFR & ( 1 << 5 ))

#define ADC_PRESCALAR_2     (( 0 << ADPS2 ) | ( 0 << ADPS1 ) | ( 1 << ADPS0 ))
#define ADC_PRESCALAR_4     (( 0 << ADPS2 ) | ( 1 << ADPS1 ) | ( 0 << ADPS0 ))
#define ADC_PRESCALAR_8     (( 0 << ADPS2 ) | ( 1 << ADPS1 ) | ( 1 << ADPS0 ))
#define ADC_PRESCALAR_16    (( 1 << ADPS2 ) | ( 0 << ADPS1 ) | ( 0 << ADPS0 ))
#define ADC_PRESCALAR_32    (( 1 << ADPS2 ) | ( 0 << ADPS1 ) | ( 1 << ADPS0 ))
#define ADC_PRESCALAR_64    (( 1 << ADPS2 ) | ( 1 << ADPS1 ) | ( 0 << ADPS0 ))
#define ADC_PRESCALAR_128   (( 1 << ADPS2 ) | ( 1 << ADPS1 ) | ( 1 << ADPS0 ))

#define UART0_BAUD_RATE     9600
#define UART1_BAUD_RATE     38400

#define UART_DATA_BIT_8  (( 1 << UCSZ1 ) | ( 1 << UCSZ0 ))
#define UART_PARITY_NONE (( 0 << UPM1 )  | ( 0 << UPM0 ))
#define UART_STOP_BIT_1  ( 1 << USBS )

#define UBRR0_INIT   (( 1000000 / UART0_BAUD_RATE ) - 1 )
#define UBRR1_INIT   (( 1000000 / UART1_BAUD_RATE ) - 1 )

#define UCSR0A_INIT  0
#define UCSR0B_INIT  (( 1 << RXEN ) | ( 1 << TXEN ))
#define UCSR0C_INIT  ( UART_DATA_BIT_8 | UART_PARITY_NONE | UART_STOP_BIT_1 )

#define UCSR1A_INIT  0
#define UCSR1B_INIT  (( 1 << RXEN ) | ( 1 << TXEN ))
#define UCSR1C_INIT  ( UART_DATA_BIT_8 | UART_PARITY_NONE | UART_STOP_BIT_1 )

Justin

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #18 on: July 15, 2008, 05:54:05 PM »
So then changing the trigger sequence this should work

Code: [Select]
#define PORT_ON( port_letter, number )         port_letter |= (1<<number)            // ultrasonic out, ultrasonic set
#define PORT_OFF( port_letter, number )         port_letter &= ~(1<<number)      // ultrasonic in, ultrasonic reset
#define PORT_ALL_ON( port_letter, number )      port_letter |= (number)
#define PORT_ALL_OFF( port_letter, number )      port_letter &= ~(number)
#define FLIP_PORT( port_letter, number )      port_letter ^= (1<<number)
#define PORT_IS_ON( port_letter, number )      ( port_letter & (1<<number) )
#define PORT_IS_OFF( port_letter, number )      !( port_letter & (1<<number) )

PORT_ON(DDRC, PingPin);  // Set Pin to OUTPUT
//----Trigger Pulse----------
PORT_ON(PORTC, PingPin);
delay_us(10);
PORT_OFF(PORTC, PingPin);
//-----End Trigger Pulse-----
PORT_OFF(DDRC, PingPin);  // Set Pin to INPUT

but can you explain the last half of your code to me?

Code: [Select]
#define ULTRA_SONIC_CAP_RISING (TCCR1B|=(1<<ICES1))

#define Clear_ICF1 TIFR|=(1<<5)
#define ICF1_Empty !(TIFR & ( 1 << 5 ))

    Clear_ICF1;
    TCNT1=0;
    ULTRA_SONIC_CAP_RISING;
    while (ICF1_Empty);//wait for capture
    Clear_ICF1;
    fcap=ICR1;
    ULTRA_SONIC_CAP_FALLING;
    while (ICF1_Empty);//wait for capture
    Clear_ICF1;
    scap=ICR1;
    return scap-fcap;


heavy commenting would be great  ;D

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #19 on: July 15, 2008, 06:06:00 PM »
Also, I'm using the atmega168



PC1 is connected to the Ping Sensor. I heard that the Ping sensor is digital. Would this port work for that? Or do I need to breakout the PB0 pin?

BTW, what do all those acronyms in parenthesis mean?

Offline Commanderbob

  • Robot Overlord
  • ****
  • Posts: 146
  • Helpful? 2
  • Embeddedmicro.com
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #20 on: July 15, 2008, 06:24:34 PM »
OK. Sorry I did not comment before I just got it to work. I found my old working code.
Code: [Select]
uint16_t ultra_sonic (void)
{
    uint16_t fcap=0,scap=0;//fcap stores first capture, scap stores second
    ULTRA_SONIC_OUT;//set pin to output
    ULTRA_SONIC_SET;//set pin to high
    _delay_us (10);//delay for a pulse
    ULTRA_SONIC_RESET;//set pin low
    ULTRA_SONIC_IN;//set pin to input
    Clear_ICF1;//clear the capture flag
    TCNT1=0;//set timer 1 to 0 to prevent overflow
    ULTRA_SONIC_CAP_RISING;//capture the rising edge of the pulse
    while (ICF1_Empty);//wait for capture
    Clear_ICF1;//clear the capture flag
    fcap=ICR1;//save the captured value
    ULTRA_SONIC_CAP_FALLING;//capture the falling edge of the pulse
    while (ICF1_Empty);//wait for capture
    Clear_ICF1;//clear the capture flag
    scap=ICR1;//save the captured value
    return scap-fcap;//subtract the timer values to find the pulse lenght
}

This code uses the input capture unit on timer 1. You must configure timer 1 with
Code: [Select]
TCCR1A=0;
TCCR1B=2;
You could modify it a bit if you needed servos as well but it is much better to use timer 1 for just the PING. I had it set up once with two servos and the PING but it would sometimes overflow so you would have to account for that. You also don't get as good of resolution.

The capture unit saves the timer value in ICR1 when the pin goes from low to high or high to low. By subtracting the begging value from the end value you get the time of the pulse. You would then divide it by 2 and use the speed of sound to find how far away the object is.

You must breakout PB0 as it is the only pin connected to the capture unit. You could use PC1 but your results would not be as accurate.

As for the acronyms I don't know all of them off the top of my head, they are all in the datasheet, but RXD is receive for the USART, TXD is transmit, OCxy is "Output Compare timer# letter" they are used for PWM. ADC is analog to digital converter. I think PCINT is pin change interrupt. SCK, MISO, MOSI, and SS are all for SPI or I2C.

All the things in the parenthesis can be turned on or off. You can use portc for digital I/O but since it is the only port with an ADC it is used mostly for analog inputs. When in doubt read the datasheet.

For more on the capture unit look on page 116 of the datasheet.

Justin

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #21 on: July 15, 2008, 10:35:41 PM »
hmmm my new code didn't do anything  ???
Code: [Select]
void ping(void)
     {
     int PingPin = 0x02;// assign a pin to the Ping Sensor
     int PingVal = 0;// initialize and assign Ping Sensor Reading Value

PORT_ON(DDRC, PingPin);  // Set Pin to OUTPUT
//----Trigger Pulse----------
PORT_ON(PORTC, PingPin);
delay_us(10);
PORT_OFF(PORTC, PingPin);
//-----End Trigger Pulse-----
PORT_OFF(DDRC, PingPin);  // Set Pin to INPUT

     //PORT_ON(DDRC, 1);// Switch signalpin to output
     // ------Trigger Pulse--------------
     //PORT_OFF(PORTC, 1);   // Send low pulse, 0=low, 1=high
     //delay_us(2);        // Wait for 2 microseconds
     //PORT_ON(PORTC, 1); // Send high pulse, 0=low, 1=high
     //delay_us(5);       // Wait for 5 microseconds
     //PORT_OFF(PORTC, 1);; // Holdoff low
     //--------End Trigger Pulse---------------------
     //FLIP_PORT(DDRC, 1);   //  Switch signalpin to input
     

     //clears timer, reset overflow counter
     reset_timer_0();//reset timer 0
     delay_us(200);   //   wait for burst frequency to end.
     PINC = PINC | PingPin;
     while(PINC == 1) {   
          // wait until pin goes low or times out
  //asm volatile ("NOP");
          nop();   //  to prevent an optimized compiler from removing the loop
     }
     //read timer0's overflow counter
     //255 is count before overflow, dependent on clock
     int elapsed_time=timer0GetOverflowCount()*255+TCNT0;
     PingVal = elapsed_time/93;
     rprintf("Ping: %d", PingVal );
     delay_us(200);   // delay before next measurment

     } // end ping function




Offline Commanderbob

  • Robot Overlord
  • ****
  • Posts: 146
  • Helpful? 2
  • Embeddedmicro.com
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #22 on: July 15, 2008, 10:55:12 PM »
Why use timer 0 and not timer 1? timer 1 is 16 bit = 256 times better resolution. I am getting data accurate to the mm. I am actually now converting it to mm. If you have your heart set on using portC I'll help you, but I would strongly recommend using the capture unit.

What is
delay_us(200);
for? You should not be waiting for anything. If you want  to do it with a general I/O you should have two whiles.

while low //wait for the pulse to start
reset timer here
while high //wait for the pulse to end
save time here //rough measure of the pulse length

Also what is PINC?

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #23 on: July 15, 2008, 11:05:24 PM »
i don't know nothin about timers

I'm using the $50 robot board the B port isnt broken out

delay_us(); is in timer.h in the avrlib

PINC:
http://ccrma.stanford.edu/courses/250a/lectures/programming/node19.html


Offline Commanderbob

  • Robot Overlord
  • ****
  • Posts: 146
  • Helpful? 2
  • Embeddedmicro.com
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #24 on: July 15, 2008, 11:21:22 PM »
Ha Ha Ha  ;D That is why my other code did not work! Another side effect from using PIC. With PIC you use portx for input and output.

I know what delay_us is but why are you waiting?

Try something like this
Code: [Select]
#define ULTRA_SONIC_MASK (1<<4)

#define ULTRA_SONIC_OUT (DDRD|=ULTRA_SONIC_MASK)
#define ULTRA_SONIC_IN (DDRD&=~ULTRA_SONIC_MASK)
#define ULTRA_SONIC_SET (PORTD|=ULTRA_SONIC_MASK)
#define ULTRA_SONIC_RESET (PORTD&=~ULTRA_SONIC_MASK)
#define ULTRA_SONIC_IS_LOW (!(PIND&ULTRA_SONIC_MASK))
#define ULTRA_SONIC_IS_HIGH ((PIND&ULTRA_SONIC_MASK)==ULTRA_SONIC_MASK)

uint16_t ultra_sonic (void)
{
    uint16_t fcap=0,scap=0;
    ULTRA_SONIC_OUT;
    ULTRA_SONIC_SET;
    _delay_ms (1);
    ULTRA_SONIC_RESET;
    ULTRA_SONIC_IN;
    TCNT1=0;
    while(ULTRA_SONIC_IS_LOW);
    fcap=TCNT1;
    while(ULTRA_SONIC_IS_HIGH);
    scap=TCNT1;
    return scap-fcap;
}

Change the ports/pins for your setup.

How hard would it be to break out PortB 0? I would really consider using the capture unit. It is your friend. Also use timer1 if you can. Post your entire code and I can help you more.

Justin

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #25 on: July 16, 2008, 11:54:26 AM »
I just learned this....

sfr_def.h is included by io.h and has these macros:

------------------------------------------------------------------

#define _BV     (     bit            )         (1 << (bit))

 #include <avr/io.h>

Converts a bit number into a byte value.

Note:
    The bit shift is performed by the compiler which then inserts the result into the code. Thus, there is no run-time overhead when using _BV().

------------------------------------------------------------------

#define bit_is_clear    (    sfr,
      bit         )        (!(_SFR_BYTE(sfr) & _BV(bit)))

 #include <avr/io.h>

Test whether bit bit in IO register sfr is clear. This will return non-zero if the bit is clear, and a 0 if the bit is set.

------------------------------------------------------------------

#define bit_is_set    (    sfr,
      bit         )        (_SFR_BYTE(sfr) & _BV(bit))

 #include <avr/io.h>

Test whether bit bit in IO register sfr is set. This will return a 0 if the bit is clear, and non-zero if the bit is set.

------------------------------------------------------------------

#define loop_until_bit_is_clear    (    sfr,
      bit         )        do { } while (bit_is_set(sfr, bit))

 #include <avr/io.h>

Wait until bit bit in IO register sfr is clear.

------------------------------------------------------------------

#define loop_until_bit_is_set    (    sfr,
      bit         )        do { } while (bit_is_clear(sfr, bit))

 #include <avr/io.h>

Wait until bit bit in IO register sfr is set.
------------------------------------------------------------------

Offline Commanderbob

  • Robot Overlord
  • ****
  • Posts: 146
  • Helpful? 2
  • Embeddedmicro.com
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #26 on: July 16, 2008, 12:12:35 PM »
That is nice to know. I usually just make my own using the same method. Do you need any help setting up the timers? You could also do with out the timer and do something like
Code: [Select]
while (is_set)++pulse_time;Justin

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #27 on: July 16, 2008, 10:04:17 PM »
I need math help now that I got it working with my code below.

When PingVal returns 145 that is the max reading which is equal to 300cm

When PingVal returns 1 which is the min reading that equals 3cm


How can I do the math do get PingVal into human readable format?
Code: [Select]
int PingPin = 1;          // assign a pin to the Ping Sensor
int PingVal = 0;          // initialize and assign Ping Sensor Reading Value

PORT_ON(DDRC, PingPin);   // Switch PingPin to OUPUT

// ------Trigger Pulse--------------

PORT_OFF(PORTC, PingPin);   // Bring PingPin low before starting trigger pulse
delay_us(2);        //  Wait for 2 microseconds
PORT_ON(PORTC, PingPin);    // Bring PingPin High for 5us according to spec sheet.
delay_us(5);       // Wait for 5 microseconds
PORT_OFF(PORTC, PingPin);; //  Bring PingPin Low and standby

//--------End Trigger Pulse---------------------

FLIP_PORT(DDRC, PingPin);   // Switch PingPin to INPUT

loop_until_bit_is_set(PINC, PingPin);     // Loop until the the PingPin goes high  (macro found in sfr_def.h)

//clears timer, reset overflow counter
reset_timer_0();       //reset timer 0

loop_until_bit_is_clear(PINC, PingPin);     // Loop until the the PingPin goes low  (macro found in sfr_def.h)

//read timer0's overflow counter
//255 is count before overflow, dependent on clock
int elapsed_time=timer0GetOverflowCount()*255+TCNT0;

//   The PING))) returns a pulse width of 29.033 uS per centimeter
PingVal = elapsed_time;


« Last Edit: July 16, 2008, 10:05:20 PM by pomprocker »

Offline Commanderbob

  • Robot Overlord
  • ****
  • Posts: 146
  • Helpful? 2
  • Embeddedmicro.com
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #28 on: July 16, 2008, 10:50:17 PM »
First you divide by 2. That is because the sound has to travel to the object and back. So 145/2=72.5

According to what you have said 1cm = 29.033 us. So 72.5=8709.9us or 72.5=300cm. I take it you want the distance in cm.

300/72.5=4.1379...
divide by two and you get 2.068965517
To convert your reading to cm use
Code: [Select]
elapsed_time*= 2.068965517;you can shorten the decimal length to probably 2.068 with out any loss.
This accommodates for the round trip.

Here is a quick check if elapsed_time=145
145*2.068965517=300

You should note that since you are using timer0 an 8 bit timer you will not even get cm resolution. You will get 300/145=2.0689cm resolution. If you can break out PB0 you could get 0.0850725mm resolution! That is what I get, 243 times better!

Justin

Offline pomprockerTopic starter

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: $50 robot using PING))) Ultrasonic Sensor
« Reply #29 on: July 16, 2008, 11:40:15 PM »
Thanks so much Justin you've been a big help.

Ill break out the PORT B soon. But for now I'm just going to stick with PORT C.



 


Get Your Ad Here

data_list