Управление реле через ультразвуковой датчик расстояния

sondr
Offline
Зарегистрирован: 23.02.2016

Сильно не ругайтесь, если что :)

Я только сегодня стал счастливым обладателем ардуинки. Уже успел помигать светодиодом с небольшими усовершенствованиями (двойное короткое мигание + пауза), научился работать с реле, определять расстояние с УЗ-датчика расстояния (для удобства вынес в отдельную функцию).

Для случая, когда включаем реле при поднесении руки ближе чем на 15см к УЗ-датчику, проблем нет, это элементарная логика: определяем расстояние, затем если оно меньше 15см, то включаем реле, иначе отключаем.

Проблема возникла когда появилась идея при первом поднесении руки включать реле, при втором - выключать, и так далее. Сложность не в ардуинке, и не в языке программирования, а именно в мозгу - не могу понять, как правильно обрабатывать такие условия, какие переменные выставлять, как запоминать в переменных факт наведения, и  в конечном итоге - в каком случае включать/отключать реле, а в каком - ничего не делать.

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

const int pinUltraSonicTrig = 8;
const int pinUltraSonicEcho = 4;
const int pinRelay = 2;
const int pinLed = 13;
boolean RelayOn = false;
boolean LastDistIsLow = false;
boolean DistChanged = true;

void setup() {
  Serial.begin(9600);
  pinMode(pinUltraSonicTrig,OUTPUT);
  pinMode(pinUltraSonicEcho,INPUT);
  pinMode(pinRelay,OUTPUT);
  pinMode(pinLed,OUTPUT);
}

void loop() {
  int cm = GetDistance(pinUltraSonicTrig, pinUltraSonicEcho);
  boolean LowDist = cm<=15;
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  if(LowDist) {
    if(DistChanged){
      if(RelayOn) {
        digitalWrite(pinRelay,HIGH);
      } else {
        digitalWrite(pinRelay,LOW);
      }
      RelayOn = !RelayOn;
      LastDistIsLow = true;
    }
  }
  if(LastDistIsLow == LowDist) {
    DistChanged = true;
  }
  digitalWrite(pinLed,HIGH);
  delay(100);
  digitalWrite(pinLed,LOW);
  delay(100);
}

int GetDistance(int pinTrig, int pinEcho)
{
  digitalWrite(pinTrig, LOW);
  delayMicroseconds(2);
  digitalWrite(pinTrig, HIGH);
  delayMicroseconds(10);
  digitalWrite(pinTrig, LOW);
  pinMode(pinEcho, INPUT);
  long duration = pulseIn(pinEcho, HIGH);
  long cm = duration / 29 / 2;
  return cm;
}

Но тут вся логика проверка не та.. Нужно как-то по-другому. Буду благодарен всем, кто откликнется.

sondr
Offline
Зарегистрирован: 23.02.2016

Хватило поужинать, отдохнуть, поиграть с ребенком, и после этого за 5 минут все заново переписал. Вот что значит голова перестает соображать. А то я уж испугался: если такое не получается самостоятельно сделать, то что же будет дальше..

Если кому-то вдруг пригодится, то вот:

const int pinUltraSonicTrig = 8;
const int pinUltraSonicEcho = 4;
const int pinRelay = 2;
const int pinLed = 13;
boolean firstMove = true;
boolean lastIsNear = false;
boolean relayOn = false;

void setup() {
  Serial.begin(9600);
  pinMode(pinUltraSonicTrig,OUTPUT);
  pinMode(pinUltraSonicEcho,INPUT);
  pinMode(pinRelay,OUTPUT);
  pinMode(pinLed,OUTPUT);
}

void loop() {
  int cm = GetDistance(pinUltraSonicTrig, pinUltraSonicEcho);
  if(cm>0) {
    Serial.println(cm);
    boolean IsNear = cm<=15;
    if (IsNear && !lastIsNear) {
      if(relayOn) {
        digitalWrite(pinRelay,LOW);
        digitalWrite(pinLed,LOW);
      } else {
        digitalWrite(pinRelay,HIGH);
        digitalWrite(pinLed,HIGH);
      }
      relayOn = !relayOn;
    }
    lastIsNear = IsNear;
  }
  delay(100);
}

int GetDistance(int pinTrig, int pinEcho)
{
  digitalWrite(pinTrig, LOW);
  delayMicroseconds(2);
  digitalWrite(pinTrig, HIGH);
  delayMicroseconds(10);
  digitalWrite(pinTrig, LOW);
  pinMode(pinEcho, INPUT);
  long duration = pulseIn(pinEcho, HIGH);
  long cm = duration / 29 / 2;
  return cm;
}