ATtiny13 – two tone alarm

This is a simple and easy to build two-tone alarm that uses ATtiny13 to produce sound effects. Note that with little modifications the project can be easily utilized for many applications, in circuits where a double tone alarm may be required. Project’s code has been designed to make possible extend a list of two-tone sound effects. It already contains some example ringtones. Feel free to create your own tone combinations. Have fun, and please, don’t forget to share your work in the comment! As always, complete code is available on Github, click here.

Parts Required

  • ATtiny13  – i.e. MBAVR-1 development board
  • Resistor – 1kΩ (note that AVR I/O load must be < 40mA)
  • Speaker / Buzzer (without internal generator)

Circuit Diagram

tone-generator

Firmware

This code is written in C and can be compiled using the avr-gcc. More details on how compile this project is here.

/**
 * Copyright (c) 2016, Łukasz Marcin Podkalicki <lpodkalicki@gmail.com>
 * ATtiny13/015
 * Two-Tone Alarm.
 * --
 * Settings:
 *  FUSE_L=0x6A
 *  FUSE_H=0xFF
 *  F_CPU=1200000
 */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

#define    SPEAKER_PIN    PB0

#define    N_1    (_BV(CS00))
#define    N_8    (_BV(CS01))
#define    N_64   (_BV(CS01)|_BV(CS00))
#define    N_256  (_BV(CS02))
#define    N_1024 (_BV(CS02)|_BV(CS00))

static void twotone_alarm(uint8_t type);
static void tone_loop(uint8_t OCRxn, uint8_t N, uint8_t max, uint8_t delay, uint8_t pause, uint8_t fade);
static void timer_set(uint8_t OCRxn, uint8_t N);
static void sleep(uint8_t ms);


int
main(void)
{

    /* setup */
    DDRB |= _BV(SPEAKER_PIN); // set speaker pin as OUTPUT
    TCCR0A |= _BV(WGM01); // set timer mode to Fast PWM
    TCCR0A |= _BV(COM0A0); // connect PWM pin to Channel A of Timer0

    /* loop */
    while (1) {
        twotone_alarm(1);
    }
}


void
twotone_alarm(uint8_t type)
{

    switch(type) {
    /* Please, put here your own two-tone alarm composition! */
    case 1:
        tone_loop(123, N_8, 6, 10, 10, 1);
        tone_loop(22, N_8, 6, 10, 0, -1);
        break;
    default:
    case 0:
        tone_loop(32, N_8, 6, 10, 10, 1);
        tone_loop(22, N_8, 6, 10, 0, -1);
        break;
    }
}


/**
 * Single tone loop with fade-in/out effect.
 *
 * Base square wave frequency,
 * F = F_CPU / (2 * N * (1 + OCRnx)), where:
 * - F is a calculated PWM frequency
 * - F_CPU is a clock source (1.2MHz)
 * - the N variable represents the prescaler factor (1, 8, 64, 256, or 1024)
 *
 * @param OCRxn: timer OCRxn value
 * @param N: timer prescaler (N_1, N_8, N_64, N_256, N_1024)
 * @param max: number of iterations (incr/decr of OCRxn)
 * @param delay: little delay after each iteration in miliseconds
 * @param pause: delay after a tone loop, delay between tones
 * @param fade: fade-in (1) or fade-out (-1) factor
 */
void
tone_loop(uint8_t OCRxn, uint8_t N, uint8_t max, uint8_t delay, uint8_t pause, uint8_t fade)
{
    uint8_t i;

    for (i = 0; i < max; ++i) {
        timer_set(OCRxn, N);
        OCRxn += fade;
        sleep(delay);
    }

    sleep(pause);
}


void
timer_set(uint8_t OCRxn, uint8_t N)
{

    TCCR0B = (TCCR0B & ~((1<<CS02)|(1<<CS01)|(1<<CS00))) | N;
    OCR0A = OCRxn - 1;
}


void
sleep(uint8_t ms)
{
    uint8_t i;

    for (i = 0; i < ms; ++i) {
        _delay_ms(1);
    }
}

8 thoughts on “ATtiny13 – two tone alarm

  1. Hello, Łukasz! I am grateful for the program you wrote, because I am not a programmer myself. I already suffer more than one day to change the code for my needs, but it does not work. Here is what I could:
    case 1:
    tone_loop (5, N_64, 1, 0, 0, 1);
    // tone_loop (2, N_8, 6, 100, 100, -1);
    break;
    default:
    case 0:
    // tone_loop (1, N_8, 6, 100, 100, 1);
    // tone_loop (2, N_8, 6, 100, 100, -1);
    break;
    It turned out to make just a monotonous squeaker at a fairly high frequency. Tell me how to increase the frequency to a maximum, almost to ultrasound?
    Thank you in advance!

  2. Is it possible to make such alarm with Arduino board? I don’t now C and just started to play w arduino 🙂

    • Probably yes but I’m sure it need some work to port it to Arduino. However, for Arduino platforms there is a sort of libraries able to make a sound what would be easier to implement if you’re starting your adventure with C.

    • Hi, the output signal comes directly from ATtiny13 I/O, so the alarm is not very loud. However, loud enough to hear it in the next room. If you need little louder alarm, then signal amplifier is required.

Leave a Comment