wagiminator / ATtiny13-TinySonar

Ultrasonic Range Finder

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TinySonar - Ultrasonic Range Finder

TinySonar is an ultrasonic range finder based on the ATtiny13A, the ultrasonic ranging module HC-SR04 and a 7-segment display with a MAX7219 driver IC.

pic.jpg

Hardware

The wiring of the TinySonar is shown below:

wiring.png

The ultrasonic ranging module HC-SR04 provides 2cm-400cm non-contact measurement function, the ranging accuracy can reach to 3mm. The module includes ultrasonic transmitter, receiver and control circuit.

The MAX7219 is a compact, serial input/output common-cathode display drivers that interface microprocessors to 7-segment numeric LED displays of up to 8 digits, bar-graph displays, or 64 individual LEDs. Included on-chip are a BCD code-B decoder, multiplex scan circuitry, segment and digit drivers, and an 8x8 static RAM that stores each digit.

Software

Measuring the Distance with the HC-SR04

This is how the HC-SR04 module is controlled:

  • start measurement by applying high signal on TRIG for at least 10us,
  • module automatically sends eight 40 kHz pulses and detects echos,
  • module applies high signal on ECHO with the same duration as the time it took from sending ultrasonic to returning.

For measuring the duration of the ECHO signal the timer/counter0 is used with no prescaler, so it runs at MCU clock speed. Timer overflow interrupt is utilized to expand the 8-bit counter to a virtual 16-bit counter. The ECHO signal starts and stops the timer by pin change interrupt. To calculate the distance in mm from the counter value, the following approximation formula was derived:

duration[s]  = counter / F_CPU = counter / 1200000[1/s]
distance[mm] = duration * speed of sound / 2 = duration[s] * 340260[mm/s] / 2
distance[mm] = counter * 340260[mm/s] / 1200000[1/s] / 2
distance[mm] ~ counter / 7
// pin definitions
#define TRIG  PB0
#define ECHO  PB4

// global variables
volatile uint8_t  HC_done;                  // ranging complete flag
volatile uint16_t HC_counter;               // virtual 16-bit counter

// init HC-SR04
void HC_init(void) {
  DDRB  |= (1<<TRIG);                       // set TRIG pin as output
  PCMSK |= (1<<ECHO);                       // enable interrupt on ECHO pin
  TCCR0A = 0;                               // timer/counter normal mode
  TIMSK0 = (1<<TOIE0);                      // enable overflow interrupt
  sei();                                    // enable global interrupts
}

// get distance in mm from HC-SR04
uint16_t HC_ping(void) {
  HC_done = 0;                              // reset ranging complete flag
  HC_counter = 0;                           // reset counter
  TCNT0 = 0;                                // reset timer0
  GIMSK |= (1<<PCIE);                       // enable pin change interrupts
  PORTB |= (1<<TRIG);                       // send 10us trigger pulse
  _delay_us(10);
  PORTB &= ~(1<<TRIG);                      // module starts measurement now
  while(!HC_done);                          // wait for echo
  GIMSK &= ~(1<<PCIE);                      // disable pin change interrupts
  HC_counter += TCNT0;                      // calculate total 16-bit counter value
  return(HC_counter / 7);                   // calculate and return distance
}

// pin change interrupt service routine
ISR (PCINT0_vect) {
  if (PINB & (1<<ECHO)) {                   // if rising edge on ECHO pin:
    TCCR0B = (1<<CS00);                     // start the timer
  } else {                                  // if falling edge on ECHO pin:
    TCCR0B = 0;                             // stop the timer
    HC_done = 1;                            // set ranging complete flag
  }
}

// timer0 overflow interrupt service routine
ISR (TIM0_OVF_vect) {
  HC_counter += 256;                        // increment 16-bit counter by 256 on each overflow
}

Controlling the MAX7219 for the 7-Segment Display

The distance in mm is shown on a 4-digit 7-segment display which is controlled via a MAX7219 in BCD decode mode. The SPI protocol is implemented with a simple bitbanging method. The MAX7219 is fast enough to be driven without delays even at the fastest clock speed of the ATtiny13. A transmission to the MAX7219 starts with pulling the CS line LOW. Afterwards two bytes are transmitted, the register address first and the register data second. The bytes are transmitted most significant bit first by setting the DIN line HIGH for a bit "1" or LOW for a bit "0" while the CLK line is LOW. The bit is shifted out on the rising edge of the CLK line. By setting the CS line HIGH again the end of the transmission is signified, the MAX7219 latches the two received bytes and writes the data byte into the register.

logic.png data.png

// pin definitions
#define DIN   PB1
#define CLK   PB2
#define CS    PB3

// shift out byte value to MAX7219
void SEG_byte(uint8_t value) {
  for(uint8_t i=8; i; i--, value <<= 1) {   // shift out 8 bits, MSB first
    PORTB &= ~(1<<DIN);                     // clear the bit first (saves some flash this way)
    if(value & 0x80) PORTB |= (1<<DIN);     // set bit if appropriate
    PORTB |=  (1<<CLK);                     // clock high -> shift out the bit
    PORTB &= ~(1<<CLK);                     // clock low (50ns < 1000 / 1.2)
  }
}

// send command to MAX7219
void SEG_send(uint8_t reg, uint8_t data) {
  PORTB &= ~(1<<CS);                        // set CS low  -> select device
  SEG_byte(reg);                            // send address byte
  SEG_byte(data);                           // send data byte
  PORTB |= (1<<CS);                         // set CS high -> latch the bytes
}

// init MAX7219
void SEG_init(void) {
  DDRB  |= (1<<DIN) | (1<<CLK) | (1<<CS);   // set control pins as output
  PORTB |= (1<<CS);                         // pull high CS line
  SEG_send(0x09, 0x0f);                     // set BCD decode for 4 digits
  SEG_send(0x0a, 0x0f);                     // set intensity (0x00 .. 0x0f)
  SEG_send(0x0b, 0x03);                     // set scan limit at 4 digits
  SEG_send(0x0c, 0x01);                     // shutdown mode off
  SEG_send(0x0f, 0x00);                     // display test off
}

// print a number on display
void SEG_print(uint16_t number) {
  for(uint8_t i=1; i<5; i++, number /= 10) SEG_send(i, number % 10);
}

Main Function

The main function is pretty simple:

// main function
int main(void) {
  SEG_init();                               // setup MAX7219
  HC_init();                                // setup HC-SR04

  while(1) {
    SEG_print(HC_ping());                   // get distance and print it on display
    _delay_ms(200);                         // delay between pings
  }
}

Compiling and Uploading

If using the Arduino IDE

  • Make sure you have installed MicroCore.
  • Go to Tools -> Board -> MicroCore and select ATtiny13.
  • Go to Tools and choose the following board options:
    • Clock: 1.2 MHz internal osc.
    • BOD: BOD 2.7V
    • Timing: Micros disabled
  • Connect your programmer to your PC and to the ATtiny.
  • Go to Tools -> Programmer and select your ISP programmer (e.g. USBasp).
  • Go to Tools -> Burn Bootloader to burn the fuses.
  • Open TinySonar.ino and click Upload.

If using the precompiled hex-file

  • Make sure you have installed avrdude.
  • Connect your programmer to your PC and to the ATtiny.
  • Open a terminal.
  • Navigate to the folder with the hex-file.
  • Execute the following command (if necessary replace "usbasp" with the programmer you use):
    avrdude -c usbasp -p t13 -U lfuse:w:0x2a:m -U hfuse:w:0xfb:m -U flash:w:main.hex
    

If using the makefile (Linux/Mac)

  • Make sure you have installed avr-gcc toolchain and avrdude.
  • Connect your programmer to your PC and to the ATtiny.
  • Open the makefile and change the programmer if you are not using usbasp.
  • Open a terminal.
  • Navigate to the folder with the makefile and main.c.
  • Run "make install" to compile, burn the fuses and upload the firmware.

References, Links and Notes

  1. ATtiny13A Datasheet
  2. HC-SR04 Datasheet
  3. MAX7219 Datasheet

About

Ultrasonic Range Finder

License:Other


Languages

Language:C++ 44.0%Language:C 43.2%Language:Makefile 12.9%