Пример прошивки atmega328. Таймер для шашек

Таймер для шашек на arduino

Сегодня не большая статья о готовом проекте — это таймер для игры в быстрые шашки. Устройство получилось простое, на его панели располагаются два светодиода, указывающие на ход первого или второго игрока, 7-сегментный индикатор с один разрядом, на котором происходит отсчет секунд от 9 до 0, а также несколько кнопок управления и две кнопки для передачи хода сопернику. Работу готового устройства можно посмотреть на видео ниже.


Схема подключения atmega328 к arduino uno для прошивки

В устройстве нет ни чего серьезного, но мне было интересно им заниматься, поскольку тут я использовал микроконтроллер atmega328 отдельно, без платформы arduino. В этот раз программирование все точно такое же, как и при других проектах на ардуино, но схема отличается. Вместо привычной платы ардуино использовались atmega328 и кварц на 16 Mhz. В идеале еще необходимо добавить два конденсатора по 22 пФ, но их я не нашел на тот момент, хотя в следующем подобном проекте обязательно их добавлю. Ниже приведена официальная схема подключения микроконтроллера, кварца и конденсаторов. Также на картинке изображено как, подключить arduino uno к МК atmega328 для загрузки скетча. При таком подключении arduino uno будет выступать в роли программатора. Как заливать прошивку я писать не буду, об этом и так много статьей, если кому-то нужно, то можно посмотреть в мануале: тут.

 Пример прошивки atmega328

Пример работы с atmega328

Оказалось что, работать с atmega328 также просто, как и с любой ардуиной. Достаточно отладить программу использую arduino, а уже готовый скетч просто залить в atmega328, которая имеет все те же самые пины и точно также с ними работает. Ниже находится картинка, с подписанными ножками микроконтроллера.

 Пример работы с atmega328

Логика работы устройства

Как работает устройство, наглядно показывает видео в начале статьи. Для реализации проекта помимо atmega328 использовался 7-сегментный индикатор, принцип работы подобного индикатора я уже описывал с статье « 4-разрядный 7-сегментный индикатор hs420561k-32». Управлять индикатором помогал сдвиговый регистр 74hc595. Так же было задействовано 5 кнопок, три из которых используются для настройки и запуска таймера, а две для передачи хода между игроками. Чтобы во время игры не забыть про таймер, был добавлен зуммер – пищалка, ее тоном можно управлять с помощью аналогового пина.

Корпус устройства

Корпус был напечатан на 3D принтере, но с размерами платы и корпуса я как обычно накосячил, и пришлось еще печатать удлинители для кнопок, поскольку после сборки устройства, достать до кнопок пальцами, не было возможности.

Таймер для шашек на arduinoю. Фото 1
Таймер для шашек на arduinoю. Фото 2

Что использовалось в проекте:

Код скетча таймера для шашек на atmega328

Посмотреть код скетча приведен ниже, так же его можно скачать тут.

//Пин подключен к ST_CP входу 74HC595
int latchPin = 10;
//Пин подключен к SH_CP входу 74HC595
int clockPin = 12;
//Пин подключен к DS входу 74HC595
int dataPin = 11;

// Кнопка увеличения таймера
int btn_up = 2;
bool status_btn_up = false;

// Кнопка уменьшения таймера
int btn_down = 3;
bool status_btn_down = false;

// Кнопка старта/паузы
int btn_select = 4;
bool status_btn_select = false;

// Кнопка 1 игрока
int btn_red_1 = 5;
// положение кнопки
bool status_btn_red_1 = false;

// Кнопка 2 игрока
int btn_red_2 = 7;
// положение кнопки
bool status_btn_red_2 = false;

// пин пищалки
int pin_beep = 9;

// Светодиод 1
int led_1 = 6;//A0;
// Светодиод 2
int led_2 = 8;//A1;

// количество секунд в таймере, по умолчанию 5 сек
int countSeconds = 5;

// флаг таймера, запущен или нет
bool startGame = false;
// отсчет итераций, считаем миллисекунды, по 100 за итерацию
int timer = 0;
// количество установленных секунд для таймера
int currentSec = 5;

// функция вывода цифры на 7-сегментом индикаторе
void writeNum(int num){
  byte arrayNums[] = {
      B10111111, B00001100, 
      B01011011, B01011110, 
      B01101100, B01110110, 
      B01110111, B00011100, 
      B11111111, B11111110
  };
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, arrayNums[num]); 
  digitalWrite(latchPin, HIGH);
}

// функция пищалки
void beep(unsigned char delayms){
  analogWrite(pin_beep, 20);
  delay(delayms);
  analogWrite(pin_beep, 0);
  delay(delayms);
} 

void setup() {
  // настройка пинов
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
  pinMode(btn_up, INPUT);
  pinMode(btn_down, INPUT);
  pinMode(btn_select, INPUT);
  digitalWrite(btn_up, LOW);
  digitalWrite(btn_down, LOW);
  digitalWrite(btn_select, LOW);
  
  pinMode(led_1, OUTPUT);
  pinMode(led_2, OUTPUT);
  digitalWrite(led_1, LOW);
  digitalWrite(led_2, LOW);

  pinMode(pin_beep, OUTPUT);
}
 
void loop() {
  if(startGame){
    writeNum(currentSec);
  }else{
    writeNum(countSeconds);
  }
  if(digitalRead(btn_up)){
    if(!status_btn_up) {
      if(countSeconds < 9) countSeconds++;
    }
    status_btn_up = true;
  }else{
    status_btn_up = false;
  }
  if(digitalRead(btn_down)){
    if(!status_btn_down){
      if(countSeconds > 1) countSeconds--;
    }
    status_btn_down = true;
  }else{
    status_btn_down = false;
  }
  if(digitalRead(btn_select)){
    if(!status_btn_select){
      startGame = !startGame;
      timer = 0;
      currentSec = countSeconds;
      if(startGame){
        digitalWrite(led_1, HIGH);
        digitalWrite(led_2, LOW);        
      }else{
        digitalWrite(led_1, LOW);
        digitalWrite(led_2, LOW);
      }
    }
    status_btn_select = true;
  }else{
    status_btn_select = false;
  }
  if(startGame){
    timer++;
    // прошла секунда
    if(timer > 10){
      timer = 0;
      if(currentSec > 0) {
        currentSec--;
        beep(50);
      }
    }
    if(currentSec == 0){
      beep(50);
    }
    if(digitalRead(btn_red_1)){
      if(!status_btn_red_1) {
        timer = 0;
        currentSec = countSeconds;
        digitalWrite(led_1, LOW);
        digitalWrite(led_2, HIGH);         
      }
      status_btn_red_1 = true;
    }else{
      status_btn_red_1 = false;
    }
    if(digitalRead(btn_red_2)){
      if(!status_btn_red_2) {
        timer = 0;
        currentSec = countSeconds;
        digitalWrite(led_1, HIGH);
        digitalWrite(led_2, LOW); 
      }
      status_btn_red_2 = true;
    }else{
      status_btn_red_2 = false;
    }    
  }
  delay(100);
}

Послесловие

Использование в данном устройстве atmega328 — это большое расточительство, тут будет даже много и atmega8. Но цель была — использовать микроконтроллер отдельно от платы arduino, а не экономия ресурсов, заниматься оптимизаций пока нет возможности. Так же схема собрана не совсем правильно — не были добавлены конденсаторы, для более стабильной и корректной работы МК. И еще одной серьезной ошибкой является сборка схемы без стабилизатора напряжение — так делать нельзя, следующий раз обязательно буду его использовать.

Рассказать друзьям: