mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 18:55:13 +03:00
some features added
This commit is contained in:
parent
7e9f81ca54
commit
29d62c26c7
144
F1-nolib/chronometer/Readme_rus.txt
Normal file
144
F1-nolib/chronometer/Readme_rus.txt
Normal file
@ -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 & <max
|
||||||
|
adcval - get ADC value
|
||||||
|
buzzerS - turn buzzer ON/OFF
|
||||||
|
distmin - min distance threshold (cm)
|
||||||
|
distmax - max distance threshold (cm)
|
||||||
|
gpsrestart - send Full Cold Restart to GPS
|
||||||
|
gpsstring - current GPS data string
|
||||||
|
ledsS - turn leds on/off (1/0)
|
||||||
|
mcutemp - MCU temperature
|
||||||
|
pullupNS - triggers pullups state (N - trigger No, S - 0/1 for off/on)
|
||||||
|
showconf - show current configuration
|
||||||
|
time - print time
|
||||||
|
store - store new configuration in flash
|
||||||
|
triglevelNS - working trigger N level S
|
||||||
|
trigpauseNP - pause (P, ms) after trigger N shots
|
||||||
|
trigtimeN - show last trigger N time
|
||||||
|
vdd - Vdd value
|
||||||
|
|
||||||
|
Из нужного здесь:
|
||||||
|
- gpsrestart - перезапуск GPS (если вдруг начнет глючить - у меня такого не случалось), делает "холодный" рестарт. Команда
|
||||||
|
проверялась лишь на прототипе.
|
||||||
|
- gpsstring - вывод очередного сообщения от GPS. Если все нормально, то появится строка RMC вроде
|
||||||
|
$GPRMC,124001.000,A,4340.9369,N,04127.5034,E,0.00,33.26,150819,,,A*5C
|
||||||
|
- pullupNS - включить или выключить внутренние верхние подтяжки для триггеров 0..3 (особо не нужно, т.к. подтяжки слабые, и если
|
||||||
|
будет нужна подтяжка, лучше сделать сильную внешнюю).
|
||||||
|
- showconf - отображение текущей конфигурации, например:
|
||||||
|
CONFIG:
|
||||||
|
DISTMIN=50
|
||||||
|
DISTMAX=1000
|
||||||
|
ADCMIN=1024
|
||||||
|
ADCMAX=3072
|
||||||
|
PULLUPS=255
|
||||||
|
TRIGLVL=0
|
||||||
|
TRIGPAUSE={400, 400, 400, 300, 300}
|
||||||
|
ENDCONFIG
|
||||||
|
|
||||||
|
пункты конфигурации: DISTMIN/DISTMAX относятся к лидару, ADCMIN/ADCMAX ко входу АЦП, PULLUPS - состояние подтяжек
|
||||||
|
(каждый бит, начиная с младшего - состояние соответствующей подтяжки; 0 - не активна, 1 - активна).
|
||||||
|
TRIGLVL - конфигурация уровней срабатывания, каждый бит, начиная с младшего (всего три младших бита, как и в PULLUPS),
|
||||||
|
равен нулю, если для соответствующего триггера срабатывание при перепаде 1->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).
|
||||||
|
|
||||||
@ -71,18 +71,23 @@ uint32_t getVdd(){
|
|||||||
return vdd;
|
return vdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void chkADCtrigger(){
|
/**
|
||||||
|
* @brief chkADCtrigger - check ADC trigger state
|
||||||
|
* @return value of `triggered`
|
||||||
|
*/
|
||||||
|
uint8_t chkADCtrigger(){
|
||||||
static uint8_t triggered = 0;
|
static uint8_t triggered = 0;
|
||||||
savetrigtime();
|
savetrigtime();
|
||||||
uint16_t val = getADCval(0);
|
int16_t val = getADCval(0);
|
||||||
if(triggered){ // check untriggered action
|
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;
|
triggered = 0;
|
||||||
}
|
}
|
||||||
}else{ // check if thigger shot
|
}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;
|
triggered = 1;
|
||||||
fillshotms(4);
|
fillshotms(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return triggered;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,10 +24,12 @@
|
|||||||
// interval of trigger's shot (>min && <max), maybe negative
|
// interval of trigger's shot (>min && <max), maybe negative
|
||||||
#define ADC_MIN_VAL (1024)
|
#define ADC_MIN_VAL (1024)
|
||||||
#define ADC_MAX_VAL (3072)
|
#define ADC_MAX_VAL (3072)
|
||||||
|
// 2*ADC_THRESHOLD = hysteresis width
|
||||||
|
#define ADC_THRESHOLD (50)
|
||||||
|
|
||||||
extern uint16_t ADC_array[];
|
extern uint16_t ADC_array[];
|
||||||
int32_t getMCUtemp();
|
int32_t getMCUtemp();
|
||||||
uint32_t getVdd();
|
uint32_t getVdd();
|
||||||
uint16_t getADCval(int nch);
|
uint16_t getADCval(int nch);
|
||||||
void chkADCtrigger();
|
uint8_t chkADCtrigger();
|
||||||
#endif // ADC_H
|
#endif // ADC_H
|
||||||
|
|||||||
Binary file not shown.
@ -24,6 +24,8 @@
|
|||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
|
#include "lidar.h"
|
||||||
|
#include "str.h"
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
#include "usart.h"
|
#include "usart.h"
|
||||||
|
|
||||||
@ -41,10 +43,10 @@ static uint8_t trigstate[DIGTRIG_AMOUNT];
|
|||||||
trigtime shottime[TRIGGERS_AMOUNT];
|
trigtime shottime[TRIGGERS_AMOUNT];
|
||||||
// Tms value when they shot
|
// Tms value when they shot
|
||||||
static uint32_t shotms[TRIGGERS_AMOUNT];
|
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
|
// if trigger[N] shots, the bit N will be 1
|
||||||
uint8_t trigger_shot = 0;
|
uint8_t trigger_shot = 0;
|
||||||
// time when Buzzer was turned ON
|
|
||||||
uint32_t BuzzerTime = 0;
|
|
||||||
|
|
||||||
static inline void gpio_setup(){
|
static inline void gpio_setup(){
|
||||||
BUZZER_OFF(); // turn off buzzer @start
|
BUZZER_OFF(); // turn off buzzer @start
|
||||||
@ -78,7 +80,9 @@ static inline void gpio_setup(){
|
|||||||
uint16_t pin = trigpin[i];
|
uint16_t pin = trigpin[i];
|
||||||
// fill trigstate array
|
// fill trigstate array
|
||||||
uint8_t trgs = (the_conf.trigstate & (1<<i)) ? 1 : 0;
|
uint8_t trgs = (the_conf.trigstate & (1<<i)) ? 1 : 0;
|
||||||
|
#ifdef EBUG
|
||||||
trigstate[i] = trgs;
|
trigstate[i] = trgs;
|
||||||
|
#endif
|
||||||
// turn on pullups
|
// turn on pullups
|
||||||
if(the_conf.trig_pullups & (1<<i)) trigport[i]->ODR |= pin;
|
if(the_conf.trig_pullups & (1<<i)) trigport[i]->ODR |= pin;
|
||||||
EXTI->IMR |= pin;
|
EXTI->IMR |= pin;
|
||||||
@ -147,17 +151,52 @@ void savetrigtime(){
|
|||||||
memcpy(&trgtm.Time, ¤t_time, sizeof(curtime));
|
memcpy(&trgtm.Time, ¤t_time, sizeof(curtime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief fillshotms - save trigger shot time
|
||||||
|
* @param i - trigger number
|
||||||
|
*/
|
||||||
void fillshotms(int i){
|
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]){
|
if(Tms - shotms[i] > (uint32_t)the_conf.trigpause[i]){
|
||||||
shotms[i] = Tms;
|
|
||||||
memcpy(&shottime[i], &trgtm, sizeof(trigtime));
|
memcpy(&shottime[i], &trgtm, sizeof(trigtime));
|
||||||
|
shotms[i] = Tms;
|
||||||
trigger_shot |= 1<<i;
|
trigger_shot |= 1<<i;
|
||||||
BuzzerTime = Tms;
|
|
||||||
BUZZER_ON();
|
BUZZER_ON();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief fillunshotms - calculate trigger length time
|
||||||
|
*/
|
||||||
|
void fillunshotms(){
|
||||||
|
if(!trigger_shot) return;
|
||||||
|
uint8_t X = 1;
|
||||||
|
for(int i = 0; i < TRIGGERS_AMOUNT; ++i, X<<=1){
|
||||||
|
// check whether trigger is OFF but shot recently
|
||||||
|
if(trigger_shot & X){
|
||||||
|
uint32_t len = Tms - shotms[i];
|
||||||
|
uint8_t rdy = 0;
|
||||||
|
if(len > 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]
|
void exti4_isr(){ // PA4 - trigger[2]
|
||||||
savetrigtime();
|
savetrigtime();
|
||||||
fillshotms(2);
|
fillshotms(2);
|
||||||
@ -176,6 +215,7 @@ void exti15_10_isr(){ // PA13 - trigger[0], PA14 - trigger[1]
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EBUG
|
||||||
/**
|
/**
|
||||||
* @brief gettrig - get trigger state
|
* @brief gettrig - get trigger state
|
||||||
* @return 1 if trigger active or 0
|
* @return 1 if trigger active or 0
|
||||||
@ -186,3 +226,18 @@ uint8_t gettrig(uint8_t N){
|
|||||||
if(curval == trigstate[N]) return 1;
|
if(curval == trigstate[N]) return 1;
|
||||||
else return 0;
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -39,6 +39,7 @@ extern uint8_t buzzer_on;
|
|||||||
#define BUZZER_pin (1<<13)
|
#define BUZZER_pin (1<<13)
|
||||||
#define BUZZER_ON() do{if(buzzer_on)pin_set(BUZZER_port, BUZZER_pin);}while(0)
|
#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_OFF() pin_clear(BUZZER_port, BUZZER_pin)
|
||||||
|
#define BUZZER_GET() (pin_read(BUZZER_port, BUZZER_pin))
|
||||||
|
|
||||||
// PPS pin - PA1
|
// PPS pin - PA1
|
||||||
#define PPS_port GPIOA
|
#define PPS_port GPIOA
|
||||||
@ -49,11 +50,18 @@ extern uint8_t buzzer_on;
|
|||||||
#define TRIGGERS_AMOUNT (5)
|
#define TRIGGERS_AMOUNT (5)
|
||||||
// number of LIDAR trigger
|
// number of LIDAR trigger
|
||||||
#define LIDAR_TRIGGER (3)
|
#define LIDAR_TRIGGER (3)
|
||||||
|
// number of ADC trigger
|
||||||
|
#define ADC_TRIGGER (4)
|
||||||
// amount of digital triggers (on interrupts)
|
// amount of digital triggers (on interrupts)
|
||||||
#define DIGTRIG_AMOUNT (3)
|
#define DIGTRIG_AMOUNT (3)
|
||||||
|
// max length of trigger event (ms)
|
||||||
|
#define MAX_TRIG_LEN (1000)
|
||||||
|
|
||||||
|
#ifdef EBUG
|
||||||
uint8_t gettrig(uint8_t N);
|
uint8_t gettrig(uint8_t N);
|
||||||
|
#endif
|
||||||
void fillshotms(int i);
|
void fillshotms(int i);
|
||||||
|
void fillunshotms();
|
||||||
void savetrigtime();
|
void savetrigtime();
|
||||||
#define GET_PPS() ((GPIOA->IDR & (1<<1)) ? 1 : 0)
|
#define GET_PPS() ((GPIOA->IDR & (1<<1)) ? 1 : 0)
|
||||||
|
|
||||||
@ -83,11 +91,12 @@ typedef struct{
|
|||||||
extern uint8_t LEDSon;
|
extern uint8_t LEDSon;
|
||||||
// time of triggers shot
|
// time of triggers shot
|
||||||
extern trigtime shottime[TRIGGERS_AMOUNT];
|
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
|
// if trigger[N] shots, the bit N will be 1
|
||||||
extern uint8_t trigger_shot;
|
extern uint8_t trigger_shot;
|
||||||
// time when Buzzer was turned ON
|
|
||||||
extern uint32_t BuzzerTime;
|
|
||||||
|
|
||||||
|
void chk_buzzer();
|
||||||
void hw_setup();
|
void hw_setup();
|
||||||
|
|
||||||
#endif // __HARDWARE_H__
|
#endif // __HARDWARE_H__
|
||||||
|
|||||||
@ -24,14 +24,20 @@ uint16_t last_lidar_dist = 0;
|
|||||||
uint16_t last_lidar_stren = 0;
|
uint16_t last_lidar_stren = 0;
|
||||||
uint16_t lidar_triggered_dist = 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;
|
static uint8_t triggered = 0;
|
||||||
|
if(!txt) return triggered;
|
||||||
last_lidar_dist = txt[2] | (txt[3] << 8);
|
last_lidar_dist = txt[2] | (txt[3] << 8);
|
||||||
last_lidar_stren = txt[4] | (txt[5] << 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
|
if(!lidar_triggered_dist){ // first run
|
||||||
lidar_triggered_dist = last_lidar_dist;
|
lidar_triggered_dist = last_lidar_dist;
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(triggered){ // check if body gone
|
if(triggered){ // check if body gone
|
||||||
@ -60,4 +66,5 @@ void parse_lidar_data(char *txt){
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return triggered;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,6 @@ extern uint16_t last_lidar_dist;
|
|||||||
extern uint16_t lidar_triggered_dist;
|
extern uint16_t lidar_triggered_dist;
|
||||||
extern uint16_t last_lidar_stren;
|
extern uint16_t last_lidar_stren;
|
||||||
|
|
||||||
void parse_lidar_data(char *txt);
|
uint8_t parse_lidar_data(char *txt);
|
||||||
|
|
||||||
#endif // LIDAR_H__
|
#endif // LIDAR_H__
|
||||||
|
|||||||
@ -158,23 +158,26 @@ char *parse_cmd(char *buf){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define USBBUF 63
|
||||||
// usb getline
|
// usb getline
|
||||||
static char *get_USB(){
|
static char *get_USB(){
|
||||||
static char tmpbuf[512], *curptr = tmpbuf;
|
static char tmpbuf[USBBUF+1], *curptr = tmpbuf;
|
||||||
static int rest = 511;
|
static int rest = USBBUF;
|
||||||
int x = USB_receive(curptr, rest);
|
int x = USB_receive(curptr, rest);
|
||||||
curptr[x] = 0;
|
|
||||||
if(!x) return NULL;
|
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'){
|
if(curptr[x-1] == '\n'){
|
||||||
curptr = tmpbuf;
|
curptr = tmpbuf;
|
||||||
rest = 511;
|
rest = USBBUF;
|
||||||
return tmpbuf;
|
return tmpbuf;
|
||||||
}
|
}
|
||||||
curptr += x; rest -= x;
|
curptr += x; rest -= x;
|
||||||
if(rest <= 0){ // buffer overflow
|
if(rest <= 0){ // buffer overflow
|
||||||
SEND("USB buffer overflow!\n");
|
//SEND("USB buffer overflow!\n");
|
||||||
curptr = tmpbuf;
|
curptr = tmpbuf;
|
||||||
rest = 511;
|
rest = USBBUF;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -215,7 +218,6 @@ void break_handler(){ // client disconnected
|
|||||||
|
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
extern int32_t ticksdiff, timecntr, timerval, Tms1;
|
extern int32_t ticksdiff, timecntr, timerval, Tms1;
|
||||||
extern uint32_t last_corr_time;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int main(void){
|
int main(void){
|
||||||
@ -245,10 +247,8 @@ int main(void){
|
|||||||
while (1){
|
while (1){
|
||||||
IWDG->KR = IWDG_REFRESH; // refresh watchdog
|
IWDG->KR = IWDG_REFRESH; // refresh watchdog
|
||||||
if(Timer > 499) LED_on(); // turn ON LED0 over 0.25s after PPS pulse
|
if(Timer > 499) LED_on(); // turn ON LED0 over 0.25s after PPS pulse
|
||||||
if(BuzzerTime && Tms - BuzzerTime > 249){
|
// check if triggers that was recently shot are off now
|
||||||
BUZZER_OFF();
|
fillunshotms();
|
||||||
BuzzerTime = 0;
|
|
||||||
}
|
|
||||||
if(lastT > Tms || Tms - lastT > 499){
|
if(lastT > Tms || Tms - lastT > 499){
|
||||||
if(need2startseq) GPS_send_start_seq();
|
if(need2startseq) GPS_send_start_seq();
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
@ -301,8 +301,7 @@ int main(void){
|
|||||||
}
|
}
|
||||||
#endif
|
#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;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
usb_proc();
|
usb_proc();
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
@ -312,7 +311,7 @@ int main(void){
|
|||||||
DBG("Received data over USB:");
|
DBG("Received data over USB:");
|
||||||
DBG(txt);
|
DBG(txt);
|
||||||
if(parse_USBCMD(txt))
|
if(parse_USBCMD(txt))
|
||||||
USB_send(txt); // echo back non-commands data
|
USB_send("Bad command!");
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
}
|
}
|
||||||
#if defined EBUG || defined USART1PROXY
|
#if defined EBUG || defined USART1PROXY
|
||||||
@ -352,7 +351,7 @@ int main(void){
|
|||||||
parse_lidar_data(txt);
|
parse_lidar_data(txt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chkADCtrigger();
|
chk_buzzer(); // should we turn off buzzer?
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -111,6 +111,7 @@ int parse_USBCMD(char *cmd){
|
|||||||
CMD_DISTMIN " - min distance threshold (cm)\n"
|
CMD_DISTMIN " - min distance threshold (cm)\n"
|
||||||
CMD_DISTMAX " - max distance threshold (cm)\n"
|
CMD_DISTMAX " - max distance threshold (cm)\n"
|
||||||
CMD_GPSRESTART " - send Full Cold Restart to GPS\n"
|
CMD_GPSRESTART " - send Full Cold Restart to GPS\n"
|
||||||
|
CMD_GPSSTAT " - get GPS status\n"
|
||||||
CMD_GPSSTR " - current GPS data string\n"
|
CMD_GPSSTR " - current GPS data string\n"
|
||||||
CMD_LEDS "S - turn leds on/off (1/0)\n"
|
CMD_LEDS "S - turn leds on/off (1/0)\n"
|
||||||
CMD_GETMCUTEMP " - MCU temperature\n"
|
CMD_GETMCUTEMP " - MCU temperature\n"
|
||||||
@ -125,6 +126,7 @@ int parse_USBCMD(char *cmd){
|
|||||||
);
|
);
|
||||||
}else if(CMP(cmd, CMD_PRINTTIME) == 0){
|
}else if(CMP(cmd, CMD_PRINTTIME) == 0){
|
||||||
USB_send(get_time(¤t_time, get_millis()));
|
USB_send(get_time(¤t_time, get_millis()));
|
||||||
|
USB_send("\n");
|
||||||
}else if(CMP(cmd, CMD_DISTMIN) == 0){ // set low limit
|
}else if(CMP(cmd, CMD_DISTMIN) == 0){ // set low limit
|
||||||
DBG("CMD_DISTMIN");
|
DBG("CMD_DISTMIN");
|
||||||
GETNUM(CMD_DISTMIN);
|
GETNUM(CMD_DISTMIN);
|
||||||
@ -258,14 +260,34 @@ int parse_USBCMD(char *cmd){
|
|||||||
if(Nt > 1) goto bad_number;
|
if(Nt > 1) goto bad_number;
|
||||||
USB_send("BUZZER=");
|
USB_send("BUZZER=");
|
||||||
if(Nt){
|
if(Nt){
|
||||||
BuzzerTime = 0;
|
|
||||||
buzzer_on = 1;
|
buzzer_on = 1;
|
||||||
USB_send("ON\n");
|
USB_send("ON\n");
|
||||||
}else{
|
}else{
|
||||||
BuzzerTime = 0;
|
|
||||||
buzzer_on = 0;
|
buzzer_on = 0;
|
||||||
USB_send("OFF\n");
|
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;
|
}else return 1;
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(succeed) USB_send("Success!\n");
|
if(succeed) USB_send("Success!\n");
|
||||||
@ -285,7 +307,7 @@ void show_trigger_shot(uint8_t tshot){
|
|||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(tshot & X) tshot &= ~X;
|
if(tshot & X) tshot &= ~X;
|
||||||
else continue;
|
else continue;
|
||||||
if(trigger_shot & X) trigger_shot &= ~X;
|
if(!triglen[i]) continue; // noice
|
||||||
if(i == LIDAR_TRIGGER){
|
if(i == LIDAR_TRIGGER){
|
||||||
USB_send("LIDAR, dist=");
|
USB_send("LIDAR, dist=");
|
||||||
sendu(lidar_triggered_dist);
|
sendu(lidar_triggered_dist);
|
||||||
@ -296,6 +318,9 @@ void show_trigger_shot(uint8_t tshot){
|
|||||||
}
|
}
|
||||||
USB_send("=");
|
USB_send("=");
|
||||||
USB_send(get_time(&shottime[i].Time, shottime[i].millis));
|
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");
|
USB_send("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,7 @@
|
|||||||
#define CMD_LEDS "leds"
|
#define CMD_LEDS "leds"
|
||||||
#define CMD_GPSRESTART "gpsrestart"
|
#define CMD_GPSRESTART "gpsrestart"
|
||||||
#define CMD_BUZZER "buzzer"
|
#define CMD_BUZZER "buzzer"
|
||||||
|
#define CMD_GPSSTAT "gpsstat"
|
||||||
|
|
||||||
extern uint8_t showGPSstr;
|
extern uint8_t showGPSstr;
|
||||||
|
|
||||||
|
|||||||
@ -79,6 +79,26 @@ static char *puttwo(uint8_t N, char *buf){
|
|||||||
return 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
|
* print time: Tm - time structure, T - milliseconds
|
||||||
*/
|
*/
|
||||||
@ -95,26 +115,18 @@ char *get_time(curtime *Tm, uint32_t T){
|
|||||||
S /= 10;
|
S /= 10;
|
||||||
}
|
}
|
||||||
// now bstart is buffer starting index; bptr points to decimal point
|
// now bstart is buffer starting index; bptr points to decimal point
|
||||||
*bptr++ = '.';
|
ms2str(&bptr, T);
|
||||||
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';
|
|
||||||
// put current time in HH:MM:SS format into buf
|
// put current time in HH:MM:SS format into buf
|
||||||
*bptr++ = ' '; *bptr++ = '(';
|
*bptr++ = ' '; *bptr++ = '(';
|
||||||
bptr = puttwo(Tm->H, bptr); *bptr++ = ':';
|
bptr = puttwo(Tm->H, bptr); *bptr++ = ':';
|
||||||
bptr = puttwo(Tm->M, 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){
|
if(GPS_status == GPS_NOTFOUND){
|
||||||
strcpy(bptr, " GPS not found");
|
strcpy(bptr, " GPS not found");
|
||||||
bptr += 14;
|
bptr += 14;
|
||||||
}
|
}
|
||||||
*bptr++ = '\n';
|
|
||||||
*bptr = 0;
|
*bptr = 0;
|
||||||
return bstart;
|
return bstart;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,6 +46,7 @@ typedef struct{
|
|||||||
extern volatile uint32_t Tms;
|
extern volatile uint32_t Tms;
|
||||||
extern volatile uint32_t Timer;
|
extern volatile uint32_t Timer;
|
||||||
extern curtime current_time;
|
extern curtime current_time;
|
||||||
|
extern uint32_t last_corr_time;
|
||||||
|
|
||||||
extern curtime trigger_time[];
|
extern curtime trigger_time[];
|
||||||
extern uint32_t trigger_ms[];
|
extern uint32_t trigger_ms[];
|
||||||
|
|||||||
@ -45,7 +45,7 @@
|
|||||||
#define usartrx(n) (linerdy[n])
|
#define usartrx(n) (linerdy[n])
|
||||||
#define usartovr(n) (bufovr[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 transmit_tbuf(int n);
|
||||||
void usarts_setup();
|
void usarts_setup();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user