Что я делаю не так ?

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

  1. Sever 64

    Sever 64 Нерд

    Здравствуйте . Нашел код который почти подходит под мои требования ,единственная проблема что мне надо что бы реле выключалось при минус 15 гр . Если поставить как в оригинальном коде плюсовую температуру то все отрабатывает нормально . Поместив датчик в холодильную камеру и поправив в конце кода на минус 1 ,то в мониторе порта показывает минусовую температуру но реле не срабатывает .Оригинальный код можно посмотреть тут http://zelectro.cc/dallas-18b20
    Код (C++):
    #include <OneWire.h>

    OneWire  ds(10);
    void setup(void) {
      Serial.begin(9600);
      pinMode(3, OUTPUT);
      digitalWrite(3, LOW);
    }

    void loop(void) {
      byte i;
      byte present = 0;
      byte type_s;
      byte data[12];
      byte addr[8];
      float celsius, fahrenheit;

      if ( !ds.search(addr)) {
        Serial.println("No more addresses.");
        Serial.println();
        ds.reset_search();
        delay(250);
        return;
      }

      Serial.print("ROM =");
      for( i = 0; i < 8; i++) {
        Serial.write(' ');
        Serial.print(addr[i], HEX);
      }

      if (OneWire::crc8(addr, 7) != addr[7]) {
          Serial.println("CRC is not valid!");
          return;
      }
      Serial.println();
      // the first ROM byte indicates which chip
      switch (addr[0]) {
        case 0x10:
          Serial.println("  Chip = DS18S20");  // or old DS1820
          type_s = 1;
          break;
        case 0x28:
          Serial.println("  Chip = DS18B20");
          type_s = 0;
          break;
        case 0x22:
          Serial.println("  Chip = DS1822");
          type_s = 0;
          break;
        default:
          Serial.println("Device is not a DS18x20 family device.");
          return;
      }

      ds.reset();
      ds.select(addr);
      ds.write(0x44, 1);      

      delay(5000);

      present = ds.reset();
      ds.select(addr);  
      ds.write(0xBE);      

      Serial.print("  Data = ");
      Serial.print(present, HEX);
      Serial.print(" ");
      for ( i = 0; i < 9; i++) {        
        data[i] = ds.read();
        Serial.print(data[i], HEX);
        Serial.print(" ");
      }
      Serial.print(" CRC=");
      Serial.print(OneWire::crc8(data, 8), HEX);
      Serial.println();

      int16_t raw = (data[1] << 8) | data[0];
      if (type_s) {
        raw = raw << 3;
        if (data[7] == 0x10) {
          raw = (raw & 0xFFF0) + 12 - data[6];
        }
      } else {
        byte cfg = (data[4] & 0x60);
        if (cfg == 0x00) raw = raw & ~7;
        else if (cfg == 0x20) raw = raw & ~3;
        else if (cfg == 0x40) raw = raw & ~1;
      }
      celsius = (float)raw / 16.0;
      fahrenheit = celsius * 1.8 + 32.0;
      Serial.print("  Temperature = ");
      Serial.print(celsius);
      Serial.print(" Celsius, ");
      Serial.print(fahrenheit);
      Serial.println(" Fahrenheit");

     
    if (celsius>-1){
      digitalWrite(3, LOW);    //Turn on relay
     }else{
       digitalWrite(3, HIGH);   //Turn off relay
     }
      Serial.print(celsius);
    }
     
     
    Последнее редактирование: 25 сен 2016
  2. Valera_gug

    Valera_gug Нерд

    Попробуй через переменную int указать значение -1.
     
  3. Sever 64

    Sever 64 Нерд

    В этой строке изменить ? int16_t raw =(data[1]<<8)| data[0];
     
  4. Tomasina

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

    для celsius тип указан корректно - float.
    Напишите своими словами какой реакции вы ждете от условия
    Код (C++):
     if (celsius > - 1 )
     
    Sever 64 нравится это.
  5. Sever 64

    Sever 64 Нерд

    при достижение значения -1 пойдет питание на включение реле .
     
  6. Tomasina

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

    Нет, это означает , что реле включится по достижении температуры 0, и выше, т.е. +1, +2, +3 и т.д.
    Причем только по целым, без учета десятых.
    И обратного выключения реле при понижении температуры ниже ноля тоже не будет.

    P.S. реле включается каким сигналом - HIGH или LOW?
     
    Последнее редактирование: 25 сен 2016
    Sever 64 нравится это.
  7. Sever 64

    Sever 64 Нерд

    LOW (понял ошибку по включению ) ,реле выключится (но это не принципиально и поправимо )
     
  8. Sever 64

    Sever 64 Нерд

    разобрался . сейчас работает , поправить надо так
    if (celsius>-1){
    digitalWrite(3, LOW); //Turn on relay
    }else{
    digitalWrite(3, HIGH); //Turn off relay
    }
    Serial.print(celsius);
    }
     
  9. Tomasina

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

    если LOW, то почти правильно.
    Код (C++):
    #define RELAY 9
    #define ON    LOW
    #define OFF   HIGH
      ...
      if (celsius < -1.0) digitalWrite(RELAY, ON); //Turn on relay
       else digitalWrite(RELAY, OFF); //Turn off relay
     
    Sever 64 нравится это.
  10. Sever 64

    Sever 64 Нерд

    Спасибо большое дали направление куда капать )
     
  11. Sever 64

    Sever 64 Нерд

    Может ком пригодится . Прикрутил еще экран что бы видеть температуру .
    Код (C++):
    #include <DallasTemperature.h>
    #include <OneWire.h>
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    LiquidCrystal_I2C lcd(0x27,16,2);
    #define ONE_WIRE_BUS 10
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    OneWire  ds(10);
    void setup(void) { lcd.init();
    lcd.backlight();
    sensors.begin();
      pinMode(3, OUTPUT);
    digitalWrite(3, HIGH);
      Serial.begin(9600);
       
    }

    void loop(void) {
      byte i;
      byte present = 0;
      byte type_s;
      byte data[12];
      byte addr[8];
      float celsius ,fahrenheit;
     
      if ( !ds.search(addr)) {
       
        Serial.println();
        ds.reset_search();
        delay(750);
        return;
      }
      for( i = 0; i < 8; i++)

      if (OneWire::crc8(addr, 7) != addr[7])

      ds.reset();
      ds.select(addr);
      ds.write(0x44, 1);      
     
      delay(750);
     
      present = ds.reset();
      ds.select(addr);  
      ds.write(0xBE);      

     
      for ( i = 0; i < 9; i++) {          
        data[i] = ds.read();
       
      }

      int16_t raw = (data[1] << 8) | data[0];
      if (type_s) {
        raw = raw << 3;
        if (data[7] == 0x10) {
          raw = (raw & 0xFFF0) + 12 - data[6];
        }
      } else {
        byte cfg = (data[4] & 0x60);
        if (cfg == 0x00) raw = raw & ~7;
        else if (cfg == 0x20) raw = raw & ~3;
        else if (cfg == 0x40) raw = raw & ~1;
      }
      celsius = (float)raw / 16.0;
      fahrenheit = celsius * 1.8 + 32.0;
      Serial.print("  Temperature = ");
      Serial.print(celsius);
      Serial.print(" Celsius, ");
     
    sensors.requestTemperatures();
    lcd.setCursor(0, 0);
    lcd.print(sensors.getTempCByIndex(0));
    lcd.print(" C ");
    //выставляем нужную температуру
      if (celsius> 23 ){
      digitalWrite(3, LOW);  
    }else{
       digitalWrite(3, HIGH);  
    }
     
    }
     
  12. Tomasina

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

    осталоcь избавиться от delay(750), чтобы МК мог параллельно что-то еще делать.
    Все через это проходили ;)

    И еще ошибка: у тебя при старте инициализируются две сущности:
    Код (C++):
    OneWire oneWire(ONE_WIRE_BUS);
    OneWire  ds(10);
    а дальше в коде используется только ds
     
    Sever 64 нравится это.
  13. Sever 64

    Sever 64 Нерд

    Спасибо ,сейчас глянем что сделать ,,как раз хочу добавить сюда 2 модуля протечки ,еще один ds и сим800л для информации . Проблема пока встала не могу узнать адрес 2 датчика ds и прикрутить к нему реле (что бы один датчик отвечал за одно реле .второй за другое ). сколько находил примеров все датчики на одном пине и по адресам (хотя для моих задачь можно и 2 пина использовать )
     
  14. Sever 64

    Sever 64 Нерд

    если это удалить то вылазит ошибка . от delay(750) избавился .
     
  15. Sever 64

    Sever 64 Нерд

    Еще нубский вопрос . Разобрался как узнать адрес датчика ds18b20 , подобрав подходящий код для 2 датчиков с выводом на экран я столкнулся с проблемой работы реле (не отрабатывает как в верхнем коде ,просто срабатывает и все ). Пните в нужном направлении .куда капать что бы реле работало как в предыдущем коде .
    Код (C++):
    #include <OneWire.h>
    #include <DallasTemperature.h>
    #include <LiquidCrystal_I2C.h>
    LiquidCrystal_I2C lcd(0x27,16,2);

    OneWire oneWire(10); // вход датчиков 18b20
    DallasTemperature ds(&oneWire);


    DeviceAddress sensor1 = {0x28, 0xF2, 0x21, 0x08, 0x00, 0x00, 0x80, 0xA7};
    DeviceAddress sensor2 = {0x28, 0xE6, 0xBD, 0x3B, 0x05, 0x0, 0x0, 0xCF};

    void setup() {
    //  Serial.begin(9600);
    ds.begin();
       pinMode(3, OUTPUT);
    digitalWrite(3, HIGH);
      lcd.init();
    lcd.backlight();
    }

    void loop() {
      ds.requestTemperatures(); // считываем температуру с датчиков
     
        lcd.setCursor(0, 0);
        lcd.print("Sensor 1: ");
        lcd.print(ds.getTempC(sensor1)); // отправляем температуру
        lcd.print("C");
        lcd.setCursor(0, 1);
        lcd.print("Sensor 2: ");
        lcd.print(ds.getTempC(sensor2));
        lcd.print("C");
    if (sensor1> 23 ){
      digitalWrite(3, LOW);  
    }else{
       digitalWrite(3, HIGH);
    }

    }
     
  16. Tomasina

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

    Код (C++):
    if (sensor1 > 23 )
    потому что sensor1 - это адрес датчика (массив из 8 чисел), а 23 - это просто одно число.
    Сравниваешь несравнимое.

    Из предыдущего скетча куда-то пропала куча переменных. Потерялась по дороге? ;)

    ds.requestTemperatures нельзя постоянно дергать (сейчас у тебя он вызывается несколько сот раз в секунду, а надо не менее 750 мс между вызовами).
     
    Sever 64 нравится это.
  17. Sever 64

    Sever 64 Нерд

    Вырезал ) учусь помаленьку ,где просто методом народного тыка ,где программным путем ) кстати обрезанный скетч отрабатывает как мне нужно ,но захотелось еще прикрутить датчик с реле вот и полез в дебри . Спасибо что помогаете )

    добавить delay(750) ?
     
  18. MDV

    MDV Гик

    Если посмотришь внимательно, то ты заметишь, что в верхнем примере ты для начала обозначил тип переменной отвечающей за хранение значения температуры потом из кельвинов преобразовал её в Цельсии
    И только после этого сравнивал с уставкой в последнем примере этого нет
     
  19. Sever 64

    Sever 64 Нерд

    if (ds.getTempC(sensor1)> 23 ){
    digitalWrite(3, LOW);
    }else{
    digitalWrite(3, HIGH);
    }
    добавил и заработало (более 23 градусов реле включается ) как и в верхнем скетче . надо протестировать еще на минусовой температуре (тз такое )
     
  20. Tomasina

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

    даю скелет правильной архитектуры программы:
    Код (C++):
    #define RELAY_PIN  3                             // пин реле
    #define DS_PIN     9                             // пин датчиков температуры
    #define LEAK1_PIN  A0                            // пин сенсора влажности
    float temperature1;                              // переменная для хранения данных с датчика температуры
    float temperature2;                              // переменная для хранения данных с датчика температуры
    unsigned int leak1;                              // переменная для хранения данных с сенсора протечки
    unsigned int leak2;                              // переменная для хранения данных с сенсора протечки
    const float maxTemperature1 = 42.0;              // порог срабатывания для реле. Значение float всегда должно указываться с точкой, а не целое число
    const unsigned int sensUpdInterval = 800;        // интервал обновления датчиков, мс

    void setup()
    {
      pinMode(LED_BUILTIN, OUTPUT);                  // активируем светодиод на плате
      Serial.begin(9600);
    }


    void loop()
    {
      static unsigned long sensLastUpd = 0;          // переменная для хранения времени последнего обновления датчиков
      if (millis() - sensLastUpd >= sensUpdInterval) // если прошло больше 800 мс
      {
        sensLastUpd = millis();                      // запоминаем время чтения сенсоров
        digitalWrite(LED_BUILTIN, HIGH);             // показываем, что обращаемся к датчикам - включаем LED на плате
        readTemperature();                           // считываем показания датчиков температуры
        readLeakage();                               // считываем показания сенсоров протечки
        displayUpdate();                             // выводим показания на ЖК
        serialUpdate();                              // выводим показания в консоль
        delay(100);                                  // временно, для отладки. Потом убрать
        digitalWrite(LED_BUILTIN, LOW);              // отключаем LED
      }

      // здесь пихаем код, не требующий задержек (чтение кнопок и пр.)
      setRelay();                                    // управляем реле
    }


    void setRelay()
    {
      if (temperature1 > maxTemperature1) digitalWrite(RELAY_PIN, LOW);
      else digitalWrite(RELAY_PIN, HIGH);
    }


    void readTemperature()
    {
      static boolean updateNow = true;
      if (updateNow);// ds.requestTemperatures(); // даем команду на замер температуры
      else
      {
        temperature1 = ds.getTempC(sensor1));  // считываем температуру с датчиков
        temperature2 = ds.getTempC(sensor2));
      }
      updateNow = !updateNow;
    }


    void readLeakage()
    {
      leak1 = analogRead(LEAK1_PIN);
      //leak2 = analogRead(LEAK2_PIN;
    }


    void displayUpdate()
    {
      lcd.setCursor(0, 0);
      lcd.print("Sensor 1: ");
      // и т.д.
    }


    void serialUpdate()
    {
      Serial.print("Temperature #1: ");
      Serial.print(temperature1);
      // и т.д.
    }
    Это только база, как сейчас есть - работать не будет (надо вписать пины, добавить библиотеки и пр.)

    Принцип простой - не надо сваливать все в кучу, каждый модуль (в скетче это функции void) должен отвечать только за свою работу: температура - отдельно, влажность - отдельно, дисплей - отдельно, реле - отдельно.

    Когда программа построена модульно - из "кубиков" - ее легче понять и обслуживать (вставить готовый кубик в новую программу) ;)
     
    Последнее редактирование: 30 сен 2016
    Sever 64 нравится это.