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;
}
Why do ou use so much
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.
One question/suggestion
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?
MrAlexis44600 - thanks,
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-–-avr-tutorial/ ). It look easier.
Another problem
OK, I try the new code from ( http://extremeelectronics.co.in/avr-tutorials/interfacing-ultrasonic-rangefinder-with-avr-mcus-–-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 .
Another option
Try to get the 4 pin ultrasonics to work on only 3 pins and make the pins do the input/output switch.
This code is for 1 sensor
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?
**Birdmun - oh yes, Ill**<br><p>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);
}
}
Finaly Working
Thank you, I connected Trig and Echo on one pin (like birdman said) and it is work Perfectly
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);
}
}