Не кубический кубик 2

May 15, 2015 12:47

Доделал таки я игрушку - безделушку.
Почти законченное изделие получилось, этакий гиковский брелок. Осталось корпус подобрать или просто эпоксидкой залить, что бы можно было батарейку только менять и "тиньку" снимать для перепрошивки, если вдруг, захочется чего в код добавить. А так, вот... Можно нажимать на кнопку и получать случайное число от 1 до 6. Как на кубике.

image Click to view


Игрушка очень понравилась моему двухлетнему сынишке. Потыкав в единственную кнопку и помигав светодиодами, он отдаёт мне игрушку и на пальцах просит зажечь определённое количество светодиодов. Объяснить ему, что они зажигаются случайным образом мне не удалось :) Пришлось тыкать в кнопку и ждать когда загорится нужное количество.

Код прошивки "тиньки" привожу ниже...




  1. #include

  2. #include

  3.  

  4. #define F_CPU 1200000UL // 1.2 MHz

  5. #define SLEEP_DELAY (30UL * F_CPU / 256UL) // Задержка примерно в 5 - 10 секунд для перехода в режим сна

  6.  

  7. volatile uint8_t random_counter; // счётчик "случайного" значения

  8. volatile uint8_t show_time; // счётчик ограничивающий по времени показ отдельного сегмента значения на кубике

  9. volatile uint8_t cur_dice_value; // текущее значение на грани кубика

  10. volatile uint32_t sleep_counter; // счётчик тиков до засыпания

  11. volatile boolean button = 0; // флаг нажатия на кнопку

  12. volatile uint8_t cur_bit; // номер сегмента, который нужно отобразить в текущий момент изменяется от 1 до 4 (PINB1..PINB4)

  13. volatile uint8_t cur_portb_status; // текущие состояние регистра, отвечающего за отображение значения на кубике (PORTB)

  14.  

  15. // Для платы с выводными компонентами

  16. unsigned char digits[6] = {

  17. 0b00010000, //1

  18. 0b00000010, //2

  19. 0b00010100, //3

  20. 0b00000110, //4

  21. 0b00010110, //5

  22. 0b00001110 //6

  23. };

  24.  

  25. // Прерывание по нажатию на кнопку

  26. ISR(PCINT0_vect)

  27. {

  28. // Если кнопка нажата и флаг нажатия на кнопку равен нулю

  29. if ((!(PINB&0b00000001)) && (!button)){

  30. button = 1; // Поднимаем флаг нажатия на кнопку

  31. sleep_counter = 1; //Сбрасываем счётчик тиков до засыпания

  32. }

  33. }

  34.  

  35. int main(void){

  36. cli();

  37. // Инициируем порты

  38. PORTB = 0b00000000;

  39. DDRB = 0b00011110;

  40. GIMSK = 0b00100000;

  41. PCMSK = 0b00000001;

  42. WDTCR |= 0b00000000; // отключаем watchdog timer

  43. // Инициируем переменные, обнуляем счётчики

  44. random_counter = 0;

  45. sleep_counter = 0;

  46. show_time = 0;

  47. cur_bit = 1;

  48. cur_dice_value = digits[5]; // показывает шестёрку при включении

  49. sei();

  50. while(1){

  51. sleep_counter++; // Увеличиваем счётчик тиков

  52. // Если счётчик тиков досчитал до заданного для сна значения, отправляем микроконтроллер спать

  53. if (sleep_counter >= SLEEP_DELAY)

  54. {

  55. sleep_counter = 0;

  56. system_sleep();

  57. }

  58. // Постоянно увеличиваем счётчик "случайного" значения, если досчитали до пяти, то обнуляем его

  59. if (random_counter < 5) random_counter++;

  60. else random_counter = 0;

  61. // Если поднят флаг нажатия на кнопку

  62. if (button){

  63. animation(); // показываем анимацию

  64. cur_dice_value = digits[random_counter]; // сохраняем в переменной cur_dice_value выпавшее на кубике значение

  65. button = 0; // опускаем флаг нажатия на кнопку

  66. }

  67. // Увеличиваем счётчик показа текущего сегмента значения на кубике

  68. show_time++;

  69. // При достижении заданного значения меняем сегмент, который надо сейчас показать на следующи и обнуляем счётчик показа текущего сегмента

  70. if (show_time > 50){

  71. if (cur_bit < 4) cur_bit++;

  72. else cur_bit = 1;

  73. show_time = 0;

  74. cur_portb_status = (1 << cur_bit) & cur_dice_value;

  75. }

  76. // Отображаем текущий сегмент значения на кубике

  77. PORTB = cur_portb_status;

  78. }

  79. }

  80.  

  81. // Функция отображения мельтешения граней на кубике

  82. void animation(){

  83. for(int i=0; i<6; i++){

  84. PORTB = digits[i];

  85. _delay_ms(30);

  86. }

  87. }

  88.  

  89. // Функция сна

  90. void system_sleep(){

  91. PORTB = 0b00000000;

  92. ADCSRA &= ~(1 << ADEN); // перед сном отключим АЦП

  93. ACSR |= (1 << ACD); // и компаратор

  94. set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  95. while(!sleep_counter){

  96. sleep_enable();

  97. sleep_cpu();

  98. }

  99. }

#define, attiny13, электроника, видео, самоделки, #include

Previous post Next post
Up