датчик dallas ds1820 не работает, если я использую прерывания

stncld
Offline
Зарегистрирован: 28.10.2014

Всем привет!

я строю простую метеостанцию (анемометр + температурный датчик), использую оптический приемник и передатчик из обычной шариковой мышки и датчик температуры dallas DS1820

если я запускаю только код анемометра, то он работает

если я запускаю только код (из примеров) датчика DS1820, он тоже работает

но когда я сливаю все в один скетч, перестают работать обе части, и анемометр и температурная часть ))

на самом деле даже если я только вставляю строку "sensors.begin()" код уже перестает работать, по крайней мере на запросы веб сервер уже не отвечает ((

я использую таймер и прерывания (для анемометра) в коде. Подскажите, где собака порылась, как только ставлю sensors.being() в процедуру setup, код перестает работать ((

код ниже:

#include <SPI.h>
#include <Ethernet.h>
#include <TimerThree.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 10
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 20, 210); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80
const int led = LED_BUILTIN;  // the pin with a LED
unsigned long windCount = 0;
unsigned long windCountCopy = 0;
float curTemp = 0;
int ledState = LOW;

void setup()
{
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
    pinMode(led, OUTPUT);
    attachInterrupt(1, blink, RISING);
    Timer3.initialize(1000000); //1 second
    Timer3.attachInterrupt(writeToPort); // blinkLED to run every 0.15 seconds
    Serial.begin(9600);
    sensors.begin();
}

void writeToPort(void)
{
  noInterrupts();
  windCountCopy = windCount;
  windCount = 0;
  interrupts();
  //sensors.requestTemperatures();
  //curTemp = sensors.getTempCByIndex(0);
  Serial.print("windCount = ");
  Serial.println(windCountCopy);  
}

void blink(void)
{
  windCount = windCount + 1;
  if (ledState == LOW) {
    ledState = HIGH;
  } else {
    ledState = LOW;
  }
  digitalWrite(led, ledState);
}

void loop()
{
    EthernetClient client = server.available();  // try to get client

    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println("Connection: close");
                    client.println();
                    // send web page
                    client.println("<!DOCTYPE html>");
                    client.println("<html>");
                    client.println("<head>");
                    client.println("<title>Arduino Web Page</title>");
                    client.println("<meta http-equiv=\"refresh\" content=\"1\" >");
                    client.println("</head>");
                    client.println("<body>");
                    String windCountStr = "";
//                    char curTempStr[15];
                    windCountStr += windCountCopy;
//                    dtostrf(curTemp, 3, 2, curTempStr);
//                    String curTempStr = dtostrf(curTemp, 2, 2, 10);
                    client.println("<p>Wind speed: " + windCountStr + "</p>");
     //               client.println("<p>Temperature: ");
       //             client.println(curTemp);
         //           client.println("</p>");
                    client.println("</body>");
                    client.println("</html>");
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}
Araris
Offline
Зарегистрирован: 09.11.2012

Мой Вам совет - уберите измерение температуры из обработчика прерывания.

1. Заведите в loop некий вызыватель некой функции (ReadTemperatures())













//////////////////// RUN EVERY 5 SEC
if ( millis() < Every5SecondTimer ) { Every5SecondTimer = millis(); } // after millis() overflow
if ( (millis() - Every5SecondTimer) > 5000 )
 {
 // Read temperatures
 ReadTemperatures();
 Every5SecondTimer = millis();
 }

2. Заведите некий селектор (DS18B20mode) и в функции по очереди вызывайте requestTemperatures() и функцию считывания температуры (getTempC(DS18B20_devaddr0))









void ReadTemperatures()
{
// Read temperatures
if (DS18B20mode) 
 {
 DS18B20sensors1.requestTemperatures();
 }
else 
 {
 float tempGet;
 tempGet = DS18B20sensors1.getTempC(DS18B20_devaddr0);
 }
DS18B20mode = !DS18B20mode; 
}

 

stncld
Offline
Зарегистрирован: 28.10.2014

спасибо, сделал как вы сказали, то же самое. У меня возникло много вопросов пока я внедрял ваш код, но я вроде самостоятельно разобрался с помощью документации и гугла.

Но, не работает почему-то. А именно, загрузил скетч, обратился по айпи адресу, получил ответ, через 10 секунд должен был быть рефреш, но страницу ардуино не отдает. Хотя я кручу колесико мыши, у меня диод моргает, значит, прерывание отрабатывает. Пинги до устройства идут. Куда смотреть? Взгляните, пожалуйста, на конечный код, может я что-то напутал? Спасибо!

#include <SPI.h>
#include <Ethernet.h>
#include <TimerThree.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 10
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
boolean DS18B20mode = true;
DeviceAddress DS18B20_devaddr0;
unsigned long Every5SecondTimer;
// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 41); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80
const int led = LED_BUILTIN;  // the pin with a LED
unsigned long windCount = 0;
unsigned long windCountCopy = 0;
float curTemp = 0;
int ledState = LOW;


void setup()
{
    sensors.begin();
    sensors.getAddress(DS18B20_devaddr0, 0);
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
    pinMode(led, OUTPUT);
    attachInterrupt(1, blink, RISING);
    Timer3.initialize(10000000); //1 second
    Timer3.attachInterrupt(writeToPort); // blinkLED to run every 0.15 seconds
    //Serial.begin(9600);
}

void writeToPort(void)
{
//  noInterrupts();
  windCountCopy = windCount;
  windCount = 0;
//  interrupts();
//  sensors.requestTemperatures();
//  curTemp = sensors.getTempCByIndex(0);
  //Serial.print("windCount = ");
  //Serial.println(windCountCopy);  
}

void blink(void)
{
  windCount = windCount + 1;
  if (ledState == LOW) {
    ledState = HIGH;
  } else {
    ledState = LOW;
  }
  digitalWrite(led, ledState);
}

void ReadTemperatures()
{
  // Read temperatures
  if (DS18B20mode) 
   {
     sensors.requestTemperatures();
   }
  else 
   {
    curTemp = sensors.getTempC(DS18B20_devaddr0);
   }
  DS18B20mode = !DS18B20mode; 
}


void loop()
{

//////////////////// RUN EVERY 5 SEC
if ( millis() < Every5SecondTimer ) { Every5SecondTimer = millis(); } // after millis() overflow
if ( (millis() - Every5SecondTimer) > 5000 )
 {
    // Read temperatures
    ReadTemperatures();
    Every5SecondTimer = millis();
 }

  EthernetClient client = server.available();  // try to get client

    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println("Connection: close");
                    client.println();
                    // send web page
                    client.println("<!DOCTYPE html>");
                    client.println("<html>");
                    client.println("<head>");
                    client.println("<title>Arduino Web Page</title>");
                    client.println("<meta http-equiv=\"refresh\" content=\"10\" >");
                    client.println("</head>");
                    client.println("<body>");
                    String windCountStr = "";
//                    char curTempStr[15];
                    windCountStr += windCountCopy;
//                    dtostrf(curTemp, 3, 2, curTempStr);
//                    String curTempStr = dtostrf(curTemp, 2, 2, 10);
                    client.println("<p>Wind speed: " + windCountStr + "</p>");
                    client.println("<p>Temperature: ");
                    client.println(curTemp);
                    client.println("</p>");
                    client.println("</body>");
                    client.println("</html>");
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}

 

Araris
Offline
Зарегистрирован: 09.11.2012

У меня в свое время были большие (и так и не решенные) проблемы с meta http-equiv="refresh" content="10"

Пару раз (рандомно) срабатывало и переставало отдавать контент. Убирал http-equiv="refresh" content="10", ставил автообновление страницы из браузера - та же фигня. Ничего не добился, поменял подход и ушел с TCP на UDP.

Скетч выглядит вполне рабочим и достаточно малым в плане использования памяти. Колесико мыши, моргающий диод и отрабатывающее прерывание, на мой взгляд, к проблеме с выдачей странички отношения не имеют. 

stncld
Offline
Зарегистрирован: 28.10.2014

ну да, опрос датчика температуры надо конечно пореже делать, он небыстро делается

я правильно понимаю, что нужно делать попеременно requestTemperatures и getTempC чтобы ускорить процесс получения температуры? в документации опять же особо ничего не расписано

Araris
Offline
Зарегистрирован: 09.11.2012

stncld пишет:

ну да, опрос датчика температуры надо конечно пореже делать, он небыстро делается

я правильно понимаю, что нужно делать попеременно requestTemperatures и getTempC чтобы ускорить процесс получения температуры? в документации опять же особо ничего не расписано

Да, можно делать попеременно.

Почитайте о функциях setResolution() и setWaitForConversion() библиотеки DallasTemperature, там про "быстро" и "небыстро" как раз.

stncld
Offline
Зарегистрирован: 28.10.2014

Цитата:

Да, можно делать попеременно.

Почитайте о функциях setResolution() и setWaitForConversion() библиотеки DallasTemperature, там про "быстро" и "небыстро" как раз.

все, нашел, в DallasTemperature.cpp ))) Получается, что если не выставить setWaitForConversion() в false, то оно будет работать "медленно". Спасибо за наводку, очень помогли, теперь понятна схема, которую вы подкинули. Осталось разобраться, почему же он все-таки зависает. Я еще на arduino.cc форуме задал вопрос, но пока ничего путнего мне там не ответили

А "нормальной" доки на dallastemperature нет? только сорцы смотреть? )

Araris
Offline
Зарегистрирован: 09.11.2012

stncld пишет:

А "нормальной" доки на dallastemperature нет? только сорцы смотреть? )

DallasTemperature.h - наше все, полноценной документации не встречал, впрочем, так ли она нужна ?

GreenDer
Offline
Зарегистрирован: 06.09.2013

Крайне не рекомендую использовать библиотеки для конкретных устройств 1wire. Лучше использовать библиотеку 1wire и отдавать команды устройствам "вручную". Сразу избавитесь от кучи проблем связанных с конфликтами библиотек.

Вот доки по "однопроводу".

http://chipenable.ru/index.php/programming-avr/item/81-1-wire-rabota-s-d...

http://owfs.sourceforge.net/family.html

http://www.maximintegrated.com/en/products/1-wire/flash/overview/

http://www.mirpu.ru/interface/87-1-wire/180--1-wire-.html?7e140644fd59b5...