Круговое сенсорное зондирование с микроконтроллером EFM8
В этом проекте мы разработаем алгоритм для точного определения местоположения сенсорного события, которое происходит где-то на круговом емкостном датчике.
Связанная информация
- Управление ЖК-дисплеем через SPI: введение в разработку проекта с помощью микроконтроллера EFM8
- Монитор окружающего освещения: отображение измерений на ЖК-дисплее
- Введение в емкостное сенсорное зондирование
- Схемы и методы для обеспечения емкостного сенсорного зондирования
Требуемое оборудование / программное обеспечение
- SLSTK2010A Набор для начинающих сонных пчел
- Студия Simplicity
Циркулярный датчик
В оценочную плату SLSTK2010A входят, среди прочего, микроконтроллер EFM8 Sleepy Bee и круглый емкостной сенсор. С помощью любого микроконтроллера можно выполнять емкостное сенсорное зондирование, но вы получите лучшие результаты со специализированным аппаратным модулем, разработанным экспертами, и именно это интегрировано в Sleepy Bee. В предыдущей статье, озаглавленной «Емкостное сенсорное зондирование» с микроконтроллером EFM8, исследуется функциональность этого периферийного устройства, которая упоминается как CS0 (емкостное чувство 0) в справочном руководстве EFM8 Sleepy Bee.
Круглый емкостной датчик обеспечивает не трехмерную-торообразную (или, если хотите, понтообразную) область, в которой пользовательский ввод может быть получен через приложение кончика пальца. Существуют ограничения в реальном мире, которые ограничивают количество отдельных позиций касания, которые могут быть точно идентифицированы, но в целом я бы сказал, что разрешение довольно хорошее - я предполагаю, что тщательно разработанная прошивка может надежно различать 5 ° приращений, а это означает, что круговой датчик может предложить до 72 отдельных позиций ввода пользователя.
Это довольно впечатляет, но это становится еще более впечатляющим, если учесть, что эти 72 отдельных положения достигнуты только с тремя каналами емкостного смысла. Однако эти три канала могут обеспечить эту функциональность только потому, что они соединены с тремя очень умными емкостными датчиками PCB, как показано на следующих фотографиях и диаграммах.

Графическая любезность Марка Хьюза
Центральная часть каждого датчика соответствует радиальному участку между концами изгибающих выступов. Когда вы прикасаетесь к центральной части, изменение емкости (ака «дельта крышки») для этого датчика будет самым высоким, и дельта колпака будет неуклонно уменьшаться, когда кончик пальца удаляется от центральной части в любом направлении.
Как вы можете видеть, однако, когда вы отодвигаетесь от одной центральной части, вы двигаетесь к другой. Это означает, что уменьшающаяся дельта крышки на первом канале происходит в сочетании с увеличивающейся дельтой дельта на другом канале. Объединив измерения cap-delta от соседних датчиков, мы можем вычислить приблизительное угловое положение для любого события касания, которое происходит где-то на торе.
Прежде чем двигаться дальше, давайте кратко обсудим, почему этот круговой слайдер настолько изящен в контексте современной электроники. В конце концов, нам нужно довольно сложное прошивку, чтобы получить приличное угловое позиционирование, используя только три датчика. Почему бы просто не использовать дюжину обычных круглых датчиков, расположенных равномерно вокруг круга?
Ну, каждый датчик нуждается в контакте на микроконтроллере, так что теперь вы потребляете 12 контактов, и в процессе вы значительно снизили разрешение. Прошивка дешевая и не занимает места, в то время как микроконтроллеры (и связанные с ними следы печатных плат) занимают много места по сравнению с небольшими устройствами, которые, как ожидается, планируют инженеры. И в долгосрочной перспективе аппаратное обеспечение дорого, по крайней мере, по сравнению с прошивкой. Меньше контактов, меньше микросхем, меньше аппаратных средств, больше прошивки - это текущая парадигма, по крайней мере, для бытовой электроники.
Отслеживание наших датчиков
Следующая диаграмма показывает, как номера датчиков, используемые в коде, соответствуют физическому расположению.

Опять же, это «номера датчиков» -и, произвольные идентификаторы, назначенные для трех физических датчиков. Эти цифры не совпадают с «каналом» -ie, который подключен к физическому датчику с внутренним каналом считывания. И, конечно, номер канала необязательно соответствует интуитивно понятным образом внешнему контакту, к которому подключен датчик. Вот отображение:
Номер датчика | канал | Штырь | Место нахождения |
---|---|---|---|
1 | 2 | Р0.2 | снизу среднего |
2 | 3 | P0.3 | верхний левый |
3 | 13 | P1.5 | в правом верхнем углу |
Создание базовой линии
Первое, что нам нужно сделать, это установить определенное значение как официальную «неударенную» емкость конкретного датчика. Этот шаг имеет решающее значение - во-первых, потому что емкостное сенсорное сенсорное взаимодействие вращается вокруг изменений емкости, а не абсолютной емкости, а во-вторых, потому что три датчика могут иметь большие вариации в сжатой емкости. Например, я просто подключил свою плату, и в настоящий момент три (казалось бы, идентичные) датчика имеют сжатые значения емкости приблизительно 15700 отсчетов, 14800 отсчетов и 14150 отсчетов.
Я устанавливаю значения сжатых емкостей следующим образом:
Accumulated_Capacitance_Sensor1 = 0; Accumulated_Capacitance_Sensor2 = 0; Accumulated_Capacitance_Sensor3 = 0; for (n = 0; n > 4); Sensor2_Unpressed = (Accumulated_Capacitance_Sensor2 >> 4); Sensor3_Unpressed = (Accumulated_Capacitance_Sensor3 >> 4);
Вы можете видеть здесь, что я делаю много усреднения. Аппаратное обеспечение CS0 настроено на среднее число 64 выборок на измерение, тогда я усредняю 16 из этих уже усредненных измерений. Может быть, это слишком много, но все функциональные возможности, основанные на кепке, основаны на этих нежатых значениях, поэтому я хочу убедиться, что они не повреждаются источниками переходных помех или какой-то сбой измерения.
Примечание. Важно избегать существенных различий между этими начальными измерениями без сжатия и, тем не менее, вы производите выборку каналов с датчиком в течение нормальной работы. Я специально ссылаюсь на поддержание последовательности каналов и обеспечение аналогичных интервалов между измерениями. Например, если во время нормальной работы вы выбираете датчик 1, затем датчик 2, затем датчик 3, с 1 мс между каждым измерением, вы не хотите определять свои неударенные значения, принимая 16 измерений быстрого срабатывания датчика 1, а затем сразу 16 измерений с быстрым датчиком 2, а затем немедленно принять 16 измерений с быстрым датчиком 3. Это приведет к небольшим, но заметным несоответствиям между измерениями нормальной работы и измерениям с измерением без сжатия, так что ваши официальные значения без сжатия будут отличаться от фактических типичных неударенных значений, наблюдаемых при нормальной работе программы.
Обнаружение прессы
Перед вычислением углового положения нам нужно признать, что кончик пальца находится в контакте с круглым датчиком. Мы делаем это, просматривая каналы, вычисляя дельту крышки и сравнивая ее с порогом.
Sensor1_Measurement = Measure_Capacitance(SENSOR_1); Sensor1_Delta = Sensor1_Measurement - Sensor1_Unpressed; if(Sensor1_Delta < 0) Sensor1_Delta = 0; Delay_us(1000); Sensor2_Measurement = Measure_Capacitance(SENSOR_2); Sensor2_Delta = Sensor2_Measurement - Sensor2_Unpressed; if(Sensor2_Delta < 0) Sensor2_Delta = 0; Delay_us(1000); Sensor3_Measurement = Measure_Capacitance(SENSOR_3); Sensor3_Delta = Sensor3_Measurement - Sensor3_Unpressed; if(Sensor3_DeltaTOUCH_DELTA_THRESHOLD || Sensor2_Delta > TOUCH_DELTA_THRESHOLD || Sensor3_Delta > TOUCH_DELTA_THRESHOLD) { …
Через эксперименты я обнаружил, что минимальное увеличение емкости от не очень твердого пальцевого пресса было около 6000 отсчетов (у меня есть коэффициент чувствительности к крышке, установленный в 4 раза). Я сделал это, коснувшись на полпути между двумя датчиками; это приводит к минимальному увеличению емкости с одним датчиком, поскольку общее увеличение распределяется поровну между двумя датчиками.

Таким образом, мы можем предположить, что кончик пальца, контактирующий с любой частью кругового датчика, приведет к дельтам крышки не менее 6000 отсчетов. Исходя из этого, вы можете использовать 4000 или 5000 отсчетов в качестве порога cap-delta, но я выбрал 2000, просто потому, что 2000 по-прежнему намного выше типичной амплитуды шума и даст нам более высокую чувствительность (возможно, некоторые пальцы имеют меньшую емкость, чем другие..).
Затем мы просто сравниваем дельта крышки каждого датчика с порогом, и если хотя бы один превышает пороговое значение, мы продолжаем обрабатывать данные датчика, чтобы определить угловое положение события касания.
Расчет позиции
Прежде чем идти дальше, я должен упомянуть следующее: Алгоритм угловой позиции, который я разработал, может быть далеко не оптимальным. Но дело не в этом. Дело в том, что этот алгоритм является результатом мыслительного процесса здравого смысла, который отражает «интуитивный путь» от намерения, путем рассмотрения и наблюдения и анализа, до реализации. Я предпочитаю начать с этого интуитивного пути, потому что он надежно приведет к более глубокому пониманию проблемы, и лучше подумать об этом более глубоком понимании, прежде чем оглядываться на потенциально лучшую реализацию, созданную кем-то другим.
Сначала я определяю сегмент 120 °, в котором происходит событие касания; это делается путем поиска датчика с самым низким измерением. Например, если датчик 1 имеет самое низкое измерение, кончик пальца находится между датчиками 2 и 3.

if(Sensor1_Delta > TOUCH_DELTA_THRESHOLD || Sensor2_Delta > TOUCH_DELTA_THRESHOLD || Sensor3_Delta > TOUCH_DELTA_THRESHOLD) { switch(Find_Minimum(Sensor1_Delta, Sensor2_Delta, Sensor3_Delta)) { case SENSOR_1: Segment = UPPER_MIDDLE; break; case SENSOR_2: Segment = LOWER_RIGHT; break; case SENSOR_3: Segment = LOWER_LEFT; break; } …
Ключом к следующей части алгоритма является предположение, что общее увеличение емкости одинаково независимо от углового положения. Предположим, что палец находится в центре датчика 2 и производит увеличение 15000 отсчетов от датчика 2 и увеличение количества отсчетов нуля от датчика 3. В этом предположении, как датчик 2, так и датчик 3 будут иметь увеличение на 7500 отсчетов, если событие касания находится на полпути между ними. Я не знаю, насколько точным является это предположение, но общая идея кажется достаточно обоснованной, чтобы дать хорошие результаты.
Затем мы просто делим дельта датчика 2 (или датчик 3 или датчик 1) на общую дельта, а затем умножим это соотношение на 120 °. Наконец, мы добавляем этот угол к углу, соответствующему «началу» сегмента 120 °.

Основной недостаток этого метода заключается в следующем: углы вблизи центра датчиков (т. Е. 30 °, 150 °, 270 °) получаются «пропущенными», потому что дельта колпачка не проходит до нуля, например, если ваш кончик пальца находится справа от центра датчика 3, показание датчика 2 может составлять 400 отсчетов вместо нуля. В результате отношение дельта датчика 2 к общей дельте не будет распространяться полностью от 0% до 100%. Чтобы исправить это, я полагаю (на основе наблюдений), что первоначально рассчитанное отношение будет простираться от 5% до 95%, а затем я сопоставляю отношение от диапазона 5-95 до диапазона 0-100. Константы отображения определяются путем решения следующих одновременных уравнений:
$$ \ begin {cases} 0.05x + y = 0 \\ 0.95x + y = 1 \\ \ end {cases} $$
Я доволен производительностью, обеспечиваемой этим подходом, но для полной ликвидации «прыгающих» измерений, которые происходят в переходных областях 30 °, 150 ° и 270 °, потребуется дополнительная тонкая настройка.
if(Segment == UPPER_MIDDLE) { TotalDelta = Sensor2_Delta + Sensor3_Delta; Ratio = (float)Sensor2_Delta/TotalDelta; Ratio = (Ratio*1.1111) - 0.05556; AngularPosition = (Ratio*120) + 30; } else if(Segment == LOWER_RIGHT) { TotalDelta = Sensor3_Delta + Sensor1_Delta; Ratio = (float)Sensor3_Delta/TotalDelta; Ratio = (Ratio*1.1111) - 0.05556; AngularPosition = (Ratio*120) + 270; if(AngularPosition >= 360) AngularPosition = AngularPosition - 360; } else if(Segment == LOWER_LEFT) { TotalDelta = Sensor2_Delta + Sensor1_Delta; Ratio = (float)Sensor1_Delta/TotalDelta; Ratio = (Ratio*1.1111) - 0.05556; AngularPosition = (Ratio*120) + 150; }
Вывод
Вы можете использовать следующую ссылку для загрузки всех исходных файлов и файлов проекта.
Файлы источника и проекта
Как показано в видео ниже, программа имеет два режима: в режиме по умолчанию отображается угловая позиция текущего или последнего события касания. Во втором режиме он отображает дельту крышки для каждого канала.

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