Ultrasonic sensor HCSR04 with registers

Hi! Can someone help me with this code? I tried to write this code for the ultrasonic sensor component in order to understand how to use the registers of arduino. Someone can look at it, because there is obviously something wrong? (I apologize in advance if i write something no sense).

const uint8_t echoPin=3;
volatile double distance=0.0;
volatile uint8_t stato=0;
volatile long duration;
void setup() {
  Serial.begin(9600);
  DDRD = 0xF7; // sets all pins on PORTD to input, except pin 3 which is set to output
  DDRB = 0x3F; // sets all pins on PORTB to input, except pins 0-5 which are set to output
  TCCR1A = 0;
  TCCR1B |= _BV(CS11); // sets prescaler for Timer/Counter1 to 8
  EICRA |= _BV(ISC10); // sets external interrupt request 1 (INT1) to trigger on falling edge
  EICRA &= ~_BV(ISC11); // sets external interrupt request 1 (INT1) to trigger on falling edge
  EIMSK |= _BV(INT1); // enables external interrupt request 1 (INT1)
  PORTB |= _BV(triggerPin-8); // sets triggerPin-8 pin on PORTB to high
  PORTB &= ~_BV(echoPin-8); // sets echoPin-8 pin on PORTB to low
}

void loop() {
  // Send trigger pulse
  PORTB |= _BV(PB0);
  delayMicroseconds(10);
  PORTB &= ~_BV(PB0);
  // Wait for echo pulse to start
  while (!(PINB & _BV(PB1)));
  // Start timer
  TCNT2 = 0;
  // Wait for echo pulse to end
  while (PINB & _BV(PB1));
  // Stop timer
  duration = TCNT2;
  // Calculate distance
  distance = (duration / 2) * 0.034;
  // Print distance to serial monitor
  Serial.println(distance);
  // Wait before next measurement
  delay(1000);
}

// Interrupt service routine for echo pin
ISR(PCINT0_vect) {
  if (PINB & _BV(PB1)) {
    TCNT2 = 0;
  } else {
    duration = TCNT2;
  }
}

Your code has a multiple problems...

The comment doesn't match the code, in fact this line will set all pins on PORTD except pin 3 to OUTPUT

triggerPin doesn't declared anywhere in the code

Your echopin is 3, what do you expect by subtract 8 from it?

Your echoPin was declared as 3 (PD3), why do you wait for pulse on PB1?

Too many mistakes, didn't look further

You are setting up Timer1 and using the count from Timer2.

You enable External Interrupt 1 but define an ISR for Pin Change Interrupt 0. That will cause a crash every time INT1 occurs.

You are turning on a bit in TCCR1B without turning off the other bits. Change that to:
TCCR1B = _BV(CS11); // set prescaler to 8

So, what is the right solution?

Read the datasheet and still learning

Fix the mistakes that have been pointed out. Fix any mistakes you find on your own. If the code still doesn't work, post your latest code here and we'll look for any remaining mistakes.

1 Like

Perhaps it would help to not use Arduino pin numbers:

#define EchoPORT PORTD
#define EchoPIN PIND
#define EchoDDR DDRD
#define EchoBit _BV(PD3) // Arduino UNO Pin 3
#define TriggerPORT PORTB
#define TriggerPIN PINB
#define TriggerDDR DDRB
#define TriggerBit _BV(PB0) // Arduino UNO Pin 8

Then the code would be easier to write:

void setup()
{
  TriggerDDR |= TriggerBit; // Set Trigger to OUTPUT
  EchoDDR &= ~EchoBit; // Set Echo to INPUT
}

void loop()
{
  TriggerPort |= TriggerBit;  // Trigger = HIGH
  delayMicroseconds(10);
  TriggerPort &= ~TriggerBit;  // Trigger = LOW

  while (!(EchoPIN & EchoBit));  // Wait until Echo HIGH
  TCNT1 = 0;
  while (EchoPIN & EchoBit);  // Wait until Echo LOW
  duration = TCNT1;
}

WARNING: If no echo is detected (nothing in range) the wait-for-HIGH loop will wait forever.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.