воскресенье, 17 августа 2014 г.

Музыкальный звонок на Attiny13 Arduino Imperial March(перезалито)

UPD Перезалил файлы, добавил код на Си.




Давно хотел себе такой музыкальный дверной звонок, чтобы при нажатии на кнопку играл марш империи(Imperial March или Imperial March or Darth Vader's Theme) из «Звёздных войн», они же Star Wars.
( Полная статья с доработанной прошивкой тут http://habrahabr.ru/post/234763/ )

Как видно из названия, главный компонент устройства - микроконтроллер Attiny13, его применение сделало возможным сделать размеры платы в несколько раз меньше по размерах чем спичечной коробк.


Можно оценить размеры платы.




Диапазон питания примерно от 2 В до 6 В(от двух до четырех батареек формата AA) в идеале напряжение 3-4 В, то есть аккумулятор формата 18650(литиевый аккумулятор, точней литий ионный, он же li-ion), но желательно с защитой, так как я пока не реализовал никакой защиты от глубокого разряда.

Так как МК(микроконтроллер) не может самостоятельно вытянуть достаточную громкость для того чтобы было слышно звонок по всему доме я добавил NPN транзистор 2N3904, довольно таки распространенный транзистор, в принципе может подойти любой транзистор который потянет динамик, в моём случае транзистор рассчитан на 100 мА.

Как прошивать и программировать тиньки при помощи ардуино я показал в этом видео:


Текстовая часть к видео выше: http://razniepodelki.blogspot.com/2014/05/attiny13-arduino.html

Скажу сразу, код нагуглил:


В описании к видео есть ссылка на страничку с рабочим кодом. 
А вот собственно из странички код из автора видео:

#include <avr/pgmspace.h>

// by @tartakynov

#define PIN_BUZZER 0
#define COUNT_NOTES 39

word frequences[COUNT_NOTES] PROGMEM = {
  392, 392, 392, 311, 466, 392, 311, 466, 392,
  587, 587, 587, 622, 466, 369, 311, 466, 392,
  784, 392, 392, 784, 739, 698, 659, 622, 659,
  415, 554, 523, 493, 466, 440, 466,
  311, 369, 311, 466, 392 };
word durations[COUNT_NOTES] PROGMEM = {  
  350, 350, 350, 250, 100, 350, 250, 100, 700,
  350, 350, 350, 250, 100, 350, 250, 100, 700,
  350, 250, 100, 350, 250, 100, 100, 100, 200,
  100, 350, 250, 100, 100, 100, 200,
  100, 350, 250, 100, 750 };

void setup()
{
  pinMode(PIN_BUZZER, OUTPUT);
}

void loop()
{
  for (byte i = 0; i < COUNT_NOTES; i++)
  {
    buzz(PIN_BUZZER, pgm_read_word(&(frequences[i])), 2 * pgm_read_word(&(durations[i])));
    delay(100);
  }
  delay(3000);
}

void buzz(unsigned char pin, word frequencyInHertz, word timeInMilliseconds)
{
  long delayAmount = (long)(long(1000000) / (long)frequencyInHertz);
  long loopTime = (long)(((long)timeInMilliseconds * 500) / delayAmount);
  for (long i = 0; i < loopTime; i++)  
  {  
    digitalWrite(pin, HIGH);
    delayMicroseconds(delayAmount);
    digitalWrite(pin, LOW);
    delayMicroseconds(delayAmount);
  }
}


Прошил, включаю, прикольно, но... как-то звучит не так, что-то быстровато моментами, да и частота маленькая, увеличил частоту в 3 раза(смотрите комментарии на 50 строчке кода), ато слышно маленбко слабовато если использовать маленький динамик типа такого:


Немного изменил скетч, добавил кнопку и поднял частоту и маленько описал скетч:

// by @tartakynov:
// http://youtu.be/5R7NeQkVS_8
// and me - vk.com/razniepodelkiblogspot
// как прошить тини: 
// http://razniepodelki.blogspot.com/2014/05/attiny13-arduino.html
// Этот код взято из статьи:
// http://razniepodelki.blogspot.com/2014/08/attiny13-arduino.html

#define F_CPU 1200000L  // Частота МК в герцах
#include <avr/pgmspace.h> // нужно для PROGMEM

#define PIN_BUZZER 2 // PB2 Динамик
#define BUTTON 4 // PB4 Кнопка

#define COUNT_NOTES 39

word frequences[COUNT_NOTES] PROGMEM = { // тут лежат частоты
  392, 392, 392, 311, 466, 392, 311, 466, 392,
  587, 587, 587, 622, 466, 369, 311, 466, 392,
  784, 392, 392, 784, 739, 698, 659, 622, 659,
  415, 554, 523, 493, 466, 440, 466,
  311, 369, 311, 466, 392 };

word durations[COUNT_NOTES] PROGMEM = { // тут их длительность 
  350, 350, 350, 250, 100, 350, 250, 100, 700,
  350, 350, 350, 250, 100, 350, 250, 100, 700,
  350, 250, 100, 350, 250, 100, 100, 100, 450,
  150, 350, 250, 100, 100, 100, 450,
  150, 350, 250, 100, 750 };

//void setup()
//{
  
int main( void ) // это аналог void setup(), для экономии места
{
  pinMode(PIN_BUZZER, OUTPUT); // инициализация пинов
  pinMode(BUTTON, INPUT); // подключаем подтягивающий резистор
  digitalWrite(BUTTON, HIGH); // чтобы кнопка возвращала 
  //LOW при нажатии

  //}
  //void loop()
  //{
    
  while(1){ // аналог void loop()(вечный цикл)
    if (digitalRead(BUTTON) == LOW) {   // когда кнопка нажата
      for (byte i = 0; i < COUNT_NOTES; i++) // собственно проигрываем мелодию
      {
        buzz(PIN_BUZZER, pgm_read_word(&(frequences[i])) * 3, 2 * pgm_read_word(&(durations[i])));
        // изначально было:
        // buzz(PIN_BUZZER, pgm_read_word(&(frequences[i])), 2 * pgm_read_word(&(durations[i])));
        // но я умножил частоту на 3
        //(pgm_read_word(&(frequences[i])) * 3) 
        //чтобы было громче слышно на небольшом динамике
        //delay(100); // этого не нужно
      }
    }
    //delay(3000); // и этого
    
  }         // эти строчки нужны 
  return 0; // int main( void ) 
}           // и while(1)

void buzz(unsigned char pin, word frequencyInHertz, word timeInMilliseconds) // по сути это 
{                                                                            // генератор частоты            
  long delayAmount = (long)(long(1000000) / (long)frequencyInHertz);         // имеет 3 параметра
  long loopTime = (long)(((long)timeInMilliseconds * 500) / delayAmount);    // 1 - пин
  for (long i = 0; i < loopTime; i++)                                      // 2 - частота
  {                                                                          // 3 - длительность
    digitalWrite(pin, HIGH);        // генерируем импульсы нужной частоты  
    delayMicroseconds(delayAmount);
    digitalWrite(pin, LOW);
    delayMicroseconds(delayAmount);
  }
}


Данный код, должен быть ардуино совместимым и работать даже на Arduino Uno, Arduino Nano или же Arduino Pro Mini.

Код на тини13 занимает много, "Размер скетча в двоичном коде: 976 байт (из 1 024 байт максимум)" причём приходилось даже вставлять куски кода на Си чтобы влезть в 1024 байта, на Си этот код бы весил ну как минимум на треть меньше.
----------------------------------------------------------------------------------------------
Добавил код на Си:

// by @tartakynov:
// http://youtu.be/5R7NeQkVS_8
// and me - vk.com/razniepodelkiblogspot
// как прошить тини: 
// http://razniepodelki.blogspot.com/2014/05/attiny13-arduino.html
// Этот код взято из статьи:
// http://razniepodelki.blogspot.com/2014/08/attiny13-arduino.html

#define F_CPU 1200000UL  // Частота МК в герцах
#include <avr/io.h>  // библиотека ввода вывода
#include <util/delay.h> // библиотека для работы с задержками
#include <avr/pgmspace.h> // нужно для PROGMEM

#define PIN_BUZZER 2 // PB2 Динамик
#define BUTTON 4 // PB4 Кнопка

#define COUNT_NOTES 39

word frequences[COUNT_NOTES] PROGMEM = { // тут лежат частоты
  392, 392, 392, 311, 466, 392, 311, 466, 392,
  587, 587, 587, 622, 466, 369, 311, 466, 392,
  784, 392, 392, 784, 739, 698, 659, 622, 659,
  415, 554, 523, 493, 466, 440, 466,
  311, 369, 311, 466, 392 };

word durations[COUNT_NOTES] PROGMEM = { // тут их длительность 
  350, 350, 350, 250, 100, 350, 250, 100, 700,
  350, 350, 350, 250, 100, 350, 250, 100, 700,
  350, 250, 100, 350, 250, 100, 100, 100, 450,
  150, 350, 250, 100, 100, 100, 450,
  150, 350, 250, 100, 750 };

//void setup()
//{

int main( void ) // это аналог void setup(), для экономии места
{
  DDRB |= (1<<PIN_BUZZER); // иницыализация портов
  DDRB &= ~(1<<BUTTON); // подключаем подтягивающий резистор
  PORTB |= (1<<BUTTON);  // чтобы кнопка возвращала 
  //0 при нажатии(замыкинии)

  //}
  //void loop()
  //{

  while(1){ // аналог void loop()(вечный цикл)
    if (!(PINB & (1<<BUTTON))) {   // когда кнопка нажата
      for (byte i = 0; i < COUNT_NOTES; i++) // собственно проигрываем мелодию
      {
        buzz(pgm_read_word(&(frequences[i])) * 3, 2 * pgm_read_word(&(durations[i])));
        // изначально было:
        // buzz(PIN_BUZZER, pgm_read_word(&(frequences[i])), 2 * pgm_read_word(&(durations[i])));
        // но я умножил частоту на 3
        //(pgm_read_word(&(frequences[i])) * 3) 
        //чтобы было громче слышно на небольшом динамике
      }
      //_delay_ms(100); // для отладки
    }

    //_delay_ms(3000); // для отладки

  }         // эти строчки нужны 
  return 0; // int main( void ) 
}           // и while(1)

//void buzz(unsigned char pin, word frequencyInHertz, word timeInMilliseconds) 
void buzz(word frequencyInHertz, word timeInMilliseconds)  // по сути это 
{                                                                            // генератор частоты            
  long delayAmount = (long)(long(1000000) / (long)frequencyInHertz);         // имеет 3 параметра
  long loopTime = (long)(((long)timeInMilliseconds * 500) / delayAmount);    // 1 - пин
  for (long i = 0; i < loopTime; i++)                                      // 2 - частота
  {                                                                          // 3 - длительность
    //digitalWrite(pin, HIGH);        // генерируем импульсы нужной частоты  
    PORTB |= (1<<PIN_BUZZER);  // для экономии вставлю строчки на Си
    //delayMicroseconds(delayAmount); // мкс задержка на ардуино
    _delay_us(delayAmount); // на Си

    //digitalWrite(pin, LOW);
    PORTB &= ~(1<<PIN_BUZZER);
    //delayMicroseconds(delayAmount); // мкс задержка на ардуино
    _delay_us(delayAmount); // на Си
  }
}
А вот Arduino IDE почему-то не хочет проглатывать этот код:
"Размер скетча в двоичном коде: 1 986 байт (из 1 024 байт максимум)"
Но думаю другая среда разработки примет как родненького.
----------------------------------------------------------------------------------------------
Тестировал (видео в начале странички) на частоте в 1.2 MHz(default), то есть той что записана на заводе, так что ничего с фьюзами изменять не нужно, они стандартные, но всё равно приведу скрин из калькулятора фьюзов:


Схема выглядит вот так(файлы Proteus прилагаются в конце статьи, можно даже ничего не собирать на макетке):


Как моделировать Arduino(на примере Attiny13) в программе Proteus o я показывал вот в этом видео:


Как Вы можете догадаться, к порту PB4 подтянут внутренний PULLUP резистор. Можно PB4 вообще замкнуть на землю и будет работать всегда когда есть питание, или же при нажатии на кнопку, питание будет подаваться и будет играть любимая сердцу мелодия ;) . 

Схема как видите элементарно простая, 6 элементов включая МК и динамик.

Итак, все файлы, а именно, скрин с фьюзами, HEX файл, код, он же скетч(файл *.ino, открывается блокнотом, или же Arduino IDE), файлы протеуса можно скачать в моей группе ВКонтакте, или вот по прямой ссылке:

http://vk.com/doc256435878_322479039

(Для буржуев напишу - Download)

Сразу скажу что остаточный код на Си будет не скоро.


"Да прибудет с Вами сила" :) .

Комментариев нет:

Отправить комментарий