Мишкофон

  • Платформы: Iskra Neo
  • Языки программирования: Arduino (C++)
  • Тэги: Детский телефон, мягкая игрушка, радионяня, общение с ребёнком.

Что это?

С помощью этого «мишкофона» можно болтать со своим ребёнком и рассказывать ему сказки, не отходя от рабочего места. Да, есть вариант научить чадо пользоваться смартфоном. Но в смартфоне нет ничего волшебного. А плюшевый медведь, говорящий папиным голосом, — самое, что ни на есть настоящее волшебство. При чём сделанное своими руками.

Что нам понадобится?

Как собрать?

  1. Для начала вставьте сим-карту в GPRS Shield и установите его на платформу Iskra Neo.
  2. Подключите внешнюю антенну через SMA-разъём.
  3. На платах Arduino с микроконтроллером ATmega32U4 (Iskra Neo, Arduino Leonardo, Arduino ETH, Arduino Micro и Arduino Yún) пины 2 и 3 используются для протокола I²C. В GPRS Shield контакты PK и ST также по умолчанию находятся на пинах 2 и 3. Чтобы избежать конфликта с I²C-гироскопом перебросим контакты PK и ST GPRS Shield’a на пины 6 и 5. Для этого снимите джамперы с контактов ST и PK GPRS Shield’a. На их место воткните два провода «мама-мама».
  4. Присоедините к Troyka Shield контактные колодки и установите получившуюся конструкцию на GPRS Shield. Соединяем с помощью проводов «мама-мама» контакты ST и PK GPRS Shield’a с пинами 5 и 6 платы Iskra Neo соответственно.
  5. Используя два 3-проводных шлейфа подключите Troyka-гироскоп к Troyka Shield следующим образом:
    • Контакты питания:
    1. Земля (G) — чёрный провод. Соединить с пином GND Troyka Shield.
    2. Питание (V) — красный провод. Соединить с пином VCC Troyka Shield.
    3. Не используется.
    • Контакты шины I²C:
    1. Сигнальный (D) — чёрный провод. Подключить к 2 пину Troyka Shield.
    2. Сигнальный (С) — красный провод. Подключить к 3 пину Troyka Shield.
    3. Не используется.
  6. Используйте 3-проводной шлейф, чтобы подключить Troyka-светодиод к цифровому пину 13 на Troyka Shield.
  7. Теперь подключите динамик и микрофон в соответствующие разъёмы GPRS Shield.
  8. Вставьте шесть NiMH аккумуляторов в батарейный отсек 3×2 AA. Через штекер питания 2,1 мм с клеммником подключите его к плате Iskra Neo.По итогу должна получиться следующая схема:
  9. Теперь вам нужно упаковать устройство в плюшевого зверя. Для этого переверните игрушку спиной к себе, сделайте аккуратный надрез по шву и разместите всю электронику внутри. Проще сразу взять игрушку с молнией на спине, как у нас, иначе замаетесь штопать, и получите в итоге монстра Франкинштейна вместо милой зверушки.

Алгоритм

  • Сразу после подачи питания считываем данные с гироскопа.
    • Если данные больше заданного порога в течении 5 секунд, звоним на указанный в коде номер.
  • Каждую секунду проверяем — не пришёл ли входящий звонок.
    • Если входящий номер совпадает с номером в коде, берём трубку. Другие номера игнорируем.
  • Повторяем весь цикл.

Исходный код

gsmbear.ino
// подключаем библиотеку для работы I²C
#include <Wire.h>
// подключаем библиотеку для работы с модулями IMU
#include <TroykaIMU.h>
 
// подключаем библиотеку для работы с GPRS устройством
#include <GPRS_Shield_Arduino.h>
// подключаем библиотеку для эмуляции Serial порта
// она нужна для работы библиотеки GPRS_Shield_Arduino
#include <SoftwareSerial.h>
 
#define GPRS_BUFFER_LENGTH    46
#define TELEPHONE_NUM_LENGTH  12
 
// порог скорости вращения гироскопа
#define ROTATE_SPEED_TRESHOLD 10
 
// время задержки, после которой будет совершён исходящий вызов
#define OUTCOMING_CALL_TIMEOUT 5000
 
// порог после которого будем звонить
#define OUTCOMING_CALL_TRESHOLD 500
 
// индикаторный светодиод расположен на 13 пине
#define INDICATOR_PIN 13
 
char fathersNumber[] = "+74993221317";
 
char incomingPhoneNumber[GPRS_BUFFER_LENGTH];
 
// создаём объект класса GPRS, передаём ему
// номера пинов PK, ST и скорость 9600 бод
GPRS gprs(6, 5, 9600);
 
// создаём объект для работы с гироскопом
Gyroscope gyro;
 
unsigned long waitTime = 0;
 
unsigned long rotateTime = 0;
 
int rotateCounter = 0;
 
void setup()
{
  //настраиваем пин 13 в режим выхода,
  pinMode(INDICATOR_PIN, OUTPUT);
  // подаём на пин 13 «низкий уровень»
  digitalWrite(INDICATOR_PIN, LOW);
  // включаем GPRS Shield
  gprs.powerUpDown();
 
  while (!gprs.init()) {
    // завелся ли GPRS Shield?
    digitalWrite(INDICATOR_PIN, !digitalRead(INDICATOR_PIN));
    // если связи нет, ждём 1 секунду
    // процесс повторяется в цикле,
    // пока не появится ответ от GPRS устройства
    delay(1000);
  }
  digitalWrite(INDICATOR_PIN, LOW);
 
  // запускаем гироскоп
  gyro.begin();
}
 
void loop()
{
  // если функция возвращает true
  if (gyroCall()) {
    // звоним на заданный в коде номер
    gprs.callUp(fathersNumber);
    // индикация звонка
    calling();
  }
  // каждую секунду ожидаем входящий звонок
  if (millis() - waitTime > 1000) {
    incomingCall();
    // запоминаем текущее время
    waitTime = millis();
  }
}
 
void incomingCall()
{
  // ожидаем звонка
  if (gprs.ifcallNow()) {
    // если поступает входящий звонок,
    // подаём на пин 13 «высокий уровень», чтобы
    // зажечь светодиод на 13 пине
    digitalWrite(INDICATOR_PIN, HIGH);
    // считываем номер входящего звонка
    gprs.isCallActive(incomingPhoneNumber);
    if (!strncmp(incomingPhoneNumber, fathersNumber, TELEPHONE_NUM_LENGTH)) {
      // если звонит папа
      // по истечении 3 секунд берём трубку
      delay(3000);
      gprs.answer();
      // индикация звонка
      calling();
    } else {
      // если нет, кладём трубку
      gprs.callEnd();
    }
  }
}
 
bool gyroCall()
{
  // считываем абсолютную скорость вращения гироскопа по трём осям
  float bearRotate = abs(gyro.readDegPerSecX())
  + abs(gyro.readDegPerSecY())
  + abs(gyro.readDegPerSecZ());
  // если это не случайные помехи
  if (bearRotate > ROTATE_SPEED_TRESHOLD) {
    // запоминаем текущее время
    rotateTime = millis();
    // увеличиваем счётчик вращения
    ++rotateCounter;
    // увеличиваем яркость светодиода
    analogWrite(INDICATOR_PIN, map(rotateCounter, 0, OUTCOMING_CALL_TRESHOLD, 0, 255));
 
  } else if (millis() - rotateTime > OUTCOMING_CALL_TIMEOUT) {
    // если же скорость вращение была ниже порога в течении 5 секунд
    // гасим светодиод
    digitalWrite(INDICATOR_PIN, LOW);
    // обнуляем счётчик вращения
    rotateCounter = 0;
  }
  // возвращаем результат
  // превысил ли счётчик вращения порог срабатывания исходящего звонка
  return (rotateCounter > OUTCOMING_CALL_TRESHOLD);
}
 
void calling()
{
  while (!gprs.ifcallEnd()) {
    // моргаем и ждём пока абонент не положит трубку
    digitalWrite(INDICATOR_PIN, HIGH);
    delay(50);
    digitalWrite(INDICATOR_PIN, LOW);
    delay(200);
    digitalWrite(INDICATOR_PIN, HIGH);
    delay(50);
    digitalWrite(INDICATOR_PIN, LOW);
  }
}

Демонстрация работы устройства

Что дальше?

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

Если воткнуть в медведя датчик шума и настроить SMS-оповещения, при превышении определённого порога, сможете звонить каждый раз, как только малыш начнёт капризничать. WOW-эффект обеспечен.