Let's Make Robots!

3x Ultrasonic sensor

Hi I have problem with reading value from 3 ultrasonic sensor. I use Atmega644P and trig is conected to PD5-PD7, but echo from all sensors conected to PD2. I tried read value and wrote to LCD. When I disconnected all sensors the some values are on LCD, but when I connected all sensors and click to reset the LCD is clear.

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd.c"
#include "lcd.h"
#include "myutils.h"

#define trigf PD5
#define trigl PD6
#define trigr PD7
#define echo PD2

volatile unsigned int pulse = 0;
volatile uint8_t INT0_interrupt = 0;
volatile uint8_t measurement_complete = 0;

void Init_Ultra() {
    TCCR0A = (1<<WGM01);
    OCR0A=19;
    TIMSK0|=(1<<OCIE0A);
    EIMSK|=(1<<INT0);
    DDRD|=(1<<trigl)|(1<<trigf)|(1<<trigr);
    DDRD&=~(1<<echo);
}

uint16_t Ultra_distance(unsigned char sensor) {
    uint16_t dist=0;
    dist=0;
    pulse=0;
    TCNT0=0;

    PORTD|=(1<<sensor);
    _delay_us(12);
    PORTD&=~(1<<sensor);

    EICRA = (1<<ISC01)|(1<<ISC00);

    sei();

    while(measurement_complete!=1) {

    }

    cli();

    measurement_complete = 0;

    dist = pulse/58;

    return dist;
}

int main(void) {
    InitLCD(LS_BLINK|LS_ULINE);
    LCDClear();

    Init_Ultra();

    uint16_t distance = 0;

        while(1) {

            distance = Ultra_distance(7);
            LCDWriteIntXY(0,0,distance,3);
            _delay_ms(100);
       
            distance = Ultra_distance(6);
            LCDWriteIntXY(4,0,distance,3);
            _delay_ms(100);
       
            distance = Ultra_distance(5);
            LCDWriteIntXY(8,0,distance,3);
            _delay_ms(100);
        }
}

ISR(INT0_vect) {
    if(INT0_interrupt == 0) {
        TCCR0B|=(1<<CS01);
        EICRA=(1<<ISC01);
        INT0_interrupt=1;
    }
    else {
        TCCR0B&=~(1<<CS01);
        INT0_interrupt=0;
        measurement_complete=1;
    }
}

ISR(TIMER0_COMPA_vect) {
    pulse+=10;
}

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Thank you, I connected Trig and Echo on one pin (like birdman said) and it is work Perfectly :D

 

Here is the NEW Working code:

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>
#include "lcd.c"
#include "lcd.h"
#include "myutils.h"


// Ultrasonic HC-SR04
//PA5 trig and echo
//PA6 trig and echo
//PA7 trig and echo


uint16_t readuss(uint8_t sensor) {

    uint32_t i,result;

    //Make Pins OUT
    DDRA|=(1<<PA5)|(1<<PA6)|(1<<PA7);

    //TRIG
    PORTA|=(1<<sensor);
    _delay_us(12);
    PORTA&=~(1<<sensor);
   
    //Make pins IN
    DDRA&=~(1<<PA5);
    DDRA&=~(1<<PA6);
    DDRA&=~(1<<PA7);

    //ECHO
    //waiting for the rising edge
    for(i=0;i<600000;i++)
    {
        if(!(PINA&(1<<sensor))) continue; else break;
    }

    if (i==600000)
        return 0;

    //High edge found

    //Setup timer
    TCCR1A=0x00;
    TCCR1B=(1<<CS11);//Prescaler = Fcpu/8
    TCNT1=0x00;//Init. counter

    //Wait for the falling edge
    for(i=0;i<600000;i++)
    {
        if(PINA&(1<<sensor))
        {
            if(TCNT1>60000) break; else continue;
        }

    else
        break;
    }

    if(i==600000)
        return 0;

    //Falling edge found

    result=TCNT1;

    //Stop Timer
    TCCR1B=0x00;

    //Convetr to CM
    result/=58;

    return (result>>1);
}

int main(void) {
    InitLCD(LS_BLINK|LS_ULINE);
    LCDClear();

    DDRB=0xFF;
    PORTB=0x00;

   
    while(1) {
        LCDWriteIntXY(0,0,readuss(5),4);
        _delay_ms(500);

        LCDWriteIntXY(5,1,readuss(6),4);
        _delay_ms(500);

        LCDWriteIntXY(9,0,readuss(7),4);
        _delay_ms(500);
    }
}


Birdmun - oh yes, I`ll change it. thanks

 

Here is the "old" code:

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>
#include "lcd.c"
#include "lcd.h"
#include "myutils.h"

#define trigr PA5
#define trigf PA6
#define trigl PA7
#define echo PA2

uint16_t readuss(uint8_t sensor) {

    uint32_t i,result;

    //TRIG
    PORTA|=(1<<sensor);
    _delay_us(12);
    PORTA&=~(1<<sensor);

    //ECHO
    //waiting for the rising edge
    for(i=0;i<600000;i++)
    {
        if(!(PINA&(1<<echo))) continue; else break;
    }

    if (i==600000)
        return 0;

    //High edge found

    //Setup timer
    TCCR1A=0x00;
    TCCR1B=(1<<CS11);//Prescaler = Fcpu/8
    TCNT1=0x00;//Init. counter

    //Wait for the falling edge
    for(i=0;i<600000;i++)
    {
        if(PINA&(1<<echo))
        {
            if(TCNT1>60000) break; else continue;
        }

    else
        break;
    }

    if(i==600000)
        return 0;

    //Falling edge found

    result=TCNT1;

    //Stop Timer
    TCCR1B=0x00;

    //Convetr to CM
    result/=58;

    return (result>>1);
}

int main(void) {
    InitLCD(LS_BLINK|LS_ULINE);
    LCDClear();

    DDRB=0xFF;
    PORTB=0x00;

    DDRA|=(1<<PA5)|(1<<PA6)|(1<<PA7);
   
    while(1) {
        LCDWriteIntXY(0,0,readuss(5),4);
        _delay_ms(500);

        LCDWriteIntXY(5,1,readuss(6),4);
        _delay_ms(500);

        LCDWriteIntXY(9,0,readuss(7),4);
        _delay_ms(500);
    }
}


This code is for 1 sensor only. how did you modify it?

You had a parameter to getpulsewidth(void) to select witch sensor you want to read?

Try to get the 4 pin ultrasonics to work on only 3 pins and make the pins do the input/output switch.

OK, I try the new code from ( http://extremeelectronics.co.in/avr-tutorials/interfacing-ultrasonic-rangefinder-with-avr-mcus-%E2%80%93-avr-tutorial/ ) and modify to 3 sensors. When I connected first sensor on a PA2 (echo), then on LCD i can see the distance. OK, when I connected ONLY second sensor, I see the distance and with third is the same. But when I connected ALL 3 sensors on PA2, then on the LCD are only zeros. Sorry for my  english :D .

MrAlexis44600 - thanks, before the program stoped on:

sei();

    while(measurement_complete!=1) {

    }

cli();

now it wirte on LCD, but only 0.

 

Birdmun - It is good idea, but I am begginer with AVR and I do not know how communicate via UART. :(

 

I found another tutorial to Ultrasinic sensor ( http://extremeelectronics.co.in/avr-tutorials/interfacing-ultrasonic-rangefinder-with-avr-mcus-%E2%80%93-avr-tutorial/ ). It look easier.

Would it be possible to lose the LCD for the moment and send the data via serial to the computer instead of to an LCD?

Why do ou use so much interruptions?

I'm really not an expert in AVR code (just begun it some months ago, and not with this chip)

But I would have used something like this:

 

/**************************************/

pulse=0;
TCNT0=0;

PORTD|=(1<<sensor);
_delay_us(12);
PORTD&=~(1<<sensor);

while(PIND & (1<<sensor) == 0) ;    //wait fo beginning of pulse

//here the pulse has begun

sei(); //allows overflow interrupt

while(PIND & (1<<sensor)); //wait for end of pulse

cli();

dist = pulse/58;

 

/*******************************************************/

and you keep the same overflow interrupt.

Another idea: can't you just use a 16 bits timer, with a good prescaler, and no overflows?

(write TCNTn=0 at the begining of the pulse and read TCNTn at the end f the pulse)

And sorry for my english :) I'm french.