1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/tytokongjian-StepCountingUpperPC

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
README.md 13 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 30.11.2024 12:10 9baacfa

Перевод текста на русский язык:

1. Описание проекта

Этот хост использует платформу .NET для реализации WPF для передачи данных с MPU6050 через Bluetooth от устройства к хосту, а затем через Wi-Fi. Данные визуализируются.

Рисунок 1.

1.1 Среда выполнения

Платформа .NET, WPF. VS2019 (требуется установка среды, поддерживающей C#). После получения исходного кода откройте BluetoothPC.sln и запустите его.

Разработан красивый пользовательский интерфейс:

Рисунок 2.

2. Процесс проектирования

2.1 Структура проекта

Дизайн пользовательского интерфейса переднего плана XAML не требует подробного описания. Основное внимание уделяется требованиям дизайна, таким как шаблоны, триггеры, анимация и стили.

На заднем плане C# в основном потоке пользовательского интерфейса запущены три дочерних потока:

  1. Поток для прослушивания и приёма UDP-данных.
  2. Поток обновления данных по трём осям.
  3. Поток обновления количества шагов и хода выполнения.

Поскольку не было обнаружено одновременного доступа нескольких потоков к одному и тому же элементу управления пользовательского интерфейса или записи в один и тот же элемент управления, мьютекс не использовался, но была добавлена асинхронная задержка для более плавного обновления пользовательского интерфейса.

2.2 Дизайн подключения к серверу

Необходимо убедиться, что IP-адрес и номер порта UDP-сервера действительны и доступны. Если появится следующее сообщение об ошибке, пожалуйста, повторно введите информацию:

Рисунок 3.

Рисунок 4.

2.3 Отображение данных о скорости по трём осям

При наличии оборудования: после успешного подключения необходимо использовать соответствующее оборудование нижнего уровня для получения значений скорости по трём осям, полученных через UDP.

Без оборудования: если нет оборудования, вы можете использовать сетевой отладчик для создания службы UDP и подключиться к ней на локальном компьютере. Отправленные данные должны содержать следующий формат:

  • Любой символ (:1.23938 mG) любой символ.

Объяснение: отправленные данные должны включать :xxxx mG, двоеточие и mG обязательны, можно отправить несколько групп, каждая группа представляет данные по одной оси.

Рисунок 5.

2.4 Отображение количества шагов

Количество шагов рассчитывается на основе данных о скорости по трем осям. Необходимо включить кнопку управления количеством шагов в левом нижнем углу. После включения появится подсказка:

Рисунок 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 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/tytokongjian-StepCountingUpperPC.git
git@api.gitlife.ru:oschina-mirror/tytokongjian-StepCountingUpperPC.git
oschina-mirror
tytokongjian-StepCountingUpperPC
tytokongjian-StepCountingUpperPC
master