Главная страница
Навигация по странице:

  • else if (levo) //сразу не приступаем к анимации, скетч пробегает снова сверху вниз - А не нажат ли тормоз

  • else if (pravo) //сразу не приступаем к анимации, скетч пробегает снова сверху вниз - А не нажат ли тормоз

  • Проектирование поворотно-остановочного сигнала на Arduino. Курсовая МС. 1 Общая часть 5 1 Анализ существующих аналогичных устройств 6


    Скачать 3.94 Mb.
    Название1 Общая часть 5 1 Анализ существующих аналогичных устройств 6
    АнкорПроектирование поворотно-остановочного сигнала на Arduino
    Дата12.04.2023
    Размер3.94 Mb.
    Формат файлаdocx
    Имя файлаКурсовая МС.docx
    ТипРеферат
    #1056356
    страница4 из 4
    1   2   3   4

    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 // подключаем библиотеку EEPROM

    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;// готовимся вкл знак /!/ если, что то нажималось

    }





    1   2   3   4


    написать администратору сайта