Файл: 1 Общая часть 5 1 Анализ существующих аналогичных устройств 6.docx
Добавлен: 11.01.2024
Просмотров: 205
Скачиваний: 2
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
, как работает устройство, как его детали соединены друг с другом. Кроме того, схема электрическая принципиальная, является исходным заданием для конструктора.
Схема была разработана в онлайн сервисе EasyEDA и представлена на рисунке 2.30
EasyEDA - кросс-платформенная, веб-ориентированная среда автоматизации проектирования электроники включающая в себя редактор принципиальных схем, редактор топологии печатных плат, также средства заказа изготовления печатных плат
Рисунок 2.29 - Принципиальная схема
Программирование микроконтроллеров Arduino осуществляется на языке программирования C++. Этот язык является низкоуровневым, поэтому считается сложным и имеет высокий порог вхождения. Но для программирования Arduino используется упрощенная версия этого языка программирования. Так же для упрощения разработки прошивок существует множество функций, классов, методов и библиотек. Благодаря этому работать с этими микроконтроллерами очень удобно и легко.
Программный код для данного устройства представлен в приложении А.
В ходе данной курсовой работе я изучил основы работы с Arduino, также познал технологию создания программ на данной платформе.
Результатом курсового проекта является разработанный проект поворотно-остановочного сигнала на базе Arduino Nano. Также были разработаны структурные и принципиальные схемы и программа на языке Arduino.
Благодаря минимальному количеству элементов в устройстве, а также их дешевизны, и знаниям по микропроцессорным системам и базовых знаний в электротехнике, то данное устройство очень просто в реализации. Благодаря несложному, удобному и настраиваемому управлению всего устройства, пользователь может легко его использовать.
В течение выполнения курсового проекта был приобретен опыт работы и умение проектировать цифровые микропроцессорные устройства.
Приложение А. Листинг программы
#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;// готовимся вкл знак /!/ если, что то нажималось
}
Схема была разработана в онлайн сервисе EasyEDA и представлена на рисунке 2.30
EasyEDA - кросс-платформенная, веб-ориентированная среда автоматизации проектирования электроники включающая в себя редактор принципиальных схем, редактор топологии печатных плат, также средства заказа изготовления печатных плат
Рисунок 2.29 - Принципиальная схема
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;// готовимся вкл знак /!/ если, что то нажималось
}
1 2 3 4