Автоматическая кухонная подсветка по ультразвуковому датчику

p-a-h-a
Offline
Зарегистрирован: 17.01.2019

Привет. Проект для управления светодиодной подсветкой.

При приближении человека на 1,2 метра плавно включается светодиодная лента на 12 Вольт. Если человек продолжает присутствовать в "поле зрения" датчика - лента светится. При покидании зоны через 30 секунд лента плавно гаснет. При поднесении руки к датчику на растояние менее 5 см - начинает увеличиваться яркость ленты и при достижении максимума сбрасывается на ноль.

Использованные компоненты: Arduino Pro mini, ультразвуковой дальномер HC-SR04, фоторезистор 1-20КОм, Мосфет с материнской платы, резистор 330 Ом.

Подключение: Датчик на пины 2,3,4,5. 2+, 3Trig, 4 Echo, 5-. Фоторезистор на + питания и A3. Резистор 330 Ом на А3 и минус. Мосфет затвор на 9, сток исток на минус и минус светодиодной ленты. Светодиодная лента вторым концом на +12В. Питание ардуино 12В на пин RAW.

#include "GyverFilters.h"
GMedian testFilter;
#include <EEPROM.h>
#define trigPin  3    //Триггер
#define echoPin  4    //Эхо
#define Ledpin  9    //Светодиодная лента через транзистор годятся только 9 или 10 пины для ШИМ 32 кГц!!!! Иначе медленный ШИМ убъет глаза!!
#define MinesPin  5    //- датчика
#define PlusPin  2    //+ Датчика
#define MinesPin  5    //- датчика
#define delay_Led 30000 //Задержка выключения света в мс
#define distOn 120//дистанция включения
#define distSet 5//дистанция срабатывания
#define analogSens 140// фотодатчик 0..1023. Не включаем подсветку днем
byte LightLed = EEPROM.read(0);//Яркость ленты 0..255. При первом включении яркость максимальная 255
unsigned long next_time;//Переменная задержки выключения
byte flag = LOW;// Флаг однократного плавного затухания

void setup() {
  TCCR1A = 0b00000001;  // 8bit
  TCCR1B = 0b00000001;  // x1 phase correct//разгоняем ШИМ на 9,10 пинах до 31,4 кГц
  analogReference(INTERNAL);//устанавливаем максимальное измеряемое напряжение аналогового входа 1,1В.
  pinMode(trigPin, OUTPUT);  //пин триггера в режиме выхода
  pinMode(echoPin, INPUT);  //пин эхо в режиме входа
  pinMode(MinesPin, OUTPUT);  digitalWrite(5, LOW); //питание датчика
  pinMode(PlusPin, OUTPUT);  digitalWrite(2, HIGH);//питание датчика
  pinMode(9, OUTPUT);// светодиод
}

void loop() {
  if (testFilter.filtered(measure()) < distOn) {//Обнаружение
    if (analogRead(A3) < analogSens) { //Проверяем яркость вокруг после обнаружения
      for (byte i = 0; i < LightLed; i++) {
        analogWrite(Ledpin, i);
        delay(10);
        if (i < 20) delay (30);
        if (i < 5) delay (50);
      }
      flag = HIGH;
presence:
      if (testFilter.filtered(measure()) < distOn) {// Светим пока присутствуем
        next_time = millis() + delay_Led;
        if (testFilter.filtered(measure()) < distSet) {//Управление ШИМ
          LightLed++;
          analogWrite(Ledpin, LightLed);
          if (LightLed == 255); delay (20000); //Остановка на макс яркости
          if (LightLed == 1); delay (5000); //Остановка на мин яркости
          goto presence;
        } else goto presence;
      } else goto Off;

    } else goto Off;
  } else goto Off;

Off:
  if (next_time > millis())goto presence;
  for (int i = LightLed * flag; i != 0; i--) {
    analogWrite(Ledpin, i);
    delay(20);
    if (i < 20) delay (30);
    if (i < 5) delay (50);
  }
  if (flag) EEPROM.update(0, LightLed);
  flag = LOW; analogWrite(Ledpin, 0);
}

long measure() {  //блок, измеряющий расстояние
  delay(50);//рекомендуемая задержка измерений
  digitalWrite(trigPin, LOW); delayMicroseconds(5);
  digitalWrite(trigPin, HIGH); delayMicroseconds(15);
  digitalWrite(trigPin, LOW);
  return (pulseIn(echoPin, HIGH) / 66);  //получаем расстояние с датчика
}

Библиотека цифровой фильтрации тут https://github.com/AlexGyver/GyverLibs

p-a-h-a
Offline
Зарегистрирован: 17.01.2019

Немного подправил код.

Теперь 5-8 см увеличивают яркость, менее 5см уменьшает яркость. Также добавил защиту от переполнения millis.

#include "GyverFilters.h"
GMedian testFilter;
#include <EEPROM.h>
#define trigPin  3    //Триггер
#define echoPin  4    //Эхо
#define Ledpin  9    //Светодиодная лента через транзистор годятся только 9 или 10 пины для ШИМ 32 кГц!!!! Иначе медленный ШИМ убъет глаза!!
#define MinesPin  5    //- датчика
#define PlusPin  2    //+ Датчика
#define delay_Led 30000 //Задержка выключения света в мс
#define distOn 120//дистанция включения
#define distSet 5//дистанция срабатывания
#define analogSens 140// фотодатчик 0..1023. Не включаем подсветку днем
byte LightLed = EEPROM.read(0);//Яркость ленты 0..255. При первом включении яркость максимальная 255
unsigned long next_time;//Переменная задержки выключения
byte flag = LOW;// Флаг однократного плавного затухания

void setup() {
  TCCR1A = 0b00000001;  // 8bit
  TCCR1B = 0b00000001;  // x1 phase correct//разгоняем ШИМ на 9,10 пинах до 31,4 кГц
  analogReference(INTERNAL);//устанавливаем максимальное измеряемое напряжение аналогового входа 1,1В.
  pinMode(trigPin, OUTPUT);  //пин триггера в режиме выхода
  pinMode(echoPin, INPUT);  //пин эхо в режиме входа
  pinMode(MinesPin, OUTPUT);  digitalWrite(5, LOW); //питание датчика
  pinMode(PlusPin, OUTPUT);  digitalWrite(2, HIGH);//питание датчика
  pinMode(9, OUTPUT);// светодиод
}

void loop() {
  if (testFilter.filtered(measure()) < distOn) {//Обнаружение
    if (analogRead(A3) < analogSens) { //Проверяем яркость вокруг после обнаружения
      for (byte i = 0; i < LightLed; i++) {
        analogWrite(Ledpin, i);
        delay(10);
        if (i < 20) delay (30);

      }
      flag = HIGH;
presence:
      if (testFilter.filtered(measure()) < distOn) {// Светим пока присутствуем
        next_time = millis() + delay_Led;
        long data = testFilter.filtered(measure());
        if (data < 8 && data > 4) { //Управление ШИМ
          LightLed++; if (LightLed == 255) {
            LightLed = 254;
          }
          analogWrite(Ledpin, LightLed);
          goto presence;
        }
        if (data < 5) {//Управление ШИМ
          LightLed--; if (LightLed == 0) {
            LightLed = 1;
          }
          analogWrite(Ledpin, LightLed);
          goto presence;
        } else goto presence;
      } else goto Off;
    } else goto Off;
  } else goto Off;

Off:
  if (next_time - millis() > delay_Led) {next_time = millis();} //Защита от переполнения millis()
  if (next_time > millis())goto presence;
  for (int i = LightLed * flag; i != 0; i--) {
    analogWrite(Ledpin, i);
    delay(20);
    if (i < 20) delay (30);
  }
  if (flag) EEPROM.update(0, LightLed);
  flag = LOW; analogWrite(Ledpin, 0);
}

long measure() {  //блок, измеряющий расстояние
  delay(50);//рекомендуемая задержка измерений
  digitalWrite(trigPin, LOW); delayMicroseconds(5);
  digitalWrite(trigPin, HIGH); delayMicroseconds(15);
  digitalWrite(trigPin, LOW);
  return (pulseIn(echoPin, HIGH) / 66);  //получаем расстояние с датчика
}

 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

p-a-h-a пишет:

 добавил защиту от переполнения millis.

Нахуа?  Она прекрасно защищена грамотным программированием.  А если ее надо защищать принудительно, то чота не в порядке в консерватории, например, программирование вапще не преподавают. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

p-a-h-a пишет:
Также добавил защиту от переполнения millis.

DetSimen пишет:
Нахуа?

Дык, школа-ж!

p-a-h-a пишет:

#include "GyverFilters.h"

p-a-h-a
Offline
Зарегистрирован: 17.01.2019

Дык, школа-ж!

p-a-h-a пишет:

#include "GyverFilters.h"

 

Он неоспоримый бог микроконтроллеров. Принимайте "Бомбит" и больше НЕБОМБИТ))) Лучше б goto покритиковали. Гайвер себе такого не позволяет.

Ну а по серйозному, какая разница кто библиотеку фильтра собрал. Фильтрует себе тихонько и кушать не просит. Проект рабочий. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

p-a-h-a пишет:
Лучше б goto покритиковали.
Вы правда считаете, что знаете что для нас лучше, а что хуже и вправе давать советы, о которых Вас никто не просил?

p-a-h-a пишет:
Фильтрует себе тихонько и кушать не просит.
Это Вам так кажется потому, что Вы не проверяли что и как там фильтруется (кто ж будет Бога проверять? Ни одна религия такого не позволит!).

С тех пор, как Гиверу показали грубую ошибку в этой библиотеке (см. #52) он попытался её исправить (см. ту же функцию здесь). Но, исправил неправильно. Так что ... «фильтрует, не сомневайтесь» :=)

v258
Offline
Зарегистрирован: 25.05.2020

p-a-h-a пишет:

Лучше б goto покритиковали. Гайвер себе такого не позволяет.

Да без проблем - вместо goto нужный блок кода выносится в отдельную процедуру, которая и вызывается при необходимости. Не верите? Спросите у Гайвера ))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

v258 пишет:
Спросите у Гайвера ))
Спрашивать надо у Рабиновича! :-)

v258
Offline
Зарегистрирован: 25.05.2020

ЕвгенийП пишет:

v258 пишет:
Спросите у Гайвера ))
Спрашивать надо у Рабиновича! :-)

Я в их религиях не силен ))

ziyara
Offline
Зарегистрирован: 05.11.2019

здравствуйте

помогите пожалуйста разобраться со скетчем

,библиотеку по ссылке скачал положил в библиотеки,не компилируется,пишет ошибку
invalid use of template-name 'GMedian' without an argument list

p-a-h-a
Offline
Зарегистрирован: 17.01.2019

Скетч - подключить библиотеку - добавить zip библиотеку.

ziyara
Offline
Зарегистрирован: 05.11.2019

спасибо p-a-h-a,попробывал этот вариант,теперь кампилятор ругается на это

C:\Users\name\Documents\Arduino\libraries\GyverFilters\src/GyverFilters.h:4:10: fatal error: filters/linear.h: No such file or directory
 #include <filters/linear.h>
видимо не может найти файл в библиотеке.
может библиотека обновленная?
а старая есть библиотека у кого нибудь?
ziyara
Offline
Зарегистрирован: 05.11.2019

столько всего кампилировалось,а это ни какую,что вообще происходит

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

ziyara пишет:

столько всего кампилировалось,а это ни какую,что вообще происходит

Попробуй компилировать, может удачнее будет.

ziyara
Offline
Зарегистрирован: 05.11.2019

вы какую версию GyverFilters использовали:
1.6
1.7
1.8
2.0
??

ziyara
Offline
Зарегистрирован: 05.11.2019

так вот и так и так пробовал.

ziyara
Offline
Зарегистрирован: 05.11.2019

Ворота пишет:

ziyara пишет:

столько всего кампилировалось,а это ни какую,что вообще происходит

Попробуй компилировать, может удачнее будет.

так вот и так и так пробовал.

ziyara
Offline
Зарегистрирован: 05.11.2019

может кому пригодится:
GyverFilters V 1.3
файлы с расширением "h";"ccp"
положить туда где лежит файл скетча.

ziyara
Offline
Зарегистрирован: 05.11.2019

p-a-h-a пишет:

Скетч - подключить библиотеку - добавить zip библиотеку.

доброго дня,

p-a-h-a вы можете поправить код,под новую библиотеку фильтров или помочь разобраться с этим?

ещё подсветка выключается и обратно включается,хотя и находишся в поле зрения дальномера 30 см (уставка 80 см)

задержка выключения 3 сек(3000)

ziyara
Offline
Зарегистрирован: 05.11.2019

ещё бы,индикацию ввести при регулировке яркости (на цыфровые пины)когда прибавляешь и убавляешь,и ночной режим,допустим в % от максимальной яркости,

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ziyara пишет:

может кому пригодится:
GyverFilters V 1.3

Интересно, кому может пригодится неработающий код? GyverFilters же цену на прошлогодний овёс выдаёт, это давно известно.

p-a-h-a
Offline
Зарегистрирован: 17.01.2019

Да выкиньте вы этот фильтр, скользящее среднее вставьте вместо него да и все. А еще лучше на прерываниях сделать измерение с фильтром. Что было под рукой то и взял. Кому не нравится, тот сам делает устройство своим кодом. На коленке за пол часа набросал код да и все. Хоть кто то бы альтернативу предложил. Что ж все такие недоброжелательные профессионалы, диванные критики тут?

ziyara
Offline
Зарегистрирован: 05.11.2019

p-a-h-a пишет:
Да выкиньте вы этот фильтр, скользящее среднее вставьте вместо него да и все. А еще лучше на прерываниях сделать измерение с фильтром. Что было под рукой то и взял. Кому не нравится, тот сам делает устройство своим кодом. На коленке за пол часа набросал код да и все. Хоть кто то бы альтернативу предложил. Что ж все такие недоброжелательные профессионалы, диванные критики тут?

1.вариант подсветки супер,по памяти влезет в атмегу 8,клаас.
2.я вообще код не могу писать,тем более какие то фильтры вставлять)))

3.поэтому и задаю вопросы,вот так,можете попинать малехо))

ziyara
Offline
Зарегистрирован: 05.11.2019

p-a-h-a пишет:
На коленке за пол часа набросал код да и все. Хоть кто то бы альтернативу предложил. Что ж все такие недоброжелательные профессионалы, диванные критики тут?

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

b707
Offline
Зарегистрирован: 26.05.2017

p-a-h-a пишет:

... Что было под рукой то и взял. ...

... На коленке за пол часа набросал код да и все....

Гайвер-стиль - "тяп-ляп  - в продакшн?"

Что ж тогда удивлятся на реакцию сообщества?

p-a-h-a
Offline
Зарегистрирован: 17.01.2019

Три светодиода добавились. На 10,11,12 пины. Два показывают в какую сторону яркость изменяется, третий (10) изменяет свою яркость в зависимости от расстояния. Гайвер фильтр заменен функцией скользящего среднего.

//----------Используемые библиотеки---------------------
#include <EEPROM.h> // Стандартная библиотека, не требует установки.
//--------- Пины подключения периферии------------------
//Сигнальные светодиоды:
#define ledDistance 10 // Светодиод указывает дистанцию до объекта. Ярче - ближе.
#define ledLightUp 11 // Светодиод указывает, что яркость увеличивается
#define ledLightDown 12// Светодиод указывает, что яркость уменьшается
#define ledPin  9    //Светодиодная лента через транзистор годятся только 9 или 10 пины для ШИМ 32 кГц!!!! Иначе медленный ШИМ убъет глаза!!
//Датчик расстояния
#define trigPin  3    //Триггер
#define echoPin  4    //Эхо
#define MinesPin  5    //- датчика
#define PlusPin  2    //+ Датчика
//Датчик освещенности (фоторезистор)
#define lightPin  A3
//----------------Настройки поведения-------------------
#define NUM_AVER 10       // Количество измерений для расчета среднего значения расстояния. Больше - медленнее реакция
#define delay_Led 60000 //Задержка выключения света в мс после последнего обнаружения человека
#define distOn 100 //дистанция в см, на которой при обнаружении объекта включется свет
#define distLightUp 12//дистанция в см, при которой начинается увеличение яркости
#define distLightDown 5 // дистанция в см, при которой начинается уменьшение яркости
#define analogSens 110// Фотодатчик 0..1023. Не включаем подсветку днем. 
#define delayMeasurement 20 // Задержка перед каждым измерением дистанции. Рекомендована 50. Влияет на скорость реакции, особенно при изменении яркости.
//-------------------Переменные-------------------------
uint8_t LightLed = EEPROM.read(0);//Яркость ленты. Читаем из энергонезависимой памяти 0..255.
uint32_t timePowerrOff;// Переменная содержит время, когда нужно выключить свет
boolean ledOffFlag = true;// Флаг однократного плавного затухания
boolean eepromNeedUpdate = false; // Флаг что яркость поменялась и ее нужно запомнить при следующем выключении света

void setup() {
  Serial.begin(115200);
  TCCR1A = 0b00000001;  // 8bit
  TCCR1B = 0b00000001;  // x1 phase correct//разгоняем ШИМ на 9,10 пинах до 31,4 кГц
  analogReference(INTERNAL);//устанавливаем максимальное измеряемое напряжение аналогового входа 1,1В.
  pinMode(trigPin, OUTPUT);  //пин триггера в режиме выхода
  pinMode(echoPin, INPUT);  //пин эхо в режиме входа
  pinMode(MinesPin, OUTPUT);  digitalWrite(MinesPin  , LOW); //питание датчика
  pinMode(PlusPin, OUTPUT);  digitalWrite(PlusPin  , HIGH);//питание датчика
  pinMode(ledPin, OUTPUT);// светодиодная лента
  pinMode(ledLightUp, OUTPUT);
  pinMode(ledLightDown, OUTPUT);
}

void setLedOn() {
  if (ledOffFlag) { // Если свет был выключен то плавно зажигаем его
    for (int i = 0; i <= LightLed; ++i) {
      analogWrite(ledPin, i);
      delay(30);
      if (i < 20) delay (40);
    }
  }
  timePowerrOff = delay_Led + millis();
  digitalWrite (ledLightUp, false);// Гасим светодиод настройки яркости
  digitalWrite (ledLightDown, false);// Гасим светодиод настройки яркости
  ledOffFlag = false; // Опустили флаг. Свет включен.
}

void setLedDistance(uint32_t distance) {// меняем яркость индикаторного светодиода в соответствии с дистанцией
  if (distance > distLightUp) { //Если мы не в режиме настроек яркости то отобразим дистанцию.
    distance = constrain(distance, 0, distOn);
    distance =  map(distance, 0, distOn, 100, 0);
    analogWrite(ledDistance, distance);
  }
}

void setLedLightDown() {// Настройка уменьшения яркости
  analogWrite(ledDistance, 0); // Гасим светодиод настройки яркости
  if (LightLed == 1)
    digitalWrite (ledLightDown, LOW);
  else
    digitalWrite (ledLightDown, HIGH);// Включаем светодиод настройки яркости
  if (LightLed > 1) {
    LightLed--;
    analogWrite(ledPin, LightLed);
  }
  eepromNeedUpdate = true; // Поднимаем флаг что нужно сохранить настройки яркости в энергонезависимую память
}

void setLedLightUp() {// Настройка увеличения яркости
  analogWrite(ledDistance, 0);// Гасим светодиод настройки яркости
  if (LightLed == 255)
    digitalWrite (ledLightUp, LOW);
  else
    digitalWrite (ledLightUp, HIGH);// Включаем светодиод настройки яркости
  if (LightLed < 255) {
    LightLed++;
    analogWrite(ledPin, LightLed);
  }
  eepromNeedUpdate = true;  // Поднимаем флаг что нужно сохранить настройки яркости в энергонезависимую память
}

void powerrOff() {//Плавное выключение
  for (int i = LightLed; i != 0; --i) {
    analogWrite(ledPin, i - 1);
    delay(30);
    if (i < 20) delay (40);
  }

  ledOffFlag = true; // Подняли флаг что свет выключен
  if (eepromNeedUpdate) { // В случае изменения, сохраняем текущие настройки яркости в энергонезависимую память.
    EEPROM.update(0, LightLed);
    eepromNeedUpdate = false;
  }

}

void loop() {
  uint32_t distance = middleArifm(measure()); //Показания датчика расстояния
  uint16_t light = analogRead(lightPin); //Показания датчика света
  setLedDistance(distance);// Обновить яркость светодиода, показывающего дистанцию
  if (light < analogSens || timePowerrOff > millis()) { // Если недостаточно света или сейчас включен свет
    if (distance < distOn)  //И если в поле зрения датчика кто-то есть
      setLedOn();// Включить свет
    if (distance < distLightUp && distance > distLightDown)// Если дистанция небольшая то увеличиваем яркость
      setLedLightUp();
    if (distance <= distLightDown) // Если дистанция совсем маленькая то уменьшаем яркость
      setLedLightDown();
  }
  if (timePowerrOff < millis() && !ledOffFlag) // Если долго никого не было и свет еще не выключали то гасим свет
    powerrOff();
  if (ledOffFlag)
    2 + 2 != 4;
}

uint32_t measure() {  //блок, измеряющий расстояние
  delay(delayMeasurement);//Задержка перед измерением дистанции
  digitalWrite(trigPin, LOW); delayMicroseconds(5);
  digitalWrite(trigPin, HIGH); delayMicroseconds(15);
  digitalWrite(trigPin, LOW);
  return (pulseIn(echoPin, HIGH) / 66);  //получаем расстояние с датчика
}

uint32_t middleArifm(uint32_t newVal) {       // принимает новое значение
  uint32_t average;             // перем. среднего
  static uint32_t valArray[NUM_AVER];   // массив
  static byte idx = 0;             // индекс
  static boolean firstRun = true;
  valArray[idx] = newVal;           // пишем каждый раз в новую ячейку
  if (++idx >= NUM_AVER) idx = 0;   // перезаписывая самое старое значение
  average = 0;                      // обнуляем среднее
  for (int i = 0; i < NUM_AVER; i++) {
    if (firstRun) valArray[i] = distOn + 1; // при первом включении устанавливаем дистанцию чтоб не менялась яркость
    average += valArray[i];         // суммируем
  }
  average /= NUM_AVER;              // делим
  firstRun = false;
  return average;                   // возвращаем
}

 

ziyara
Offline
Зарегистрирован: 05.11.2019

Во красавчик p-a-h-a .