Делаем ассистент-парковщик для гаража с помощью Arduino

Мы уже сделали один помощник при парковке автомобиля ранее, но сегодня мы создадим немного другой гаджет с помощью Arduino Nano Rev 3.

Часто когда мы паркуемся в своем гараже пространство очень ограничено. Например, семейный автомобиль нашего коллеги примерно на 10 см короче свободного пространства в его гараже. В машине есть датчики парковки, но они очень ограничены: когда до стены меньше 20 см они показывают предупреждение, поэтому очень трудно остановить автомобиль ближе чем на 8 см.

Идея состояла в том, чтобы использовать ультразвуковой датчик расстояния для этой цели вместе с Arduino. Примеров устройств очень много (и часть мы еще сделаем вместе в ближайшее время), но мы хотели получить более точное устройство, чем просто «слишком далеко / слишком близко» с 2 светодиодами. Сначала мы хотели сделать гаджет с 7-сегментным светодиодным дисплеем, но процесс измерения расстояния полезно только в течение нескольких секунд, а что будет делать устройство оставшуюся часть дня? Поэтому мы добавил часы реального времени, но как гаджет переключится между отображением времени и парковкой? Для этого мы добавили датчик освещенности.

Шаг 1: Список комплектующих

  • Arduino Nano Rev3
  • HC-SR04 ультразвуковой датчик расстояния (около 1 доллара США)
  • 7-сегментный 4-разрядный 12-контактный светодиодный индикатор с диагональю 0,56 дюйма (1,77 доллара США)
  • Плата DS3231RTC (0,87 доллара США)
  • Плата датчика освещенности (0,4 доллара)
  • 2 штуки 74HC595N IC сдвиговых регистра ($0,54 за 10 комплектов)
  • Красный светодиод
  • Зеленый светодиод
  • 4 резистора 220 Ом
  • 1 резистор 560 Ом

Все комплектующие доступны во многих Интернет-магазинах. Мы добавили цены для конкретных деталей, основываясь на опыте заказа их в Китае. Датчик света - дешевый и простой, но уже имеет компаратор напряжения LM393.

7-сегментный светодиодный дисплей имеет 12 контактов. Вы также можете использовать любой другой тип, но некоторые дальнейшие шаги описаны на основе назначений контактов этого дисплея. Вы можете найти схему дисплея на следующих шагах.

Шаг 2: Схема

U1 - Arduino Nano Rev3, но схема также хорошо работает с Arduino Uno.

U2, U3: Из-за дешевого светодиодного дисплея приходится использовать сдвиговые регистры, чтобы не съедать все цифровые выходы. U2 управляет катодами, а U3 подключен к анодам с резисторами 220 Ом.

LED2, LED3: зеленый и красный светодиоды, чтобы помочь парковке визуально. Это не обязательно, но может немного помочь.

S1: датчик освещенности. Когда въезжаем в гараж где нет света, автоматически загораются огни автомобиля, поэтому с этим датчиком можно легко решить, стоит ли автомобилю остановиться или нет. Если да, тогда укажем расстояние, иначе показываем время. Это устройство имеет цифровой выход, который может быть высоким или низким на основе внешнего освещения и настройки потенциометра триггера.

S2: Ультразвуковой датчик. Действительно дешевый. Он имеет триггер и эхо-штырь. Использование довольно прямолинейно, особенно если вы используете библиотеку, предназначенную для этой цели. Мы использовали NewPing.

RTC1: плата DS3231 Real Time Clock. Довольно точная и имеет особенность - измеряет температуру и вы также можете отобразить эту информацию.

Шаг 3: Собираем схему

Мы собрали схему на макетной плате и смоделировали всё используя fritzing для лучшего понимания. Понимаем, что многовато кабелей, поэтому не смогли выбрать разные цвета для всех катодных контактов. Надеемся, что итак всё понятно.

Шаг 4: Код

Вот исходный код для нашего устройства - парковщика.

/*
 HC-SR04 Ping distance sensor based wall clock with light sensor and RTC support.
 If the light sensor getting high then display changes from time display to distance display in cm.

 pin | usage
 -----------------------------
 A4  | SDA of RTC (I2C)
 A5  | SCL of RTC (I2C)
 10  | Shift register data
 9   | Shift register latch
 8   | Shift register clock
 7   | light sensor
 6   | LED shows too far
 5   | LED shows close enough
 4   | TRIG of distance sensor
 3   | ECHO of distance sensor
*/

#include <Arduino.h>
#include <TimeLib.h>
#include <DS3232RTC.h>
#include <NewPing.h>

//7 segment 4 digit display's shift register pins:
#define PIN_SHIFT_DATA 10
#define PIN_SHIFT_LATCH 9
#define PIN_SHIFT_CLOCK 8
//Light sensor pin:
#define PIN_LIGHT_SENSOR 7
//Distance led pins:
#define PIN_LED_FAR 6
#define PIN_LED_CLOSE 5
//Distance sensor pins:
#define PIN_TRIG 4
#define PIN_ECHO 3

#define WARN_DISTANCE 5  //in cm
#define MAX_DISTANCE 100 //in cm

#define brightnessHigh 20
#define brightnessLow 12

const byte num[] = {
  B11111100, //0
  B01100000, //1
  B11011010, //2
  B11110010, //3
  B01100110, //4
  B10110110, //5
  B10111110, //6
  B11100000, //7
  B11111110, //8
  B11110110, //9
  B00000000, //empty
  B00000010  //minus sign
};


NewPing distSensor(PIN_TRIG, PIN_ECHO, MAX_DISTANCE);
static unsigned long last = 0;
static unsigned long now_ = 0;

void setup() {
	Serial.begin(9600);
//Init the distance sensor:
	pinMode(PIN_LED_CLOSE, OUTPUT);
	digitalWrite(PIN_LED_FAR, LOW);
	pinMode(PIN_LED_FAR, OUTPUT);
	pinMode(PIN_LIGHT_SENSOR, INPUT);
//Init the RTC:
	setSyncProvider(RTC.get);
	setSyncInterval(600);
  setTime(RTC.get());
	if (timeStatus() == timeSet)
  	Serial.println("RTC: Ok!");
	else
	  Serial.println("RTC: FAIL!");
//Init the display:
  pinMode(PIN_SHIFT_LATCH, OUTPUT); // Define the 3 digital pins as output
  pinMode(PIN_SHIFT_CLOCK, OUTPUT);
  pinMode(PIN_SHIFT_DATA, OUTPUT);

	last = millis();
}

void loop() {
  static byte numbers[4];
	now_ = millis();
	if (!digitalRead(PIN_LIGHT_SENSOR)) { //show distance
		if (now_ - last >= 500) {
			unsigned long distance = distSensor.convert_cm(distSensor.ping_median(1, MAX_DISTANCE));
			if (distance <= WARN_DISTANCE && distance > 0) {
				digitalWrite(PIN_LED_CLOSE, HIGH);
				digitalWrite(PIN_LED_FAR, LOW);
			} else {
				digitalWrite(PIN_LED_CLOSE, LOW);
				digitalWrite(PIN_LED_FAR, HIGH);
			}
			if (distance == 0) {
        numbers[0] = 9;
        numbers[1] = 9;
        numbers[2] = 9;
        numbers[3] = 9;
//				Serial.println("Out of range");
			} else {
        numbers[0] = distance / 1000;
        numbers[1] = distance / 100;
        numbers[2] = distance / 10;
        numbers[3] = distance % 10;
//				Serial.print(distance);
//				Serial.println(" cm");
			}
			last = now_;
		}
    displayDigits(numbers, false, brightnessHigh);
	} else { //show time
		digitalWrite(PIN_LED_FAR, LOW);
		digitalWrite(PIN_LED_CLOSE, LOW);
		time_t t = now();
		byte h = hour(t);
		byte m = minute(t);
		byte s = second(t);
//			Serial.println((h < 10 ? "0" : "") + String(h) + (s % 2 ? " " : ":") + (m < 10 ? "0" : "") + String(m));
    numbers[0] = h/10;
    numbers[1] = h%10;
    numbers[2] = m/10;
    numbers[3] = m%10;
    displayDigits(numbers,s%2,brightnessLow);
		last = now_;
	}
}

void displayDigits(byte numbers[], bool colon, int brightness){
  static unsigned long last;
  unsigned long brightnessDelay = 20 - constrain(brightness, 1, 20);
  if ((millis() - last) < brightnessDelay)
    return;
  last = millis();
  for (int i=0;i<4;i++){
    digitalWrite(PIN_SHIFT_LATCH, LOW);
    shiftOut(PIN_SHIFT_DATA, PIN_SHIFT_CLOCK, LSBFIRST, ~128>>i);     //Select digit #i
    byte seg = num[numbers[i]];
    if (colon && i == 1)
      seg++;
    shiftOut(PIN_SHIFT_DATA, PIN_SHIFT_CLOCK, LSBFIRST, seg);         //Set the segments
    digitalWrite(PIN_SHIFT_LATCH, HIGH);
  }
  digitalWrite(PIN_SHIFT_LATCH, LOW);
  shiftOut(PIN_SHIFT_DATA, PIN_SHIFT_CLOCK, LSBFIRST, ~16);           //Select digit #4
  shiftOut(PIN_SHIFT_DATA, PIN_SHIFT_CLOCK, LSBFIRST, 0);             //Set the segments to empty
  digitalWrite(PIN_SHIFT_LATCH, HIGH);
}

Шаг 5: Тестируем результат

Мы смоделировали устройство на макете. В нижней левой части вы можете увидеть ультразвуковой датчик, зеленый светодиод на другом подключенном кабеле показывает, что датчик внешней освещенности имеет входное напряжение. На втором снимке на датчике освещенности есть 2 зеленых индикатора, но это не так просто продемонстрировать с помощью изображений.

Фото 1. В гараже нет машины. Устройство отображает время с не слишком яркими цифрами.

Фото 2. Автомобиль освещает датчик, но слишком далеко, чтобы измерить. Мы установили это расстояние практически в 1 метр. В этом случае на дисплее отображается «9999».

Фото 3. Автомобиль находится на расстоянии 10 см от датчика расстояния и освещает датчика освещенности. Зеленые светодиод показывают, что можно подъехать поближе, но осторожнее.

Фото 4. Автомобиль находится примерно на расстоянии 5 см от датчика расстояния, поэтому красный светодиод показывает, что он достаточно близко и можно остановиться. Т.е. наш коллега сможет закрыть дверь гаража без каких-либо проблем.

Ардуино+