Файл: Пояснительная записка к курсовой работе Разработка по для кодового замка по курсу Программирование микропроцессоров.docx
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 22.11.2023
Просмотров: 126
Скачиваний: 3
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
2 АНАЛИЗ РЕАЛИЗУЕМОЙ МИКРОПРОЦЕССОРНОЙ СИСТЕМЫ
3 РАЗРАБОТКА ТЕХНИЧЕСКОГО ЗАДАНИЯ НА ПРОГРАММИРОВАНИЕ
4 ОПИСАНИЕ ИСПОЛЬЗУЕМЫХ КОМПОНЕНТОВ В ПРОГРАММИРУЕМОЙ СИСТЕМЕ
4.5 Пьезоизлучатель звука KY-006
5 РАЗРАБОТКА НЕОБХОДИМОГО МАТЕМАТИЧЕСКОГО ОБЕСПЕЧЕНИЯ КОНТРОЛЛЕРА
6 ОПИСАНИЕ РАЗРАБОТАННОЙ СТРУКТУРЫ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
7 ОПИСАНИЕ ПРОЦЕССА ОТЛАДКИ РАЗРАБОТАННОГО ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
ПРИЛОЖЕНИЕ 1Схема электрическая принципиальная
ЗАКЛЮЧЕНИЕ
В данной курсовой работе произведена разработка программного обеспечения для кодового замка на базе микроконтроллеров ESP8266 и ATMega328p. Также осуществлена разработка программного обеспечения для сервера, поддерживающего Java Virtual Machine.
Вся структура проекта и способ взаимодействия каждой из частей были придуманы мною и реализован в средах разработки ArduinoIDE, Microsoft Visual Code и IntelliJ Idea.
Устройство моего кодового замка очень просто и удобно в использовании для пользователя, а серверное программное обеспечение легко внедряется в уже готовое серверное окружение, что обеспечивает его дешевизну, и минимизацию затрат на внедрение этого устройства в корпоративной среде.
В ходе проектирования приобретен опыт работы и умение проектировать цифровые и микропроцессорные устройства, взаимодействующие сweb-сервисами, а также опыт разработки микросервисных серверных приложений.
Весь исходный код программного обеспечения расположен на сервисе GitHub по ссылке https://github.com/Niatomi/keylock.
СПИСОК ЛИТЕРАТУРЫ
-
Общие сведения и характеристики Arduino. — Текст : электронный // Форум о разработке на Arduino : [сайт]. — 2022. — URL: http://arduino.ru/ (дата обращения: 25.05.2022). -
Общие сведения и характеристики NodeMCU. — Текст : электронный // Российское ардуино-сообщество : [сайт]. — 2022. — URL: https://arduinomaster.ru/ (дата обращения: 25.05.2022). -
Описание и характеристики LCD 2004 дисплея. — Текст : электронный // Проекты на ардуино : [сайт]. — 2022. — URL: http://arduino-project.net/ (дата обращения: 25.05.2022). -
Описание и характеристики пьезоэлемента. — Текст : электронный // Автоблог : [сайт]. — 2022. — URL: https://shamrin.ru/datchik-zummer-chto-eto/ (дата обращения: 25.05.2022). -
Описание и характеристики линейного датчика Холла KY-024. — Текст : электронный // Сайт магазина DUINO : [сайт]. — 2022. — URL: https://duino.ru/datchik-kholla-ky-024 (дата обращения: 25.05.2022). -
Описание и характеристики Сервоприводы Ардуино SG90. — Текст : электронный // Российское ардуино-сообщество : [сайт]. — 2022. — URL: https://arduinomaster.ru/motor-dvigatel-privod/servoprivody-arduino-sg90-mg995-shema-podklyuchenie-upravlenie/ (дата обращения: 25.05.2022). -
Библиотека для отладки на AVR устройствах. — Текст : электронный // Веб-сервис для хостинга IT-проектов и их совместной разработки GitHub : [сайт]. — 2022. — URL: https://github.com/jdolinay/avr_debug (дата обращения: 25.05.2022). -
Формализованная спецификация и экосистема множества инструментов, предоставляющая интерфейс между front-end системами. — Текст : электронный // The OpenAPI Initiative (OAI) : [сайт]. — 2022. — URL: https://www.openapis.org/ (дата обращения: 25.05.2022). -
Документация к сURL. — Текст : электронный // сURL : [сайт]. — 2022. — URL: https://curl.se/ (дата обращения: 25.05.2022). -
Документация по работе с Postman. — Текст : электронный // Postman API platform for building and using APIs : [сайт]. — 2022. — URL: https://www.postman.com/ (дата обращения: 25.05.2022). -
Building a REST API with Spring. — Текст : электронный // Baeldung : [сайт]. — 2022. — URL: https://www.baeldung.com/ (дата обращения: 25.05.2022). -
Spring MVC. — Текст : электронный // Baeldung : [сайт]. — 2022. — URL: https://www.baeldung.com/spring-mvc-tutorial (дата обращения: 25.05.2022). -
The DTO Pattern (Data Transfer Object). — Текст : электронный // Baeldung : [сайт]. — 2022. — URL: https://www.baeldung.com/java-dto-pattern (дата обращения: 25.05.2022). -
ResponseEntity (Spring Framework 5.3.20 API). — Текст : электронный // Baeldung : [сайт]. — 2022. — URL: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/ResponseEntity.html (дата обращения: 25.05.2022). -
CrudRepository, JpaRepository, and PagingAndSortingRepository in Spring Data. — Текст : электронный // Baeldung : [сайт]. — 2022. — URL: https://www.baeldung.com/spring-data-repositories (дата обращения: 25.05.2022).
ПРИЛОЖЕНИЕ 1
Схема электрическая принципиальная
ПРИЛОЖЕНИЕ 2
Спецификация
ПРИЛОЖЕНИЕ 3
Исходное ПО аппаратного уровня
#include
#include
#define GREEN A0
#define RED A1
#define ZOOMER 10
#define HALL 2
#define SS_PIN A2
#define RST_PIN A3
// Keypad init
const byte ROWS = 3;
const byte COLS = 4;
charhexaKeys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','0'},
{'7','8','9','C'}
};
byterowPins[ROWS] = {5, 4, 3};
bytecolPins[COLS] = {9, 8, 7, 6};
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
// LCD init
LiquidCrystal_I2C lcd (0x27, 20, 4);
byteupsideDownDegree[8]= {
B00000,
B00000,
B00000,
B00000,
B00000,
B10001,
B01010,
B00100,
};
bytefilledSpace[8]= {
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
};
byteunFilledSpace[8]= {
B11111,
B10001,
B10001,
B10001,
B10001,
B10001,
B10001,
B11111,
};
booleanshowPassword = true;
boolean sound = false;
booleanisLocked = false;
volatile unsigned long globalTimeBufferMillis = 0;
byteincorrectCount = 0;
void setup(){
Serial.begin(9600);
Serial.setTimeout(100);
lcd.init();
lcd.backlight();
lcd.createChar(1,upsideDownDegree);
lcd.createChar(2,filledSpace);
lcd.createChar(3,unFilledSpace);
pinMode(GREEN, OUTPUT);
pinMode(RED, OUTPUT);
doorIsOpened();
attachInterrupt(0, doorInteruptAction, FALLING);
}
booleanisAccessFromPassword = false;
voiddoorInteruptAction() {
detachInterrupt(0);
incorrectCount = 6;
if (!isAccessFromPassword) Serial.write("hall:UnauthorizedAccess@");
Serial.flush();
}
void loop() {
attachInterrupt(0, doorInteruptAction, FALLING);
openMenu();
}
voiddoorIsOpened() {
if (digitalRead(HALL)) {
digitalWrite(GREEN, 0);
digitalWrite(RED, 1);
// return false;
} else {
digitalWrite(GREEN, 1);
digitalWrite(RED, 0);
// return true;
}
}
voidopenMenu() {
getConfig();
if (!(incorrectCount>= 3) && !isLocked) {
drawMenu();
listenKeyboardAndChanegeLcd();
} else {
if (isLocked == false)
incorrectCount = 0;
drawBlock();
}
}
voiddrawBlock() {
lcd.clear();
getConfig();
lcd.setCursor(0, 0);
lcd.print("Access blocked");
improvedDelay(5000);
}
voiddrawMenuHeader() {
lcd.setCursor(0, 0);
lcd.print("Choose action");
lcd.setCursor(0, 1);
for (inti = 0; i< 20; i++) {
lcd.print("-");
}
lcd.setCursor(0, 2);
lcd.print("^");
lcd.setCursor(0, 3);
lcd.write(1);
}
voiddrawMenu() {
drawMenuHeader();
keyAndSettingsScene();
lcd.setCursor(1, 2);
lcd.blink_on();
}
voidkeyAndSettingsScene() {
lcd.clear();
drawMenuHeader();
lcd.setCursor(2, 2);
lcd.print("Keyboard");
lcd.setCursor(2, 3);
lcd.print("Settings");
}
booleanisPriorized = false;
voidgetConfig() {
Serial.flush();
Serial.write("getConfig");
Serial.flush();
longawaitTime = 1000;
longenterWithTime = millis();
while (true) {
if (Serial.available()) {
String expression = Serial.readStringUntil('-');
expression = expression.substring(expression.indexOf(':') + 1, expression.length());
String config = "1";
if (!isPriorized&&expression.charAt(0) == '1') {
sound = true;
} else if (!isPriorized&&expression.charAt(0) == '0') {
sound = false;
}
if (!isPriorized&&expression.charAt(1) == '1') {
showPassword = true;
} else if (!isPriorized&&expression.charAt(1) == '0') {
showPassword = false;
}
if (expression.charAt(2) == '1') {
isLocked = true;
} else {
isLocked = false;
}
Serial.flush();
return;
} else if (millis() - enterWithTime>awaitTime) {
incorrectCount = 0;
drawUpLimitAwaitTime();
return;
}
}
Serial.flush();
}
voidlistenKeyboardAndChanegeLcd() {
byte type = 2;
while (true) {
charcustomKey = customKeypad.getKey();
if (customKey) {
getConfig();
if (sound) tone(ZOOMER, 220, 50);
if (customKey == '2') {
if (type == 2) {
type = 3;
drawScene(type, false);
} else if (type == 3) {
type--;
drawScene(type, true);
} else {
type--;
drawScene(type, false);
}
} else if (customKey == '5') {
if (type == 2) {
openUsingKeypad();
return;
} else if (type == 3) {
openSettings();
return;
} else if (type == 4) {
openSettings();
return;
}
} else if (customKey == '8') {
if (type == 3) {
type = 2;
} else {
type++;
}
drawScene(type, false);
}
}
}
}
voidopenSettings() {
drawMenuSettings();
listenKeyboardOnSettings();
}
voiddrawMenuSettings() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Settings");
lcd.setCursor(0, 1);
if (showPassword) lcd.write(2);
if (!showPassword) lcd.write(3);
lcd.setCursor(2, 1);
lcd.print("Show password");
lcd.setCursor(0, 2);
if (sound) lcd.write(2);
if (!sound) lcd.write(3);
lcd.setCursor(2, 2);
lcd.print("Sound");
lcd.setCursor(1, 1);
}
voidlistenKeyboardOnSettings() {
bytetypeSetting = 1;
while (true) {
charcustomKey = customKeypad.getKey();
if (customKey) {
if (customKey == '2') {
if (typeSetting == 1) {
typeSetting = 2;
} else {
typeSetting--;
}
lcd.setCursor(1, typeSetting);
} else if (customKey == '5') {
isPriorized = true;
if (typeSetting == 1) {
showPassword = !showPassword;
printSuccesSettingsUpdate();
return;
} else if (typeSetting == 2) {
sound = !sound;
printSuccesSettingsUpdate();
return;
}
} else if (customKey == '8') {
if (typeSetting == 2) {
typeSetting = 1;
} else {
typeSetting++;
}
lcd.setCursor(1, typeSetting);
} else if (customKey == 'C') {
return;
}
}
}
}
voidprintSuccesSettingsUpdate() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Settings updated");
improvedDelay(1000);
}
voiddrawScene(byte type, booleanisPrevious) {
if (type == 2) {
keyAndSettingsScene();
lcd.setCursor(1, type);
}
if (type == 3) {
keyAndSettingsScene();
lcd.setCursor(1, type);
}
}
String pass = "";
String key = "";
String enteringPassword = "";
voidopenUsingKeypad() {
lcd.clear();
drawCodeHeader();
while (true) {
charcustomKey = customKeypad.getKey();
if (customKey) {
if (sound) tone(ZOOMER, 220, 50);
if (customKey == 'A') {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Password check");
break;
} else if (customKey == 'C') {
enteringPassword = enteringPassword.substring(0, enteringPassword.length() - 1);
drawPassword();
} else {
enteringPassword += customKey;
drawPassword();
}
}
}
applyPassword(!isLocked&&sendPasswordOnCheck(enteringPassword, "keypad"));
enteringPassword = "";
}
charconstPassword[71];
booleansendPasswordOnCheck(String enteringPassword, String type) {
Serial.flush();
for (inti = 0; i
constPassword[i] = '-';
}
String sendingData = "check:" + type + ":" + enteringPassword;
for (inti = 0; i
constPassword[i] = sendingData.charAt(i);
}
Serial.write(constPassword);
Serial.flush();
improvedDelay(2000);
longawaitTime = 10000;
longenterWithTime = millis();
while (true) {
if (Serial.available()) {
String isRight;
isRight = Serial.readStringUntil('*');
Serial.println();
Serial.println(isRight);
if (isRight.indexOf("open") != -1) {
Serial.flush();
return true;
} else if (isRight.indexOf("wrong") != -1) {
Serial.flush();
return false;
}
}
if (millis() - enterWithTime>awaitTime) {
incorrectCount = 0;
drawUpLimitAwaitTime();
return false;
}
}
}
voiddrawUpLimitAwaitTime() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Uptime server limit");
improvedDelay(1000);
lcd.clear();
}
voidapplyPassword(booleanpasswordIsRight) {
if (passwordIsRight) {
isAccessFromPassword = true;
confirmed();
detachInterrupt(0);
improvedDelay(10000);
checkDoor();
attachInterrupt(0, doorInteruptAction, FALLING);
isAccessFromPassword = false;
} else {
denied();
incorrectCount++;
if (incorrectCount == 3) {
isLocked = true;
sendBlockState();
}
}
}
booleancheckDoor() {
if (!digitalRead(HALL)) {
Serial.flush();
Serial.write("hall:unClosed@");
Serial.flush();
} else {
Serial.flush();
Serial.write("hall:Closed@");
Serial.flush();
}
Serial.flush();
doorIsOpened();
}
voidsendBlockState() {
Serial.flush();
Serial.write("lock");
Serial.flush();
}
voiddrawCodeHeader() {
lcd.setCursor(0, 0);
lcd.print("Enter your password:");
lcd.setCursor(0, 1);
}
voiddrawPassword() {
lcd.clear();
drawCodeHeader();
lcd.setCursor(0, 1);
if (showPassword) {
lcd.print(enteringPassword);
} else {
for (inti = 0; i
lcd.print("*");
}
}
}
void confirmed() {
drawConfirm();
openLock();
if (sound) confirmSound();
}
voiddrawConfirm() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Password confirmed");
}
voidopenLock() {
digitalWrite(GREEN, 1);
digitalWrite(RED, 0);
}
voidconfirmSound() {
tone(ZOOMER, 220, 100);
improvedDelay(200);
noTone(ZOOMER);
tone(ZOOMER, 220, 100);
improvedDelay(200);
noTone(ZOOMER);
tone(ZOOMER, 220, 100);
}
void denied() {
drawIncorrectPassword();
deniedSound();
improvedDelay(500);
}
voiddrawIncorrectPassword() {
digitalWrite(GREEN, 0);
digitalWrite(RED, 1);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Password denied");
}
voiddeniedSound() {
tone(ZOOMER, 320, 100);
improvedDelay(200);
noTone(ZOOMER);
tone(ZOOMER, 320, 100);
improvedDelay(200);
noTone(ZOOMER);
tone(ZOOMER, 320, 100);
}
voidimprovedDelay(unsigned intwaitTime) {
globalTimeBufferMillis = millis();
booleancooldownState = true;
while (cooldownState) {
if (millis() - globalTimeBufferMillis>waitTime)
cooldownState = false;
}
}
1 2 3 4 5 6 7 8 9 10
ПРИЛОЖЕНИЕ 4
Исходное ПО сетевого уровня
#include
#include
#include
#include
#include
#include
#define HTTP 5
#define HARDWARE_INDICATION 4
#define LED_BUILTIN 2
volatile unsigned long globalTimeBufferMillis = 0;
// WiFi, HTTP
// const char* ssid = "Ttk 139";
// const char* password = "631790355";
const char* ssid = "Niatomi";
const char* password = "1234567890";
WiFiClient client;
IPAddresslocal(192, 168, 137, 1);
uint16_t port = 8080;
DynamicJsonDocumentdoc(2048);
unsigned long openerId;
String enteringPassword = "";
void setup() {
WiFi.begin(ssid, password);
pinMode(HTTP, OUTPUT);
pinMode(HARDWARE_INDICATION, OUTPUT);
digitalWrite(HTTP, LOW);
digitalWrite(HARDWARE_INDICATION, LOW);
while (WiFi.status() != WL_CONNECTED)
delay(500);
Serial.begin(9600);
Serial.setTimeout(5);
}
voidgetPasswords() {
if (client.connect(local, port)) {
digitalWrite(HTTP, HIGH);
// Send HTTP request
client.println("GET /esp HTTP/1.0\r\n");
client.println("Host: " + local.toString() + ":8080");
// Skip HTTP headers
charendOfHeaders[] = "\r\n\r\n";
if (!client.find(endOfHeaders)) {
// Serial.println("Invalid response");
return;
}
deserializeJson(doc, client);
client.stop();
digitalWrite(HTTP, LOW);
}
}
booleancheckPassword(String enteringPassword, String enteringType) {
getPasswords();
for (JsonObject item : doc.as
openerId = item["openerId"];
String type = item["type"];
String value = item["value"];
if (type == enteringType) {
if (value == enteringPassword) {
return true;
}
}
}
openerId = 1;
return false;
}
void loop() {
hardwareListener();
}
voidhardwareListener() {
if (Serial.available()) {
String expression = Serial.readStringUntil('-');
String method = expression.substring(0, expression.indexOf(':'));
expression = expression.substring(expression.indexOf(':') + 1, expression.length());
if (method == "check") {
String type = expression.substring(0, expression.indexOf(':'));
expression = expression.substring(expression.indexOf(':') + 1, expression.length());
enteringPassword = expression.substring(0, expression.length());
if (type == "keypad") {
if (checkPassword(enteringPassword, type)) {
digitalWrite(HARDWARE_INDICATION, HIGH);
Serial.flush();
Serial.write("open*");
Serial.flush();
sendAction("Open");
digitalWrite(HARDWARE_INDICATION, LOW);
} else {
digitalWrite(HARDWARE_INDICATION, HIGH);
Serial.flush();
Serial.write("wrong*");
Serial.flush();
sendAction("WrongKeyAccess");
digitalWrite(HARDWARE_INDICATION, LOW);
}
}
}
if (method == "hall") {
openerId = 1;
expression = expression.substring(0, expression.indexOf('@'));
sendAction(expression);
}
if (method == "getConfig") {
getServerConfig();
}
if (method.indexOf("lock") != -1) {
sendLockConfigAction();
}
if (method.indexOf("config") != -1) {
sendSettingsConfigAction();
}
if (method == "getConfig") {
getServerConfig();
}
Serial.flush();
}
}
voidsendSettingsConfigAction() {
digitalWrite(HTTP, HIGH);
if (client.connect(local, port)) {
client.println("POST /esp/setConfig HTTP/1.1");
client.println("Host: " + local.toString() + ":8080");
client.println();
improvedDelay(200);
client.stop();
}
digitalWrite(HTTP, LOW);
}
voidsendLockConfigAction() {
digitalWrite(HTTP, HIGH);
if (client.connect(local, port)) {
client.println("POST /esp/setLock HTTP/1.1");
client.println("Host: " + local.toString() + ":8080");
client.println();
improvedDelay(200);
client.stop();
}
digitalWrite(HTTP, LOW);
}
booleanre_read_password;
charsendingConfig[12];
voidgetServerConfig() {
String arduinoConfiguration = "config:";
DynamicJsonDocumentconfig(128);
if (client.connect(local, port)) {
digitalWrite(HTTP, HIGH);
// Send HTTP request
client.println("GET /esp/getConfig HTTP/1.0\r\n");
client.println("Host: " + local.toString() + ":8080");
// Skip HTTP headers
charendOfHeaders[] = "\r\n\r\n";
if (!client.find(endOfHeaders)) {
// Serial.println("Invalid response");
return;
}
deserializeJson(config, client);
client.stop();
digitalWrite(HTTP, LOW);
}
boolean sound = config["sound"].as
booleanshowPassword = config["showPassword"].as
re_read_password = config["re_read_password"].as
boolean lock = config["lock"].as
arduinoConfiguration.concat(sound);
arduinoConfiguration.concat(showPassword);
arduinoConfiguration.concat(lock);
arduinoConfiguration.concat("-");
for (inti = 0; i
sendingConfig[i] = arduinoConfiguration.charAt(i);
}
digitalWrite(HARDWARE_INDICATION, HIGH);
Serial.write(sendingConfig);
Serial.flush();
digitalWrite(HARDWARE_INDICATION, LOW);
}
voidsendAction(String action) {
if (client.connect(local, port)) {
digitalWrite(HTTP, HIGH);
StaticJsonDocument<250>docOut;
docOut["openerId"] = openerId;
docOut["description"] = action;
// Write response headers
client.println("POST /esp HTTP/1.1");
client.println("Host: " + local.toString() + ":8080");
client.println("Content-Type: application/json");
client.println("Connection: close");
client.print("Content-Length: ");
client.println(measureJsonPretty(docOut));
client.println();
serializeJsonPretty(docOut, client);
client.stop();
digitalWrite(HTTP, LOW);
}
}
voidsendHttpAction() {
StaticJsonDocument<48>docOut;
}
voidimprovedDelay(unsigned intwaitTime) {
globalTimeBufferMillis = millis();
booleancooldownState = true;
while (cooldownState) {
if (millis() - globalTimeBufferMillis>waitTime)
cooldownState = false;
}
}
ПРИЛОЖЕНИЕ 5
Антиплагиат
48>250>
1 2 3 4 5 6 7 8 9 10