Шум на датчике далласа db18b20

Тема в разделе "Arduino & Shields", создана пользователем 64detali, 20 янв 2021.

  1. parovoZZ

    parovoZZ Гуру

    в смысле выдаёт? Ты ж CRC проверяешь? Если CRC не совпадает, то и не надо ничего вычислять. А на заведённой машине ни один пакет не пройдёт проверку. 750 мс преобразования - все помехи соберёт, а не температуру.
     
  2. 64detali

    64detali Нерд

    Как бы строка
    return;
    должна прекращать дальнейшее вычисление, ошибки сыпятся и при питании от usb в квартире при неподключенном датчике холла. Я грешу на сам код, потому что скетч измерения температуры отдельно работает нормально.
     
  3. KindMan

    KindMan Гуру

    Так тогда полностью его выложите, а не кусочек. Например, что за переменная type_s?
    Про 85 я ещё соглашусь, но вот 0.06 у меня ни разу эти датчики не выдавали, даже китайцы.
     
  4. 64detali

    64detali Нерд

    type_s отсюда:
    http://forum.amperka.ru/threads/ds18b20.2375/page-19#post-131917
    Она не нужна по сути.
     
  5. 64detali

    64detali Нерд

    Первая часть кода:
    Код (C++):
    #include <SPI.h>            // Подключаем библиотеку для работы с устройством по интерфейсу SPI
    #include <Adafruit_GFX.h>   // Подключаем библиотеку для работы с текстом и графикой
    #include <TFT_ILI9163C.h>   // Подключаем библиотеку программных драйверов для работы с дисплеем 1.44 128x128 SPI
    #include <OneWire.h> // Инициализация библиотеки шины OneWire.
    #include <Servo.h> // библиотека серво
    OneWire ds(4);  //подключение датчика к 4 пину
      byte addr[8]={0x28, 0xFF, 0x7C, 0x51, 0xC0, 0x17, 0x01, 0xDC}; // адрес датчика, необходимо ввести адрес своего датчика
      byte i;
      byte present = 0;
      byte type_s;
      byte data[12];
      float Temp;
    Servo servo;  //объявить серво - назвать servo
    int s; // переменная угла поворота серво
    int flag = 1;
    int zaslonka; // переменная положения воздушной заслонки
    // Переменные для тахометра
    unsigned long RPM_impuls;  // переменная считает импульсы тахометра
    int RPM = 0;                // переменная измеренных данных тахометра
    unsigned long cur_ms = 0;  // переменная для вычисления отрезков времени температуры
    unsigned long prev_ms = 0; // переменная для вычисления отрезков времени оборотов
    // В следующих 8-и строках опеределяем названия и соответствующие им RGB обозначения цветов, которые будем выводить на дисплей
    #define  BLACK   0x0000
    #define BLUE    0x001F
    #define RED     0xF800
    #define GREEN   0x07E0
    #define CYAN    0x07FF
    #define MAGENTA 0xF81F
    #define YELLOW  0xFFE0
    #define WHITE   0xFFFF

    #define __CS 10                                           // Определяем пин к которому подключен разъем CS дисплея
    #define __DC 9                                            // Определяем пин к которому подключен разъем A0 дисплея
    #define __RES 8                                           // Определяем пин к которому подключен разъем RESET дисплея
    TFT_ILI9163C display = TFT_ILI9163C(__CS, __DC, __RES);
    // Начало функции обработки кириллических символов
    String utf8rus(String source)     // Функция для конвертации русских символов из кодировки CP1251 в UTF8
    {
      int i,k;
      String target;
      unsigned char n; // задействована буква n, внимательнее с углом поворота серво
      char m[2] = { '0', '\0' };
      k = source.length(); i = 0;
      while (i < k) {
        n = source[i]; i++;
        if (n >= 0xBF){
          switch (n) {
            case 0xD0: {
              n = source[i]; i++;
              if (n == 0x81) { n = 0xA8; break; }
              if (n >= 0x90 && n <= 0xBF) n = n + 0x2F;
              break;
            }
            case 0xD1: {
              n = source[i]; i++;
              if (n == 0x91) { n = 0xB7; break; }
              if (n >= 0x80 && n <= 0x8F) n = n + 0x6F;
              break;
            }
          }
        }
        m[0] = n; target = target + String(m);
      }
      return target;
    }
    // Конец функции обработки кириллических симоволов
     
  6. 64detali

    64detali Нерд

    вторая часть:
    Код (C++):
    void setup() {
      pinMode(2, INPUT); // тахометр задаем пин на вход
      digitalWrite(2, HIGH); // включаем подтягивающий резистор на 2 пине
      attachInterrupt(0,RPMmetr,RISING); //задать функцию прерывания на 2 пин
      display.begin(); // Инициализируем дисплей
      servo.attach(7);  //серво подключен к 7 порту,заслонка открыта

    // отображение данных
      display.fillScreen();                                             // Очищаем дисплей перед выводом
       display.setTextSize(1);                                         // Определяем размер шрифта
      display.setCursor(0,32);                                        // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(YELLOW);                                   // Определяем цвет вывода на дисплей
      display.print(utf8rus("Заслонка"));                            // Выводим строку на русском
       display.setCursor(20,0);
      display.print(utf8rus("% откр."));
       display.setCursor(67,32);                                        // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(GREEN);                                   // Определяем цвет вывода на дисплей
      display.print(utf8rus("Напряжение"));                            // Выводим строку на русском
       display.setCursor(95,0);
      display.print(utf8rus("вольт"));
      display.setCursor(0,90);                                       // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(GREEN);                                    // Определяем цвет вывода на дисплей
      display.print(utf8rus("Температура"));                          // Выводим строку на русском
      display.setCursor(55,103);                                       // Устанавливаем курсор в левый верхний угол области вывода
        display.print("C");
      display.setCursor(67,90);                                       // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(YELLOW);                                  // Определяем цвет вывода на дисплей
      display.print(utf8rus("Угол серво"));                                            // Выводим строку на русском
      display.setCursor(100,103);                                       // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(BLUE);                                  // Определяем цвет вывода на дисплей
      display.print(utf8rus("град"));                                            // Выводим строку на русском
      display.setTextSize(2);
      display.setCursor(90,45);                                        // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(RED);                                   // Определяем цвет вывода на дисплей
      display.print(utf8rus("Об."));                            // Выводим строку на русском
      display.setCursor(90,65);                                        // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(RED);                                   // Определяем цвет вывода на дисплей
      display.print(utf8rus("мин"));                            // Выводим строку на русском
      display.drawLine (64, 0, 64, 30, WHITE);
      display.drawLine (64, 98, 64, 128, WHITE);
       display.drawLine (0, 30, 128, 30, WHITE);
       display.drawLine (0, 40, 128, 40, WHITE);
       display.drawLine (0, 98, 128, 98, WHITE);
       display.drawLine (0, 88, 128, 88, WHITE);
       display.drawLine (85, 64, 128, 64, WHITE);
    }

    void loop()
    {
    getOboroti();  //функция оборотов
    getTemperature();  //функция температуры
    }
    int getTemperature()
    {

      if (OneWire::crc8(addr, 7) != addr[7]) {
      return;
      }
    if (flag == 1) {
      flag = 0;
      ds.reset(); //сброс датчика
      ds.select(addr); //выбор адреса датчика
      ds.write(0x44); //команда на расчет температуры
      }
      if (millis() - cur_ms > 1000) //считаем температуру, через каждую секунду
    {
      cur_ms = millis(); // обнуляем отрезок времени
      present = ds.reset(); //сброс датчика
      ds.select(addr); //выбор адреса датчика
      ds.write(0xBE); //команда чтения температуры
      for ( i = 0; i < 9; i++) {           // we need 9 bytes
        data[i] = ds.read();
          }
          int16_t raw = (data[1] << 8) | data[0];
      if (type_s) {
        raw = raw << 3; // 9 bit resolution default
        if (data[7] == 0x10) {
          // "count remain" gives full 12 bit resolution
          raw = (raw & 0xFFF0) + 12 - data[6];
        }
      } else {
        byte cfg = (data[4] & 0x60);
        // at lower res, the low bits are undefined, so let's zero them
        if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
        else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
        else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
        //// default is 12 bit resolution, 750 ms conversion time
      }
      Temp = (float)raw / 16.0;
      flag = 1;
      display.setTextSize(2);
      display.setCursor(0,113);   // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(MAGENTA,BLACK);   // Определяем цвет вывода на дисплей
      display.print(Temp);
      }

    return Temp; // прекращение вычислений в функции, возвращение значения температуры
      }
    int getOboroti()
    {

    if (millis() - prev_ms > 500) //считаем обороты, через каждую секунду
    {
    // Считаем тахометр
        RPM=((RPM_impuls*30000)/(millis() - prev_ms)); // формула расчета оборотов
                                       
        RPM_impuls=0;                    // обнуляем счетчик прерываний
        prev_ms = millis();                // обнуляем отрезок времени
      display.setTextSize(3);
       if (RPM<1000)
    {

      display.setCursor(0,55);                                        // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(YELLOW,BLACK);                                   // Определяем цвет вывода на дисплей
      display.print(RPM);
      display.print("  ");
    }
    else
    {
      display.setCursor(0,55);                                        // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(YELLOW,BLACK);                                   // Определяем цвет вывода на дисплей
      display.print(RPM);
                                                  // Выводим строку на русском
    }
    //Начало блока управления воздушной заслонкой

    // 1я ступень, прогрев до 5 градусов

       if (Temp<=5 && RPM==0) {   // двигатель заглушен
         
        servo.write(175);  // закрываем заслонку полностью
    }
    s=servo.read();
    if (Temp<=5 && RPM>2500) {   // двигатель запущен, регулируем обороты не выше 2300
         
          servo.write(130);  // снижаем обороты
    }
    s=servo.read();
    if (Temp<=5 && RPM>2100) {   // двигатель запущен, регулируем обороты не выше 2300
         
        s --;
        servo.write(s);  // снижаем обороты
    }
    if (Temp<=5 && RPM>100 && RPM<1900) {   // двигатель запущен, регулируем обороты не ниже 2000
     
        s ++;
        servo.write(s);  // повышаем обороты
    }
    // 2я ступень, прогрев до 40 градусов
    s=servo.read();
    if (Temp>5 && Temp<=40 && RPM>1600) {   // двигатель запущен и частично прогрет, регулируем обороты не выше 1600
     
        s --;
        servo.write(s);  // снижаем обороты
    }
    if (Temp>5 && Temp<=40 && RPM>100 && RPM<1400) {   // двигатель запущен и частично прогрет, регулируем обороты не ниже 1400
     
        s ++;
        servo.write(s);  // повышаем обороты
    }

    // 3я ступень, завершение прогрева
    if (Temp>40) {   // двигатель прогрет достаточно, для поддержания холостых
     
        servo.write(30);  // открываем заслонку полностью
    }
    //конец блока управления воздушной заслонкой
    zaslonka = map(s, 175, 30, 0, 100); // перевод угла открытия сервопривода в проценты открытия
    s=servo.read();
    display.setTextSize(2);
    if (zaslonka < 100)
    {
      display.setCursor(0,12);                                        // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(GREEN,BLACK);                                   // Определяем цвет вывода на дисплей
      display.print(zaslonka);
      display.print("  ");
    }
    else
    {
      display.setCursor(0,12);                                        // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(GREEN,BLACK);                                   // Определяем цвет вывода на дисплей
      display.print(zaslonka);
                                                  // Выводим строку на русском
    }
    if (s < 100)
    {
      display.setCursor(80,113);                                        // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(CYAN,BLACK);                                   // Определяем цвет вывода на дисплей
      display.print(s);
      display.print("  ");
    }
    else
    {
      display.setCursor(80,113);                                        // Устанавливаем курсор в левый верхний угол области вывода
      display.setTextColor(CYAN,BLACK);                                   // Определяем цвет вывода на дисплей
      display.print(s);
                                                  // Выводим строку на русском
    }
    }
    return RPM; // прекращение вычислений в функции, возвращение значения оборотов
    }
    // Запуск счетчика прерываний тахометра с нуля
    void RPMmetr()
    {
       RPM_impuls++;
    }
     
  7. b707

    b707 Гуру

    дерганья серво и глюки температуры совпадают... может серво влияет?
     
  8. parovoZZ

    parovoZZ Гуру

    бррр. Мы получаем от датчика пакет с данными и CRC. Получив данные, мы сами вычисляем CRC и сравниваем её с полученной от датчика. Где это в коде?
     
  9. 64detali

    64detali Нерд

    Я посчитал что этих строк достаточно:
    Код (C++):
    if (OneWire::crc8(addr, 7) != addr[7]) {
          Serial.println("CRC is not valid!");
          return;
      }
    Не серво, я вешал конденсатор на него, плюс ноутбука у меня нет, я каждый раз заношу в квартиру только блок с ардуино, без обвеса.
     
  10. parovoZZ

    parovoZZ Гуру

    Можешь сам себе объяснить, что записано в этих строчках? За какими переменными прячутся принятые данные и CRC? Зачем брать 7-ой бит АДРЕСА датчика и с чем-то его сравнивать? Не понимаю смысла записи
    Код (C++):
    OneWire::crc8(addr, 7)
    Что вернёт эта функция? CRC седьмого байта адреса? А на кой нам вычислять CRC седьмого байта адреса, которая ему же и равна? И почему именно седьмого, а не первого? И почему проверка делается ДО ПРИЁМА данных???
     
  11. 64detali

    64detali Нерд

    Я по примеру делал http://forum.amperka.ru/threads/ds18b20.2375/page-19#post-131917 , были конечно мысли почему седьмой, а не восьмой и где предыдущие строки. Ткните носом где подсмотреть правильную проверку.
     
  12. parovoZZ

    parovoZZ Гуру

  13. 64detali

    64detali Нерд

  14. SergeiL

    SergeiL Оракул Модератор

    А есть какие то подтверждения? Или опять просто ляпнуть?
    Впрочем, как в всегда...
    У меня с 2007-го по 2019 на машине Пандора с датчиками DS18B20 стояла.
    Один к корпусу двигателя был прикручен, второй в салоне у пола был выведен.
    И ни разу ни один, ни второй, не дали неправильного значения температуры.
     
  15. parovoZZ

    parovoZZ Гуру

    Тачка карбюраторная была?
    Что за пандора с возможностью подключения ds18b20?
    Я когда интересовался (примерно в те же года), они все с аналоговыми были.

    очень сомнительное утверждение.
     
  16. SergeiL

    SergeiL Оракул Модератор

    Смешно :):):):):)
    Какая разница какая тачка? Карбюратор, инжектор, дизель? Сигнализации с датчиками температуры работают на них на всех. ;)
    Пандора - это комплекс защиты и мониторинга машины.
    В то время (в 2007) их два было, адекватных и диалоговых.
    Пандора от Алармтрейд из Калуги, и Старлайн Питерский.
    Хоть я и из Питера, но тогда выбрал Пандору, как более прогрессивное решение.
    Но очень сильно пожалел. Никому не посоветую Пандору.
    Старлайн тоже не "Айс", но лучше Пандоры в плане надежности.
    Лучше свое (свое решение), что можно править на лету и не глючит. ;)
     
  17. parovoZZ

    parovoZZ Гуру

    Большая. Если карб, то это провода зажигания, возможно даже, трамблёр со всеми вытекающими.
    В дизеле в принципе нет источников искровых помех.

    вот только там датчики аналоговые.
     
  18. SergeiL

    SergeiL Оракул Модератор

    :)
    Переубеждать не буду.
    Инжектор, карбюратор - принципиальной разницы - нет.
    Какие аналоговые датчики?
    Пандора стояла на инжекторе. Датчики DS18B20.
     
  19. parovoZZ

    parovoZZ Гуру

    PT100 и подобные им. Схема включения - трёхпроводка.

    Где об этом написано?
     
  20. SergeiL

    SergeiL Оракул Модератор

    В мануале:
    upload_2021-1-24_7-25-37.png
     
    vvr нравится это.