hc-sr04 Наполнение бочки для полива, помогите пожалуйста.

Тема в разделе "Arduino & Shields", создана пользователем kka, 27 апр 2016.

  1. kka

    kka Нуб

    Есть емкость на 1000 литров, дальномер hc-sr04, электромагнитный клапан 12 вольт, Ардуино UNO и реле.

    Задача ултразвукового hc-sr04: Включить реле ( открыть клапан ) на расстоянии 90 см от дальномера и выключить реле на расстоянии 10 см, и ОЧЕНЬ важный цикл - НЕ включать реле пока уровень воды не опустился на 90 см, потом открыл клапан, емкость наполнилась до 10 см от УЗ hc-sr04, и снова реле выключилось, и НЕ включается до 90 см. Нашел в форуме код но для моей задачи он не пдходит. Помогите с кодом.
    01 #define Trig 6
    02 #define Echo 7
    03 #define ledPin 8
    04
    05 void setup()
    06 {
    07 pinMode(Trig, OUTPUT); //инициируем как выход
    08 pinMode(Echo, INPUT); //инициируем как вход
    09 pinMode(ledPin, OUTPUT);
    10 Serial.begin(9600);
    11 /* задаем скорость общения. В нашем случае с компьютером */
    12 }
    13 unsigned int impulseTime=0;
    14 unsigned int distance_sm=0;
    15
    16 void loop()
    17 {
    18 digitalWrite(Trig, HIGH);
    19 /* Подаем импульс на вход trig дальномера */
    20 delayMicroseconds(10); // равный 10 микросекундам
    21 digitalWrite(Trig, LOW); // Отключаем
    22 impulseTime=pulseIn(Echo, HIGH); // Замеряем длину импульса
    23 distance_sm=impulseTime/58; // Пересчитываем в сантиметры
    24 Serial.println(distance_sm); // Выводим на порт
    25 if (distance_sm<40) // Если расстояние менее 30 сантиметром
    26 {
    27 digitalWrite(ledPin, HIGH); // Светодиод горит
    28 }
    29 else
    30 {
    31 digitalWrite(ledPin, LOW); // иначе не горит
    32 }
    33 delay(100);
    34 /* ждем 0.1 секунды, Следующий импульс может быть излучён, только после исчезновения эха от предыдущего.
    35 Это время называется периодом цикла (cycle period).
    36 Рекомендованный период между импульсами должен быть не менее 50 мс. */
    37 }
     
  2. ostrov

    ostrov Гуру

    Код в тег засуньте для начала.

    На вскидку вижу, что светодиод (видимо он является прототипом реле клапана) включается только один раз при расстоянии до воды менее 40см. Соответственно, когда уровень прибавится хоть на 1мм он выключится. Это не правильно. Расстояние, между точками "полный" и "пустой", которые активируют выкл и вкл, называется гистерезисом, то есть состояние реле клапана в нем определяется предысторией. Проблема решается добавлением одной переменной - флага, который и будет свидетельствовать о том, наполняется сосуд в данный момент или опорожняется.
     
    Последнее редактирование: 28 апр 2016
  3. Tomasina

    Tomasina Сушитель лампочек Модератор

    @kka, у тебя исходные требования настолько сумбурные, что 70% можно выкинуть.
    Вот вся логика:
    Код (C++):
    volume = readUltarsonic();
    if(volume > MAX) relay(ON);
    if(volume < MIN) relay(OFF);
     
     
    ostrov нравится это.
  4. ostrov

    ostrov Гуру

    Можно и так:
    [​IMG]

    Эта конструкция не только дешевле, проще и надежнее, но и полностью автономна. А еще имейте в виду, что УЗ датчик долго в сырой емкости не проработает. Уже на этом форуме обсуждалось.
     
    Последнее редактирование: 10 май 2016
    cody_c++ нравится это.
  5. kka

    kka Нуб

    Про "сырость для УЗ" слышал, осталось убедиться .
     
  6. kka

    kka Нуб

    Должно получиться так ?

    #include <Ultrasonic.h>

    #define Trig 6
    #define Echo 7
    #define ledPin 8

    void setup()
    {
    const int LowLevel=90, HighLebel=10;
    pinMode(ledPin, OUTPUT);
    }
    void loop()
    {
    volume = readUltarsonic();
    if(volume > MAX) relay(ON);
    if(volume < MIN) relay(OFF);

    }
     
  7. Tomasina

    Tomasina Сушитель лампочек Модератор

    ты забыл чтение данных с датчика :)
    Код (C++):
    #include <Ultrasonic.h>

    #define Trig   6
    #define Echo   7
    #define ledPin 8
    #define ON     HIGH    // если реле инверсное, то LOW
    #define OFF    LOW     // если реле инверсное, то HIGH
    const int LowLevel=90;
    const int HighLevel=10;

    void setup()
    {
      pinMode(ledPin, OUTPUT);
      pinMode(Trig, OUTPUT);  //возможно это не нужно
      pinMode(Echo, INPUT);   //возможно это не нужно
    }

    void loop()
    {
      volume = readUltarsonic();
      if(volume > HighLevel) relay(ON);
      if(volume < LowLevel) relay(OFF);
      delay(100);
    }

    int readUltarsonic()
    {
      unsigned int impulseTime=0;
      unsigned int distance_sm=0;
      digitalWrite(Trig, HIGH);
      /* Подаем импульс на вход trig дальномера */
      delayMicroseconds(10); // равный 10 микросекундам
      digitalWrite(Trig, LOW); // Отключаем
      impulseTime=pulseIn(Echo, HIGH); // Замеряем длину импульса
      distance_sm=impulseTime/58; // Пересчитываем в сантиметры
      //Serial.println(distance_sm); // Выводим на порт
      return distance_sm;
    }
     
  8. kka

    kka Нуб

     
  9. kka

    kka Нуб

    Ругается на строку
    volume = readUltarsonic();
    не получается скомпилировать, не понимаю что не так-то ?
     
  10. Tomasina

    Tomasina Сушитель лампочек Модератор

    надо так:
    volume = readUltrasonic();
     
  11. kka

    kka Нуб

    Спасибо за внимательность ! я долго искал разницу в разных но похожих выражениях, вот что получилось, и все же ругается на volume = readUltrasonic(); проверил для Меги та-же строка подсвечена, прошу помогите доделать код

    #include <Ultrasonic.h>

    #define Trig 6
    #define Echo 7
    #define ledPin 8
    #define ON HIGH // если реле инверсное, то LOW
    #define OFF LOW // если реле инверсное, то HIGH
    const int LowLevel=90;
    const int HighLevel=10;

    void setup()
    {
    pinMode(ledPin, OUTPUT);
    pinMode(Trig, OUTPUT); //возможно это не нужно
    pinMode(Echo, INPUT); //возможно это не нужно
    }

    void loop()
    {
    volume = readUltrasonic();
    if(volume > HighLevel) relay(ON);
    if(volume < LowLevel) relay(OFF);
    delay(100);
    }

    int readUltrasonic()
    {
    unsigned int impulseTime=0;
    unsigned int distance_sm=0;
    digitalWrite(Trig, HIGH);
    /* Подаем импульс на вход trig дальномера */
    delayMicroseconds(10); // равный 10 микросекундам
    digitalWrite(Trig, LOW); // Отключаем
    impulseTime=pulseIn(Echo, HIGH); // Замеряем длину импульса
    distance_sm=impulseTime/58; // Пересчитываем в сантиметры
    //Serial.println(distance_sm); // Выводим на порт
    return distance_sm;
    }
     
  12. ostrov

    ostrov Гуру

    Когда же мы научимся тегами пользоваться?
     
    Tomasina нравится это.
  13. Tomasina

    Tomasina Сушитель лампочек Модератор

    а если явно задать тип?
    Код (C++):
    int volume = readUltrasonic();
     
  14. kka

    kka Нуб

    Спасибо ! помогло ! похоже я безнадежный тормоз, но теперь
    if (volume > HighLevel) relay(ON);
    if (volume < LowLevel) relay(OFF);

    if менял на int не помогло, пожалуйста помогите разобраться .
     
  15. Tomasina

    Tomasina Сушитель лампочек Модератор

    В самый конец скетча, после всех скобок:
    Код (C++):
    #define RELAY_PIN   13   // реле подключено к пину 13
    void relay(byte state)
    {
      digitalWrite(RELAY_PIN, state);
     // Serial.print("Relay click!");
    }
     
  16. kka

    kka Нуб

    Круто скетч скомпилировался без ошибок ! Tomasina Спасибо !
    Похоже Ардуина не правильно понимает on, off, реле выключено на расстоянии более 90 см и включено при менее 90 как надо, но на 10 см ни как не реагирует хотя должно выключиться, пока ситуация вот такая попробую что нибудь поменять, будет результат отпишусь,Tomasina Большое спасибо за вашу помощь !!! Буду разбираться с работой.
     
  17. kka

    kka Нуб

    Ура !!! Ура !!! Ура !!! Поменял в некоторых строках HIGH на LOW, ON на OFF и все получилось !!!
    Tomasina ПРИОГРОМНЕЙШЕЕ Вам СПАСИБО !!!!!! Без вашей помощи... , что-б я делал ????
    Работает так : (по месту скоро прикреплю) Бочка пустая - включается эл.клапан - наполняет бочку - наполнилась - выключился клапан - при сливе воды до 90 см ни чего ни происходит (так и надо ) - бочка опустела до 90 см клапан открылся наполняет. Полный цикл !!!
    Собственно сам результат 100% рабочий:

    Код (C++):
    #include <Ultrasonic.h>

    #define Trig 6
    #define Echo 7
    #define ledPin 8
    #define ON LOW // если реле инверсное, то LOW
    #define OFF HIGH // если реле инверсное, то HIGH
    const int HighLevel=90;
    const int LowLevel=10;

    void setup()
    {
    pinMode(ledPin, OUTPUT);
    pinMode(Trig, OUTPUT); //возможно это не нужно
    pinMode(Echo, INPUT); //возможно это не нужно
    }

    void loop()
    {
    int volume = readUltrasonic();
    if(volume > HighLevel) relay(ON);
    if(volume < LowLevel) relay(OFF);
    delay(100);
    }

    int readUltrasonic()
    {
    unsigned int impulseTime=0;
    unsigned int distance_sm=0;
    digitalWrite(Trig, HIGH);
    /* Подаем импульс на вход trig дальномера */
    delayMicroseconds(10); // равный 10 микросекундам
    digitalWrite(Trig, LOW); // Отключаем
    impulseTime=pulseIn(Echo, HIGH); // Замеряем длину импульса
    distance_sm=impulseTime/58; // Пересчитываем в сантиметры
    //Serial.println(distance_sm); // Выводим на порт
    return distance_sm;
    }
    #define RELAY_PIN   8   // реле подключено к пину 8
    void relay(byte state)
    {
      digitalWrite(RELAY_PIN, state);
    // Serial.print("Relay click!");
    }