From 29d62c26c782fe762029355418b79a749d29fb0e Mon Sep 17 00:00:00 2001 From: eddyem Date: Mon, 19 Aug 2019 16:26:36 +0300 Subject: [PATCH] some features added --- F1-nolib/chronometer/Readme_rus.txt | 144 ++++++++++++++++++++++++++++ F1-nolib/chronometer/adc.c | 13 ++- F1-nolib/chronometer/adc.h | 4 +- F1-nolib/chronometer/chrono.bin | Bin 13348 -> 13348 bytes F1-nolib/chronometer/hardware.c | 65 ++++++++++++- F1-nolib/chronometer/hardware.h | 13 ++- F1-nolib/chronometer/lidar.c | 13 ++- F1-nolib/chronometer/lidar.h | 2 +- F1-nolib/chronometer/main.c | 29 +++--- F1-nolib/chronometer/str.c | 31 +++++- F1-nolib/chronometer/str.h | 1 + F1-nolib/chronometer/time.c | 36 ++++--- F1-nolib/chronometer/time.h | 1 + F1-nolib/chronometer/usart.h | 2 +- 14 files changed, 307 insertions(+), 47 deletions(-) create mode 100644 F1-nolib/chronometer/Readme_rus.txt diff --git a/F1-nolib/chronometer/Readme_rus.txt b/F1-nolib/chronometer/Readme_rus.txt new file mode 100644 index 0000000..7feff2a --- /dev/null +++ b/F1-nolib/chronometer/Readme_rus.txt @@ -0,0 +1,144 @@ +****** Распиновка ****** + +=== Интерфейсы I/O === +- PA11/12 - USB +- PA9(Tx), PA10(Rx) - USART1 - прокси RMC-сообщений GPS. +- PA2(Tx), PA3(Rx) - USART2 - подключение GPS-приемника. +- PB10(Tx), PB11(Rx) - USART3 - подключение лидара. + +=== Остальные порты === +- PA1 - PPS сигнал от GPS; сюда можно подключать любой дополнительный высокоомный вход напрямую. +- PA4 - TRIG2 - подключен к каналу 12В. +- PA13 - TRIG0 - кнопка или створ, замыкающий контакты. +- PA14 - TRIG1 - так же, как и вход TRIG0. +- PA15 - подтяжка USB. +- PB0 - TRIG4 - триггер по АЦП. +- PB8, PB9 - индикаторные светодиоды. +- PC13 - пищалка. + +=== Светодиоды === +- LED0 (зеленый) - при отсутствии сигнала PPS просто горит, если PPS появляется - мигает (затухает на 0.25с на каждый сигнал). +- LED1 (красный) - индикатор GPS: не горит, если приемник не обнаружен, горит, если неуверенный прием времени (буква "V" во второй позиции RMC-сообщения), мигает при уверенном приеме (буква "A" во второй позиции). +Судя по эксперименту, даже через час после пропадания сигнала точность определения события - не хуже 1мс. Сам GPS-приемник выдает +PPS даже при отсутствии спутников - лишь бы он успел "подхватить" точное время и начать генерировать pps. Начинать работу можно сразу, +как только замигает зеленый светодиод после мигающего красного. + + +****** Триггеры ****** +На прототипе распаяно два входа на триггеры: TRIG0 и TRIG2. К TRIG2 нужно подключать 12-вольтный сигнал, ток не меньше 10мА. +Если створ имеет открытый коллектор, то выход створа подключается к минусу TRIG2, а к плюсу подключается 12В с источника питания. +TRIG0 предназначен для подключения кнопки или концевика, просто замыкающего контакты. Никакого внешнего напряжения там быть не должно! + +TRIG4 - аналоговый вход. Если будут ложные срабатывания на девбордах, порт PB0 нужно напрямую или через резистор до 10кОм посадить на землю. + +Иногда бывают ложные срабатывания триггеров TRIG0..TRIG2, связанные с мощными источниками искр (зажигание, искрящиеся обмотки и т.п.). +В случае таких ложных срабатываний рекомендуется заземлить катод источника питания хронометра. + +При подключении внешней кнопки желательно, чтобы она имела нормально замкнутые контакты - это предотвратит ложные срабатывания из-за электромагнитных помех. + + +****** Подключение ****** +Хронометр эмулирует "китайский" преобразователь PL2303. В линуксе нужно, чтобы был скомпилирован соответствующий модуль ядра. +В андроиде работает "из коробки". В мастдайке новые драйвера PL2303 имеют защиту от подделок (те просто не работают с этими дровами), +поэтому для нормальной работы необходимо найти и установить старые драйвера. + +К выходам PA9/PA10 можно подключить преобразователь USART<>USB или накинуть их напрямую на ноги Rx/Tx "малинки" (не забыв соединить +земли хронометра и малинки): PA9(Tx) соединить с Rx, PA10(Rx) - с Tx. Этот USART проксирует RMC-сообщения GPS-приемника (уже после +обработки микроконтроллером, поэтому если МК выключен, а приемник включен, сигнала все равно не будет). + +Для подключения PPS сигнала к "малинке" нужно напрямую соединить соответствующую ногу GPIO "малинки" с портом PA1 девборды. +На прототипе нужно подпаяться к дорожке, выходящей с ноги PPS (отмечено маркером). + +Подтяжка USB есть лишь на прототипе, на девбордах ее нет. Поэтому в случае перезагрузки микроконтроллера девборды для возобновления +соединения необходимо переткнуть шнурок USB. В этом плане прототип надежней: сбросить МК можно независимо от питания GPS. + +На прототипе и девбордах отсутствует подсоединение пищалки. На девбордах при желании можно накинуть на PC13 что-нибудь для индикации +срабатывания створа (активный выход - "1" в течение 0.3с). + +На девбордах не распаяны светодиодные индикаторы. Особого смысла в них нет, но если понадобится подключить, нагрузка должна висеть на +PB8/PB9. Активный выход - низкий. Нога МК настроена в режиме open-drain, но внешняя подтяжка не должна быть выше +3.5В. И потребление +не больше 5мА на ногу. + + +****** Конфигурация ****** +Хронометр конфигурируется через USB. Ввод команд не сопровождается эхом (чтобы удобней было работать из внешних программ), поэтому +для удобства можно тексты команд копировать из окна текстового редактора. +Чтобы увидеть подсказку, достаточно отправить любую строку, начинающуюся с вопросительного знака. Появится справка: + +adcmax - max ADC value treshold for trigger +adcmin - min -//- (triggered when ADval>min & 0, равен единице, если при + перепаде 0->1. + TRIGPAUSE - пауза между срабатываниями триггера: если после срабатывания произойдет следующее событие за интервал, меньший + данного, это событие учитываться не будет. +- time - отображает текущее время так, как оно бы отобразилось при срабатывании триггера, например, + 55725.961 (15:28:45) + ВРЕМЯ ИЗМЕРЯЕТСЯ В UTC!!! Первое число - количество секунд и миллисекунд с начала суток по UTC, в скобках + указывается человекочитаемое время. +- store - сохранить новую конфигурацию во флеш-памяти МК. +- triglevelNS - рабочий уровень триггера. Здесь N - номер триггера (0..2), S - уровень (0/1). Скажем, чтобы триггер 0 срабатывал + при перепаде 1->0, нужно написать команду + triglevel00 + а чтобы триггер 2 срабатывал при перепаде 0->1, + triglevel21 +- trigpauseNP - задать паузу для триггера N, пауза в миллисекундах. Если написать 0, паузы не будет и каждое срабатывание + будет вызывать соответствующее сообщение. Эта пауза нужнад для защиты от "звона" и нескольких срабатываний на "дырках" + в объекте. Меньше 50мс лучше не делать. +- trigtimeN - отображение последнего времени срабатывания триггера N, например, на запрос trigtime0, может быть выведено: + TRIG0=45212.930 (12:33:32) + Если срабатываний с момента включения не было, выведутся нули: + TRIG4=0.000 (00:00:00) + +После изменения конфигурации и ее сохранения необходимо нажатием на reset или отключением/включением питания перезагрузить МК, +т.к. некоторые параметры активируются лишь при старте. + + +****** Девборды и плата-прототип ****** +На платках из девборд два канала опторазвязок подключены к триггерам TRIG0 и TRIG1. +Синий провод - земля, красные - +12В для каждого канала. Т.е. схема рассчитана на срабатывание по появлению плюса на одном из каналов. + +В случае необходимости срабатывания по подтяжке к земле, нужно разорвать землю на входах опторазвязок и, наоборот, объединить плюсы. +На плюсы подать +12В, минусы подключить к сигнальным выходам створов. + +На прототипе распаяны развязки только на два канала: TRIG0 - для подключения чего-то, замыкающего контакты, и TRIG2 - для подключения +чего-то, выдающего 12В. Я оставил такую конфигурацию: к TRIG0 можно подключить нормально замкнутую кнопку (triglevel01), а TRIG2 +сработает при поступлении туда 12В (triglevel21). + diff --git a/F1-nolib/chronometer/adc.c b/F1-nolib/chronometer/adc.c index eadbd4f..80a98e2 100644 --- a/F1-nolib/chronometer/adc.c +++ b/F1-nolib/chronometer/adc.c @@ -71,18 +71,23 @@ uint32_t getVdd(){ return vdd; } -void chkADCtrigger(){ +/** + * @brief chkADCtrigger - check ADC trigger state + * @return value of `triggered` + */ +uint8_t chkADCtrigger(){ static uint8_t triggered = 0; savetrigtime(); - uint16_t val = getADCval(0); + int16_t val = getADCval(0); if(triggered){ // check untriggered action - if(val < the_conf.ADC_min || val > the_conf.ADC_max){ + if(val < (int16_t)the_conf.ADC_min - ADC_THRESHOLD || val > (int16_t)the_conf.ADC_max + ADC_THRESHOLD){ triggered = 0; } }else{ // check if thigger shot - if(val > the_conf.ADC_min && val < the_conf.ADC_max){ + if(val > (int16_t)the_conf.ADC_min + ADC_THRESHOLD && val < (int16_t)the_conf.ADC_max - ADC_THRESHOLD){ triggered = 1; fillshotms(4); } } + return triggered; } diff --git a/F1-nolib/chronometer/adc.h b/F1-nolib/chronometer/adc.h index 08d253b..f6dc45e 100644 --- a/F1-nolib/chronometer/adc.h +++ b/F1-nolib/chronometer/adc.h @@ -24,10 +24,12 @@ // interval of trigger's shot (>min && tHG64((G=Nnvwj~CLkN{Dvty0~F7Ta-ENCmgSYn%Am zWw*9frw}3EnYmMtG7E64k^jrQc{WlW0GtM_yXp9!+j0N@o&DS});Uk8tdlAx zmCxWNStq%)t{o<`$T;Gy@x}4w)bLqK=cGU0K1idq4!e5?AM8abs{%v~xBvOkL02u)vq;>As{$PZ@?n5sO(mXSO)qnCX?}%=7AOy7J{>x-n0ju5NX6_MuW`vibf{ zi%1M6c!>eMr5qHHfX545#D#81F2CJbYWWWz-QGPYJdLu4eWjMOet6OQu)v0i4Pqgw z10Re#U21vTZx>|o{eHZU67s_Mpt1vHf9?HI%Pz>{Kk<_`If9@K?LC+QsrpDW8t zQH-nE7+X!P*nMlgNOcDJX4zt@Z;U@9%XEJ*W*_mGWuUmQ8};0(ie%U%nY&rgcw36A z^)!9WQ%v7zDLBaOlc_GmSod-*GUbK6T)9ksVIOx+Q33@+)zHXGNNh-nO>oO9ohr`%h9ZOv^%H-jxMG4<@#%9$x6Z%z>;GB{OsNwC@mCl!k&DfaN?>ywx zq)`s?hK=c?ej|I;k9uy~HN5Q4y}iABiTse8G=p&Ro{Amq9q`KVGmo9y;aX%^-EY)Y zSI9(Jk=%lhOtwS=4N*p`XL0MwRJk;wU_0o!(J|pW&1-bhl6pp&^{#e6ZeMYT0)mVU? zl!zDQK@fOfG>{w3(&E-R)`=jdL3f(HxD~OCMdPH~g>F}>k^R75>ROchVjtz2nSH3w zK2rOTB249fI4n<`I=qYKy=hgihv{l5Q28sv{J3JWyTzYW!B~ia>E-6sm&5e3kCk|M z8;DCu9(iy3C;!v@4*Ky6akiLG^p06A`(3zoo#Rc%TicE_PA+KocSBuI0Z5^9XvC#A&=NanqO193LD8Hld@Tgi;M*esgdqMwFwEA&dAH^ z%t+{q5N^UvuI~)$*`LQNra0WS-rT>6cDV(m+XWnF9epz^w`z|4viO+?(5@MhPx(kh zdkVa72N9Do6eo}CqH_wpnPo`WCYk(w7ztY=D=kQ9j@&ECQWruWP6ytm$Slxlh`>68 z^l2Bd@EUL*j%a{e7s2!FLsnXzbH6*ZBSd?t`N{<-_ak5Tp!oDpB9M$qk~99vu*e$u z+CK?KOGIT=w_xFMFlUOy0q4$0kDpZF2-L|1IFW~xX8<0+2Y^F>0eEG{U_?e_sxu;` za8hpB(T?=)La)qK(gk_Xe!gmfgLV}eZuiRAXUn63lBmpr^z*$j?7nh6WOYaMR7VWE zN1D%%B0cAovrkFXTuF1T?}u*{Nl8n<@c@Dy?9cRw~(>M|bCL(Tzh>`wH-$cx>pIc)+Co0rWn0YT|s>|OO6-K3VfnyZ} z=YdRq>t6wK3gkOLZUs3d$^YiZ>@u*vz~S;E;gtx|ukz`E`o$gnA zT{PO*_U4v}$csidwqdPFihXd)s?K65_OCp;Aq=taHxF+*?0eO(WEV+hoKihp-dJ{_ zM04ZZyBoF`@3_(_%PATyYm;A#L*zwF4#OKCF}0b0P;bJmyt!!9UD!6elA0$U-bqz+ zyqWT1ZHhI4)I&Sn3S9YmM}p%Ce>!BU3NLUZ`sw0}oezLxMshSya%>Ww^%#CiBB2el z6qLNLGa9HKCzZueS@A0BAphw*6TF$nGtp$j5~urL}#!l}>^;G6`G0yy6Tr!DjvaE^se z1{o9$ygzmrsMmmEkvkfAckCq~|1ET63l{zpln;bn0Q$MmAkcpSdT;0;&`*UjEeGuL zPY-ff_yD-S4&nI$|3cXJ+d^Hb^5GryN|3w*lIDBlm-m)T>x{AtbkOz>NoIi!a8_J{b;-8bQAZ z^l``mlJQ_nc*fE%{bVi%$#EMK`rNNz*GR!@$5wVJ*!!e;${5m{y>aZya=n`zmr`Cx z81N|A6_P@{#4!mSp5s5|I(Xa;hI@l3cZCdG$ zKaN}J8=mUU8|eO`(ca_f)|Af9AgexLeh%)5@G_X9itO^`J2RY0hnu-Nv3Tdr#V7yQ z;Z!JAcmvi1h>d_{y2%-(+DrV;yawR*#2U8jnipP-f zU_{Gd25ts0U&A-2rrh}sT>gp96@UnpCieyM3koszk=tV6O8?Nawr8!$+^+V;0>;UX zRh;>UDVyU=H4Y88hxeswXVZH$oO#5PuW?WVbn8*GypL|h1vIbY4$z|)9=B<@eRSys zH=mqV>ZYHOgAOhrzp!YYI!AM@c=Q6&uC>*0NfuV1sTxNOXBH?J>Akn=%FY#Yw4kDu zh7q5@#IPuRwQW`T>dKcbYaH944G%e>p#qBW@c;@&17{)-xp{>R>Ykygg_A#AVZAJJ z=`Sz;2EJT^3hvtF%{DEFY+X&bD<_@_5!XH~fyEAIbn%Cn6b+J`t%G!j&XxjJC9QAnig9^Y7gq4fI6{Ik?(uH6>F; ztcufb_JSrVbo^0+3~*~Sny$a;K{|?W1P_~iUGOvsyFAyq;*Jal^#=HG3+|A*gW4Yr zEEyXQyh9FLoz9VNOX0e1gxrer41_BE2cU75bz1Fs;P*lD!_!u(I8Vk`hGS`>cl7*4 zppe1on`z5%q_`+Ut(P|J^un>!sD^bvCi$dSaw?RDTKv+_am3HRZH9X*?8p*07Dzvl zBZV9bq$DruPtn3n;Hbh)FB!U;O$X((lMvuJb{|NXh3gvv3t}W0G+(zm{2rXYf5t zE)@*&e`9849ti&hKD;qDy`_85Y0|(38#tW~t4Mm}ZXuIW=JU0k3R01le11rqIm-wd zcMvVW)|=WG{O{^PJ^K8vIqa{o=2#43R>P8GfI9$ZfUbaXE6snZn?LzS7O`4E^Hb9w zpSl~SyTKYMc`s=9#`A~MYvKs|CaK8y#Vur4eMUZ>ajTyRW5gH#c4j?gr1{L*k5l{e zyI!B&iK$ERd`*`19`(tw!0izPCt*!Ap@QyAC}&(9L5ATv@(T}|sV@=3IMv-9L6*tS zKWGkqLFiFGnP2}x;)2%SzQj5iqjQc0(j$yZ-91&sk7k)Q%Y);7^gaAr2dd@(9D;1f zI9>*ETUrmM&)+n`)ajH+C(_ z*^j#ha(Cl`hnzD@{Hg2q~uhW8*|732rf;3nW>Uzqk!TaW={||ery+i;2 delta 4821 zcmbtYdstIvn*Y9&3kgUGq8I||;e@z&iFYouh-}}9{?|L}mJmU1ArHEGKAr%IU=6)CGdw)cSfQSk0OaHF^_s4h0{;z+Q ze7t=-XPmZI(5^=+GTl2YscfP>p*Y{2SVj$=rt~h^pSOGZWoT+gWf)bd9lBcn zlxs2SzCj_n4k7v|fCXTH8_)tk8f>ZL(NpF)H7O5R()0mg%!9|KB& z-&h&e*rAI^-^^JFt7a8hLD$e#q@gS*3tLo( zvXleepNMD~_M%uU3GzhrM*vkP;)7A{kZevO$-W&R2Pn8}GJW!a-e@vwZ&Aa<(XPcLx8(p5JGWE$zK2BIac`T) zb;8T<_3m&lFg@S5)L~{aY;r+9a|ZKVZq4Quy=F$8dvNobK8OAAFs|xRQQw#q)ZljN zw(o;MD>gE8ws}@s{pHPT>JQdaZgpNmpQY@BVd|+rtMK4!io=5?RFBU*Yrer;plj%> zU)^8@ooD;zmVMy)yGj=u4m3>NvK^EheKUw5EEz(F2Q8AJTti-|xd6EjZmHgKc?&W= z5y+{C*PFbw%>@Oo%g&O*tWqn7Cnl3n2Ye*_mR_^rSZI-Z!J}{YQtl~vyL&6cDYfeq z!&JeigYroe2Y1T02d0!y)x0k}|tBd#LpKjS{rO)z;C z0yXouA=G^WYWVrtvuFF|h&}`D>AMD>`WUDa3cV$ddspR~NXi@rka-h;jv%f^?ZYZA zG5!s#^8ai6Novj+49jX2vLK*x(q@sR5$FWaR{{M9%$)`V0A~R^0df=fdSZ=|bem27 zTZwsiGHIUyRI8B+PC}ZPYvc?`#o%py(sS_pdD4O>h!%Ee-DE!#4Na$fn(`8D!~DQ- zSHH%B_4uW^y(S>scDe|4OLbVM7L-Wgq%5*RbS@@R2vG z5`J4I4J0J#OV0?XDL3%n#q-_I_!z5fAR!^6JH@iVCCfJi5I<+c2!?kJBYxJ%QXArD zjI0#o8D?87k_@t(5&T$6DdP1bbx4ta!zT-<=A8TnB?W_B{ldTC$Lc(iSOD>vP&_Cm zjl?^&jhJ5zgViG{kSIsag_)_RK&kzEfe_(TKR5>p;S#=3xl zIWBP}pvs;+R$+1@lZD^qoy*cTSv%j=KNTOt{I7@QHtol_*?-SlwC-FBgy|nfS>qZg z>!-jUAEs^K97Z%dnoHB1vB;Yu;#(d_)y#Xuk0+8W#Z(zkGW#UQY6xR_@c35qf=fQR zDcC!()jYq)hx5+%;>_d4L{-<930G3_y?YADUrvjLH#i4US-por5 z9Xt8zc&N1yDl)bP$AdlA^Rm51P-=Et-wj}TbD8H8L1|XG=CVJ6n5!U%J)s6rpg`eu zP*`8~i9kvHe+yyehhTm#`*H~J&yOHubk2z0n+GbvO!zX{V zXvoo~_$D5aDHsxw(GxCiv)<9v<7UoUH1v2|Nd+}qF}Rbea&lIvN9KHcGO0&qp&g`( zjchWzJ7k4K|0>R9wV{OKOFqw9aQuYiXo=+5!vEZBdXUAWHq1~^@?KvovT2NzmWI*} z-!fGcfSHrxd4WQhSHsM9iZemt1BntO2qYhgCXgHxJEJs;MdHSCfjbNw0~{L52Ci8= z>e&W+HH!FmMLh^Ou^;&Bz`rfh!0#5bZPP2!j3dy_x5PCAhm57L;2X<~9@vGPBv=W1beE*CTjEy)^S7EGzwN{MMMG7;@_++{ zi1HEtM=x3DuaxRsh#!d(mkr>u@YXia2uJG-m~Ru?hwt5045uixa5OE1Q2V3m{C(Z^ zr468SJxUI&Ss=X}b(MM$e^D~B7K|j{!u*d!g>56K{UwU>9hc&BI)@`eW*CqL13rsB z2R)xevmv+D5|<5}BM{F#BXQHE#1Q|QSIImr zNm4zM=%rxmgIq7SR)OIraQ`f<;HCDZj^ff}R|bpt*QG$`L7-hX%S)e!Q~j0buR=$q z1F1eris}jfz7;pi?s=y9RR}^7O)4}WG9fFf+k># z7I}Z?da9)B`$S!2NO_@C7$DZ9RUIdn3(cUMuF=a&5E? zy=T$KBF~5>Xyw{0jEs&&mWxl5-=eY{q&pgC9 zc_Vyr--!_@c5qRIT#Jd8(79-l*!TCi1xmn2!{MG-9^n5Dri&Nyq)6Vrx{b6$LD6HR+ zOedxh{|vNW=BlTqKi&<4iOyA`2W2G>67unY=*sZ)IQW$K!6C;Xdzy1c`;$DzX>7IA zdMD|{cuNhda~|M2re)^fCY{q7_7><^>MCwNZdLT+W?YClz4L%<==>WFo%0=8$@xYu zI<3Tm_bEUJ7y9AJi#e)C=4{48=TYVhjvA-d#_%$#hOKd0c?u}r`>?LOr`RduC&*N$ zaFD0t7?icnv9@eo#bMiO_BBC|-e+}eETSA6iws3$kxxe;a_brg)Y_n{Mf`=~74|E_ z{;a*rHe3<*brkd7hGlEvXpcP&kEX`gR#rY;zT)cBj&!%9VkW zi)jPw;USTN!rc{R@XL#Khk@0)k9goV+jwRqU1?VR#!Rjr2xyFSV}f|mzw9X zs3{hy6p*nfXkbYhio*5a1Vi4FL>U~3Md1x?C=(r|=-_g60P(*N4J;{BQFv_|l&IE5 z<|7s*iZyMBLCw15Xg}h!gsRY3q$`#iBF+-*XzzTMI4laOpRWB4y{f5thCwyu7cMduoeO#Izh*jc0oh%c_j_yYB{ocj;s ztCYp;x99pWwLg&?%d=OhI!7ZZqX5BjW diff --git a/F1-nolib/chronometer/hardware.c b/F1-nolib/chronometer/hardware.c index 0fd3bf9..3bc94a3 100644 --- a/F1-nolib/chronometer/hardware.c +++ b/F1-nolib/chronometer/hardware.c @@ -24,6 +24,8 @@ #include "adc.h" #include "hardware.h" #include "flash.h" +#include "lidar.h" +#include "str.h" #include "time.h" #include "usart.h" @@ -41,10 +43,10 @@ static uint8_t trigstate[DIGTRIG_AMOUNT]; trigtime shottime[TRIGGERS_AMOUNT]; // Tms value when they shot static uint32_t shotms[TRIGGERS_AMOUNT]; +// trigger length (-1 if > MAX_TRIG_LEN) +int16_t triglen[TRIGGERS_AMOUNT]; // if trigger[N] shots, the bit N will be 1 uint8_t trigger_shot = 0; -// time when Buzzer was turned ON -uint32_t BuzzerTime = 0; static inline void gpio_setup(){ BUZZER_OFF(); // turn off buzzer @start @@ -78,7 +80,9 @@ static inline void gpio_setup(){ uint16_t pin = trigpin[i]; // fill trigstate array uint8_t trgs = (the_conf.trigstate & (1<ODR |= pin; EXTI->IMR |= pin; @@ -147,17 +151,52 @@ void savetrigtime(){ memcpy(&trgtm.Time, ¤t_time, sizeof(curtime)); } +/** + * @brief fillshotms - save trigger shot time + * @param i - trigger number + */ void fillshotms(int i){ - if(i < 0 || i > TRIGGERS_AMOUNT) return; + if(i < 0 || i >= TRIGGERS_AMOUNT) return; if(Tms - shotms[i] > (uint32_t)the_conf.trigpause[i]){ - shotms[i] = Tms; memcpy(&shottime[i], &trgtm, sizeof(trigtime)); + shotms[i] = Tms; trigger_shot |= 1< MAX_TRIG_LEN){ + triglen[i] = -1; + rdy = 1; + }else triglen[i] = (uint16_t) len; + if(i == LIDAR_TRIGGER){ + if(!parse_lidar_data(NULL)) rdy = 1; + }else if(i == ADC_TRIGGER){ + if(!chkADCtrigger()) rdy = 1; + }else{ + uint8_t pinval = (trigport[i]->IDR & trigpin[i]) ? 1 : 0; + if(pinval != trigstate[i]) rdy = 1; // trigger is OFF + } + if(rdy){ + shotms[i] = Tms; + show_trigger_shot(X); + trigger_shot &= ~X; + } + } + } +} + void exti4_isr(){ // PA4 - trigger[2] savetrigtime(); fillshotms(2); @@ -176,6 +215,7 @@ void exti15_10_isr(){ // PA13 - trigger[0], PA14 - trigger[1] } } +#ifdef EBUG /** * @brief gettrig - get trigger state * @return 1 if trigger active or 0 @@ -186,3 +226,18 @@ uint8_t gettrig(uint8_t N){ if(curval == trigstate[N]) return 1; else return 0; } +#endif + +void chk_buzzer(){ + if(!trigger_shot && BUZZER_GET()){ // should we turn off buzzer? + uint8_t notrg = 1; + for(int i = 0; i < DIGTRIG_AMOUNT; ++i){ + uint8_t curval = (trigport[i]->IDR & trigpin[i]) ? 1 : 0; + if(curval == trigstate[i]){ + notrg = 0; + break; + } + } + if(notrg) BUZZER_OFF(); // turn off buzzer when there's no trigger events + } +} diff --git a/F1-nolib/chronometer/hardware.h b/F1-nolib/chronometer/hardware.h index fd5bad8..a54c01e 100644 --- a/F1-nolib/chronometer/hardware.h +++ b/F1-nolib/chronometer/hardware.h @@ -39,6 +39,7 @@ extern uint8_t buzzer_on; #define BUZZER_pin (1<<13) #define BUZZER_ON() do{if(buzzer_on)pin_set(BUZZER_port, BUZZER_pin);}while(0) #define BUZZER_OFF() pin_clear(BUZZER_port, BUZZER_pin) +#define BUZZER_GET() (pin_read(BUZZER_port, BUZZER_pin)) // PPS pin - PA1 #define PPS_port GPIOA @@ -49,11 +50,18 @@ extern uint8_t buzzer_on; #define TRIGGERS_AMOUNT (5) // number of LIDAR trigger #define LIDAR_TRIGGER (3) +// number of ADC trigger +#define ADC_TRIGGER (4) // amount of digital triggers (on interrupts) #define DIGTRIG_AMOUNT (3) +// max length of trigger event (ms) +#define MAX_TRIG_LEN (1000) +#ifdef EBUG uint8_t gettrig(uint8_t N); +#endif void fillshotms(int i); +void fillunshotms(); void savetrigtime(); #define GET_PPS() ((GPIOA->IDR & (1<<1)) ? 1 : 0) @@ -83,11 +91,12 @@ typedef struct{ extern uint8_t LEDSon; // time of triggers shot extern trigtime shottime[TRIGGERS_AMOUNT]; +// length (in ms) of trigger event (-1 if > MAX_TRIG_LEN +extern int16_t triglen[TRIGGERS_AMOUNT]; // if trigger[N] shots, the bit N will be 1 extern uint8_t trigger_shot; -// time when Buzzer was turned ON -extern uint32_t BuzzerTime; +void chk_buzzer(); void hw_setup(); #endif // __HARDWARE_H__ diff --git a/F1-nolib/chronometer/lidar.c b/F1-nolib/chronometer/lidar.c index 45b3fc0..156890d 100644 --- a/F1-nolib/chronometer/lidar.c +++ b/F1-nolib/chronometer/lidar.c @@ -24,14 +24,20 @@ uint16_t last_lidar_dist = 0; uint16_t last_lidar_stren = 0; uint16_t lidar_triggered_dist = 0; -void parse_lidar_data(char *txt){ +/** + * @brief parse_lidar_data - parsing of string from lidar + * @param txt - the string or NULL (if you want just check trigger state) + * @return trigger state + */ +uint8_t parse_lidar_data(char *txt){ static uint8_t triggered = 0; + if(!txt) return triggered; last_lidar_dist = txt[2] | (txt[3] << 8); last_lidar_stren = txt[4] | (txt[5] << 8); - if(last_lidar_stren < LIDAR_LOWER_STREN) return; // weak signal + if(last_lidar_stren < LIDAR_LOWER_STREN) return 0; // weak signal if(!lidar_triggered_dist){ // first run lidar_triggered_dist = last_lidar_dist; - return; + return 0; } IWDG->KR = IWDG_REFRESH; if(triggered){ // check if body gone @@ -60,4 +66,5 @@ void parse_lidar_data(char *txt){ #endif } } + return triggered; } diff --git a/F1-nolib/chronometer/lidar.h b/F1-nolib/chronometer/lidar.h index ad90268..903feee 100644 --- a/F1-nolib/chronometer/lidar.h +++ b/F1-nolib/chronometer/lidar.h @@ -34,6 +34,6 @@ extern uint16_t last_lidar_dist; extern uint16_t lidar_triggered_dist; extern uint16_t last_lidar_stren; -void parse_lidar_data(char *txt); +uint8_t parse_lidar_data(char *txt); #endif // LIDAR_H__ diff --git a/F1-nolib/chronometer/main.c b/F1-nolib/chronometer/main.c index 6889944..f060690 100644 --- a/F1-nolib/chronometer/main.c +++ b/F1-nolib/chronometer/main.c @@ -158,23 +158,26 @@ char *parse_cmd(char *buf){ } #endif +#define USBBUF 63 // usb getline static char *get_USB(){ - static char tmpbuf[512], *curptr = tmpbuf; - static int rest = 511; + static char tmpbuf[USBBUF+1], *curptr = tmpbuf; + static int rest = USBBUF; int x = USB_receive(curptr, rest); - curptr[x] = 0; if(!x) return NULL; + curptr[x] = 0; + USB_send(curptr); // echo +//if(x == 1 && *curptr < 32){USB_send("\n"); USB_send(u2str(*curptr)); USB_send("\n");} if(curptr[x-1] == '\n'){ curptr = tmpbuf; - rest = 511; + rest = USBBUF; return tmpbuf; } curptr += x; rest -= x; if(rest <= 0){ // buffer overflow - SEND("USB buffer overflow!\n"); + //SEND("USB buffer overflow!\n"); curptr = tmpbuf; - rest = 511; + rest = USBBUF; } return NULL; } @@ -215,7 +218,6 @@ void break_handler(){ // client disconnected #ifdef EBUG extern int32_t ticksdiff, timecntr, timerval, Tms1; -extern uint32_t last_corr_time; #endif int main(void){ @@ -245,10 +247,8 @@ int main(void){ while (1){ IWDG->KR = IWDG_REFRESH; // refresh watchdog if(Timer > 499) LED_on(); // turn ON LED0 over 0.25s after PPS pulse - if(BuzzerTime && Tms - BuzzerTime > 249){ - BUZZER_OFF(); - BuzzerTime = 0; - } + // check if triggers that was recently shot are off now + fillunshotms(); if(lastT > Tms || Tms - lastT > 499){ if(need2startseq) GPS_send_start_seq(); IWDG->KR = IWDG_REFRESH; @@ -301,8 +301,7 @@ int main(void){ } #endif } - IWDG->KR = IWDG_REFRESH; - if(trigger_shot) show_trigger_shot(trigger_shot); + //if(trigger_shot) show_trigger_shot(trigger_shot); IWDG->KR = IWDG_REFRESH; usb_proc(); IWDG->KR = IWDG_REFRESH; @@ -312,7 +311,7 @@ int main(void){ DBG("Received data over USB:"); DBG(txt); if(parse_USBCMD(txt)) - USB_send(txt); // echo back non-commands data + USB_send("Bad command!"); IWDG->KR = IWDG_REFRESH; } #if defined EBUG || defined USART1PROXY @@ -352,7 +351,7 @@ int main(void){ parse_lidar_data(txt); } } - chkADCtrigger(); + chk_buzzer(); // should we turn off buzzer? } return 0; } diff --git a/F1-nolib/chronometer/str.c b/F1-nolib/chronometer/str.c index 8f6929e..462dc86 100644 --- a/F1-nolib/chronometer/str.c +++ b/F1-nolib/chronometer/str.c @@ -111,6 +111,7 @@ int parse_USBCMD(char *cmd){ CMD_DISTMIN " - min distance threshold (cm)\n" CMD_DISTMAX " - max distance threshold (cm)\n" CMD_GPSRESTART " - send Full Cold Restart to GPS\n" + CMD_GPSSTAT " - get GPS status\n" CMD_GPSSTR " - current GPS data string\n" CMD_LEDS "S - turn leds on/off (1/0)\n" CMD_GETMCUTEMP " - MCU temperature\n" @@ -125,6 +126,7 @@ int parse_USBCMD(char *cmd){ ); }else if(CMP(cmd, CMD_PRINTTIME) == 0){ USB_send(get_time(¤t_time, get_millis())); + USB_send("\n"); }else if(CMP(cmd, CMD_DISTMIN) == 0){ // set low limit DBG("CMD_DISTMIN"); GETNUM(CMD_DISTMIN); @@ -258,14 +260,34 @@ int parse_USBCMD(char *cmd){ if(Nt > 1) goto bad_number; USB_send("BUZZER="); if(Nt){ - BuzzerTime = 0; buzzer_on = 1; USB_send("ON\n"); }else{ - BuzzerTime = 0; buzzer_on = 0; USB_send("OFF\n"); } + }else if(CMP(cmd, CMD_GPSSTAT) == 0){ + USB_send("GPS status: "); + const char *str = "unknown"; + switch(GPS_status){ + case GPS_NOTFOUND: + str = "not found"; + break; + case GPS_WAIT: + str = "waiting"; + break; + case GPS_NOT_VALID: + str = "no satellites"; + break; + case GPS_VALID: + str = "valid time"; + break; + } + USB_send(str); + if(Tms - last_corr_time < 1500) + USB_send(", PPS working\n"); + else + USB_send(", no PPS\n"); }else return 1; IWDG->KR = IWDG_REFRESH; if(succeed) USB_send("Success!\n"); @@ -285,7 +307,7 @@ void show_trigger_shot(uint8_t tshot){ IWDG->KR = IWDG_REFRESH; if(tshot & X) tshot &= ~X; else continue; - if(trigger_shot & X) trigger_shot &= ~X; + if(!triglen[i]) continue; // noice if(i == LIDAR_TRIGGER){ USB_send("LIDAR, dist="); sendu(lidar_triggered_dist); @@ -296,6 +318,9 @@ void show_trigger_shot(uint8_t tshot){ } USB_send("="); USB_send(get_time(&shottime[i].Time, shottime[i].millis)); + USB_send(", len="); + if(triglen[i] < 0) USB_send(">1s"); + else sendu((uint32_t) triglen[i]); USB_send("\n"); } } diff --git a/F1-nolib/chronometer/str.h b/F1-nolib/chronometer/str.h index 399c415..c3d7f48 100644 --- a/F1-nolib/chronometer/str.h +++ b/F1-nolib/chronometer/str.h @@ -42,6 +42,7 @@ #define CMD_LEDS "leds" #define CMD_GPSRESTART "gpsrestart" #define CMD_BUZZER "buzzer" +#define CMD_GPSSTAT "gpsstat" extern uint8_t showGPSstr; diff --git a/F1-nolib/chronometer/time.c b/F1-nolib/chronometer/time.c index d36c9b7..7a562f6 100644 --- a/F1-nolib/chronometer/time.c +++ b/F1-nolib/chronometer/time.c @@ -79,6 +79,26 @@ static char *puttwo(uint8_t N, char *buf){ return buf; } +/** + * @brief ms2str - fill buffer str with milliseconds ms + * @param str (io) - pointer to buffer + * @param T - milliseconds + */ +static void ms2str(char **str, uint32_t T){ + char *bptr = *str; + *bptr++ = '.'; + if(T > 99){ + *bptr++ = T/100 + '0'; + T %= 100; + }else *bptr++ = '0'; + if(T > 9){ + *bptr++ = T/10 + '0'; + T %= 10; + }else *bptr++ = '0'; + *bptr++ = T + '0'; + *str = bptr; +} + /** * print time: Tm - time structure, T - milliseconds */ @@ -95,26 +115,18 @@ char *get_time(curtime *Tm, uint32_t T){ S /= 10; } // now bstart is buffer starting index; bptr points to decimal point - *bptr++ = '.'; - if(T > 99){ - *bptr++ = T/100 + '0'; - T %= 100; - }else *bptr++ = '0'; - if(T > 9){ - *bptr++ = T/10 + '0'; - T %= 10; - }else *bptr++ = '0'; - *bptr++ = T + '0'; + ms2str(&bptr, T); // put current time in HH:MM:SS format into buf *bptr++ = ' '; *bptr++ = '('; bptr = puttwo(Tm->H, bptr); *bptr++ = ':'; bptr = puttwo(Tm->M, bptr); *bptr++ = ':'; - bptr = puttwo(Tm->S, bptr); *bptr++ = ')'; + bptr = puttwo(Tm->S, bptr); + ms2str(&bptr, T); + *bptr++ = ')'; if(GPS_status == GPS_NOTFOUND){ strcpy(bptr, " GPS not found"); bptr += 14; } - *bptr++ = '\n'; *bptr = 0; return bstart; } diff --git a/F1-nolib/chronometer/time.h b/F1-nolib/chronometer/time.h index 569524d..c76f081 100644 --- a/F1-nolib/chronometer/time.h +++ b/F1-nolib/chronometer/time.h @@ -46,6 +46,7 @@ typedef struct{ extern volatile uint32_t Tms; extern volatile uint32_t Timer; extern curtime current_time; +extern uint32_t last_corr_time; extern curtime trigger_time[]; extern uint32_t trigger_ms[]; diff --git a/F1-nolib/chronometer/usart.h b/F1-nolib/chronometer/usart.h index 4ddcf80..638e5dd 100644 --- a/F1-nolib/chronometer/usart.h +++ b/F1-nolib/chronometer/usart.h @@ -45,7 +45,7 @@ #define usartrx(n) (linerdy[n]) #define usartovr(n) (bufovr[n]) -extern volatile int linerdy[4], bufovr[4], txrdy[4]; +extern volatile int linerdy[], bufovr[], txrdy[]; void transmit_tbuf(int n); void usarts_setup();