Не корректно отображает температуру

Boris
Boris аватар
Offline
Зарегистрирован: 16.10.2011

Собственно проблема в следующем - при использовании как аналогового (LM35) так и цифрового (DS18B20) датчика температуры симптомы одни и те же: Если подключить только датчк температуры, либо LM35 либо DS18B20, и использовать базовый скетч из примеров, то все в порядке - отображение температуры корректное, даже если немного усложнить кнопками или диодами тоже работает, но при использовани сдвигового регистра (74HC595) и соответственно библиотек (DallasTemperature.h, SPI.h) начинаются непонятки, тоесть температура датчика DS18B20 все время 0, а аналогового примерно 16 гр. и хоть грей хоть охлождай все равно не чего не меняется.

С бубном ходил, перечитал кучу форумов но ответа не нашел. Подскажите новичку!

leshak
Offline
Зарегистрирован: 29.09.2011

 Честно говоря не работал, c этим железом, но из общих соображений возникают такие вопросы:

1. Зачем? Для экономии ног? Так SPI сама-по себе позволяет подключать несколько ведомых устройст на одну линию. Или вы регистром пытаетесь выбирать "активное в данный момент" устройство?

2. Разве 74HC595 предназначен не для размножения выходов, а не входов?

3. Разве 74HC595 может работать с аналоговым сигналом?

Boris
Boris аватар
Offline
Зарегистрирован: 16.10.2011

leshak пишет:

 Честно говоря не работал, c этим железом, но из общих соображений возникают такие вопросы:

1. Зачем? Для экономии ног? Так SPI сама-по себе позволяет подключать несколько ведомых устройст на одну линию. Или вы регистром пытаетесь выбирать "активное в данный момент" устройство?

2. Разве 74HC595 предназначен не для размножения выходов, а не входов?

3. Разве 74HC595 может работать с аналоговым сигналом?

Я наверное неправильно выразился, ибо SPI используется сугубо для датчика температуры (в будущем планируется несколько), аналоговый датчик естественно подсоеденен к отдельному аналоговому входу, а регистр используется действительно для увеличения выходов. Проблема в том что при использовании регистра (разумеется на отдельном выводе ардуино) вместе с каким либо датчиком показания последнего некорректны.

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

Собственно отвлекся вот тестовый вариант, просьба с ходу не пинать он очень сырой.

#include <DallasTemperature.h>
#include <SPI.h>

/*
    Vcc ⇨ +5 В
    GND ⇨ GND
    QA-QH ⇨ светодиоды через резисторы на 200 Ом
    SI ⇨ пин 11 Arduino (MOSI)
    G ⇨ GND (выводы включены)
    RCK ⇨ пин 8 (SS)
    SCK ⇨ пин 13 (SCLK)
    SCLR ⇨ +5 В (сброс неактивен)
    QH' оставим неподключенным
*/
DallasTemperature tempSensor;             // Инициализируем сенсор температуры

enum { REG = 8 };                         // К выводу ардуино

// для хранения 16 битов используем unsigned int
unsigned int bitsToSend = 0;

// Подключения к выходам сдвигового регистра 74HC595
int regPinStatusLed = 0;                  // Пин регистра светодиодного индикатора

int regPinMotorV = 1;                     // Пин регистра двигателя вытяжного вентилятора
int regPinMotorP = 2;                     // Пин регистра двигателя приточного вентилятора
int regPinServo = 3;                      // Пин регистра двигателя сервомотора

int regPinHE1 = 6;                        // Пин регистра нагревательнах спиралей (heating elements) 1/3
int regPinHE2_3 = 7;                      // Пин регистра нагревательнах спиралей (heating elements) 2/3

// Переменные для управления системой
char* vsStatus = "Stop";                  // Состояние состемы

float tempCurrent = 0;                    // Текущая температура
int tempSet = 30;                         // Установленная температура
int tempHE1 = 8;                          // Установленная температура
int tempHE2_3 = 12;                       // Установленная температура

// Подключение к ардуино напрямую
int pinServoStatus = 5;                   // Состояние заслонки (открыта, закрыта)
int pinHE_Alarm = 6;                      // Термостат перегрева тенов
int pinTempSensor = 12;                   // Подключаем датчик типа DS18B20, DS18S20, DS1820

int pinButtonOn = 3;                      // Кнопка включить
int pinButtonOff = 4;                     // Кнопка выключить

int pinTempAnalog = A1;                   // Аналоговый датчик температуры

void setup()
{
  Serial.begin(9600);
  SPI.begin();
  pinMode(REG, OUTPUT);
  // Гасим все ключи
  for (int i = 0; i < 16; i++)
    registerWrite(i, LOW);
  
  pinMode(pinServoStatus, INPUT);
  pinMode(pinHE_Alarm, INPUT);
  pinMode(pinTempSensor, INPUT);
  pinMode(pinButtonOn, INPUT);
  pinMode(pinButtonOff, INPUT);
  
  pinMode(pinTempAnalog, OUTPUT);
  
  tempSensor.begin(pinTempSensor);        // Стартуем датчик температуры
}

// Функция открытия конкретного ключа на сдвиговом регистру
void registerWrite(int whichPin, int whichState)
{
  // выключаем светодиоды на время передачи битов
  digitalWrite(REG, LOW);
 
  // устанавливаем HIGH в соответствующий бит
  bitWrite(bitsToSend, whichPin, whichState);
 
  // Фокус вот в чём: сначала шлём старший байт
  SPI.transfer(highByte(bitsToSend));
  // А потом младший
  SPI.transfer(lowByte(bitsToSend));
  digitalWrite(REG, HIGH);
}

// Функция запуска вентиляционной установки
void vsStart ()
{
  // Изменяем статус состояния состемы
  vsStatus = "Starting";
  Serial.println ("The system starts ...");
  
  // Зажигаем индикатор
  registerWrite (regPinStatusLed, HIGH);
  
  // Стартуем вытяжной вентилятор
  registerWrite (regPinMotorV, HIGH);
  Serial.println ("---> exhaust fan is running");
  
  // Запускаем сервопривод для открытия заслонок
  registerWrite (regPinServo, HIGH);
  
  // Контролируем открытие заслонки, если заслонка закрыта ждем открытия
  Serial.println ("---> louvre shutter is opened ...");
  while (digitalRead(pinServoStatus) == LOW)
  {
    registerWrite (regPinStatusLed, LOW);
    delay (500);
    registerWrite (regPinStatusLed, HIGH);
    delay (500);
  }
  
  Serial.println ("---> louvre shutter is open");
  
  // Стартуем приточный вентилятор
  registerWrite (regPinMotorP, HIGH);
  Serial.println ("---> supply fan is running");
  
  // Пауза для разгона приточного вентилятора 3 секунды
  delay (3000);
  
  // Изменяем статус состояния состемы
  Serial.println ("System is running");
  vsStatus = "Start";
}

void vsStop ()
{
  // Изменяем статус состояния состемы
  vsStatus = "Stoping";
  Serial.println ("The system stops ...");
  
  // Отключаем нагревательные элементы
  registerWrite (regPinHE1, LOW);
  registerWrite (regPinHE2_3, LOW);
  Serial.println ("---> turning off the heating elements");
  
  // Если тены работали, делаем задержку для остывания спиралей
  Serial.println ("---> delay for cooling heating elements");
  for (int i = 0; i < 10; i++)
  {
    registerWrite (regPinStatusLed, LOW);
    delay (500);
    registerWrite (regPinStatusLed, HIGH);
    delay (500);
  }
  
  // Выключаем приточный и вытяжной вентиляторы
  registerWrite (regPinMotorV, LOW);
  Serial.println ("---> turn off exhaust fans");
  registerWrite (regPinMotorP, LOW);
  Serial.println ("---> turn off the supply air fan");
  
  // Отключаем сервопривод для закрывания заслонки
  registerWrite (regPinServo, LOW);
  Serial.println ("---> turning off the servo valve to close");
  
  // Гасим индикатор
  registerWrite (regPinStatusLed, LOW);
  
  // Изменяем статус состояния состемы
  Serial.println ("System halted");
  vsStatus = "Stop";
}

void heatersControl (float tempCurren)
{
  // Вычисляем дельту между текущей температурой и заданной
  float tempDelta = tempSet - tempCurren;
  
  // Определяем какие из ступеней необходимо включать
  if (tempDelta > 0 && tempDelta <= tempHE1)
  {
    registerWrite (regPinHE1, HIGH);
    registerWrite (regPinHE2_3, LOW);
  }
  else if (tempDelta >= tempHE1 && tempDelta <= tempHE2_3)
  {
    registerWrite (regPinHE1, LOW);
    registerWrite (regPinHE2_3, HIGH);
  }
  else if (tempDelta >= tempHE2_3)
  {
    registerWrite (regPinHE1, HIGH);
    registerWrite (regPinHE2_3, HIGH);
  }
  else
  {
    registerWrite (regPinHE1, LOW);
    registerWrite (regPinHE2_3, LOW);
  }
}

void loop(void)
{
  // Реакция на нажатие кнопки "Старт"
  if (digitalRead(pinButtonOn) == HIGH && vsStatus == "Stop")
    vsStart ();
  
  // Реакция на нажатие кнопки "Стоп"
  if (digitalRead(pinButtonOff) == HIGH && vsStatus == "Start")
    vsStop ();
  
  /*
  // Сканируем датчик температупы и вычисляем температуру
  float tempC = tempSensor.getTemperature();
  Serial.print (tempC);
  Serial.println (" C");
  */
  float tempC = (5.0 * analogRead(pinTempAnalog) * 100.0) / 1024.0;
  Serial.print(tempC);
  Serial.println(" C");
  delay (1000);
  
  // Запускаем контроль тенов
  if (digitalRead(pinHE_Alarm) == HIGH && vsStatus == "Start")
    heatersControl(tempC);
  
  // Сканируем состояние датчиков на предмет аварий
  // Проверяем нет ли перегрева, если да ждем остывания
  if (digitalRead(pinHE_Alarm) == LOW)
  {
    // Изменяем статус состояния состемы
    vsStatus = "Alarm!!!";
    Serial.println ("Alarm!!! overheating of the heating elements");

    // Отключаем нагревательные элементы
    registerWrite (regPinHE1, LOW);
    registerWrite (regPinHE2_3, LOW);
    Serial.println ("---> turning off the heating elements");
    
    // Ждем остывания аварийного термостата
    while (digitalRead(pinHE_Alarm) == LOW)
    {
      registerWrite (regPinStatusLed, LOW);
      delay (300);
      registerWrite (regPinStatusLed, HIGH);
      delay (300);
    }
    // Пауза после остывания, на всякий случай
    for (int i = 0; i < 5; i++)
    {
      registerWrite (regPinStatusLed, LOW);
      delay (300);
      registerWrite (regPinStatusLed, HIGH);
      delay (300);
    }
    Serial.println ("---> heating elements are cooled");

    Serial.println ("System in normal state");
    // Изменяем статус состояния состемы
    vsStatus = "Start";
  }
  
  // Не санкционированное закрытие заслонки
  if (digitalRead(pinServoStatus) == LOW && vsStatus == "Start")
    vsStop ();
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

 Ну не вчитываясь в код, первое что бросается в глаза pinMode(pinTempAnalog, OUTPUT);

Boris
Boris аватар
Offline
Зарегистрирован: 16.10.2011

leshak пишет:

 Ну не вчитываясь в код, первое что бросается в глаза pinMode(pinTempAnalog, OUTPUT);

Да это косяк, но суть не в этом. Моего вопроса это не решает.