Pull to refresh

Электронный «шар судьбы» на ATtiny13

DIY
image

Привет. Недавно пересматривал один из моих любимых фильмов, а именно «Трасса 60» с Эми Смарт в главной роли. Там у главного героя была такая вещица, под названием «шар судьбы», который отвечал ему на разные вопросы. Ну и после просмотра у меня появилась мысль, а почему бы не сделать что-то подобное на микроконтроллере, тем более недавно разблокировал 4 штуки ATtiny13 которые, когда-то заблокировал по незнанию, что такое фьюзы и с чем его едят. Ещё один аргумент ATtiny13 — цена, очень дешёвый микроконтроллер.

Размеры устройства можете оценить на фоне моей ладони, получился такой себе высокотехнологичный брелок для ключей.



В конце обязательно добавлю не только схему, файлы для Proteus 7, исходники но и фьюзы, hex-файл, чтобы каждый, кто умеет пользоваться программатором, мог повторить данное устройство.

Код для ATtiny13 написан в Arduino IDE, но в силу большого потребления ресурсов этой IDE, которые к стати итак сильно ограничены в ATtiny13(а именно 1024 байта под код), памяти мне не хватило, и тут мне пригодились мои начальные знания регистров микроконтроллера и мизерный опыт работы с ними, вот что в итоге получилось:

Посмотреть код
#define F_CPU 1200000UL  // Частота МК в герцах

#include <avr/io.h>
#include <avr/sleep.h> // здесь описаны режимы сна
#include <util/delay.h>

#define led_Yes 0 // grn
#define led_No 1 // red 
#define rand_gen 3 
#define wait 5000 // тайм аут перехода в спящий режим

void setup() {
  //pinMode(led_Yes, OUTPUT); 
  DDRB |= (1<<led_Yes);
  //pinMode(led_No, OUTPUT); 
  DDRB |= (1<<led_No);
}

void loop() {
  randomSeed(analogRead(rand_gen)); // не псевдо радном
  byte randomValue;
  randomValue = random(0,2); // диапазон генератора случайных чисел от 0 до 1
  if(randomValue > 0){   
    //digitalWrite(led_Yes, HIGH);
    PORTB |= (1<<led_Yes);  
  }
  else{
    //digitalWrite(led_No, HIGH); 
    PORTB |= (1<<led_No);  
  }

  _delay_ms(wait); 
  system_sleep();
}

void system_sleep(){ 
  //digitalWrite(led_No, LOW); 
  PORTB &= ~(1<<led_No);
  //digitalWrite(led_Yes, LOW); 
  PORTB &= ~(1<<led_Yes);

  ADCSRA &= ~(1 << ADEN); // перед сном отключим АЦП
  ACSR |= (1 << ACD); // и компаратор
  // для уменьшения энергопотребления во сне
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
  while(1) {
    sleep_enable(); // разрешаем сон
    sleep_cpu(); // спать!
  }
}

//Размер скетча в двоичном коде: 912 байт (из 1 024 байт максимум)


Как это работает? Дело в том, что мы в строчках randomSeed(analogRead(rand_gen)); задаём некое значение которое поступает в микроконтроллер из вне, так как порт микроконтроллера ни к чему не подключен, то есть «висит в воздухе», то на нём присутствует некий белый шум. Для микроконтроллера он выглядит примерно так:

image

Если микроконтроллер будет выводить не очень ожидаемый ответ, то можно переназначить пины, то есть поменять местами, порты которые заданы при помощи директивы #define led_Yes 0 и #define led_No 1 или же ещё простой способ — банально поменять местами светодиоды. В строчке #define wait 5000 задаётся тайм аут перехода в спящий режим в миллисекундах, то есть, сколько времени будет светить светодиод.

Давай посмотрим потребление микроконтроллера в спящем режиме в даташите:

image

Как видишь ток всего 0.2 мкА, при таком токе аккумулятор сам по себе быстрее «сядет», чем микроконтроллер его разрядит хотя бы на 1 процент.

В данном коде используется не псевдо генератор случайных чисел(постоянно одна и та же последовательность чисел), этого удалось добиться при помощи функции randomSeed().

Схема очень простая:

image

Всего 6 компонентов не считая литиевой батарейки CR2025. Резисторы R1 и R3 добавил чисто для приличия как говорится, без них схема будет работать не хуже чем с ними, правда резистор R1 немного уменьшает ток светодиодов, но нужен, если напряжение питания схемы превышало бы 3 вольта.

Интересно, на сколько нажатий хватит батарейки CR2025, емкость которой к стати примерно 150 мА/ч?

При единичном нажатии на кнопку светодиод горит 5 сек, то есть 60 сек / 5 = 12 нажатий на минуту * 60 минут = 720 непрерывных нажатий в час, за час схема будет потреблять ток 1.5 мА(измерил мультиметром потребление когда горит красный светодиод), при емкости в 150 мА/ч получится 150/1.5 мА/ч что схема проработает 100 часов, так как за час можно совершить максимум 720 нажатий то 720 * 100 = 72 000.

Из грубого подсчёта выходит, что до полного истощения литиевой батарейки CR2025 нужно совершить 72 тысячи нажатий, и это притом если нажимать ещё кнопку непрерывно, на это уйдёт 100 часов, что есть чуть больше 4-х суток.

Фьюзы стандартные, а именно те, которые зашиты в микроконтроллере с завода, если ATtiny13 только что из магазина, то ничего там с фьюзами изменять не нужно. Добавляю на всякий случай скрин из калькулятора фьюзов:

image

UPD по совету одного человека, я добавил в функцию system_sleep() отключение аналогового компаратора для ещё большей экономии заряда батарейки. Файлы в низу статьи перезалито.

Ссылки:

Фильм Трасса 60(википедия);
Даташит на ATtiny13;
Прошивка и программирование ATtiny13 при помощи Arduino;
Arduino IDE;
Функция randomSeed();
Белый шум;
Как экономить место на микроконтроллере?;
Софт которым сделал скриншонт шума — Serial oscilloscope;
Все файлы по этому проекту(перезалито);
Все мои публикации.

P.S. схема в Proteus работать откажется, будет постоянно гореть один и тот же светодиод, так как данная программа не умеет эмулировать те наводки на порту АЦП, что будут в реальной схеме.
Tags:
Hubs:
Total votes 32: ↑24 and ↓8 +16
Views 28K
Comments Comments 44