Перевод текста на русский язык:
Этот хост использует платформу .NET для реализации WPF для передачи данных с MPU6050 через Bluetooth от устройства к хосту, а затем через Wi-Fi. Данные визуализируются.
Рисунок 1.
Платформа .NET, WPF. VS2019 (требуется установка среды, поддерживающей C#). После получения исходного кода откройте BluetoothPC.sln и запустите его.
Разработан красивый пользовательский интерфейс:
Рисунок 2.
Дизайн пользовательского интерфейса переднего плана XAML не требует подробного описания. Основное внимание уделяется требованиям дизайна, таким как шаблоны, триггеры, анимация и стили.
На заднем плане C# в основном потоке пользовательского интерфейса запущены три дочерних потока:
Поскольку не было обнаружено одновременного доступа нескольких потоков к одному и тому же элементу управления пользовательского интерфейса или записи в один и тот же элемент управления, мьютекс не использовался, но была добавлена асинхронная задержка для более плавного обновления пользовательского интерфейса.
Необходимо убедиться, что IP-адрес и номер порта UDP-сервера действительны и доступны. Если появится следующее сообщение об ошибке, пожалуйста, повторно введите информацию:
Рисунок 3.
Рисунок 4.
При наличии оборудования: после успешного подключения необходимо использовать соответствующее оборудование нижнего уровня для получения значений скорости по трём осям, полученных через UDP.
Без оборудования: если нет оборудования, вы можете использовать сетевой отладчик для создания службы UDP и подключиться к ней на локальном компьютере. Отправленные данные должны содержать следующий формат:
Объяснение: отправленные данные должны включать :xxxx mG, двоеточие и mG обязательны, можно отправить несколько групп, каждая группа представляет данные по одной оси.
Рисунок 5.
Количество шагов рассчитывается на основе данных о скорости по трем осям. Необходимо включить кнопку управления количеством шагов в левом нижнем углу. После включения появится подсказка:
Рисунок 6.
Рисунок 7.
Алгоритм подсчёта шагов поддерживает только количество шагов, основанное на пиковых значениях колебаний руки. Если у вас есть лучший алгоритм, пожалуйста, поделитесь им!
Алгоритм подсчета шагов:
/*
* valueNum - хранит количество значений данных по трем осям (x,y,z)
* tempValue - используется для хранения массива значений разницы между пиком и впадиной (в этом методе длина массива равна 5)
* isDirectionUp - флаг направления вверх
* continueUpCount - количество последовательных подъёмов
* continueUpFormerCount - количество последовательных подъёмов на предыдущей точке, используется для записи пика подъёма
* lastStatus - статус предыдущей точки, подъём или спуск
* peakOfWave - значение пика волны
* valleyOfWave - значение впадины волны
* timeOfThisPeak - время этого пика
* timeOfLastPeak - время последнего пика
* timeOfNow - текущее время
* gravityOld - значение датчика на предыдущем шаге
* initialValue - динамический порог, требующий динамических данных, это значение используется в качестве порога для этих динамических данных. Это значение получено из большого объёма данных
* ThreadValue - начальный порог, это значение получено из большого объема данных
* minValue - начальное минимальное значение, вычисленное как произведение значения xyz на ускорение силы тяжести (9,8), это значение для телефона, удерживаемого в руке (без размахивания рукой) (получено из собственных многократных тестов)
* maxValue - начальное максимальное значение, установленное самостоятельно как максимальное значение (мы устанавливаем его равным 2), умноженное на ускорение силы тяжести (9,8), это значение для телефона, удерживаемого в руке (без размахивания рукой) (получено из собственных многочисленных тестов)
* g - ускорение свободного падения (9,8)
* thisSteps - количество шагов
*/
private int valueNum = 5;
//private double[] tempValue;
private List<double> tempValue = new List<double>();
private Boolean isDirectionUp = false;
private int continueUpCount = 0;
private int continueUpFormerCount = 0;
private Boolean lastStatus = false;
private double peakOfWave = 0;
private double valleyOfWave = 0;
private double timeOfThisPeak = 0;
private double timeOfLastPeak = 0;
private double timeOfNow = 0;
private double gravityOld = 0;
private double initialValue = 1,7;
private double ThreadValue = 2,0;
private double minValue = 11;
private double maxValue = 19,6;
private double g = 9,8;
private double thisSteps = 0; //текущее количество шагов
private double StepsCopy = 0; //количество шагов копирования
/// <summary>
/// Отслеживание новых шагов. Если обнаружен пик и он соответствует условиям времени и порога, то считается, что сделан один шаг.
/// Если разница между пиковым и минимальным значениями больше initialValue, то она включается в расчёт порога.
/// </summary>
/// <param name="_values">среднее значение ускорения по трём осям</param>
public void detectorNewStep(double _values)
{
if (gravityOld == 0)
{
gravityOld = _values;
}
else
{
if (detectorPeak(_values, gravityOld))
{
timeOfLastPeak = timeOfThisPeak;
timeOfNow = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds);
//разница во времени больше 200 мс, меньше 2 с
if (((timeOfNow - timeOfLastPeak) >= 200) && ((timeOfNow - timeOfLastPeak) <= 2000) && ((peakOfWave - valleyOfWave) >= ThreadValue))
{
timeOfThisPeak = timeOfNow;
//увеличение количества шагов
thisSteps++;
//увеличение копии количества шагов
StepsCopy++;
}
if(((timeOfNow - timeOfLastPeak) >= 200) && ((peakOfWave - valleyOfWave) >= initialValue))
{
timeOfThisPeak = timeOfNow;
double _diffWaveVal =
``` **peakOfWave - valleyOfWave;**
**ThreadValue = peak_Valley_Thread(_diffWaveVal);**
}
}
gravityOld = _values;
}
}
/// <summary>
/// 监测波峰
/// 以下四个条件判断为波峰
/// 1.目前点为下降的趋势:isDirectionUp为false
/// 2.之前的点为上升的趋势:lastStatus为true
/// 3.到波峰为止,持续上升大于等于2次
/// 4.波峰值大于minValue,小于maxValue
/// 记录波谷值
/// 1.观察波形图,可以发现在出现步子的地方,波谷的下一个就是波峰,有比较明显的特征以及差值
/// 2.所以要记录每次的波谷值,为了和下次的波峰作对比
/// </summary>
/// <param name="_newValue"></param>
/// <param name="_oldValue"></param>
/// <returns></returns>
public Boolean detectorPeak(double _newValue, double _oldValue)
{
lastStatus = isDirectionUp;
if (_newValue >= _oldValue)
{
isDirectionUp = true;
continueUpCount++;
}
else
{
continueUpFormerCount = continueUpCount;
continueUpCount = 0;
isDirectionUp = false;
}
if (!isDirectionUp && lastStatus && (continueUpFormerCount >= 2 && (_oldValue >= minValue && _oldValue < maxValue)))
{
//满足上面波峰的四个条件,此时为波峰状态
peakOfWave = _oldValue;
return true;
}
else if (!lastStatus && isDirectionUp)
{
//满足波谷条件,此时为波谷状态
valleyOfWave = _oldValue;
return false;
}
else
{
return false;
}
}
/// <summary>
/// 阈值的计算
/// 1.通过波峰波谷的差值计算阈值
/// 2.记录4个值,存入tempValue[] 数组中
/// 3.在将数组传入函数averageValue中计算阈值
/// </summary>
/// <param name="_value"></param>
/// <returns></returns>
public double peak_Valley_Thread(double _value)
{
double _tempThread = ThreadValue;
List<double> _tempValue = new List<double>(tempValue);
if (tempValue.Count < valueNum)
{
tempValue.Add(_value);
}
else
{
//tempValue数组长度=valueNum=5
_tempThread = averageValue(tempValue);
_tempValue.RemoveAt(0);
_tempValue.Add(_value);
tempValue = _tempValue;
}
return _tempThread;
}
/// <summary>
/// 梯度化阈值
/// 1.计算数组的均值
/// 2.通过均值将阈值梯度化在一个范围里
/// 这些数据是通过大量的统计得到的
/// </summary>
/// <param name="_value"></param>
/// <returns></returns>
public double averageValue(List<double> _value)
{
if (_value.Count != 0)
{
double _ave = 0;
foreach (double i in _value)
_ave += i;
_ave = _ave / _value.Count;
if(_ave >= 8)
{
_ave = 4.3;
}
else if (_ave >= 7 && _ave < 8)
{
_ave = 3.3;
}
else if (_ave >= 4 && _ave < 7)
{
_ave = 2.3;
}
else if (_ave >= 3 && _ave < 4)
{
_ave = 2.0;
}
else
{
_ave = 1.7;
}
return _ave;
}
else
{
return 1.7;
}
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )