Проектирование поворотно-остановочного сигнала на Arduino. Курсовая МС. 1 Общая часть 5 1 Анализ существующих аналогичных устройств 6
Скачать 3.94 Mb.
|
2.4 Написание программы для устройстваПрограммирование микроконтроллеров Arduino осуществляется на языке программирования C++. Этот язык является низкоуровневым, поэтому считается сложным и имеет высокий порог вхождения. Но для программирования Arduino используется упрощенная версия этого языка программирования. Так же для упрощения разработки прошивок существует множество функций, классов, методов и библиотек. Благодаря этому работать с этими микроконтроллерами очень удобно и легко. Программный код для данного устройства представлен в приложении А. ЗаключениеВ ходе данной курсовой работе я изучил основы работы с Arduino, также познал технологию создания программ на данной платформе. Результатом курсового проекта является разработанный проект поворотно-остановочного сигнала на базе Arduino Nano. Также были разработаны структурные и принципиальные схемы и программа на языке Arduino. Благодаря минимальному количеству элементов в устройстве, а также их дешевизны, и знаниям по микропроцессорным системам и базовых знаний в электротехнике, то данное устройство очень просто в реализации. Благодаря несложному, удобному и настраиваемому управлению всего устройства, пользователь может легко его использовать. В течение выполнения курсового проекта был приобретен опыт работы и умение проектировать цифровые микропроцессорные устройства. Список использованных источниковГуров, В. В. Микропроцессорные системы: учебник / В.В. Гуров. — Москва: ИНФРА-М, 2019. — 336 с. + Доп. материалы [Электронный ресурс; Режим доступа: http://new.znanium.com]. — (Среднее профессиональное образование). Булатов В.Н. Микропроцессорная техника. Схемотехника и программирование [Электронный ресурс]: учебное пособие для СПО/ Булатов В.Н., Худорожков О.В.— Электрон. текстовые данные.— Саратов: Профобразование, 2020.— 376 c.— Режим доступа: http://www.iprbookshop.ru/91893.html.— ЭБС «IPRbooks». Немцова, Т. И. Программирование на языке высокого уровня. Программирование на языке C++ : учебное пособие / Т.И. Немцова, С.Ю. Голова, А.И. Терентьев ; под ред. Л.Г. Гагариной. — Москва : ФОРУМ : ИНФРА-М, 2021. — 512 с. + Доп. материалы [Электронный ресурс]. — (Среднее профессиональное образование). - ISBN 978-5-8199-0699-6. - Текст: электронный. - URL: https://znanium.com/catalog/product/1172261 https://ampermarket.kz/base/arduino_family/?ysclid=lahyb6h5lp247647430 http://wiki.amperka.ru/продукты:arduino-nano Приложение А. Листинг программы #include #include #include "HUB08SPI.h" #include //выбираем шрифт //#include "Font_RUS1.h" //English широкий + русский узкий #include "Font_RUS2.h" //English средний + русский средний //#include "Font_RUS3.h" //English средний + русский узкий #define WIDTH 64 #define HEIGHT 16 #include uint8_t displaybuf[WIDTH * HEIGHT / 8]; HUB08SPI display; //далее рисунок на дисплей меняем под себя в приложении EXCEL //если не нужен декларируем три строчки ниже в void setup() /* стереть справа -> */ uint8_t display_risunok[WIDTH * HEIGHT / 8] = {....}; ///*/ unsigned long time_2znaka=0, time_telf=0,time_inver=0, time_povrt=0; //временные таймеры boolean tormaz=0,nazad=0,pravo=0,levo=0, avariik=0,rezt=0, //флаги // flag_tel=0, flag_len=0, new_fraza=0, flag_nazd,flag_prv=0,flag_ctop=0; ////флаги // uint8_t len=0,invers_N=0,A=3,T=4;//переменные, менять тут ничего не надо int length = WIDTH;//переменная для длины фраз String Str_telf;//объект для конвертирования массива телефоных фраз char * msg_tel; ///резервируем память под массив фраз с телефона char *msg_avto[] = /// буквы "Ё" нет!//массив автомобиля {/////////сервисные фразы. //////////////////:) "\x0c6\x0c7", //0/// знак /!/ "\x0c0\x0c1", //1// знак шины "Ш"// или, что то своё "\x0c6\x0c7\x020\x020\x020\x0c6\x0c7", //2// 2 знака "/!/ /!/ "\x0c2\x0c3\x0c4\x0c5", //3// СТОП крупным шрифтом "НАЗАД", //4// "СПАСИБО" //5// }; //-------предварительные настройки----------------------------------------------- // Библиотека увеличивает частоту Timer2 так что ШИМ работает на 32 кГц. время в скетче бежит быстрее :) #define time_invers 1000 // время между инверсиями СТОП.//с телефона не меняется #define time_povorot 800 // время между морганиями поворотов//с телефона НЕ меняется//зависит от авто, подобрать при необходимости #define time_spasibo 8000 // время горения "спасибо" //с телефона НЕ меняется unsigned long time_sbros =15000;//время горения фраз с телефона////потом меняем с телефона uint16_t Skorost=150;//от 30 до 300//0-бысто, 700 медленно//потом меняем с телефона uint8_t Jarkost=250; //0-256//256 max//потом с телефона меняем //-----------пины приема сигналов с машины (аналоговые входы)--------------------- #define trm A1 //тормоз // присваиваем пины входов от ламп машины #define nzd A2 //назад // #define prv A4 //вправо // #define lev A3 //налево // //---------------переменные для хранения в EEPROM ------------------------ // тут тип переменной "int" для корректной работы функции "sscanf() // все меняется с телефона потом //обязательно хоть раз "сохранить" нажать, а то в памяти(до первой записи) может быть мусор int adrees=0;//адрес ардуино, не меняется//29284 прописано в программе телефона (от фонаря придумал) int skorost=70;//скорость(10-99)//99 быстро 10-медлено// int jarkost=70;//яркость(10-99) int invers=6;// инверсия//0-9 int reklam=1; // режим когда фразы не уходят сами//1-уходят,2- постоянно горит последняя фраза, до выкл табло int vremya=15;//время горения фраз с телефона// сек//2-99 int coxpan=1;//сохранить еером//1-нет//2- да int begut=1;// бежит//1-нет//2- да// int shipu=1;//1-знак /!/, 2-буква "Ш" //================================================================================================// void setup() { Serial.begin(9600); // для блютуз СН-06 // Serial.begin(38400);// для блютуз СН-05 //---------------подключаем входы от машины -------------------------------------------------- digitalWrite(trm,LOW); // тормоз// digitalWrite(nzd,LOW); // назад // ВКЛ ВНУТРЕНИЕ РЕЗИСТОРЫ digitalWrite(prv,LOW); // поворот право digitalWrite(lev,LOW); // поворот лево///*/ //------------чтение сохранненых переменных их энергонезависимой памяти -------------------- skorost=EEPROM.read(51); jarkost=EEPROM.read(52); reklam=EEPROM.read(53); vremya=EEPROM.read(54); begut = EEPROM.read(55); shipu=EEPROM.read(56); invers=EEPROM.read(57); // применяем сохраненные переменные Skorost=map(skorost, 10, 99, 300, 30); //ивертирует диапазон , после новой команды. Jarkost=map(jarkost, 10, 99, 40, 255); //ивертирует диапазон , после новой команды time_sbros=(long)vremya*1000; /// переводим сек в млсек*/ //----------------прерывания--------------------------------------------------------------- Timer1.initialize(200); //частота обновления Timer1.attachInterrupt(refresh); //скорость обновления //---------печатаем рисунок---если не нужен рисунок, то закомментировать 3 строки ниже------- /*стереть справа -> */ display.begin(display_risunok, WIDTH, HEIGHT);// delay(1000); //рисунок горит 1(1000mc) секунд при старте display.clear();//чистим дисплей */ //-------------------------------------------------------------------------------------- display.begin(displaybuf, WIDTH, HEIGHT);//выводим из функции рисунок, прописываем в функцию буфер для текста } //------------------------------------------------------------------------ volatile uint16_t Nx = 0;//переменная позиции печати на табло//не разрешаем оптимизировать переменную// void refresh() //функция обновления строки,(прерывания таймера) { static uint16_t count = 0; count++; if (count > Skorost) { count= 0; Nx++; if(Nx > length) Nx = 0; //reset после xxx pixels } display.scan();//refresh//обновить одну строку дисплея } //===================================================================================================== void loop() { unsigned long new_taimer = millis();//текущее время работы скетча в мл.сек //----------------- прием по блютуз фраз и команд ----------------------------= if (Serial.available() !=0) /// если данные пришли по блютуз { Str_telf = Serial.readString();//читаем буфер порта display.clear(); new_fraza=0;Nx=0;//чистим табло// flag_tel=1; //опрокидываем флаг и запрещаем работу от вх. машины time_telf = new_taimer;///запоминаем время когда пришла новая фраза с телефона } if (flag_tel==1) //обрабатываем то, что пришло с телефона { String str = Str_telf; // создаем объект len= Str_telf.length() ;//считаем длину msg_tel = str.c_str(); //преобразовываем массив sscanf(msg_tel, "%d,", &adrees);///берем 5 символов //---------------------управление----------------------------------------------- if (adrees == 29284 && len>22&&len<26) //если пришла команда разгбераем её на части отделенные запятой { sscanf(msg_tel, "%d,%d,%d,%d,%d,%d,%d,%d,%d",//берем в десятичном значении &adrees, &skorost, &jarkost,&invers,&begut, &vremya, &coxpan, &reklam, &shipu );// переменные //--1-------2---------3--------4-------5-------6---------7-------8--------9--- № п/п //29284----70--------70-- -----0-------1-------15--------2-------1--------1--- значения(пример) //29284,70,70,0,1,15,2,1,1 // ПРИМЕР для записи EEPROM через порт//29284-прописан в программе телефона (меняется только в app.invertor2) //хоть разок вставляем ПРИМЕР в порт и отправляеем,дабы перезаписать мусор в ячейках памяти//разово делается//можно с телефона Skorost=map(skorost, 10, 99, 300, 30); //инвертирует диапазон , после новой команды. Jarkost=map(jarkost, 10, 99, 40, 255); //инвертирует диапазон , после новой команды time_sbros=(long)vremya*1000; /// переводим сек в мл.сек*/ display.setBrightness(Jarkost); //устанавливаем яркость if(coxpan==2) //если пришла команда записать//седьмая позиция в команде {// если значения новые, перезаписываем их. EEPROM.update(51, skorost);EEPROM.update(52, jarkost); EEPROM.update(53, reklam); EEPROM.update(54, vremya); EEPROM.update(55, begut); EEPROM.update(56, shipu); EEPROM.update(57, invers);//инверсия стопа }//51,52..56 от фонаря взял //лишь бы не первые// flag_tel=0; adrees = 0;//выходим из записи display.clear();//стираем фразу length = WIDTH;//делаем длину "64", для фраз от машины } // else //если это была не команда- печатаем текст, { if (!new_fraza && flag_len) //разово-только при новой фразе {printString(msg_tel,WIDTH,0);//помещаем фразу в буфер new_fraza=1; flag_len=0; //считаем длину фразы до старта анимации. display.clear();//стираем, ранний старт }// //БЕЖАТЬ, ИЛИ НЕ БЕЖАТЬ? ВОТ, В ЧЕМ ВОПРОС! if (length <= WIDTH && begut!=2) printString(msg_tel,0,0);//статика else printString(msg_tel,WIDTH-Nx,0);//бегущая строка } if (new_taimer - time_telf >= time_sbros && flag_tel && !Nx && reklam !=2)//если не вкл реклама {flag_tel=0; length = WIDTH ; display.clear();//стираем фразу телефона если время горения истекло rezt=0;//флаг готовности. для вкл знака треугольник(или шипы) }// если вкл режим "реклама" , то ниже по скетчу мы не опускаемся :)//тут остаемся т.к. флаг "flag_tel" не сбрасывается } //=====================машина=====================================================// else if (!flag_tel && !tormaz && !pravo && !levo&& !nazad && !avariik && PINC<2)//ничего не нажато и флаги сброшены { if (!Nx && !rezt) //по окончании старой фразы//даем фразе добежать {display.setBrightness(Jarkost);//устанавливаем яркость// display.clear(); rezt=1; // разочек стираем буфер invers_N=0;// готовим инверсии стоп } if (rezt && shipu !=2) printString(msg_avto[0],20,0); // пишем, знак /!/ else if (rezt && shipu ==2) printString(msg_avto[1],20,0); // пишем букву "Ш" (крупную). } //если флаги не сброшены то скетч пробегает до включенного флага //если что то нажато (PINC>=2), вначале проверяем тормоз, потом остальное // кострукция "else if" делает приоритет 1-тормоз.2-аварийка.3-назад.4,5- повороты.//блоки можно переставить //---------------------стоп ----------------------------------------------------- else if (!tormaz && digitalRead(trm)) //если нажат тормоз {tormaz=1,display.clear(); //очищаем дисплей printString(msg_avto[A],T,0); //пишем С Т О П или /!/ time_inver=new_taimer;//запоминаем время нажатия } else if (tormaz) { if (!invers) printString(msg_avto[3],4,0); // пишем сразу С Т О П, если нет инверсий else //пременная "invers_N" сбрасывается, когда загорится треугольник { //Т.е. если(например)горит поворот до СТОП и после, повторно СТОП не будет инвертироваться//не бужет раздражать лишний раз if (invers_N<=invers && new_taimer-time_inver > time_invers)//до заданного числа инверсий(с телефона выбираем) { tormaz=0; invers_N++; flag_ctop= !flag_ctop;//считаем нажатия//инверсия флага if (flag_ctop) A=0,T=20;// знак /!/ else A=3,T=4;//СТОП// } else if (invers_N > invers) {A=3;T=4;printString(msg_avto[A],T,0);} //пишем С Т О П } if (digitalRead(trm)==LOW) {tormaz=0;display.clear();A=3,T=4;flag_ctop=0;}//выходим стираем,если отпущен } //------------------аварийка----------------------------------------------------- else if (!avariik && digitalRead(prv)&& digitalRead(lev) ) //заработала аварийка { avariik=1; time_povrt = new_taimer; time_2znaka = new_taimer; display.clear();//запоминаем время } else if (avariik) //спасибо горит ХХ сек, даже если было однократное моргание //до time_sbros//меняется с телефона { if (digitalRead(prv) && digitalRead(lev)) time_povrt=new_taimer;//2поворота снова моргнули, перевзводим таймер if (new_taimer - time_2znaka >= time_spasibo)// стираем "спасибо" после хх сек "time_spasibo" { if (new_taimer - time_povrt >= time_povorot) avariik=0; //больше не моргает аварийка,выходим отсюда else { if (digitalRead(prv) && digitalRead(lev)) display.clear();//черное табло когда горят повороты ,а треугольники когда не горят else printString(msg_avto[2],2,0); //вкл /!/ /!/ моргают 2 знака если долго горит аварийка } } else printString(msg_avto[5],0,0);//печатаем "спасибо" в первые(time_spasibo) секунды вкл , аварийки } //-----------------назад------------------------------------------------------------------ else if (!nazad && digitalRead(nzd)) //если нажато НАЗАД { //такого эфекта нет в библиотеке//вот изгалялся как мог :)) static int8_t Nz=-16; static unsigned long pauz_nazd; if(!flag_nazd ) { pauz_nazd = new_taimer; flag_nazd=1; display.clear();Nz++;//наращиваем переменную позиции по вертикали printString(msg_avto[4],8,Nz);//8- это отступ от правого края//печатаем } else if (Nz >= 16) Nz= -16;//начинаем сначала if(new_taimer - pauz_nazd>= 100&& Nz!=0) flag_nazd=0;//прокручиваем вниз else if (new_taimer - pauz_nazd>= 1000) flag_nazd=0;// держим в статике в центре 1 сек(1000мс) } //--------------нажат поворот влево------------------------------------------------ else if (!levo && !avariik && !digitalRead(prv) && digitalRead(lev)) levo=1,length = WIDTH+44;// вкл поворот влево else if (levo) //сразу не приступаем к анимации, скетч пробегает снова сверху вниз - А не нажат ли тормоз? { if (!digitalRead(prv) && digitalRead(lev)) time_povrt = new_taimer;//пере взвод таймера//ждем следующего моргания поворота if (!digitalRead(lev) &&(new_taimer - time_povrt >= time_povorot)) levo=0; //выкл поворот лево//не дождались else printString("<<< <",WIDTH-Nx,0);//длина строки тут не пересчитывается, поэтому 44 вручную считал } //-------------нажат поворот вправо--------------------------------------------=-------- else if (!pravo && !avariik && digitalRead(prv) && !digitalRead(lev)) pravo=1,length = WIDTH+44;// вкл поворот вправо else if (pravo) //сразу не приступаем к анимации, скетч пробегает снова сверху вниз - А не нажат ли тормоз? { static int8_t Ny=-44; static unsigned long pauz_prv;//"-44" старт за пределами табло слева if (digitalRead(prv)) time_povrt = new_taimer;//перевзвод таймера//ждем следующего моргания поворота if (!digitalRead(prv)&&(new_taimer - time_povrt >= time_povorot)) pravo=0;//выкл поворот вправо//не дождались if (!flag_prv ) //пока флаг не сброшен продолжаем анимацию { pauz_prv = new_taimer; flag_prv=1; display.clear();//периодически стираем табло(а то накладки идут) Ny++;printString("> >>>",Ny,0);//длина строки тут не пересчитывается, поэтому 44 вручную считал } if (Ny >= 64) Ny= -44;//начинаем новый пробег вправо if(new_taimer - pauz_prv>= 20) flag_prv=0;//"20" величина от которой зависит скорость строки вправо } //---------------------------------------------------------------------------------------- if (rezt&&PINC>=2) rezt=0;// готовимся вкл знак /!/ если, что то нажималось } |