Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified 3d_model/Latency_IPCam.SLDASM
Binary file not shown.
Binary file modified 3d_model/Latency_IPCam.SLDPRT
Binary file not shown.
Binary file added 3d_model/Latency_IPCam_detail2.SLDPRT
Binary file not shown.
Binary file added 3d_model/Latency_IPCam_detail3.SLDPRT
Binary file not shown.
Binary file modified 3d_model/STL/Latency_IPCam.STL
Binary file not shown.
Binary file modified 3d_model/STL/Latency_IPCam2.STL
Binary file not shown.
Binary file added 3d_model/STL/Latency_IPCam_detail2.STL
Binary file not shown.
Binary file added 3d_model/STL/Latency_IPCam_detail3.STL
Binary file not shown.
674 changes: 674 additions & 0 deletions LICENSE.md

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Latency Meter Camera
# Latency Meter FPV-systems & Camera

Устройство для измерения раздержки различных камер и FPV-систем. Оно построено на плате Ардуино Нано и 4х разрядном 7ми-сегментном индиаторе LED 5461AS-1.

**Кнопка:** Длинное нажатие на кнопку запускает процесс измерения сначала. Короткое - переключает показания индикатора между real-time, min, max, sma.
Версия 2.0 отличается от предыдущих тем, что вспышки происходят регулярно без ожидания. Так же происходи автозапуск измерений при получении сигнала на фотодатчике.

Видео по сборке: [https://www.youtube.com/watch?v=69uGeqPZ3CI](https://www.youtube.com/watch?v=69uGeqPZ3CI)
**Кнопка:** Длинное нажатие на кнопку запускает процесс измерения сначала. Короткое - переключает показания индикатора между real-time, min, max, median.

Ютуб-видео: [https://www.youtube.com/watch?v=aBIbjmPU78k](https://www.youtube.com/watch?v=aBIbjmPU78k)

![1701351332899](images/README/1701351332899.png)![1701351013962](images/README/1701351013962.png)
93 changes: 0 additions & 93 deletions SCH_Latencycam_2023-11-22.json

This file was deleted.

Binary file removed Schematic_Latencycam_2023-11-22.pdf
Binary file not shown.
2 changes: 1 addition & 1 deletion latencymeter/button.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class Button
_flagEvent = false;
return;
}
if (time >= 30 && !_flagEvent) // Одинарно нажатие
if (time >= 50 && !_flagEvent) // Одинарно нажатие
{
onKeyUp();
onClick();
Expand Down
171 changes: 128 additions & 43 deletions latencymeter/latencymeter.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
#define PIN_IN 7
#define PIN_OUT 3
#define PIN_IN 7 // фотодатчик
#define PIN_OUT 2 // светодиод 1
#define PIN_OUT2 3 // светодиод 2
#define INTERVAL 500 // интервал переключения светодиода, мкс
#define VREF 3.33f

#include "include/AbstractEventHandler.h"

class LatencyMeter
{
uint32_t _timer = 0; // Переменная таймера
bool _flagMeasuring = false; // когда true, то идет процесс измерения
bool _flagStatus = false; // Управляет запуском/остановкой процесса измерения
List<uint16_t> _listValue; // массив измерений
uint32_t _timer = 0, _timer2 = 0, _timer3 = 0; // Переменная таймера
bool _flagMeasuring = false; // когда true, то идет процесс измерения
bool _flagStatus = false; // Управляет запуском/остановкой процесса измерения
List<uint16_t> _listValue; // массив измерений
byte _pinOut = PIN_OUT, // красный
_pinOut2 = PIN_OUT2; // синий
bool _sw = 0; // флаг переключения светодиода
uint32_t _interval = INTERVAL; // интервал переключения светодиода
float _spread = 0; // разброс измерений

public:
float startVoltage = 0;
float lowVoltage = 0;
float highVoltage = VREF;
uint16_t medianTime = 0; // Медиана значений
uint16_t minTime = 0;
uint16_t maxTime = 0;
Expand All @@ -24,30 +33,59 @@ class LatencyMeter
LatencyMeter()
{
analogReference(EXTERNAL); // внешнее опорное напряжение 3.3В
pinMode(PIN_OUT, OUTPUT);
pinMode(_pinOut, OUTPUT);
pinMode(_pinOut2, OUTPUT);
}

void Start()
{
Serial.println("Start");
startVoltage = 0;
lowVoltage = VREF;
highVoltage = 0;
medianTime = 0;
minTime = 0;
maxTime = 0;
valueTime = 0;
count = 0;
_flagMeasuring = false;
_listValue.clear();

// Проверка, какой из цветов дает высокий, а какой - низкий уровни
ledSwitch(!_sw);
delay(2000);

ledSwitch(_sw);
delay(500);
highVoltage = getVoltage();

ledSwitch(!_sw);
delay(500);
lowVoltage = getVoltage();

if (lowVoltage > highVoltage)
{ // меняем местами цвета
_sw = !_sw;
float tmp = highVoltage;
highVoltage = lowVoltage;
lowVoltage = tmp;
}

// Вычисляем разброс измерений
float low = VREF, high = 0;
for (int i = 0; i < 500; i++)
{
float voltage = getVoltage();
if (voltage < low)
low = voltage;
if (voltage > high)
high = voltage;
delay(1);
}
_spread = (high - low)*2.5f;

onUpdate();
minTime = 32767;
digitalWrite(PIN_OUT, LOW);
delay(1000);
startVoltage = getVoltage() + 0.05f; // / 2;
// delay(2000);
_flagStatus = true;

digitalWrite(PIN_OUT, LOW); // Выкл. светодиод
_flagStatus = true;
}
void Stop() { _flagStatus = false; }
void Restart()
Expand All @@ -59,41 +97,81 @@ class LatencyMeter
/// @brief Выполняет измерение
void Execute()
{
if (!_flagStatus)
if (!_flagStatus) // Ждем Старт
return;

if (!_flagMeasuring)
// Блок переключает светодиод с периодичностью _interval
// Тут нужно подобрать интервал переключения так, чтобы автоэкспозиция не менялась
uint32_t ms = (micros() - _timer2) / 1000;
if (ms >= _interval * 2)
{
// Ждем, пока датчик зафиксирует состояние выкл. светодиода
if (getVoltage() > startVoltage)
return;
_sw = !_sw;
ledSwitch(_sw);

// Авто-обновляем экстремумов
if (_sw)
highVoltage = getVoltage();
else
lowVoltage = getVoltage();

_flagMeasuring = true;
_timer = micros();
digitalWrite(PIN_OUT, HIGH); // Зажигаем светодиод
_timer2 = micros();
if (!_sw)
_timer = micros(); // сохраняем время начала измерения
}
// Ждем, сигнал от фотодатчика
else

// Блок производящий измерения на фотодатчике
if (!_sw && highVoltage != 0 && lowVoltage != VREF) // Ждем, начало измерения
{
float voltage = getVoltage();
if (voltage > startVoltage + 0.5f)
{ // Если сигнал поступил, то
count++;
valueTime = (micros() - _timer) / 1000; // Считаем задержку
AddValue(valueTime);
// Интервал изменений на фотодатчике
ms = (micros() - _timer3) / 1000;
if (ms > _interval * 2)
{
_flagMeasuring = true;
_timer3 = micros(); // Обнуляем таймер каждый _interval миллисекунд
}
else
{
float voltage = getVoltage(); // сохраняем зн. напряжения каждую миллисекунду

if (valueTime < minTime)
minTime = valueTime;
// Защита от низкой разницы между верх/нижн измерениями
if (highVoltage - lowVoltage < 0.1f)
{
valueTime = 0;
return;
}


if (valueTime > maxTime)
maxTime = valueTime;
/*if (ms % 1000 == 0)
{
Serial.print("Low: ");
Serial.print(lowVoltage);
Serial.print(" High: ");
Serial.print(highVoltage);
Serial.print(" _spread: ");
Serial.print(_spread);
}*/

medianTime = round(median());


onUpdate();
if (voltage > lowVoltage + _spread && _flagMeasuring)
{
_flagMeasuring = false;
valueTime = (micros() - _timer) / 1000;
AddValue(valueTime);
if (valueTime < minTime)
minTime = valueTime;

digitalWrite(PIN_OUT, LOW); // Выкл. светодиод
_flagMeasuring = false;
if (valueTime > maxTime)
{
maxTime = valueTime;
_interval = maxTime > INTERVAL ? INTERVAL : maxTime + 40; // сокращаем интервал проверки
}
//_timer3 = _timer3 + (valueTime - maxTime)*1000; // попытка синхронизации кадров и вспышки
medianTime = round(median());
count++;
onUpdate();
Serial.println(valueTime);
}
}
}
}
Expand All @@ -103,7 +181,14 @@ class LatencyMeter
/// @return Возвращяет напряжение
float getVoltage()
{
return (float)(analogRead(PIN_IN) * 3.3) / 1024;
return (float)(analogRead(PIN_IN) * VREF) / 1024;
}
/// @brief Переключает светодиод
/// @param in
void ledSwitch(bool in)
{
digitalWrite(_pinOut2, !in);
digitalWrite(_pinOut, in);
}

/// @brief Добавляет измерение в сортированный массив
Expand All @@ -116,7 +201,7 @@ class LatencyMeter
_listValue.removeFirst();
}
_listValue.add(value);
Serial.println(value);
// Serial.println(value);
}

/// @brief Возвращает медиану. Примечание: данные должны быть отсортированы
Expand Down Expand Up @@ -169,7 +254,7 @@ class LatencyMeter
if (limLow == 0 || limLow < _listValue[i])
limLow = _listValue[i];
}
else if(m > 0)
else if (m > 0)
{
if (limHigh == 0 || limHigh > _listValue[i])
limHigh = _listValue[i];
Expand Down
4 changes: 2 additions & 2 deletions latencymeter/latencymeter.ino
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Led_5461AS *led;
LatencyMeter *latencyMeter;
Button button1(PIN_BUTTON);

uint8_t flagTypeDataOut = 3; // 0 - задержка рела-тайм, 1 - минимальная, 2 - максимальная, 3 - медиана, 4 - кол-во измерений
uint8_t flagTypeDataOut = 0; // 0 - задержка рела-тайм, 1 - минимальная, 2 - максимальная, 3 - медиана, 4 - кол-во измерений

class EventHandler
{
Expand Down Expand Up @@ -74,7 +74,7 @@ void setup()
button1.onClick += METHOD_HANDLER(eventHandler, EventHandler::OnBtnClick);
button1.onClickLong += METHOD_HANDLER(eventHandler, EventHandler::OnBtnReset);

//latencyMeter->Start();
latencyMeter->Start();
}

void loop()
Expand Down
Loading