[#] Сигнализация для меломана на Arduino
vit01(mira, 1) — All
2017-02-18 13:56:28


Когда у меня появилась ардуинка, я хотел приспособить её для какого-нибудь действительно полезного дела. В домашних условиях такая задача всё-таки нашлась :)

Вот представь себе: ты сидишь за столом и слушаешь громкую музыку в наушниках. Может быть, делаешь какие-то другие дела попутно по работе или учёбе. А тут подходит к тебе кто-то из домашних и хочет что-то сказать. Во-первых, этот внешний раздражитель сначала надо заметить (ты ведь под кайфом от громкой музыки, да?). Во-вторых, надо переключиться на плеер и остановить воспроизведение.

Цель: сделать установку на ардуине, которая будет ставить плеер на паузу, когда подходят к твоему "рабочему месту".

Приобрёл на али инфракрасный датчик движения за 100 рублей.
Перемычек нормальных не было, поэтому пришлось криво припаять контакты к уже имеющимся.
Подсоединил один из контактов к цифровому порту, а другой - к подпитке 5V на плате.
Решил прицепить на ардуину ещё и лишний светодиод, который будет мигать при срабатывании датчика.

Нашёл в сети образцы скетчей для использования датчика движения, но они мне не очень понравились, и я решил взять один из них и максимально упростить:

#define pirPin 2  // наш датчик
#define ledPin 13 // светодиод

int wasMotion = false;

void setup() {
  Serial.begin(9600);
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);

  delay(2000); // не активируем цикл сразу, а чуть-чуть подождём
}

void loop() {
  int pirVal = digitalRead(pirPin);

  //Если обнаружили движение
  if (pirVal == HIGH)
  {
    if (wasMotion == false) {
      digitalWrite(ledPin, HIGH);
      Serial.print("Motion detected\n");
      wasMotion = true;
    }
    delay(500); // пауза для прогорания светодиода и для следующей проверки
  } else if (wasMotion == true) {
    wasMotion = false;
    digitalWrite(ledPin, LOW);
  }
}

После заливки скетча надо добавить вашего пользователя в группу uucp, которая позволит считывать данные из виртуального USB-COM порта ардуины без root-прав.

# usermod -a -G uucp youruser

Далее надо было написать программу, которая будет отслеживать сигнал, поступающий с девайса, и подавать сигнал плееру. Питон ради такой мелочи расчехлять не хотелось (будет память жрать), поэтому выбрал C.

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>

int fd;
int should_exit = 0;

static void signal_handler(int sig) {
	// Обрабатываем нажатие Ctrl-C, чтобы корректно выходить

	switch (sig) {
		case SIGINT:
			close(fd);
			printf("Exiting\n");
			should_exit = 1;
			break;
		default:
			break;
	}
}

void stop_player() {
	// Главная вещь, ради которой всё затевалось
	// Для плеера Audacious, которым пользуюсь

	system("if [ \"`audtool playback-status`\" = \"playing\" ]; then audtool playback-pause; fi");
}

void main(int argc, char** argv) {
	char buf[15];
	int r;

	signal(SIGINT, signal_handler);

	// Открываем виртуальный USB COM-port девайса
	fd = open("/dev/ttyUSB0", O_RDONLY | O_NOCTTY | O_NDELAY);
	if (fd == -1) {
		perror("open_port: Unable to open /dev/ttyUSB0 - ");
		should_exit = 1;
	} else {
		fcntl(fd, F_SETFL, FNDELAY);
	}

	while(!should_exit) {
		r = read(fd, buf, 20);
		if (r > 0 && strncmp(buf, "Motion detected", 15) == 0) {
			puts("Works!");
			stop_player();
		}
		sleep(1);
	}
}

Всё, можно добавлять в автозагрузку и пользоваться!
И да, как это выглядит на фоточках:

https://ii-net.tk/ii/files/arduino-pir1.jpg
https://ii-net.tk/ii/files/arduino-pir2.jpg