Велосипед в подъезде у меня прикован тросиком, но трос — это скорее заявление о намерениях: к раме прикладываются, качают педали, проверяют, что торчит. Я хотел, чтобы плата в кармане на раме замечала сам факт «к железу приложились» — и поднимала счётчик толчков. Кнопка для такой работы не годится: её некому жать. PIR из урока про светильник с HC-SR501 видит только тёплое тело и глух к металлу. А вот датчик наклона — в точку: внутри катается металлический шарик, и любой толчок его будоражит.
Разберём деталь KY-002 из типового набора датчиков, соберём счётчик встряхиваний с честной обработкой фронта digitalRead и антидребезгом на millis() — гейтом в 25 миллисекунд — и добавим вспышку светодиода на 100 мс, во время которой скетч не засыпает. Чтение пина по фронту уже знакомо вам по уроку про кнопку и digitalRead — здесь та же механика, только вместо пальца работает железный шарик.
Шарик в колбе: как устроен KY-002
Внутри модуля нет ни резистора, ни микросхемы — только сам ключ: колба с двумя выводами, по которой свободно катается металлический шарик. Стоит датчику вертикально — шарик лежит на дне, контакты разомкнуты. Наклонили или стукнули — шарик перекатился и на мгновение закоротил выводы. Для сравнения: родственный SW-420 собран на пружинке с компаратором LM393, у него выход уже отформатирован в HIGH/LOW и есть подстроечник. KY-002 отдаёт голый контакт, и вся электроника — наша, скетчевая.
Голый контакт диктует схему включения. Один вывод датчика садим на 5 В, второй — в пин D2, и пин подтягиваем резистором 10 кОм на GND: в покое на входе LOW, при сработке — HIGH. Кто-то делает зеркально: ключ на GND и INPUT_PULLUP — тогда логика инвертируется, сработка читается как LOW, и в скетче меняются местами две константы. Симуляторный компонент работает по первой схеме: сработал — значит HIGH.
Форма исполнения бывает разной: в классическом KY-002 именно шарик, но под тем же артикулом встречаются версии со спиральной пружинкой — маркировка SW-18015P прямо на колбе. Механика похожа, замыкание от тряски, только шарик заменяет пружинка, и характер у них разный: шарик чувствует наклон и в полном покое, пружинка спит до первого толчка. Для счётчика толчков это ничего не меняет, а вот для датчика «крышку приоткрыли» шарик интереснее — он срабатывает уже от наклона корпуса, без единого удара.
И про пределы. Контакты шарика сигнальные: типовые версии держат до 12 В и около 20 мА — это «ключ для входа», а не размыкатель нагрузки. Захотите по встряске включать лампу или мощную сирену — датчик будет говорить «трясут», а рубить цепь станет реле из урока про реле и 220 В.
| Датчик | Что внутри | Выход | Когда брать |
|---|---|---|---|
| KY-002 | шариковый ключ, без обвязки | голые контакты: нужна подтяжка, звон 5-10 мс | простая фиксация тряски за копейки: ящик, калитка, рама |
| SW-420 | пружинка и компаратор LM393 | цифровой HIGH/LOW, подстроечник чувствительности | когда хочется готовый уровень без фронтов и подтяжки |
| MPU-6050 | акселерометр на шине I2C | числа по осям X/Y/Z | когда важны сила и направление удара, а не только факт |
Антидребезг: почему счётчик врёт без фильтра
Шарик — ключ контактный и грубый: замкнувшись, он отскакивает и дозванивается ещё пять-десять миллисекунд. digitalRead за это время видит серию HIGH-LOW-HIGH-LOW: первый вариант моего счётчика насчитал пять событий на один удар молоточка по столу рядом с платой. Лечится связкой из двух проверок: считаем только переход LOW-HIGH (фронт) и только если от прошлого засчитанного фронта прошло больше 25 мс. Первый фильтр отсекает удержание, второй — звон контакта.
Число 25 — не магия, а середина вилки. Дребезг шарика укладывается в 5-10 мс, паузы между настоящими встряхиваниями начинаются от сотни миллисекунд, и гейт в 20-30 мс кладёт стену ровно между этими величинами: звон не пролезает, а два честных удара через полсекунды считаются раздельно. Это та же механика, что у антидребезга кнопки, только окно жёстче: палец на кнопке живёт сотни миллисекунд, а шарик может стучать каждый десяток.
Таймер тут обычный millis-гейт из урока про millis() вместо delay(): не «остановиться на 25 мс», а «сравнить время и молча выбросить рано пришедший фронт». Скетч не спит ни на такт, поэтому счётчик, вспышка и опрос датчика живут одновременно.
const int TILT = 2; // шарик: HIGH = сработкаconst int LED = 12;const int GATE = 25; // мс между засчитанными фронтами int prev = LOW;int shakes = 0;unsigned long lastPulse = 0;unsigned long tLed = 0;bool ledOn = false; void setup() { pinMode(TILT, INPUT); pinMode(LED, OUTPUT); Serial.begin(9600); Serial.println("Tryasite platu: scetchik tolchkov");} void loop() { int now = digitalRead(TILT); if (now == HIGH && prev == LOW && millis() - lastPulse > GATE) { lastPulse = millis(); shakes = shakes + 1; tLed = millis(); ledOn = true; digitalWrite(LED, HIGH); Serial.print("tryaska N="); Serial.println(shakes); } prev = now; if (ledOn && millis() - tLed >= 100) { // гасим вспышку ledOn = false; digitalWrite(LED, LOW); } delay(5);}Разбор по переменным. prev хранит уровень пина с прошлого прохода: фронт — это now HIGH при prev LOW. lastPulse — момент последнего засчитанного события, и гейт проверяется до инкремента, а не после. Светодиод вспыхивает сразу, а гасится отдельной проверкой, когда millis() уехал от tLed дальше сотни: пока лампочка горит, loop() продолжает крутиться и ловит следующую встряску — в этом весь смысл неблокирующей вспышки.
Подсветка события — не украшение, а квитанция. Строку в журнале можно пропустить глазом, а вспышка видна боковым зрением: если свет мигает, а счётчик стоит, значит шарик замыкается, но фронт или гейт съели событие — пора смотреть Serial. Схема у светодиода классическая из первого урока: анод к D12 через 220 Ом, катод в GND. Захотите писк вместо света — добавьте в ветку события tone(BUZZER, 1000, 30): тридцать миллисекунд на частоте 1000 Гц палец слышит как сухой щелчок, вся механика — в уроке про tone().
На живой плате добавляется монтаж, которого у симулятора нет. Шарик работает по одной оси: колба чувствует наклон в плоскости выводов, поэтому на дверце я ставлю датчик под углом 30-45 градусов — так он ловит и приоткрытие, и толчок, а не что-то одно из двух. Крепить лучше на двусторонний скотч через подложку: жёсткая площадка передаёт шарику вибрацию, а мягкая клеевая подушка гасит гул вентиляции, который иначе насчитывает десятки ложных событий за ночь. И держите датчик подальше от трансформаторов блока питания: слабый контакт любит звенеть от электромагнитных наводок — симптом тот же, что у плавающего пина, а лечение другое — перестановкой.
Симулятор: трясём виртуальную макетку
У симуляторного датчика наклона тумблер с подписями «наклонён» и «стоит прямо»: переключили — пин D2 стал HIGH, как будто шарик докатился до контактов и там держится. На живой плате событие короче: шарик замкнул цепь и тут же отскочил, поэтому счётчик на железе подрастает от каждого толчка, а в симе — на каждое положение тумблера. Задержка delay(5) в конце loop() задаёт темп опроса: двести замеров в секунду, для шарика этого хватает с запасом.
Поиграйте с гейтом. Поставьте 100 мс вместо 25 — двойные щелчки тумблера начнут сливаться в одно событие, и вы своими глазами увидите, как широкий фильтр ест честные удары. Потом уберите до 5 мс — и звон контакта вернётся, счётчик начнёт приписывать лишние события. Подбор порога на живом датчике занимает минуту: стучите по столу и сверяйте число в журнале с числом ударов.
Когда счётчик заработает, добавьте ему память и голос: сброс по долгому нажатию кнопки, писк на каждое событие, суточный итог в EEPROM. Подвесьте плату на крышку коробки с инструментом и оставьте на день — журнал покажет, кто и когда её двигал, а вы заодно проверите подбор гейта: суммарный счёт за сутки не должен уходить в сотни от проехавшего под окном трамвая.
- KY-002 — голый шариковый ключ без обвязки: при наклоне или толчке шарик замыкает выводы, контакты держат максимум 12 В и около 20 мА
- Схема: ключ на 5 В, пин D2 с подтяжкой 10 кОм на GND — покой LOW, сработка HIGH; вариант с INPUT_PULLUP даёт обратную логику
- Счёт встрясок — фронт LOW-HIGH плюс гейт millis() в 20-30 мс: звон контакта 5-10 мс отфильтрован, два честных удара считаются раздельно
- LED-вспышка на 100 мс гасится millis-проверкой, а не delay: во время горения скетч продолжает ловить события
- SW-420 с LM393 экономит обвязку, MPU-6050 добавляет силу и направление удара — но и стоит в разы дороже шарика
- 1. Что физически происходит внутри KY-002, когда датчик наклонили?
- 2. Счётчик без фильтра насчитал пять событий на один удар по столу. Почему?
- 3. Что делает проверка millis() - lastPulse > 25 в скетче счётчика?
- 4. Какой ток выдерживают контакты шарикового датчика KY-002?
- 5. Зачем светодиод вспыхивает на 100 мс без единого delay()?
Частые вопросы по теме урока
- Что физически происходит внутри KY-002, когда датчик наклонили?
- Внутри колбы только металлический шарик: в покое он на дне, при наклоне или толчке перекатывается и на мгновение закорачивает выводы. Никакой обвязки у модуля нет. шарик перекатывается и замыкает выводы
- Счётчик без фильтра насчитал пять событий на один удар по столу. Почему?
- Шарик — грубый контактный ключ: замкнувшись, он отскакивает, и digitalRead видит серию HIGH-LOW. Связка «фронт плюс гейт 25 мс» превращает серию в одно событие. контакт шарика отскакивает и дозванивается 5-10 мс
- Что делает проверка millis() - lastPulse > 25 в скетче счётчика?
- Гейт молча выбрасывает рано пришедшие фронты: звон контакта не пролезает, а два честных удара через 100 мс и больше считаются раздельно. Никаких пауз — loop() крутится дальше. пропускает фронты, пришедшие раньше чем через 25 мс после засчитанного
- Какой ток выдерживают контакты шарикового датчика KY-002?
- Контакты шарика слабые: типовые версии держат 12 В и около 20 мА. Нагрузку через него не коммутируют — для этого ставят реле или транзистор. около 20 мА при 12 В максимум: это сигнальный ключ
- Зачем светодиод вспыхивает на 100 мс без единого delay()?
- Вспышка гасится millis-проверкой, loop() не останавливается: событие, случившееся, пока светодиод горит, будет поймано и посчитано. Блокирующая пауза его съела бы. чтобы во время вспышки скетч продолжал ловить следующие встряски