изменение регистра конфигурации датчика ds18b20
- Войдите на сайт для отправки комментариев
Вс, 25/06/2017 - 12:25
Здравствуйте, подскажите как понизить точночть разрешения измерения температуры ds18b20 c 0.00625С до 0.5С в библиотеке DallasTemperature? Спасибо.
Файл DallasTemperature.cpp
/*
DallasTemperature.CPP - Dallas Temperature Control Library 1.0.0
Author: Miles Burton, miles@mnetcs.com
Copyright (c) 2009 Miles Burton All Rights Reserved
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
This code has been derived from: http://www.arduino.cc/playground/Learning/OneWire. Unknown author, unknown date
*/
#include "DallasTemperature.h"
#include "Arduino.h"
extern "C" {
#include <string.h>
#include <stdlib.h>
}
#define DS18S20MODEL 0x10 // Model ID
#define DS18B20MODEL 0x28 // Model ID
#define DS1822MODEL 0x22 // Model ID
#define STARTCONVO 0x44 // Initalises slaves
#define COPYSCRATCH 0x48 // Copy EEPROM
#define READSCRATCH 0xBE // Read EEPROM
#define WRITESCRATCH 0x4E // Write to EEPROM
#define TEMPCOMMAND 0xBE // Request temperature
#define RECALLSCRATCH 0xB8 // Reload from last known
// Slave validation
#define INVALIDCRC 1
#define INVALIDMODEL 2
#define SLAVEGOOD 0
DallasTemperature::DallasTemperature(StratBase* pTBase)
{
// Allow user to pass in a strategy if required
if(pStratBase != 0) pStratBase = pTBase;
// Warning: Nothing will be defined
}
// Start the interface with a new instance of NewOneWire
void DallasTemperature::begin(uint8_t wirePin)
{
pDataWire = new NewOneWire(wirePin); // Instance object
reset();
}
// Initalise with a reference to one wire
void DallasTemperature::begin(NewOneWire& NewOneWireRef)
{
pDataWire = &NewOneWireRef;
reset();
}
// Search the 1-wire interface for sign of our little device
void DallasTemperature::searchWire(void)
{
initArr();
if (!pDataWire->search(arSlaveAddr)){
pDataWire->reset_search();
return;
} // Note: this is enumerating
}
// Return one wire instance if required
NewOneWire DallasTemperature::getNewOneWireInstance(void)
{
return *pDataWire;
}
// Initalise arrays
void DallasTemperature::initArr(void)
{
// init array
for(int i=0;i<8;i++) arSlaveAddr[i] = 0xFF;
}
// Send command
void DallasTemperature::beginCommunication(void)
{
pDataWire->reset();
pDataWire->select(arSlaveAddr);
pDataWire->write(STARTCONVO,1); // start conversion, with parasite power on at the end
delay(1000);
}
// Send command
void DallasTemperature::requestTemperature(void)
{
pDataWire->reset();
pDataWire->select(arSlaveAddr);
pDataWire->write(READSCRATCH); // Read Scratchpad
}
float DallasTemperature::getTemperature() // ~ Double word, expensive
{
// If we're ready to rock, begin communication channel
if(isValid()==SLAVEGOOD){
beginCommunication();
}else{
return 0;
}
requestTemperature(); // Send appropriate command
// Originally you would read all n bytes (12~). We only need the first two
byte lowByte = pDataWire->read();
byte highByte = pDataWire->read();
// TODO: Doesn't consider negative.
int reading = (highByte<<8) + lowByte; // Concat word
//TODO fix me, should negate
if (reading & 0x8000) reading = (reading ^ 0xffff) + 1; // 2's comp
float temp = (6 * reading) + reading / 4; // multiply by (100 * 0.0625) or 6.25
return temp/100; // Divide by 100 to gain decimal.
}
// Validate whether the current address is correct
int DallasTemperature::isValid(void)
{
// Calculate Cycle-Redudancy-Check (ie: check the data is not invalid
if ( NewOneWire::crc8( arSlaveAddr, 7) != arSlaveAddr[7]) {
return INVALIDCRC;
}
if(!(arSlaveAddr[0] == DS18B20MODEL
|| arSlaveAddr[0] == DS18S20MODEL
|| arSlaveAddr[0] == DS1822MODEL
)){
return INVALIDMODEL;
}
// Return all good
return SLAVEGOOD;
}
// Select and initalise appropriate strategy
int DallasTemperature::loadStrategy(void)
{
switch(arSlaveAddr[0])
{
case DS18B20MODEL:
pStratBase = new BSeries();
break;
// Allow fall through
case DS18S20MODEL:
case DS1822MODEL:
pStratBase = new S20Series();
break;
default:
return INVALIDMODEL;
break;
}
return SLAVEGOOD;
}
// Fires a total reset (Useful for intermittant connections)
void DallasTemperature::reset(void)
{
initArr(); // reset arrays
searchWire();
if(isValid()==SLAVEGOOD)
{
loadStrategy();
beginCommunication();
}
}
// Convert float celcius to fahrenheit
float DallasTemperature::toFahrenheit(float celcius)
{
return (celcius*1.8)+32;
}
// MnetCS - Allocates memory for DallasTemperature. Allows us to instance a new object
void* DallasTemperature::operator new(unsigned int size) // Implicit NSS obj size
{
void * p; // void pointer
p = malloc(size); // Allocate memory
memset((DallasTemperature*)p,0,size); // Initalise memory
//!!! CANT EXPLICITLY CALL CONSTRUCTOR - workaround by using an init() methodR - workaround by using an init() method
return (DallasTemperature*) p; // Cast blank region to NSS pointer
}
// MnetCS 2009 - Unallocates the memory used by this instance
void DallasTemperature::operator delete(void* p)
{
DallasTemperature* pNss = (DallasTemperature*) p; // Cast to NSS pointer
pNss->~DallasTemperature(); // Destruct the object
free(p); // Free the memory
}
Файл DallasTemperature.h
#ifndef DallasTemperature_h
#define DallasTemperature_h
/*
DallasTemperature.h - Dallas Temperature Control Library 1.0.0
Author: Miles Burton, miles@mnetcs.com
Copyright (c) 2009 Miles Burton All Rights Reserved
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
This code has been derived from: http://www.arduino.cc/playground/Learning/OneWire. Unknown author, unknown date
*/
#include <inttypes.h>
#include "NewOneWire.h"
// Strategies to calculate tempreture for specific device
#include "StratBase.h" // Base Strategy
#include "BSeries.h" // Concrete Strat for 'b' series
#include "S20Series.h" // Concrete strat for S and '20' series
// The measurement we're taking
class DallasTemperature
{
private:
NewOneWire* pDataWire; // One Wire Instance (a copy of)
uint8_t arSlaveAddr[8]; // 64bit address of device
// I wont justify this
void searchWire();
// Send request temperature command
void requestTemperature();
// initalise arrays
void initArr();
// Initalise 1-wire communication
void beginCommunication();
// Pointer to temperature strategy
StratBase* pStratBase;
// Load appropriate strat
int loadStrategy(); // Returns invalid model or good [-1]
public:
DallasTemperature(StratBase* = 0); // Strategy
// Process temperature in given format (default is C*)
float getTemperature();
// Initalise to pin
void begin(uint8_t);
// is the slave valid
int isValid(); // strangely, 0 is "GOOD"
// reset everything. Useful if you knock the power cable etc
void reset();
// Begin with existing instance if 'NewOneWire' - could be useful
void begin(NewOneWire&);
// Allow user to repurpose onewire
NewOneWire getNewOneWireInstance();
// Convert from celcius to farenheit if required
static float toFahrenheit(float);
void* operator new (unsigned int size); // Initalise memory area
void operator delete(void* p); // delete memory reference
};
#endif
Здравствуйте, подскажите как понизить точночть разрешения измерения температуры ds18b20 c 0.00625С до 0.5С в библиотеке DallasTemperature?
1. Найти версию библиотеки посвежее, не 2009-го года.
Например, https://github.com/milesburton/Arduino-Temperature-Control-Library
2. Найти в файле https://github.com/milesburton/Arduino-Temperature-Control-Library/blob/master/DallasTemperature.h функцию setResolution();.
3. Воспользоваться.
сделал как вы сказали, выдает следующую ошибку:
сделал как вы сказали, выдает следующую ошибку:
решил данную проблемму, функцию setResolution использовать в разделе установок или в коде программы? время цикла программы станет меньше само или надо где то уменьшить время ожидания датчика?
время цикла программы станет меньше само или надо где то уменьшить время ожидания датчика?
Не понял, Вы всё эо затеяли, чтобы уменьшить время замера? Так?
Ну, во-первых delay(750) там написано тупо, незаивисмо ни от чего. Посмотрите в тексте библиотеки сами.
Во вторых:
1) (хорошая новость) библиотека предусамтривает неблокирующий вызов, безо всяких делэев
2) (плохая новость) там ошибка, и неблокирующий вызов не работает
3) (хорошая новость) ошибку можно обойти и, хоть немного через задницу, но организовать таки неблокирующие вызовы.
Пример неблокирующего вызова нужен?
не совсем понимаю про неблокируюий вызов. опишу свою задачу может станет проще нам обоим. мне на одной плате uno надо организовать измерение температуры и 2 функции по прерыванию attachInterrupt(). функции по прерыванию я организовал, без датчика работают как надо, подключаю датчик непонятную информацию получаю от прерывания, я так понимаю оно просто не успевает изменрятся пока опрашивается датчик, вот мне и надо что то с временем измерения сделать, снизить.
Для начала Вам необходимо ознакомиться и выполнять правила этого форума для включения кода в сообщения.
вот мне и надо что то с временем измерения сделать, снизить.
Ну, надо-то Вам не это, но даже если и так, то возникает законный вопрос: снизить насколько?
Неблокирующий вызов обозначает, что нет нужды ожидать его завершения 750 мс.
Представьте, что у вас есть отдельный процесс, который обновляет значение температуры в некой глобальной переменной.
Когда другим частям программы нужна температура, они просто используют это значение. Иногда оно окажется "старым" на 750 мс.
Процесс обновления температуры тоже мнгновенный, прочли текущее значение из датчика и тутже обновили запрос.
По таймеру, через 750 мс - снова обновили температуру и снова отправили запрос.
Между запросами не висим в никчемном делее, а работает остальная программа, чем-там-она-у-вас-занимается.
Понятно? Основное, что требует понимания, это то, что ждать 750 мс НЕ обязательно. Можно разорвать запрос и чтение ответа. Тогда все ваши прерывания будут нормально работать.
Выкини наконец Даллас Температуру, запили на OneWire (на сторожевом таймере или на миллисе), получи 2К флэша бонусом и избавься тупого ожидания.
Выкини наконец Даллас Температуру, запили на OneWire (на сторожевом таймере или на миллисе), получи 2К флэша бонусом и избавься тупого ожидания.
Да, ладно. Если голова на месте, так и с этой библиотекой жить можно. Блокирующий вызов не делать (тупое ожидание в минус), и вместо float возвращать целое в десятых долях градуса (минус те самые кила флеша).
А если с головой напряг, так не поможет ни OneWire, ни даже чистый, ламповый Си (кажется, я уже наговорил на "Оскорбление чувств верующих", так что замолкаю от греха :-))))
да все верно, мне надо сделать "отдельный процесс" который будет жить сам по себе, актуальность информации в 1-2 секунды мне не важна, мне и точности до целых достаточно, датчик "грубый". скиньте пожалуйста пример не блокирующего вызова.
Пожалуйста
Пожалуйста
Злобный иезуит.))))