Реле пошаливает

Тема в разделе "Arduino & Shields", создана пользователем kpa6, 1 фев 2015.

  1. kpa6

    kpa6 Нуб

    Приветствую. Прикупил себе два датчика HC-SR04, релешку. Надумал соединить их вместе. К примеру, если изменяется расстояние - включается реле. Код:
    Код (Text):
    #include "Ultrasonic.h"
    #define rele 5

    Ultrasonic ultrasonic(6, 7);
    Ultrasonic ultrasonic2(8, 9);

    // Переменные, в которых будут храниться данные для сравнения расстояния
    float cache1, cache2;

    void setup()
    {
      pinMode(rele, OUTPUT);
      Serial.begin(9600);
    }

    void loop()
    {
      // Получаю дистанцию с двух датчиков
      float dist_cm = ultrasonic.Ranging(CM);
      float dist_cm2 = ultrasonic2.Ranging(CM);
     
      // Если нынешняя дистанция меньше или больше предыдущей с учётом
      // погрешности +-20, то заводим реле, ждём 5 секунд и отключаем
      if ( dist_cm > cache1 + 20 ||
          dist_cm < cache1 - 20 ||
          dist_cm2> cache2 + 20 ||
          dist_cm2< cache2 - 20){
            digitalWrite(rele, HIGH);
            delay(5000);
            digitalWrite(rele, LOW);
          }
      // Вывод дистанции в com
      Serial.println(dist_cm);
      Serial.println(dist_cm2);
      Serial.println();
      // Получаю значения для сравнения
      cache1 = dist_cm;
      cache2 = dist_cm2;
      // Немножко жду
      delay(200);
    }
    Проблема в том, что реле само по себе включается примерно на секунду, а затем само по себе выключается. В чём проблема? Подключено всё верно. Если же я использую вместо
    Код (Text):
            digitalWrite(rele, HIGH);
            delay(5000);
            digitalWrite(rele, LOW);
    обычный вывод в COM порт (Serial.println(...)), то всё впорядке.

    P.S: все эти махинации происходят на ардуино нано, если это имеет значение.

    UPD: иногда оно зависает включённым на секунд восемь - десять
    UPD: если кто-то не понял - записал видео, на котором видно косяк:

     
    Последнее редактирование: 1 фев 2015
  2. X-Dron

    X-Dron Гик

    Знакомый голубые релюшки от Songle.
    Какая маркировка на них.
    SRD-.....
     
  3. geher

    geher Гуру

    Гипотеза 1. Наводки на пин управления реле ("привидения").
    Можно попробовать перевесить управление реле на другой пин, подальше от датчиков, или провода до реле пустить экранированной парой.
    Гипотеза 2. Что-то не так в цепи управления реле, например, транзистор, управляющий обмоткой реле, постоянно в состоянии, близком к открытию.
     
  4. kpa6

    kpa6 Нуб

    SRD-05VDC-SL-C
     
  5. kpa6

    kpa6 Нуб

    Перевесил провод управления в пин3, не помогло. Немного не понял про "провода до реле пустить экранированной парой".

    На счёт второй гипотезы - с реле всё окей. Ставил пример Blink, работает как часы.
     
  6. добавь в основной цикл digitalWrite(rele, LOW);
     
  7. kpa6

    kpa6 Нуб

    Сейчас попробую, но вопрос - зачем?

    UPD. Код стал выглядеть так. Эффекта, к несчастью, ноль. Всё также мигает\непродолжительно горит когда заблагорассудится.
    Код (Text):
    #include "Ultrasonic.h"
    #define rele 3

    Ultrasonic ultrasonic(6, 7);
    Ultrasonic ultrasonic2(8, 9);

    // Переменные, в которых будут храниться данные для сравнения расстояния
    float cache1, cache2;

    void setup()
    {
      pinMode(rele, OUTPUT);
      Serial.begin(9600);
    }

    void loop()
    {
      digitalWrite(rele, LOW);
      // Получаю дистанцию с двух датчиков
      float dist_cm = ultrasonic.Ranging(CM);
      float dist_cm2 = ultrasonic2.Ranging(CM);
     
      // Если нынешняя дистанция меньше или больше предыдущей с учётом
      // погрешности +-20, то заводим реле, ждём 5 секунд и отключаем
      if ( dist_cm > cache1 + 20 ||
          dist_cm < cache1 - 20 ||
          dist_cm2> cache2 + 20 ||
          dist_cm2< cache2 - 20){
            digitalWrite(rele, HIGH);
            delay(5000);
            digitalWrite(rele, LOW);
          }
      // Вывод дистанции в com
      Serial.println(dist_cm);
      Serial.println(dist_cm2);
      Serial.println();
      // Получаю значения для сравнения
      cache1 = dist_cm;
      cache2 = dist_cm2;
      digitalWrite(rele, LOW);
      // Немножко жду
      delay(200);
    }
     
    Последнее редактирование: 2 фев 2015
  8. kpa6

    kpa6 Нуб

    Что я ещё узнал - датчики HC-SR04 начинают получать дистанцию только и только тогда, когда реле активно, включено.

    UPD. Попробовал смастерить на библиотеке NewPing, результата почему-то тоже нет:
    (Из всего кода нужно смотреть только последний кусок - void oneSensorCycle)
    Код (Text):

    // ---------------------------------------------------------------------------
    // This example code was used to successfully communicate with 15 ultrasonic sensors. You can adjust
    // the number of sensors in your project by changing SONAR_NUM and the number of NewPing objects in the
    // "sonar" array. You also need to change the pins for each sensor for the NewPing objects. Each sensor
    // is pinged at 33ms intervals. So, one cycle of all sensors takes 495ms (33 * 15 = 495ms). The results
    // are sent to the "oneSensorCycle" function which currently just displays the distance data. Your project
    // would normally process the sensor results in this function (for example, decide if a robot needs to
    // turn and call the turn function). Keep in mind this example is event-driven. Your complete sketch needs
    // to be written so there's no "delay" commands and the loop() cycles at faster than a 33ms rate. If other
    // processes take longer than 33ms, you'll need to increase PING_INTERVAL so it doesn't get behind.
    // ---------------------------------------------------------------------------
    #include <NewPing.h>

    #define SONAR_NUM     2 // Number or sensors.
    #define MAX_DISTANCE 400 // Maximum distance (in cm) to ping.
    #define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).

    unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
    unsigned int cm[SONAR_NUM];         // Where the ping distances are stored.
    unsigned long current_time, looptime;
    int cache[2];
    uint8_t currentSensor = 0;          // Keeps track of which sensor is active.

    NewPing sonar[SONAR_NUM] = {     // Sensor object array.
      NewPing(6, 7, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
      NewPing(8, 9, MAX_DISTANCE)
    };

    void setup() {
      current_time = millis();
      looptime = current_time;
      pinMode(2, OUTPUT);
      Serial.begin(9600);
      pingTimer[0] = millis() + 75;           // First ping starts at 75ms, gives time for the Arduino to chill before starting.
      for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
        pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
    }

    void loop() {
      for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
        if (millis() >= pingTimer[i]) {         // Is it this sensor's time to ping?
          pingTimer[i] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
          if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
          sonar[currentSensor].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
          currentSensor = i;                          // Sensor being accessed.
          cm[currentSensor] = 0;                      // Make distance zero in case there's no ping echo for this sensor.
          sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
        }
      }
      // The rest of your code would go here.
    }

    void echoCheck() { // If ping received, set the sensor distance to array.
      if (sonar[currentSensor].check_timer())
        cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
    }

    void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
      for (uint8_t i = 0; i < SONAR_NUM; i++) {
        // Та же самая проверочка... Если есть отклонение от предыдущего значения на
        // +-20, то выполняем включение чёртового реле, которое через секунду отключаем
        if ( cm[i] < cache[i] - 20 ||
             cm[i] > cache[i] + 20 ){
                Serial.println("Vklychenie!");
                digitalWrite(2, HIGH);
                delay(1000);
                Serial.println("Viklychenie!");
                digitalWrite(2, LOW);
             }
        Serial.print(i);
        Serial.print("=");
        Serial.print(cm[i]);
        Serial.print("cm ");
        cache[i] = cm[i];
      }
      Serial.println();
    }
     
    Повторюсь - это какая-то дикая ересь. Датчики получают дистанцию только тогда, когда реле включено. В данном случае это интервал в одну секунду. Меняем delay - меняется и частота получения дистанции. Что же за пикапец
     
    Последнее редактирование: 2 фев 2015
  9. kpa6

    kpa6 Нуб

    Я сейчас чуть было не расхуразломал свою клавиатуру.
    Боже, я перепутал LOW и HIGH.
    Чтобы лампа светила - нужно подать LOW, чтобы выключилась - LOW. Ну БОЖЕ!!!!
     
  10. X-Dron

    X-Dron Гик

    Дык, проблема решена, или все еще актуальна?
    В начальном коде никакой ереси не вижу.
     
  11. kpa6

    kpa6 Нуб

    Да, всё решено. Проблема была в том, что чтобы включить реле нужно подать digitalWrite(rele, LOW); ну и наоборот, собственно. А я же подавал HIGH и негодовал, раза три переписывая код под разные библиотеки.
    В общем - если кому нужно - пожалуйста. Теперь у меня дома ночной светильник, реагирующий на движение(на изменение дистанции)
    Код (Text):
    #include "Ultrasonic.h"
    #define rele 2

    Ultrasonic ultrasonic(6, 7);
    Ultrasonic ultrasonic2(8, 9);

    // Переменные, в которых будут храниться данные для сравнения расстояния
    float cache1 = 0, cache2 = 0;
    boolean isactive = false;
    const int maxd = 390;

    void setup()
    {
      pinMode(rele, OUTPUT);
      Serial.begin(9600);
    }

    void loop()
    {
      // Получаю дистанцию с двух датчиков
      float dist_cm = ultrasonic.Ranging(CM);
      float dist_cm2 = ultrasonic2.Ranging(CM);
      // Если дистанция больше максимальной -
      // приравниваем её к прошлому полученному значению датчиков,
      // от сбойных включений\выключений реле
      if ( dist_cm  > maxd ) dist_cm  = cache1;
      if ( dist_cm2 > maxd ) dist_cm2 = cache2;
      // Если нынешняя дистанция меньше или больше предыдущей с учётом
      // погрешности +-20, то заводим реле, ждём 5 секунд и отключаем
      if (dist_cm > cache1 + 20 ||
          dist_cm < cache1 - 20 ||
          dist_cm2> cache2 + 20 ||
          dist_cm2< cache2 - 20 ){
            // Включение реле. Да, это LOW, это не ошибка.
            delay(50);
            digitalWrite(rele, LOW);
            Serial.println("Vkluchilos");
            for(int i = 5; i>0; i--){
              Serial.print("Vikluchenie cherez ");
              Serial.print(i);
              Serial.println();
              delay(1000);
            }
            // Выключение реле.
            delay(50);
            digitalWrite(rele, HIGH);
            Serial.println("Viklychenie");
          }
       
      // Вывод дистанции в com
      Serial.println(dist_cm);
      Serial.println(dist_cm2);
      Serial.println();
      // Получаю значения для сравнения
      cache1 = dist_cm;
      cache2 = dist_cm2;
      // Вывожу их (использовал для отладки, можно убрать)
      Serial.print("chache1= "); Serial.print(cache1); Serial.println();
      Serial.print("chache2= "); Serial.print(cache2); Serial.println();

      // Немножко жду
      delay(200);
    }
     
     
    Последнее редактирование: 2 фев 2015
  12. Максим B

    Максим B Гуру

    А в темноте как ваш светильник работает??? Почему не выбрали датчик движения?
     
  13. kpa6

    kpa6 Нуб

    В темноте тоже всё отлично, на ночь себе ставил