HC-SR04 + Relay

Dima85
Offline
Зарегистрирован: 07.01.2013
#include <NewPing.h>
#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
********************* 
void loop() {
 delay(50);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).

  if (uS / US_ROUNDTRIP_CM < 150 and uS / US_ROUNDTRIP_CM > 15)
  {
    digitalWrite(Relay_1, LOW);// on
  }
  
  if (uS / US_ROUNDTRIP_CM < 15 and uS / US_ROUNDTRIP_CM > 1)
  {
    digitalWrite(Relay_1, HIGH);// on
  }

Написал простенький код, который включается и выключает ночник. Тоесть если махнуть рукой от 150 до 15 сантиметров от HC-SR04 ночник включится, если от 1 до 15 выключится.
 
Все работает, но все таки неудобно. Помогите пожалуйста реализовать условие,

Если махнуть рукой (на любом расстояние) ночник включится, но если же он уже включен, он должен выключится. И помогите пожалуйста избавиться от delay(50), т.к. это тормозит другие мои функции.

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

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

Так же введите переменную - флаг.

Примерно вот так.  

Мне не понятно зачем в программе нужен delay. Да и скорее всего не он тормозит программу а библиотека работы с датчиком.


int flag=0; 


#include <NewPing.h>
 #define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on the ultrasonic sensor.
 #define ECHO_PIN 11 // Arduino pin tied to echo pin on the ultrasonic sensor.
 #define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
 NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.void setup()

 {

 pinMode(1, OUTPUT);

 }

 void loop()

 {

unsigned int uS = sonar.ping();

if(uS / US_ROUNDTRIP_CM < 150 and uS / US_ROUNDTRIP_CM > 15&&flag==0)//если кнопка нажата
 // и перемення flag равна 0 , то ...
 {

 digitalWrite(1,!digitalRead(1));
 flag=1;
 //это нужно для того что бы с каждым нажатием кнопки
 //происходило только одно действие
 // плюс защита от "дребезга" 100%

 }

 if(uS / US_ROUNDTRIP_CM < 150 and uS / US_ROUNDTRIP_CM > 15&&flag==1)//если кнопка НЕ нажата
 //и переменная flag равна - 1 ,то ...
 {

 flag=0;//обнуляем переменную flag
 }
 }
leshak
Offline
Зарегистрирован: 29.09.2011

 

Можно конечно как и nestandert сделал.

 digitalWrite(1,!digitalRead(1));

Более того, в таком маленьком скетче так и нужно делать. Но если он планируется как "часть чего-то большего", то лучше все-таки в отдельную переменную сохранять текущие значение. Оно может и в других частях логики пригодится.

Вообще я бы примерно так это делал


#include <NewPing.h>
#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

#define PING_PERIOD 50 // как часто будет датчик опрашивать

bool relayState=false; // текущие состояние релешки
unsigned long lastPingTime=0; // когда мы послединй раз проверяли состояние датчика

********************* 
void loop() {
  if(millis()-lastPingTime>PING_PERIOD){ // наша замена delay(50)
    // весь этот код будет вызыватся раз в      PING_PERIOD миллисекунд   
    // опросим и сразу в сантиметры переведем
    unsigned int distance = sonar.ping()/US_ROUNDTRIP_CM; // Send ping, get ping time in microseconds (uS).    
    if(distance>1 && distance<150)relayState=!relayState; // если от 1 до 150 см, то инвертируем relayState
    
    lastPingTime=millis(); // запомнили когда мы последний раз датчик проверяли
  }
  
  digitalWrite(Relay_1, relayState);// вывели "текущие состояние" на настоящую релешку
}

К сожалению вы не дали ссылку на свою библиотеку NewPing так что проверить даже что "компилируется" я не могу (а самому гугилить-искать ее - я не хочу, раз вы не озаботились предоставить). Да и скетч вы дали "не целиком", так что и его проверить у себя, без дополнительной работы - никто не может. Вот, к примеру US_ROUNDTRIP_CM что за зверь? Только догадыватся. 

И еще, как верно подметил nestandard, проблема у вас может быть не только в delay(50), но и на sonar.ping() дуплить может.

Что-бы узнать это можно сделать     Serial.println(millis()); перед его вызовом и после. И посмотреть "сколкьо времени он занимает". Если что-то "слишком долго", то ... нужно будет что-то мудрить (и вот не факт что "тривиально будет", вплоть до "писать свою библиотеку, не блокирующую").

 

dimka
dimka аватар
Offline
Зарегистрирован: 21.09.2012

v.01 Arduino бесконтактный выключатель proximity Switch HC-SR04 Distance Measuring

Version 0.1-2013/08/04

подносим руку к дальномеру на расстояние не боле 9 сантиметров (параметр можно изменять),

сразу включится timer_led (жёлтый светодиод) информируя нас что мы "дотянулись до дальномера",

и сразу убираем руку (у нас полторы секунды чтоб успеть убрать руку )

timer_led отключается и включится led5 светодиод.

повторяя это телодвижение включаем led6 и led7



если удерживать руку перед дальномером больше 2 секунд все светодиоды led выключатся



----------------------------------------­-- 

скетч sketch: 

v.01 Arduino бесконтактный выключатель proximity Switch HC-SR04 Distance Measuring

http://yadi.sk/d/MDGctp9B7Zz7y

================================ 

изчего состоит;

1.ARDUINO, или ATMEGA328P-PU Microcontrolle?r ARDUINO UNO Bootloader и 16MHz Crystal

2. дальномер HC-SR04 Distance Measuring 

3. Breadboard макетная плата

не обязательно; 

4. USB To RS232 TTL PL2303HX Auto Converter Module Converter Adapter для питания и заливки скетча + кнопка 

5. Светодиоды нужны только для визуального контроля за процессом.

/*             v.01 Arduino бесконтактный выключатель proximity Switch HC-SR04 Distance Measuring
 ****************************
 урок от Дмитрия Осипова. http://www.youtube.com/user/d36073?feature=watch
 v.01 Arduino бесконтактный выключатель proximity Switch HC-SR04 Distance Measuring
 Version 0.1-2013/08/04
 -----------------------------
 изменения; в Version 0.1- 
 1. 
 2. 
 ------------------------------
 идеология;
 подносим руку к дальномеру на расстояние не боле 9 сантиметров (параметр можно изменять),
 сразу включится timer_led (жёлтый светодиод) информируя нас что мы "дотянулись до дальномера",
 и сразу убираем руку  (у нас полторы секунды чтоб успеть убрать руку )
 timer_led отключается и включится led5 светодиод.
 повторяя это телодвижение включаем led6 и led7
 
 если удерживать руку перед дальномером больше 2 секунд все светодиоды  led выключатся
 
 ------------------------------------------ 
 скетч sketch: 
 v.01 Arduino бесконтактный выключатель proximity Switch HC-SR04 Distance Measuring
 http://yadi.sk/d/MDGctp9B7Zz7y
 ================================ 
 изчего состоит;
 1.ARDUINO, или ATMEGA328P-PU Microcontrolle?r ARDUINO UNO Bootloader и 16MHz Crystal
 2. дальномер HC-SR04 Distance Measuring 
 3. Breadboard макетная плата
 не обязательно; 
 4. USB To RS232 TTL PL2303HX Auto Converter Module Converter Adapter для питания и заливки скетча + кнопка 
 5. Светодиоды нужны только для визуального контроля за процессом.
 --------------------------------
 программное:
 2. Библиотеки.
 =======================================================
 подробную видео инструкцию выложу здесь
 v.01 Arduino бесконтактный выключатель proximity Switch HC-SR04 Distance Measuring
 http://www.youtube.com/watch?v=_IlmwgxwG7A&feature=c4-overview&list=UU7aH7HVqDvwB1xNHfSl-fDw
 
 ++++++++++++++++++++++++++++++ 
 Вспомогательные видео обзоры, скетчи.....
 
 Самый дешевый Arduino Uno 5$ Minimal Atmega328 without Arduino Board
 http://www.youtube.com/watch?v=joSc-AT8o5k
 
 
 Arduino загрузить sketch В ATmega. USB To RS232 TTL PL2303HX Converter Adapter
 http://www.youtube.com/watch?v=W4LPlKKb__8
 
 sketch Demo HC-SR04 Distance Measuring
 http://yadi.sk/d/Xf14rWXW7Zz6E
 
 *******************************************************
 магазины где я покупал детали для устройства
 
 1pcs Ultrasonic Module HC-SR04 Distance Measuring Transducer Sensor for Arduino
 http://www.ebay.com/itm/1pcs-Ultrasonic-Module-HC-SR04-Distance-Measuring-Transducer-Sensor-for-Arduino-/261009210866?pt=LH_DefaultDomain_0&hash=item3cc55c7df2
 
 5 X ATMEGA328P-PU Microcontrolle?r With ARDUINO UNO Bootloader
 http://www.ebay.co.uk/itm/5-X-ATMEGA328P-PU-Microcontrolle-r-With-ARDUINO-UNO-Bootloader-/140810130918?pt=LH_DefaultDomain_0&hash=item20c8f015e6
 
 
 20Pcs New 16.000MHZ 16MHZ 16M HZ HC-49S Crystal Oscillator
 http://www.ebay.co.uk/itm/20Pcs-New-16-000MHZ-16MHZ-16M-HZ-HC-49S-Crystal-Oscillator-/130874956574?pt=LH_DefaultDomain_0&hash=item1e78c15b1e
 
 
 New Mini Solderless Breadboard Transparent Material 400 Points Available DIY
 http://www.ebay.co.uk/itm/New-Mini-Solderless-Breadboard-Transparent-Material-400-Points-Available-DIY-/140940411704?pt=LH_DefaultDomain_0&hash=item20d0b40338
 
 
 USB To RS232 TTL PL2303HX Auto Converter Module Converter Adapter For arduino
 http://www.ebay.com/itm/USB-To-RS232-TTL-PL2303HX-Auto-Converter-Module-Converter-Adapter-For-arduino-/300881830900?pt=LH_DefaultDomain_0&hash=item460df463f4
 
 
 ************************************************************
 
 */

//для дальномера
int TrigPin = 8;
int EchoPin = 9;

//для светодиодов
int led5 = 5;
int led6 = 6;
int led7 = 7;

//1.для удержания в HIGH пока рука не убрана
//2. для визуального контроля
int timer_led = 2;


//переменная для подсчета времени, продолжительности удержания руки перед дальномером
int position = 0;

void setup()
{
  pinMode(TrigPin,OUTPUT);
  pinMode(EchoPin,INPUT);

  pinMode(led5, OUTPUT); 
  pinMode(led6, OUTPUT); 
  pinMode(led7, OUTPUT);

  pinMode(timer_led, OUTPUT); 
}
void loop()
{
  int distance,duration;

  digitalWrite(TrigPin,HIGH);
  delayMicroseconds(11);
  digitalWrite(TrigPin,LOW);
  duration = pulseIn(EchoPin, HIGH);


  // устанавливаем расстояние для дальномера (impulseTime<900)
  //например только, после поднесения руки ближе чем 9 сантиметров  <900  ардуино начнёт обрабатывать команды
  //этот параметр можно настроить по своему вкусу

  if (duration<900) // Если расстояние менее 9 сантиметров 
  {     
    digitalWrite(timer_led, HIGH); // Светодиод горит 
  }  
  else 
  {   
    digitalWrite(timer_led, LOW); // иначе не горит 
  }   
  delay(100);   //защита от дребезга

  //после обнаружения (появления) сигнала ,начинаем прибавлять к переменной position по единице + 1
  if (duration<900) position = position + 1;


  //if(position > 0 если поднесена рука
  //проверяем убрана рука или нет &&(digitalRead(timer_led) == LOW
  //если рука НЕ убрана то с led нечего не делаем
  //если рука  убрана в течение 1 секунды включаем led7, HIGH. И ставим обратно в ноль position = 0

  // то бишь если рука не убрана в течение 1 секунды переменная position продолжает нарастать дальше
  //и дойдя где то за 2 секунды до значения 7 if (position > 6 ) выключит все led   

  if(position > 0 && (digitalRead(timer_led) == LOW && (digitalRead(led7) == LOW )))
    digitalWrite(led7, HIGH),(position = 0);
  delay(100); //чтоб успели убрать руку до начала следующей команды

  if(position > 0 && (digitalRead(timer_led) == LOW && (digitalRead(led7) == HIGH && (digitalRead(led6) == LOW ))))
    digitalWrite(led6, HIGH),(position =0);

  if(position > 0 && (digitalRead(timer_led) == LOW && (digitalRead(led6) == HIGH )))
    digitalWrite(led5, HIGH),(position =0);


  //чем более значение (position > 6, тем больше потребуется удерживать руку для отключения всех led
  if (position > 6 )digitalWrite(led7, LOW),digitalWrite(led6, LOW),digitalWrite(led5, LOW),(position =0),delay(1000); 
}