Муниципальное учреждение дополнительного образования «Станция юных техников» Счетчик кругов для проведения соревнований по автотрассовому моделизму Автор: Сычев Никита МБУДО «Станция юных техников» Педагоги-наставники: Рыбьяков Алексей Владимирович, Никитин Николай Пименович Педагоги дополнительного образования МБУДО «Станция юных техников» г. Ханты-Мансийск 2016 |
Оглавление
Аннотация 3
Цели и задачи 4
Описание аппаратной части проекта 5
Описание программной части проекта 7
Приложение I. Листинг исходного кода программы 8
Приложение II. Схема электрическая принципиальная 16
Приложение III. Индикаторы. Схема электрическая монтажная 17
Приложение IV. Индикаторы. Схема электрическая монтажная 18
Приложение V. Контроллер. Схема электрическая монтажная 19
Приложение VI. Фотография действующего счётчика 20
Аннотация
На станции юных техников города Ханты-Мансийска работает объединение «Автотрассовый моделизм». В этом объединении воспитанники разрабатывают и изготавливают своими руками модели гоночных автомобилей. После сборки моделей они устраивают соревнования на специально подготовленной трассе и выясняют, чья модель быстрее и качественней. Нередко в ходе соревнований возникают споры о количестве пройденных кругов той или иной модели. Для разрешения этого конфликта я решил автоматизировать процесс подсчета пройденных кругов. Для удобства работы жюри и участников соревнований в устройстве добавлен таймер который устанавливается вручную, он индицирует на семисегментных индикаторах оставшееся время до конца отведенного времени и контролирует подачу напряжения на трассу для движения моделей. Также в устройстве предусмотрена визуальная и звуковая индикация до начала и конца соревнования.
Современное спортивное табло – это тот вариант, который удовлетворяет участников и организаторов соревнования.
Цель проекта
Автоматизировать подсчёт кругов
Задача проекта
Разработать устройство для подсчёта кругов
Описание аппаратной части проекта
В основе модуля лежит 8-битный микроконтроллер фирмы «Atmel» ATMEGA328P (U1). Объем flash-памяти 32 Кбайт, энергонезависимой памяти – 1 Кбайт, оперативной – 2 Кбайт. Это позволяет перейти от аппаратного метода исполнения конструкции к программному, это значительно упрощает конструкцию и уменьшает ее себестоимость. Тактовая частота микроконтроллера задается внешним кварцевым резонатором 16МГц (X1).
Для настройки времени гонок используются 4 кнопки: «+» (прибавляет десять секунд), «-» (вычитает десять секунд), «OK» (начинает гонку через 3 секунды после нажатия), «Reset» (сбрасывает устройство). Максимальное время заезда 9 минут.
Индикация предупреждающая о начале соревнования выполнена с помощью трех светодиодов: красного, желтого и зеленого – и семи семисегментных индикаторов: трёх для отображения оставшегося времени, двух – для отображения счёта одного игрока, ещё двух – для отображения счёта второго игрока.
Все семисегментные индикаторы управляются микроконтроллером с помощью семи сдвиговых регистров 74HC595 (U1, U3, U5, U7, U9, U11, U13) – восьмиразрядных сдвиговых регистров с последовательным вводом, последовательным или параллельным выводом информации, с триггером-защелкой и тремя состояниями на выходе. Этот регистр позволяет контролировать 8 выходов, используя всего несколько выходов на самом контроллере. При этом несколько таких регистров можно объединять последовательно для каскадирования. Необходимые значения сигнала (биты HIGH или LOW) передаются в регистр один за другим, при этом регистр получает синхронизирующий сигнал, который заставляет его считать сигнал с входа. Когда байт (1 байт = 8 бит) считан, значения всех 8 бит распределены по выходам. 74HC595 может отдавать сигналы не только параллельно, но и последовательно. Это необходимо при объединении нескольких регистров, для получения 16 и более выходов. В этом случае первые 8 бит сигнала передаются на следующий регистр для параллельного вывода на нем. Также используются транзисторные ключи ULN2003A (U2, U4, U6, U8, U10,U12, U14) для увеличения входного тока на семисегметных индикаторах.
Для определения момента, когда автомодель пересек точку отсчета, используются два инфракрасных светодиода (D1 и D2) и два фотодиода (LDR1 и LDR2) установленные друг напротив друга. При пересечении этой линии фотодиод срабатывает и дает команду для дальнейшей ее обработки.
Звуковая индикация через транзисторный ключ (Q3) выполнена на пьезодинамике (BUZ1).
Описание программной части проекта
Листинг исходного кода программы приведен в Приложении №6.
Микроконтроллер ATMEGA328P можно запрограммировать на языках Си, Basic, Ассемблер. Я выбрал Си, так как уже давно программирую именно на этом языке. Для написания кода, отладки, компиляции и прошивки микроконтроллера использовалась программа Arduino IDE.
При запуске счётчика осуществляется инициализация фоторезисторов, светодиодов, кнопок, семисегментных индикаторов. Загорается красный светодиод, на всех индикаторах появляются нули.
Во время включения аппарат находится в режиме настройки. В этом режиме судья может настроить время работы счётчика с помощью кнопок «+» и «-». Шаг изменения времени – 10 секунд. Ввиду того, что для отображения времени предусмотрено лишь три индикатора, максимальное время работы – 590 секунд (9 минут 50 секунд). После настройки времени судья должен нажать кнопку «Старт». Через 2 секунды после нажатия начинается обратный отсчёт (3 секунды) со звуковым сопровождением. Также в это время загорается сначала желтый, а затем зеленый светодиод. При включении зеленого светодиода издаётся длинный звуковой сигнал, а на трассу подается напряжение.
При проезде машинки под трассой значение соответствующего табло увеличивается на 1. Значения на семисегментных индикаторах обновляются один раз в секунду. Ровно за пять секунд до окончания выделенного времени издается короткий звуковой сигнал.
После окончания времени издается длинный звуковой сигнал, загорается красный светодиод, а трасса обесточивается. Чтобы запустить трассу заново, нужно перезапустить аппарат с помощью специальной кнопки (RESET). До перезапуска на табло отображаются результаты участников.
Приложение I. Листинг исходного кода программы
enum Status {
SETUP = 0, // Set up game time
START = 1, // Start of game (back counter)
GAME = 2, // Game as is
FINISH = 3 // does nothing
};
enum Pins {
DATA = 5, // DS, DC
CLOCK = 6, // SH_CP
ENABLE = 7, // ST_CP, LATCH
// Indication LEDs
LED_RED = 0,
LED_YELLOW = 3,
LED_GREEN = 2,
BTN_PLUS = 10, // Button which increase time
BTN_MINUS = 11, // Button which decrease time
BTN_START = 12, // START Button
SOUND = 9, // Buzzer
// Receivers
RECV1 = 14,
RECV2 = 15
};
// Charset for 7-segment indicators
const byte charset[] = {
0xC0,
0xF9,
0xA4,
0xB0,
0x99,
0x92,
0x82,
0xF8,
0x80,
0x90
};
byte latchState = HIGH;
int
result1,
result2,
time;
byte
mode,
state1,
state2;
unsigned long long
end;
/* validate - function which checks whether value is in correct interval
*
* @params:
* int value - value, which needs to be checked
* int min - lower bound of interval
* int max - higher bound of interval
*
* @return:
* if max
* if value in [min, max] returns value
* if value max returns max
* if value
*/
int validate(int value, int min, int max)
{
if (max
if (value max) return max;
if (value
return value;
}
/* shiftNum - function which shifts out some numeric
*
* @params:
* int num - numeric which need to show
*
* @return:
* void
*/
void shiftNum(int num) {
shiftOut(DATA, CLOCK, MSBFIRST, 255-charset[num]);
}
/* doLatch - function which opens/closes the latch
*
* @params:
* void
*
* @return:
* void
*/
void doLatch(void) {
latchState = 1 - latchState;
digitalWrite(ENABLE, latchState);
}
/* display - function which shows some numbers on indicators
*
* @params:
* int left_num - number on left indicator
* int middle_num - number on middle indicator
* int right_num - number on right indicator
*
* @return:
* void
*/
void display(int left_num, int middle_num, int right_num) {
int left = validate(left_num, 0, 99);
int middle = validate(middle_num, 0, 599);
int right = validate(right_num, 0, 99);
// Open latch
doLatch();
// Firstly, shift out middle number from right to left
shiftNum((middle%60)%10);
shiftNum((middle%60)/10);
shiftNum(middle/60);
// Secondly, shift out right number from right to left
shiftNum(right%10);
shiftNum(right/10);
// And thirdly, shift out left number from right to left
shiftNum(left%10);
shiftNum(left/10);
// Do not forget close the latch
doLatch();
}
/* lightOn - lights "traffic light" by bit mask of light
*
* @params:
* int mask - bit mask of "traffic light"
*
* @return:
* void
*/
void lightOn(int mask) {
digitalWrite(LED_RED, (mask & 4 == 4));
digitalWrite(LED_YELLOW, (mask & 2 == 2));
digitalWrite(LED_GREEN, (mask & 1 == 1));
}
// Standard Arduino setup function
void setup() {
// Set output pins
pinMode(ENABLE, OUTPUT);
pinMode(DATA, OUTPUT);
pinMode(CLOCK, OUTPUT);
pinMode(LED_RED, OUTPUT);
pinMode(LED_YELLOW, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(SOUND, OUTPUT);
// Display zeros on indicators
display(0, 0, 0);
// Now setup the buttons
pinMode(BTN_MINUS, INPUT_PULLUP);
pinMode(BTN_PLUS, INPUT_PULLUP);
pinMode(BTN_START, INPUT_PULLUP);
// Setup "traffic light"
lightOn(4);
// Set current mode & time
mode = SETUP;
time = 0;
// It's magic, i really don't know what it means.
// Anyway nobody will read this code :)
digitalWrite(RECV1, HIGH);
digitalWrite(RECV2, HIGH);
}
void loop() {
if (mode == SETUP) {
// Minimal time - 10 seconds
// Maximal time - 590000 seconds (9 mins 50 secs)
if (digitalRead(10) == LOW) { // Plus button handler
time = validate(time + 10000, 10000, 590000); // Increase time by 10 seconds
display(0, time / 1000, 0); // Show updates on display
delay(250); // Wait for 1/4 sec
}
if (digitalRead(11) == LOW) { // Minus button handler
time = validate(time - 10000, 10000, 590000); // Decrease time by 10 seconds
display(0, time / 1000, 0); // Show updates on display
delay(250); // Wait for 1/4 sec
}
if (digitalRead(12) == LOW) { // Start button handler
time = validate(time, 10000, 590000); // Check time anyway
mode = START; // Start game
delay(2000); // in 2 seconds after pressing this button
}
} else
if (mode == START) {
display(0, 2, 0); // Show "2" on display!
tone(SOUND, 1000, 150); // Make a small sound
delay(1000); // Wait for a second
display(0, 1, 0); // Show "1" on display!
lightOn(2); // Light YELLOW led
tone(SOUND, 1400, 250); // Make a middle sound
delay(1000); // Wait for a second
display(0, 0, 0); // Show "0" on display!
lightOn(1); // Light GREEN led
tone(SOUND, 2000, 500); // Make a big sound
// Results are equal -1 because when cars will pass start line
// first time, their result will became 0.
result1 = -1;
result2 = -1;
state1 = LOW;
state2 = LOW;
end = millis() + time;
mode = GAME;
} else
if (mode == GAME) {
if (millis()%1000
display(result1, (end - millis()) / 1000, result2); // displays
}
if ((end - millis()) == 5000) { // When the estimated time lower
tone(SOUND, 1400, 600); // than 5 seconds, make the sound
}
if (millis() = end) { // When game is finished
tone(SOUND, 2000, 900); // Make the sound
mode = FINISH; // Proceed to finish mode
lightOn(4); // Light the RED led
}
// Receivers handlers
if (digitalRead(RECV1) == LOW) {
if (state1 == LOW) {
state1 = HIGH;
result1++;
}
} else {
state1 = LOW;
}
if (digitalRead(RECV2) == LOW) {
if (state2 == LOW) {
state2 = HIGH;
result2++;
}
} else {
state2 = LOW;
}
} else
if (mode == FINISH) {
// Don't do anything!
// Use RESET button to continue
}
}
Список используемой литературы
Тимофеева Г.А. Теория механизмов и механика машин. Издательство Московский государственный технический университет имени Н,Е, Баумана, 2009 г.
Токхейм Р. Основы цифровой электроники. Москва. «Мир». 1988 г.
Шило В. Л. Популярные цифровые микросхемы. Издательство «Металлургия» 1988 г