mult. DS18B20 Temp demo
This commit is contained in:
parent
1a309e6632
commit
4ff973a0cc
618
examples/osd/arduino-dallastemp/DallasTemperature.cpp
Normal file
618
examples/osd/arduino-dallastemp/DallasTemperature.cpp
Normal file
|
@ -0,0 +1,618 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#include "DallasTemperature.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "Arduino.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
DallasTemperature::DallasTemperature(OneWire* _oneWire)
|
||||||
|
#if REQUIRESALARMS
|
||||||
|
: _AlarmHandler(&defaultAlarmHandler)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
_wire = _oneWire;
|
||||||
|
devices = 0;
|
||||||
|
parasite = false;
|
||||||
|
conversionDelay = TEMP_9_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize the bus
|
||||||
|
void DallasTemperature::begin(void)
|
||||||
|
{
|
||||||
|
DeviceAddress deviceAddress;
|
||||||
|
|
||||||
|
_wire->reset_search();
|
||||||
|
devices = 0; // Reset the number of devices when we enumerate wire devices
|
||||||
|
|
||||||
|
while (_wire->search(deviceAddress))
|
||||||
|
{
|
||||||
|
if (validAddress(deviceAddress))
|
||||||
|
{
|
||||||
|
if (!parasite && readPowerSupply(deviceAddress)) parasite = true;
|
||||||
|
|
||||||
|
ScratchPad scratchPad;
|
||||||
|
|
||||||
|
readScratchPad(deviceAddress, scratchPad);
|
||||||
|
|
||||||
|
if (deviceAddress[0] == DS18S20MODEL) conversionDelay = TEMP_12_BIT; // 750 ms
|
||||||
|
else if (scratchPad[CONFIGURATION] > conversionDelay) conversionDelay = scratchPad[CONFIGURATION];
|
||||||
|
|
||||||
|
devices++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the number of devices found on the bus
|
||||||
|
uint8_t DallasTemperature::getDeviceCount(void)
|
||||||
|
{
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if address is valid
|
||||||
|
bool DallasTemperature::validAddress(uint8_t* deviceAddress)
|
||||||
|
{
|
||||||
|
return (_wire->crc8(deviceAddress, 7) == deviceAddress[7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finds an address at a given index on the bus
|
||||||
|
// returns true if the device was found
|
||||||
|
bool DallasTemperature::getAddress(uint8_t* deviceAddress, uint8_t index)
|
||||||
|
{
|
||||||
|
uint8_t depth = 0;
|
||||||
|
|
||||||
|
_wire->reset_search();
|
||||||
|
|
||||||
|
while (depth <= index && _wire->search(deviceAddress))
|
||||||
|
{
|
||||||
|
if (depth == index && validAddress(deviceAddress)) return true;
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// attempt to determine if the device at the given address is connected to the bus
|
||||||
|
bool DallasTemperature::isConnected(uint8_t* deviceAddress)
|
||||||
|
{
|
||||||
|
ScratchPad scratchPad;
|
||||||
|
return isConnected(deviceAddress, scratchPad);
|
||||||
|
}
|
||||||
|
|
||||||
|
// attempt to determine if the device at the given address is connected to the bus
|
||||||
|
// also allows for updating the read scratchpad
|
||||||
|
bool DallasTemperature::isConnected(uint8_t* deviceAddress, uint8_t* scratchPad)
|
||||||
|
{
|
||||||
|
readScratchPad(deviceAddress, scratchPad);
|
||||||
|
return (_wire->crc8(scratchPad, 8) == scratchPad[SCRATCHPAD_CRC]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read device's scratch pad
|
||||||
|
void DallasTemperature::readScratchPad(uint8_t* deviceAddress, uint8_t* scratchPad)
|
||||||
|
{
|
||||||
|
// send the command
|
||||||
|
_wire->reset();
|
||||||
|
_wire->select(deviceAddress);
|
||||||
|
_wire->write(READSCRATCH);
|
||||||
|
|
||||||
|
// read the response
|
||||||
|
|
||||||
|
// byte 0: temperature LSB
|
||||||
|
scratchPad[TEMP_LSB] = _wire->read();
|
||||||
|
|
||||||
|
// byte 1: temperature MSB
|
||||||
|
scratchPad[TEMP_MSB] = _wire->read();
|
||||||
|
|
||||||
|
// byte 2: high alarm temp
|
||||||
|
scratchPad[HIGH_ALARM_TEMP] = _wire->read();
|
||||||
|
|
||||||
|
// byte 3: low alarm temp
|
||||||
|
scratchPad[LOW_ALARM_TEMP] = _wire->read();
|
||||||
|
|
||||||
|
// byte 4:
|
||||||
|
// DS18S20: store for crc
|
||||||
|
// DS18B20 & DS1822: configuration register
|
||||||
|
scratchPad[CONFIGURATION] = _wire->read();
|
||||||
|
|
||||||
|
// byte 5:
|
||||||
|
// internal use & crc
|
||||||
|
scratchPad[INTERNAL_BYTE] = _wire->read();
|
||||||
|
|
||||||
|
// byte 6:
|
||||||
|
// DS18S20: COUNT_REMAIN
|
||||||
|
// DS18B20 & DS1822: store for crc
|
||||||
|
scratchPad[COUNT_REMAIN] = _wire->read();
|
||||||
|
|
||||||
|
// byte 7:
|
||||||
|
// DS18S20: COUNT_PER_C
|
||||||
|
// DS18B20 & DS1822: store for crc
|
||||||
|
scratchPad[COUNT_PER_C] = _wire->read();
|
||||||
|
|
||||||
|
// byte 8:
|
||||||
|
// SCTRACHPAD_CRC
|
||||||
|
scratchPad[SCRATCHPAD_CRC] = _wire->read();
|
||||||
|
|
||||||
|
_wire->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// writes device's scratch pad
|
||||||
|
void DallasTemperature::writeScratchPad(uint8_t* deviceAddress, const uint8_t* scratchPad)
|
||||||
|
{
|
||||||
|
_wire->reset();
|
||||||
|
_wire->select(deviceAddress);
|
||||||
|
_wire->write(WRITESCRATCH);
|
||||||
|
_wire->write(scratchPad[HIGH_ALARM_TEMP]); // high alarm temp
|
||||||
|
_wire->write(scratchPad[LOW_ALARM_TEMP]); // low alarm temp
|
||||||
|
// DS18S20 does not use the configuration register
|
||||||
|
if (deviceAddress[0] != DS18S20MODEL) _wire->write(scratchPad[CONFIGURATION]); // configuration
|
||||||
|
_wire->reset();
|
||||||
|
// save the newly written values to eeprom
|
||||||
|
_wire->write(COPYSCRATCH, parasite);
|
||||||
|
if (parasite) delay(10); // 10ms delay
|
||||||
|
_wire->reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads the device's power requirements
|
||||||
|
bool DallasTemperature::readPowerSupply(uint8_t* deviceAddress)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
_wire->reset();
|
||||||
|
_wire->select(deviceAddress);
|
||||||
|
_wire->write(READPOWERSUPPLY);
|
||||||
|
if (_wire->read_bit() == 0) ret = true;
|
||||||
|
_wire->reset();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the current resolution, 9-12
|
||||||
|
uint8_t DallasTemperature::getResolution(uint8_t* deviceAddress)
|
||||||
|
{
|
||||||
|
if (deviceAddress[0] == DS18S20MODEL) return 9; // this model has a fixed resolution
|
||||||
|
|
||||||
|
ScratchPad scratchPad;
|
||||||
|
readScratchPad(deviceAddress, scratchPad);
|
||||||
|
switch (scratchPad[CONFIGURATION])
|
||||||
|
{
|
||||||
|
case TEMP_12_BIT:
|
||||||
|
return 12;
|
||||||
|
break;
|
||||||
|
case TEMP_11_BIT:
|
||||||
|
return 11;
|
||||||
|
break;
|
||||||
|
case TEMP_10_BIT:
|
||||||
|
return 10;
|
||||||
|
break;
|
||||||
|
case TEMP_9_BIT:
|
||||||
|
return 9;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set resolution of a device to 9, 10, 11, or 12 bits
|
||||||
|
void DallasTemperature::setResolution(uint8_t* deviceAddress, uint8_t newResolution)
|
||||||
|
{
|
||||||
|
ScratchPad scratchPad;
|
||||||
|
if (isConnected(deviceAddress, scratchPad))
|
||||||
|
{
|
||||||
|
// DS18S20 has a fixed 9-bit resolution
|
||||||
|
if (deviceAddress[0] != DS18S20MODEL)
|
||||||
|
{
|
||||||
|
switch (newResolution)
|
||||||
|
{
|
||||||
|
case 12:
|
||||||
|
scratchPad[CONFIGURATION] = TEMP_12_BIT;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
scratchPad[CONFIGURATION] = TEMP_11_BIT;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
scratchPad[CONFIGURATION] = TEMP_10_BIT;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
default:
|
||||||
|
scratchPad[CONFIGURATION] = TEMP_9_BIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
writeScratchPad(deviceAddress, scratchPad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends command for all devices on the bus to perform a temperature
|
||||||
|
void DallasTemperature::requestTemperatures(void)
|
||||||
|
{
|
||||||
|
_wire->reset();
|
||||||
|
_wire->skip();
|
||||||
|
_wire->write(STARTCONVO, parasite);
|
||||||
|
|
||||||
|
switch (conversionDelay)
|
||||||
|
{
|
||||||
|
case TEMP_9_BIT:
|
||||||
|
delay(94);
|
||||||
|
break;
|
||||||
|
case TEMP_10_BIT:
|
||||||
|
delay(188);
|
||||||
|
break;
|
||||||
|
case TEMP_11_BIT:
|
||||||
|
delay(375);
|
||||||
|
break;
|
||||||
|
case TEMP_12_BIT:
|
||||||
|
default:
|
||||||
|
delay(750);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends command for one device to perform a temperature by address
|
||||||
|
void DallasTemperature::requestTemperaturesByAddress(uint8_t* deviceAddress)
|
||||||
|
{
|
||||||
|
_wire->reset();
|
||||||
|
_wire->select(deviceAddress);
|
||||||
|
_wire->write(STARTCONVO, parasite);
|
||||||
|
|
||||||
|
switch (conversionDelay)
|
||||||
|
{
|
||||||
|
case TEMP_9_BIT:
|
||||||
|
delay(94);
|
||||||
|
break;
|
||||||
|
case TEMP_10_BIT:
|
||||||
|
delay(188);
|
||||||
|
break;
|
||||||
|
case TEMP_11_BIT:
|
||||||
|
delay(375);
|
||||||
|
break;
|
||||||
|
case TEMP_12_BIT:
|
||||||
|
default:
|
||||||
|
delay(750);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends command for one device to perform a temp conversion by index
|
||||||
|
void DallasTemperature::requestTemperaturesByIndex(uint8_t deviceIndex)
|
||||||
|
{
|
||||||
|
DeviceAddress deviceAddress;
|
||||||
|
getAddress(deviceAddress, deviceIndex);
|
||||||
|
requestTemperaturesByAddress(deviceAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Fetch temperature for device index
|
||||||
|
float DallasTemperature::getTempCByIndex(uint8_t deviceIndex)
|
||||||
|
{
|
||||||
|
DeviceAddress deviceAddress;
|
||||||
|
getAddress(deviceAddress, deviceIndex);
|
||||||
|
return getTempC((uint8_t*)deviceAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch temperature for device index
|
||||||
|
float DallasTemperature::getTempFByIndex(uint8_t deviceIndex)
|
||||||
|
{
|
||||||
|
return DallasTemperature::toFahrenheit(getTempCByIndex(deviceIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads scratchpad and returns the temperature in degrees C
|
||||||
|
float DallasTemperature::calculateTemperature(uint8_t* deviceAddress, uint8_t* scratchPad)
|
||||||
|
{
|
||||||
|
int16_t rawTemperature = (((int16_t)scratchPad[TEMP_MSB]) << 8) | scratchPad[TEMP_LSB];
|
||||||
|
|
||||||
|
switch (deviceAddress[0])
|
||||||
|
{
|
||||||
|
case DS18B20MODEL:
|
||||||
|
case DS1822MODEL:
|
||||||
|
switch (scratchPad[CONFIGURATION])
|
||||||
|
{
|
||||||
|
case TEMP_12_BIT:
|
||||||
|
return (float)rawTemperature * 0.0625;
|
||||||
|
break;
|
||||||
|
case TEMP_11_BIT:
|
||||||
|
return (float)(rawTemperature >> 1) * 0.125;
|
||||||
|
break;
|
||||||
|
case TEMP_10_BIT:
|
||||||
|
return (float)(rawTemperature >> 2) * 0.25;
|
||||||
|
break;
|
||||||
|
case TEMP_9_BIT:
|
||||||
|
return (float)(rawTemperature >> 3) * 0.5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DS18S20MODEL:
|
||||||
|
/*
|
||||||
|
|
||||||
|
Resolutions greater than 9 bits can be calculated using the data from
|
||||||
|
the temperature, COUNT REMAIN and COUNT PER °C registers in the
|
||||||
|
scratchpad. Note that the COUNT PER °C register is hard-wired to 16
|
||||||
|
(10h). After reading the scratchpad, the TEMP_READ value is obtained
|
||||||
|
by truncating the 0.5°C bit (bit 0) from the temperature data. The
|
||||||
|
extended resolution temperature can then be calculated using the
|
||||||
|
following equation:
|
||||||
|
|
||||||
|
COUNT_PER_C - COUNT_REMAIN
|
||||||
|
TEMPERATURE = TEMP_READ - 0.25 + --------------------------
|
||||||
|
COUNT_PER_C
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Good spot. Thanks Nic Johns for your contribution
|
||||||
|
return (float)(rawTemperature >> 1) - 0.25 +((float)(scratchPad[COUNT_PER_C] - scratchPad[COUNT_REMAIN]) / (float)scratchPad[COUNT_PER_C] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns temperature in degrees C or DEVICE_DISCONNECTED if the
|
||||||
|
// device's scratch pad cannot be read successfully.
|
||||||
|
// the numeric value of DEVICE_DISCONNECTED is defined in
|
||||||
|
// DallasTemperature.h. it is a large negative number outside the
|
||||||
|
// operating range of the device
|
||||||
|
float DallasTemperature::getTempC(uint8_t* deviceAddress)
|
||||||
|
{
|
||||||
|
// TODO: Multiple devices (up to 64) on the same bus may take some time to negotiate a response
|
||||||
|
// What happens in case of collision?
|
||||||
|
|
||||||
|
ScratchPad scratchPad;
|
||||||
|
if (isConnected(deviceAddress, scratchPad)) return calculateTemperature(deviceAddress, scratchPad);
|
||||||
|
return DEVICE_DISCONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns temperature in degrees F
|
||||||
|
float DallasTemperature::getTempF(uint8_t* deviceAddress)
|
||||||
|
{
|
||||||
|
return toFahrenheit(getTempC(deviceAddress));
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if the bus requires parasite power
|
||||||
|
bool DallasTemperature::isParasitePowerMode(void)
|
||||||
|
{
|
||||||
|
return parasite;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if REQUIRESALARMS
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
ALARMS:
|
||||||
|
|
||||||
|
TH and TL Register Format
|
||||||
|
|
||||||
|
BIT 7 BIT 6 BIT 5 BIT 4 BIT 3 BIT 2 BIT 1 BIT 0
|
||||||
|
S 2^6 2^5 2^4 2^3 2^2 2^1 2^0
|
||||||
|
|
||||||
|
Only bits 11 through 4 of the temperature register are used
|
||||||
|
in the TH and TL comparison since TH and TL are 8-bit
|
||||||
|
registers. If the measured temperature is lower than or equal
|
||||||
|
to TL or higher than or equal to TH, an alarm condition exists
|
||||||
|
and an alarm flag is set inside the DS18B20. This flag is
|
||||||
|
updated after every temperature measurement; therefore, if the
|
||||||
|
alarm condition goes away, the flag will be turned off after
|
||||||
|
the next temperature conversion.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// sets the high alarm temperature for a device in degrees celsius
|
||||||
|
// accepts a float, but the alarm resolution will ignore anything
|
||||||
|
// after a decimal point. valid range is -55C - 125C
|
||||||
|
void DallasTemperature::setHighAlarmTemp(uint8_t* deviceAddress, char celsius)
|
||||||
|
{
|
||||||
|
// make sure the alarm temperature is within the device's range
|
||||||
|
if (celsius > 125) celsius = 125;
|
||||||
|
else if (celsius < -55) celsius = -55;
|
||||||
|
|
||||||
|
ScratchPad scratchPad;
|
||||||
|
if (isConnected(deviceAddress, scratchPad))
|
||||||
|
{
|
||||||
|
scratchPad[HIGH_ALARM_TEMP] = (uint8_t)celsius;
|
||||||
|
writeScratchPad(deviceAddress, scratchPad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets the low alarm temperature for a device in degreed celsius
|
||||||
|
// accepts a float, but the alarm resolution will ignore anything
|
||||||
|
// after a decimal point. valid range is -55C - 125C
|
||||||
|
void DallasTemperature::setLowAlarmTemp(uint8_t* deviceAddress, char celsius)
|
||||||
|
{
|
||||||
|
// make sure the alarm temperature is within the device's range
|
||||||
|
if (celsius > 125) celsius = 125;
|
||||||
|
else if (celsius < -55) celsius = -55;
|
||||||
|
|
||||||
|
ScratchPad scratchPad;
|
||||||
|
if (isConnected(deviceAddress, scratchPad))
|
||||||
|
{
|
||||||
|
scratchPad[LOW_ALARM_TEMP] = (uint8_t)celsius;
|
||||||
|
writeScratchPad(deviceAddress, scratchPad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns a char with the current high alarm temperature or
|
||||||
|
// DEVICE_DISCONNECTED for an address
|
||||||
|
char DallasTemperature::getHighAlarmTemp(uint8_t* deviceAddress)
|
||||||
|
{
|
||||||
|
ScratchPad scratchPad;
|
||||||
|
if (isConnected(deviceAddress, scratchPad)) return (char)scratchPad[HIGH_ALARM_TEMP];
|
||||||
|
return DEVICE_DISCONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns a char with the current low alarm temperature or
|
||||||
|
// DEVICE_DISCONNECTED for an address
|
||||||
|
char DallasTemperature::getLowAlarmTemp(uint8_t* deviceAddress)
|
||||||
|
{
|
||||||
|
ScratchPad scratchPad;
|
||||||
|
if (isConnected(deviceAddress, scratchPad)) return (char)scratchPad[LOW_ALARM_TEMP];
|
||||||
|
return DEVICE_DISCONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// resets internal variables used for the alarm search
|
||||||
|
void DallasTemperature::resetAlarmSearch()
|
||||||
|
{
|
||||||
|
alarmSearchJunction = -1;
|
||||||
|
alarmSearchExhausted = 0;
|
||||||
|
for(uint8_t i = 0; i < 7; i++)
|
||||||
|
alarmSearchAddress[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a modified version of the OneWire::search method.
|
||||||
|
//
|
||||||
|
// Also added the OneWire search fix documented here:
|
||||||
|
// http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295
|
||||||
|
//
|
||||||
|
// Perform an alarm search. If this function returns a '1' then it has
|
||||||
|
// enumerated the next device and you may retrieve the ROM from the
|
||||||
|
// OneWire::address variable. If there are no devices, no further
|
||||||
|
// devices, or something horrible happens in the middle of the
|
||||||
|
// enumeration then a 0 is returned. If a new device is found then
|
||||||
|
// its address is copied to newAddr. Use
|
||||||
|
// DallasTemperature::resetAlarmSearch() to start over.
|
||||||
|
bool DallasTemperature::alarmSearch(uint8_t* newAddr)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
char lastJunction = -1;
|
||||||
|
uint8_t done = 1;
|
||||||
|
|
||||||
|
if (alarmSearchExhausted) return false;
|
||||||
|
if (!_wire->reset()) return false;
|
||||||
|
|
||||||
|
// send the alarm search command
|
||||||
|
_wire->write(0xEC, 0);
|
||||||
|
|
||||||
|
for(i = 0; i < 64; i++)
|
||||||
|
{
|
||||||
|
uint8_t a = _wire->read_bit( );
|
||||||
|
uint8_t nota = _wire->read_bit( );
|
||||||
|
uint8_t ibyte = i / 8;
|
||||||
|
uint8_t ibit = 1 << (i & 7);
|
||||||
|
|
||||||
|
// I don't think this should happen, this means nothing responded, but maybe if
|
||||||
|
// something vanishes during the search it will come up.
|
||||||
|
if (a && nota) return false;
|
||||||
|
|
||||||
|
if (!a && !nota)
|
||||||
|
{
|
||||||
|
if (i == alarmSearchJunction)
|
||||||
|
{
|
||||||
|
// this is our time to decide differently, we went zero last time, go one.
|
||||||
|
a = 1;
|
||||||
|
alarmSearchJunction = lastJunction;
|
||||||
|
}
|
||||||
|
else if (i < alarmSearchJunction)
|
||||||
|
{
|
||||||
|
// take whatever we took last time, look in address
|
||||||
|
if (alarmSearchAddress[ibyte] & ibit) a = 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Only 0s count as pending junctions, we've already exhasuted the 0 side of 1s
|
||||||
|
a = 0;
|
||||||
|
done = 0;
|
||||||
|
lastJunction = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we are blazing new tree, take the 0
|
||||||
|
a = 0;
|
||||||
|
alarmSearchJunction = i;
|
||||||
|
done = 0;
|
||||||
|
}
|
||||||
|
// OneWire search fix
|
||||||
|
// See: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a) alarmSearchAddress[ibyte] |= ibit;
|
||||||
|
else alarmSearchAddress[ibyte] &= ~ibit;
|
||||||
|
|
||||||
|
_wire->write_bit(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done) alarmSearchExhausted = 1;
|
||||||
|
for (i = 0; i < 8; i++) newAddr[i] = alarmSearchAddress[i];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if device address has an alarm condition
|
||||||
|
bool DallasTemperature::hasAlarm(uint8_t* deviceAddress)
|
||||||
|
{
|
||||||
|
ScratchPad scratchPad;
|
||||||
|
if (isConnected(deviceAddress, scratchPad))
|
||||||
|
{
|
||||||
|
float temp = calculateTemperature(deviceAddress, scratchPad);
|
||||||
|
|
||||||
|
// check low alarm
|
||||||
|
if ((char)temp <= (char)scratchPad[LOW_ALARM_TEMP]) return true;
|
||||||
|
|
||||||
|
// check high alarm
|
||||||
|
if ((char)temp >= (char)scratchPad[HIGH_ALARM_TEMP]) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no alarm
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns true if any device is reporting an alarm condition on the bus
|
||||||
|
bool DallasTemperature::hasAlarm(void)
|
||||||
|
{
|
||||||
|
DeviceAddress deviceAddress;
|
||||||
|
resetAlarmSearch();
|
||||||
|
return alarmSearch(deviceAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
// runs the alarm handler for all devices returned by alarmSearch()
|
||||||
|
void DallasTemperature::processAlarms(void)
|
||||||
|
{
|
||||||
|
resetAlarmSearch();
|
||||||
|
DeviceAddress alarmAddr;
|
||||||
|
|
||||||
|
while (alarmSearch(alarmAddr))
|
||||||
|
{
|
||||||
|
if (validAddress(alarmAddr))
|
||||||
|
_AlarmHandler(alarmAddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets the alarm handler
|
||||||
|
void DallasTemperature::setAlarmHandler(AlarmHandler *handler)
|
||||||
|
{
|
||||||
|
_AlarmHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The default alarm handler
|
||||||
|
void DallasTemperature::defaultAlarmHandler(uint8_t* deviceAddress)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Convert float celsius to fahrenheit
|
||||||
|
float DallasTemperature::toFahrenheit(float celsius)
|
||||||
|
{
|
||||||
|
return (celsius * 1.8) + 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert float fahrenheit to celsius
|
||||||
|
float DallasTemperature::toCelsius(float fahrenheit)
|
||||||
|
{
|
||||||
|
return (fahrenheit - 32) / 1.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if REQUIRESNEW
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
213
examples/osd/arduino-dallastemp/DallasTemperature.h
Normal file
213
examples/osd/arduino-dallastemp/DallasTemperature.h
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
#ifndef DallasTemperature_h
|
||||||
|
#define DallasTemperature_h
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// set to true to include code for new and delete operators
|
||||||
|
#ifndef REQUIRESNEW
|
||||||
|
#define REQUIRESNEW false
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// set to true to include code implementing alarm search functions
|
||||||
|
#ifndef REQUIRESALARMS
|
||||||
|
#define REQUIRESALARMS true
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <OneWire.h>
|
||||||
|
|
||||||
|
// Model IDs
|
||||||
|
#define DS18S20MODEL 0x10
|
||||||
|
#define DS18B20MODEL 0x28
|
||||||
|
#define DS1822MODEL 0x22
|
||||||
|
|
||||||
|
// OneWire commands
|
||||||
|
#define STARTCONVO 0x44 // Tells device to take a temperature reading and put it on the scratchpad
|
||||||
|
#define COPYSCRATCH 0x48 // Copy EEPROM
|
||||||
|
#define READSCRATCH 0xBE // Read EEPROM
|
||||||
|
#define WRITESCRATCH 0x4E // Write to EEPROM
|
||||||
|
#define RECALLSCRATCH 0xB8 // Reload from last known
|
||||||
|
#define READPOWERSUPPLY 0xB4 // Determine if device needs parasite power
|
||||||
|
#define ALARMSEARCH 0xEC // Query bus for devices with an alarm condition
|
||||||
|
|
||||||
|
// Scratchpad locations
|
||||||
|
#define TEMP_LSB 0
|
||||||
|
#define TEMP_MSB 1
|
||||||
|
#define HIGH_ALARM_TEMP 2
|
||||||
|
#define LOW_ALARM_TEMP 3
|
||||||
|
#define CONFIGURATION 4
|
||||||
|
#define INTERNAL_BYTE 5
|
||||||
|
#define COUNT_REMAIN 6
|
||||||
|
#define COUNT_PER_C 7
|
||||||
|
#define SCRATCHPAD_CRC 8
|
||||||
|
|
||||||
|
// Device resolution
|
||||||
|
#define TEMP_9_BIT 0x1F // 9 bit
|
||||||
|
#define TEMP_10_BIT 0x3F // 10 bit
|
||||||
|
#define TEMP_11_BIT 0x5F // 11 bit
|
||||||
|
#define TEMP_12_BIT 0x7F // 12 bit
|
||||||
|
|
||||||
|
// Error Codes
|
||||||
|
#define DEVICE_DISCONNECTED -127
|
||||||
|
|
||||||
|
typedef uint8_t DeviceAddress[8];
|
||||||
|
|
||||||
|
class DallasTemperature
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
DallasTemperature(OneWire*);
|
||||||
|
|
||||||
|
// initalize bus
|
||||||
|
void begin(void);
|
||||||
|
|
||||||
|
// returns the number of devices found on the bus
|
||||||
|
uint8_t getDeviceCount(void);
|
||||||
|
|
||||||
|
// returns true if address is valid
|
||||||
|
bool validAddress(uint8_t*);
|
||||||
|
|
||||||
|
// finds an address at a given index on the bus
|
||||||
|
bool getAddress(uint8_t*, const uint8_t);
|
||||||
|
|
||||||
|
// attempt to determine if the device at the given address is connected to the bus
|
||||||
|
bool isConnected(uint8_t*);
|
||||||
|
|
||||||
|
// attempt to determine if the device at the given address is connected to the bus
|
||||||
|
// also allows for updating the read scratchpad
|
||||||
|
bool isConnected(uint8_t*, uint8_t*);
|
||||||
|
|
||||||
|
// read device's scratchpad
|
||||||
|
void readScratchPad(uint8_t*, uint8_t*);
|
||||||
|
|
||||||
|
// write device's scratchpad
|
||||||
|
void writeScratchPad(uint8_t*, const uint8_t*);
|
||||||
|
|
||||||
|
// read device's power requirements
|
||||||
|
bool readPowerSupply(uint8_t*);
|
||||||
|
|
||||||
|
// returns the current resolution, 9-12
|
||||||
|
uint8_t getResolution(uint8_t*);
|
||||||
|
|
||||||
|
// set resolution of a device to 9, 10, 11, or 12 bits
|
||||||
|
void setResolution(uint8_t*, uint8_t);
|
||||||
|
|
||||||
|
// sends command for all devices on the bus to perform a temperature conversion
|
||||||
|
void requestTemperatures(void);
|
||||||
|
|
||||||
|
// sends command for one device to perform a temperature conversion by address
|
||||||
|
void requestTemperaturesByAddress(uint8_t*);
|
||||||
|
|
||||||
|
// sends command for one device to perform a temperature conversion by index
|
||||||
|
void requestTemperaturesByIndex(uint8_t);
|
||||||
|
|
||||||
|
// returns temperature in degrees C
|
||||||
|
float getTempC(uint8_t*);
|
||||||
|
|
||||||
|
// returns temperature in degrees F
|
||||||
|
float getTempF(uint8_t*);
|
||||||
|
|
||||||
|
// Get temperature for device index (slow)
|
||||||
|
float getTempCByIndex(uint8_t);
|
||||||
|
|
||||||
|
// Get temperature for device index (slow)
|
||||||
|
float getTempFByIndex(uint8_t);
|
||||||
|
|
||||||
|
// returns true if the bus requires parasite power
|
||||||
|
bool isParasitePowerMode(void);
|
||||||
|
|
||||||
|
#if REQUIRESALARMS
|
||||||
|
|
||||||
|
typedef void AlarmHandler(uint8_t*);
|
||||||
|
|
||||||
|
// sets the high alarm temperature for a device
|
||||||
|
// accepts a char. valid range is -55C - 125C
|
||||||
|
void setHighAlarmTemp(uint8_t*, const char);
|
||||||
|
|
||||||
|
// sets the low alarm temperature for a device
|
||||||
|
// accepts a char. valid range is -55C - 125C
|
||||||
|
void setLowAlarmTemp(uint8_t*, const char);
|
||||||
|
|
||||||
|
// returns a signed char with the current high alarm temperature for a device
|
||||||
|
// in the range -55C - 125C
|
||||||
|
char getHighAlarmTemp(uint8_t*);
|
||||||
|
|
||||||
|
// returns a signed char with the current low alarm temperature for a device
|
||||||
|
// in the range -55C - 125C
|
||||||
|
char getLowAlarmTemp(uint8_t*);
|
||||||
|
|
||||||
|
// resets internal variables used for the alarm search
|
||||||
|
void resetAlarmSearch(void);
|
||||||
|
|
||||||
|
// search the wire for devices with active alarms
|
||||||
|
bool alarmSearch(uint8_t*);
|
||||||
|
|
||||||
|
// returns true if ia specific device has an alarm
|
||||||
|
bool hasAlarm(uint8_t*);
|
||||||
|
|
||||||
|
// returns true if any device is reporting an alarm on the bus
|
||||||
|
bool hasAlarm(void);
|
||||||
|
|
||||||
|
// runs the alarm handler for all devices returned by alarmSearch()
|
||||||
|
void processAlarms(void);
|
||||||
|
|
||||||
|
// sets the alarm handler
|
||||||
|
void setAlarmHandler(AlarmHandler *);
|
||||||
|
|
||||||
|
// The default alarm handler
|
||||||
|
static void defaultAlarmHandler(uint8_t*);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// convert from celcius to farenheit
|
||||||
|
static float toFahrenheit(const float);
|
||||||
|
|
||||||
|
// convert from farenheit to celsius
|
||||||
|
static float toCelsius(const float);
|
||||||
|
|
||||||
|
#if REQUIRESNEW
|
||||||
|
|
||||||
|
// initalize memory area
|
||||||
|
void* operator new (unsigned int);
|
||||||
|
|
||||||
|
// delete memory reference
|
||||||
|
void operator delete(void*);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef uint8_t ScratchPad[9];
|
||||||
|
|
||||||
|
// parasite power on or off
|
||||||
|
bool parasite;
|
||||||
|
|
||||||
|
// used to determine the delay amount needed to allow for the
|
||||||
|
// temperature conversion to take place
|
||||||
|
int conversionDelay;
|
||||||
|
|
||||||
|
// count of devices on the bus
|
||||||
|
uint8_t devices;
|
||||||
|
|
||||||
|
// Take a pointer to one wire instance
|
||||||
|
OneWire* _wire;
|
||||||
|
|
||||||
|
// reads scratchpad and returns the temperature in degrees C
|
||||||
|
float calculateTemperature(uint8_t*, uint8_t*);
|
||||||
|
|
||||||
|
#if REQUIRESALARMS
|
||||||
|
|
||||||
|
// required for alarmSearch
|
||||||
|
uint8_t alarmSearchAddress[8];
|
||||||
|
char alarmSearchJunction;
|
||||||
|
uint8_t alarmSearchExhausted;
|
||||||
|
|
||||||
|
// the alarm handler function pointer
|
||||||
|
AlarmHandler *_AlarmHandler;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif
|
87
examples/osd/arduino-dallastemp/Makefile
Normal file
87
examples/osd/arduino-dallastemp/Makefile
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
# Set this to the name of your sketch (without extension .pde)
|
||||||
|
SKETCH=sketch
|
||||||
|
|
||||||
|
ifeq ($(TARGET), osd-merkur)
|
||||||
|
PLATFORM_FILES= avr-size arduino-example.osd-merkur.hex \
|
||||||
|
arduino-example.osd-merkur.eep
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: arduino-example $(PLATFORM_FILES)
|
||||||
|
|
||||||
|
CONTIKI=../../..
|
||||||
|
|
||||||
|
# Contiki IPv6 configuration
|
||||||
|
CONTIKI_WITH_IPV6 = 1
|
||||||
|
|
||||||
|
CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\"
|
||||||
|
LFLAGS += -lm
|
||||||
|
|
||||||
|
PROJECT_SOURCEFILES += ${SKETCH}.cpp OneWire.cpp DallasTemperature.cpp
|
||||||
|
|
||||||
|
# automatically build RESTful resources
|
||||||
|
REST_RESOURCES_DIR = ./resources
|
||||||
|
REST_RESOURCES_DIR_COMMON = ../resources-common
|
||||||
|
REST_RESOURCES_FILES= $(notdir \
|
||||||
|
$(shell find $(REST_RESOURCES_DIR) -name '*.c') \
|
||||||
|
$(shell find $(REST_RESOURCES_DIR_COMMON) -name '*.c') \
|
||||||
|
)
|
||||||
|
|
||||||
|
PROJECTDIRS += $(REST_RESOURCES_DIR) $(REST_RESOURCES_DIR_COMMON)
|
||||||
|
PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES)
|
||||||
|
|
||||||
|
# variable for Makefile.include
|
||||||
|
ifneq ($(TARGET), minimal-net)
|
||||||
|
CFLAGS += -DUIP_CONF_IPV6_RPL=1
|
||||||
|
else
|
||||||
|
# minimal-net does not support RPL under Linux and is mostly used to test CoAP only
|
||||||
|
${info INFO: compiling without RPL}
|
||||||
|
CFLAGS += -DUIP_CONF_IPV6_RPL=0
|
||||||
|
CFLAGS += -DHARD_CODED_ADDRESS=\"fdfd::10\"
|
||||||
|
${info INFO: compiling with large buffers}
|
||||||
|
CFLAGS += -DUIP_CONF_BUFFER_SIZE=2048
|
||||||
|
CFLAGS += -DREST_MAX_CHUNK_SIZE=1024
|
||||||
|
CFLAGS += -DCOAP_MAX_HEADER_SIZE=640
|
||||||
|
endif
|
||||||
|
|
||||||
|
# linker optimizations
|
||||||
|
SMALL=1
|
||||||
|
|
||||||
|
|
||||||
|
# REST Engine shall use Erbium CoAP implementation
|
||||||
|
APPS += er-coap
|
||||||
|
APPS += rest-engine
|
||||||
|
APPS += arduino
|
||||||
|
|
||||||
|
include $(CONTIKI)/Makefile.include
|
||||||
|
include $(CONTIKI)/apps/arduino/Makefile.include
|
||||||
|
|
||||||
|
avr-size: arduino-example.osd-merkur
|
||||||
|
avr-size -C --mcu=MCU=atmega128rfa1 arduino-example.osd-merkur
|
||||||
|
|
||||||
|
arduino-example.osd-merkur.hex: arduino-example.osd-merkur
|
||||||
|
avr-objcopy -j .text -j .data -O ihex arduino-example.osd-merkur \
|
||||||
|
arduino-example.osd-merkur.hex
|
||||||
|
|
||||||
|
arduino-example.osd-merkur.eep: arduino-example.osd-merkur
|
||||||
|
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
|
||||||
|
--change-section-lma .eeprom=0 -O ihex \
|
||||||
|
arduino-example.osd-merkur arduino-example.osd-merkur.eep
|
||||||
|
|
||||||
|
flash: arduino-example.osd-merkur.hex arduino-example.osd-merkur.eep
|
||||||
|
avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \
|
||||||
|
flash:w:arduino-example.osd-merkur.hex:a -U \
|
||||||
|
eeprom:w:arduino-example.osd-merkur.eep:a
|
||||||
|
|
||||||
|
.PHONY: flash avr-size
|
||||||
|
|
||||||
|
$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c
|
||||||
|
(cd $(CONTIKI)/tools && $(MAKE) tunslip6)
|
||||||
|
|
||||||
|
connect-router: $(CONTIKI)/tools/tunslip6
|
||||||
|
sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64
|
||||||
|
|
||||||
|
connect-router-cooja: $(CONTIKI)/tools/tunslip6
|
||||||
|
sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 aaaa::1/64
|
||||||
|
|
||||||
|
connect-minimal:
|
||||||
|
sudo ip address add fdfd::1/64 dev tap0
|
563
examples/osd/arduino-dallastemp/OneWire.cpp
Normal file
563
examples/osd/arduino-dallastemp/OneWire.cpp
Normal file
|
@ -0,0 +1,563 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2007, Jim Studt (original old version - many contributors since)
|
||||||
|
|
||||||
|
The latest version of this library may be found at:
|
||||||
|
http://www.pjrc.com/teensy/td_libs_OneWire.html
|
||||||
|
|
||||||
|
OneWire has been maintained by Paul Stoffregen (paul@pjrc.com) since
|
||||||
|
January 2010. At the time, it was in need of many bug fixes, but had
|
||||||
|
been abandoned the original author (Jim Studt). None of the known
|
||||||
|
contributors were interested in maintaining OneWire. Paul typically
|
||||||
|
works on OneWire every 6 to 12 months. Patches usually wait that
|
||||||
|
long. If anyone is interested in more actively maintaining OneWire,
|
||||||
|
please contact Paul.
|
||||||
|
|
||||||
|
Version 2.3:
|
||||||
|
Unknonw chip fallback mode, Roger Clark
|
||||||
|
Teensy-LC compatibility, Paul Stoffregen
|
||||||
|
Search bug fix, Love Nystrom
|
||||||
|
|
||||||
|
Version 2.2:
|
||||||
|
Teensy 3.0 compatibility, Paul Stoffregen, paul@pjrc.com
|
||||||
|
Arduino Due compatibility, http://arduino.cc/forum/index.php?topic=141030
|
||||||
|
Fix DS18B20 example negative temperature
|
||||||
|
Fix DS18B20 example's low res modes, Ken Butcher
|
||||||
|
Improve reset timing, Mark Tillotson
|
||||||
|
Add const qualifiers, Bertrik Sikken
|
||||||
|
Add initial value input to crc16, Bertrik Sikken
|
||||||
|
Add target_search() function, Scott Roberts
|
||||||
|
|
||||||
|
Version 2.1:
|
||||||
|
Arduino 1.0 compatibility, Paul Stoffregen
|
||||||
|
Improve temperature example, Paul Stoffregen
|
||||||
|
DS250x_PROM example, Guillermo Lovato
|
||||||
|
PIC32 (chipKit) compatibility, Jason Dangel, dangel.jason AT gmail.com
|
||||||
|
Improvements from Glenn Trewitt:
|
||||||
|
- crc16() now works
|
||||||
|
- check_crc16() does all of calculation/checking work.
|
||||||
|
- Added read_bytes() and write_bytes(), to reduce tedious loops.
|
||||||
|
- Added ds2408 example.
|
||||||
|
Delete very old, out-of-date readme file (info is here)
|
||||||
|
|
||||||
|
Version 2.0: Modifications by Paul Stoffregen, January 2010:
|
||||||
|
http://www.pjrc.com/teensy/td_libs_OneWire.html
|
||||||
|
Search fix from Robin James
|
||||||
|
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27
|
||||||
|
Use direct optimized I/O in all cases
|
||||||
|
Disable interrupts during timing critical sections
|
||||||
|
(this solves many random communication errors)
|
||||||
|
Disable interrupts during read-modify-write I/O
|
||||||
|
Reduce RAM consumption by eliminating unnecessary
|
||||||
|
variables and trimming many to 8 bits
|
||||||
|
Optimize both crc8 - table version moved to flash
|
||||||
|
|
||||||
|
Modified to work with larger numbers of devices - avoids loop.
|
||||||
|
Tested in Arduino 11 alpha with 12 sensors.
|
||||||
|
26 Sept 2008 -- Robin James
|
||||||
|
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27
|
||||||
|
|
||||||
|
Updated to work with arduino-0008 and to include skip() as of
|
||||||
|
2007/07/06. --RJL20
|
||||||
|
|
||||||
|
Modified to calculate the 8-bit CRC directly, avoiding the need for
|
||||||
|
the 256-byte lookup table to be loaded in RAM. Tested in arduino-0010
|
||||||
|
-- Tom Pollard, Jan 23, 2008
|
||||||
|
|
||||||
|
Jim Studt's original library was modified by Josh Larios.
|
||||||
|
|
||||||
|
Tom Pollard, pollard@alum.mit.edu, contributed around May 20, 2008
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Much of the code was inspired by Derek Yerger's code, though I don't
|
||||||
|
think much of that remains. In any event that was..
|
||||||
|
(copyleft) 2006 by Derek Yerger - Free to distribute freely.
|
||||||
|
|
||||||
|
The CRC code was excerpted and inspired by the Dallas Semiconductor
|
||||||
|
sample code bearing this copyright.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included
|
||||||
|
// in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
// IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||||
|
// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// Except as contained in this notice, the name of Dallas Semiconductor
|
||||||
|
// shall not be used except as stated in the Dallas Semiconductor
|
||||||
|
// Branding Policy.
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "OneWire.h"
|
||||||
|
|
||||||
|
|
||||||
|
OneWire::OneWire(uint8_t pin)
|
||||||
|
{
|
||||||
|
pinMode(pin, INPUT);
|
||||||
|
bitmask = PIN_TO_BITMASK(pin);
|
||||||
|
baseReg = PIN_TO_BASEREG(pin);
|
||||||
|
#if ONEWIRE_SEARCH
|
||||||
|
reset_search();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Perform the onewire reset function. We will wait up to 250uS for
|
||||||
|
// the bus to come high, if it doesn't then it is broken or shorted
|
||||||
|
// and we return a 0;
|
||||||
|
//
|
||||||
|
// Returns 1 if a device asserted a presence pulse, 0 otherwise.
|
||||||
|
//
|
||||||
|
uint8_t OneWire::reset(void)
|
||||||
|
{
|
||||||
|
IO_REG_TYPE mask = bitmask;
|
||||||
|
volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t retries = 125;
|
||||||
|
|
||||||
|
noInterrupts();
|
||||||
|
DIRECT_MODE_INPUT(reg, mask);
|
||||||
|
interrupts();
|
||||||
|
// wait until the wire is high... just in case
|
||||||
|
do {
|
||||||
|
if (--retries == 0) return 0;
|
||||||
|
delayMicroseconds(2);
|
||||||
|
} while ( !DIRECT_READ(reg, mask));
|
||||||
|
|
||||||
|
noInterrupts();
|
||||||
|
DIRECT_WRITE_LOW(reg, mask);
|
||||||
|
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
|
||||||
|
interrupts();
|
||||||
|
delayMicroseconds(480);
|
||||||
|
noInterrupts();
|
||||||
|
DIRECT_MODE_INPUT(reg, mask); // allow it to float
|
||||||
|
delayMicroseconds(70);
|
||||||
|
r = !DIRECT_READ(reg, mask);
|
||||||
|
interrupts();
|
||||||
|
delayMicroseconds(410);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write a bit. Port and bit is used to cut lookup time and provide
|
||||||
|
// more certain timing.
|
||||||
|
//
|
||||||
|
void OneWire::write_bit(uint8_t v)
|
||||||
|
{
|
||||||
|
IO_REG_TYPE mask=bitmask;
|
||||||
|
volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;
|
||||||
|
|
||||||
|
if (v & 1) {
|
||||||
|
noInterrupts();
|
||||||
|
DIRECT_WRITE_LOW(reg, mask);
|
||||||
|
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
|
||||||
|
delayMicroseconds(10);
|
||||||
|
DIRECT_WRITE_HIGH(reg, mask); // drive output high
|
||||||
|
interrupts();
|
||||||
|
delayMicroseconds(55);
|
||||||
|
} else {
|
||||||
|
noInterrupts();
|
||||||
|
DIRECT_WRITE_LOW(reg, mask);
|
||||||
|
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
|
||||||
|
delayMicroseconds(65);
|
||||||
|
DIRECT_WRITE_HIGH(reg, mask); // drive output high
|
||||||
|
interrupts();
|
||||||
|
delayMicroseconds(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read a bit. Port and bit is used to cut lookup time and provide
|
||||||
|
// more certain timing.
|
||||||
|
//
|
||||||
|
uint8_t OneWire::read_bit(void)
|
||||||
|
{
|
||||||
|
IO_REG_TYPE mask=bitmask;
|
||||||
|
volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;
|
||||||
|
uint8_t r;
|
||||||
|
|
||||||
|
noInterrupts();
|
||||||
|
DIRECT_MODE_OUTPUT(reg, mask);
|
||||||
|
DIRECT_WRITE_LOW(reg, mask);
|
||||||
|
delayMicroseconds(3);
|
||||||
|
DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise
|
||||||
|
delayMicroseconds(10);
|
||||||
|
r = DIRECT_READ(reg, mask);
|
||||||
|
interrupts();
|
||||||
|
delayMicroseconds(53);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write a byte. The writing code uses the active drivers to raise the
|
||||||
|
// pin high, if you need power after the write (e.g. DS18S20 in
|
||||||
|
// parasite power mode) then set 'power' to 1, otherwise the pin will
|
||||||
|
// go tri-state at the end of the write to avoid heating in a short or
|
||||||
|
// other mishap.
|
||||||
|
//
|
||||||
|
void OneWire::write(uint8_t v, uint8_t power /* = 0 */) {
|
||||||
|
uint8_t bitMask;
|
||||||
|
|
||||||
|
for (bitMask = 0x01; bitMask; bitMask <<= 1) {
|
||||||
|
OneWire::write_bit( (bitMask & v)?1:0);
|
||||||
|
}
|
||||||
|
if ( !power) {
|
||||||
|
noInterrupts();
|
||||||
|
DIRECT_MODE_INPUT(baseReg, bitmask);
|
||||||
|
DIRECT_WRITE_LOW(baseReg, bitmask);
|
||||||
|
interrupts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 */) {
|
||||||
|
for (uint16_t i = 0 ; i < count ; i++)
|
||||||
|
write(buf[i]);
|
||||||
|
if (!power) {
|
||||||
|
noInterrupts();
|
||||||
|
DIRECT_MODE_INPUT(baseReg, bitmask);
|
||||||
|
DIRECT_WRITE_LOW(baseReg, bitmask);
|
||||||
|
interrupts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read a byte
|
||||||
|
//
|
||||||
|
uint8_t OneWire::read() {
|
||||||
|
uint8_t bitMask;
|
||||||
|
uint8_t r = 0;
|
||||||
|
|
||||||
|
for (bitMask = 0x01; bitMask; bitMask <<= 1) {
|
||||||
|
if ( OneWire::read_bit()) r |= bitMask;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OneWire::read_bytes(uint8_t *buf, uint16_t count) {
|
||||||
|
for (uint16_t i = 0 ; i < count ; i++)
|
||||||
|
buf[i] = read();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Do a ROM select
|
||||||
|
//
|
||||||
|
void OneWire::select(const uint8_t rom[8])
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
write(0x55); // Choose ROM
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++) write(rom[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Do a ROM skip
|
||||||
|
//
|
||||||
|
void OneWire::skip()
|
||||||
|
{
|
||||||
|
write(0xCC); // Skip ROM
|
||||||
|
}
|
||||||
|
|
||||||
|
void OneWire::depower()
|
||||||
|
{
|
||||||
|
noInterrupts();
|
||||||
|
DIRECT_MODE_INPUT(baseReg, bitmask);
|
||||||
|
interrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ONEWIRE_SEARCH
|
||||||
|
|
||||||
|
//
|
||||||
|
// You need to use this function to start a search again from the beginning.
|
||||||
|
// You do not need to do it for the first search, though you could.
|
||||||
|
//
|
||||||
|
void OneWire::reset_search()
|
||||||
|
{
|
||||||
|
// reset the search state
|
||||||
|
LastDiscrepancy = 0;
|
||||||
|
LastDeviceFlag = FALSE;
|
||||||
|
LastFamilyDiscrepancy = 0;
|
||||||
|
for(int i = 7; ; i--) {
|
||||||
|
ROM_NO[i] = 0;
|
||||||
|
if ( i == 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the search to find the device type 'family_code' on the next call
|
||||||
|
// to search(*newAddr) if it is present.
|
||||||
|
//
|
||||||
|
void OneWire::target_search(uint8_t family_code)
|
||||||
|
{
|
||||||
|
// set the search state to find SearchFamily type devices
|
||||||
|
ROM_NO[0] = family_code;
|
||||||
|
for (uint8_t i = 1; i < 8; i++)
|
||||||
|
ROM_NO[i] = 0;
|
||||||
|
LastDiscrepancy = 64;
|
||||||
|
LastFamilyDiscrepancy = 0;
|
||||||
|
LastDeviceFlag = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Perform a search. If this function returns a '1' then it has
|
||||||
|
// enumerated the next device and you may retrieve the ROM from the
|
||||||
|
// OneWire::address variable. If there are no devices, no further
|
||||||
|
// devices, or something horrible happens in the middle of the
|
||||||
|
// enumeration then a 0 is returned. If a new device is found then
|
||||||
|
// its address is copied to newAddr. Use OneWire::reset_search() to
|
||||||
|
// start over.
|
||||||
|
//
|
||||||
|
// --- Replaced by the one from the Dallas Semiconductor web site ---
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing
|
||||||
|
// search state.
|
||||||
|
// Return TRUE : device found, ROM number in ROM_NO buffer
|
||||||
|
// FALSE : device not found, end of search
|
||||||
|
//
|
||||||
|
uint8_t OneWire::search(uint8_t *newAddr)
|
||||||
|
{
|
||||||
|
uint8_t id_bit_number;
|
||||||
|
uint8_t last_zero, rom_byte_number, search_result;
|
||||||
|
uint8_t id_bit, cmp_id_bit;
|
||||||
|
|
||||||
|
unsigned char rom_byte_mask, search_direction;
|
||||||
|
|
||||||
|
// initialize for search
|
||||||
|
id_bit_number = 1;
|
||||||
|
last_zero = 0;
|
||||||
|
rom_byte_number = 0;
|
||||||
|
rom_byte_mask = 1;
|
||||||
|
search_result = 0;
|
||||||
|
|
||||||
|
// if the last call was not the last one
|
||||||
|
if (!LastDeviceFlag)
|
||||||
|
{
|
||||||
|
// 1-Wire reset
|
||||||
|
if (!reset())
|
||||||
|
{
|
||||||
|
// reset the search
|
||||||
|
LastDiscrepancy = 0;
|
||||||
|
LastDeviceFlag = FALSE;
|
||||||
|
LastFamilyDiscrepancy = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// issue the search command
|
||||||
|
write(0xF0);
|
||||||
|
|
||||||
|
// loop to do the search
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// read a bit and its complement
|
||||||
|
id_bit = read_bit();
|
||||||
|
cmp_id_bit = read_bit();
|
||||||
|
|
||||||
|
// check for no devices on 1-wire
|
||||||
|
if ((id_bit == 1) && (cmp_id_bit == 1))
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// all devices coupled have 0 or 1
|
||||||
|
if (id_bit != cmp_id_bit)
|
||||||
|
search_direction = id_bit; // bit write value for search
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if this discrepancy if before the Last Discrepancy
|
||||||
|
// on a previous next then pick the same as last time
|
||||||
|
if (id_bit_number < LastDiscrepancy)
|
||||||
|
search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
|
||||||
|
else
|
||||||
|
// if equal to last pick 1, if not then pick 0
|
||||||
|
search_direction = (id_bit_number == LastDiscrepancy);
|
||||||
|
|
||||||
|
// if 0 was picked then record its position in LastZero
|
||||||
|
if (search_direction == 0)
|
||||||
|
{
|
||||||
|
last_zero = id_bit_number;
|
||||||
|
|
||||||
|
// check for Last discrepancy in family
|
||||||
|
if (last_zero < 9)
|
||||||
|
LastFamilyDiscrepancy = last_zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set or clear the bit in the ROM byte rom_byte_number
|
||||||
|
// with mask rom_byte_mask
|
||||||
|
if (search_direction == 1)
|
||||||
|
ROM_NO[rom_byte_number] |= rom_byte_mask;
|
||||||
|
else
|
||||||
|
ROM_NO[rom_byte_number] &= ~rom_byte_mask;
|
||||||
|
|
||||||
|
// serial number search direction write bit
|
||||||
|
write_bit(search_direction);
|
||||||
|
|
||||||
|
// increment the byte counter id_bit_number
|
||||||
|
// and shift the mask rom_byte_mask
|
||||||
|
id_bit_number++;
|
||||||
|
rom_byte_mask <<= 1;
|
||||||
|
|
||||||
|
// if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
|
||||||
|
if (rom_byte_mask == 0)
|
||||||
|
{
|
||||||
|
rom_byte_number++;
|
||||||
|
rom_byte_mask = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(rom_byte_number < 8); // loop until through all ROM bytes 0-7
|
||||||
|
|
||||||
|
// if the search was successful then
|
||||||
|
if (!(id_bit_number < 65))
|
||||||
|
{
|
||||||
|
// search successful so set LastDiscrepancy,LastDeviceFlag,search_result
|
||||||
|
LastDiscrepancy = last_zero;
|
||||||
|
|
||||||
|
// check for last device
|
||||||
|
if (LastDiscrepancy == 0)
|
||||||
|
LastDeviceFlag = TRUE;
|
||||||
|
|
||||||
|
search_result = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no device found then reset counters so next 'search' will be like a first
|
||||||
|
if (!search_result || !ROM_NO[0])
|
||||||
|
{
|
||||||
|
LastDiscrepancy = 0;
|
||||||
|
LastDeviceFlag = FALSE;
|
||||||
|
LastFamilyDiscrepancy = 0;
|
||||||
|
search_result = FALSE;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i];
|
||||||
|
}
|
||||||
|
return search_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ONEWIRE_CRC
|
||||||
|
// The 1-Wire CRC scheme is described in Maxim Application Note 27:
|
||||||
|
// "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products"
|
||||||
|
//
|
||||||
|
|
||||||
|
#if ONEWIRE_CRC8_TABLE
|
||||||
|
// This table comes from Dallas sample code where it is freely reusable,
|
||||||
|
// though Copyright (C) 2000 Dallas Semiconductor Corporation
|
||||||
|
static const uint8_t PROGMEM dscrc_table[] = {
|
||||||
|
0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
|
||||||
|
157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
|
||||||
|
35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
|
||||||
|
190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
|
||||||
|
70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
|
||||||
|
219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
|
||||||
|
101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
|
||||||
|
248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
|
||||||
|
140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
|
||||||
|
17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
|
||||||
|
175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
|
||||||
|
50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
|
||||||
|
202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
|
||||||
|
87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
|
||||||
|
233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
|
||||||
|
116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM
|
||||||
|
// and the registers. (note: this might better be done without to
|
||||||
|
// table, it would probably be smaller and certainly fast enough
|
||||||
|
// compared to all those delayMicrosecond() calls. But I got
|
||||||
|
// confused, so I use this table from the examples.)
|
||||||
|
//
|
||||||
|
uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len)
|
||||||
|
{
|
||||||
|
uint8_t crc = 0;
|
||||||
|
|
||||||
|
while (len--) {
|
||||||
|
crc = pgm_read_byte(dscrc_table + (crc ^ *addr++));
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
//
|
||||||
|
// Compute a Dallas Semiconductor 8 bit CRC directly.
|
||||||
|
// this is much slower, but much smaller, than the lookup table.
|
||||||
|
//
|
||||||
|
uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len)
|
||||||
|
{
|
||||||
|
uint8_t crc = 0;
|
||||||
|
|
||||||
|
while (len--) {
|
||||||
|
uint8_t inbyte = *addr++;
|
||||||
|
for (uint8_t i = 8; i; i--) {
|
||||||
|
uint8_t mix = (crc ^ inbyte) & 0x01;
|
||||||
|
crc >>= 1;
|
||||||
|
if (mix) crc ^= 0x8C;
|
||||||
|
inbyte >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ONEWIRE_CRC16
|
||||||
|
bool OneWire::check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc)
|
||||||
|
{
|
||||||
|
crc = ~crc16(input, len, crc);
|
||||||
|
return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t OneWire::crc16(const uint8_t* input, uint16_t len, uint16_t crc)
|
||||||
|
{
|
||||||
|
static const uint8_t oddparity[16] =
|
||||||
|
{ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
|
||||||
|
|
||||||
|
for (uint16_t i = 0 ; i < len ; i++) {
|
||||||
|
// Even though we're just copying a byte from the input,
|
||||||
|
// we'll be doing 16-bit computation with it.
|
||||||
|
uint16_t cdata = input[i];
|
||||||
|
cdata = (cdata ^ crc) & 0xff;
|
||||||
|
crc >>= 8;
|
||||||
|
|
||||||
|
if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4])
|
||||||
|
crc ^= 0xC001;
|
||||||
|
|
||||||
|
cdata <<= 6;
|
||||||
|
crc ^= cdata;
|
||||||
|
cdata <<= 1;
|
||||||
|
crc ^= cdata;
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
250
examples/osd/arduino-dallastemp/OneWire.h
Normal file
250
examples/osd/arduino-dallastemp/OneWire.h
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
#ifndef OneWire_h
|
||||||
|
#define OneWire_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
//#if ARDUINO >= 100
|
||||||
|
#include "Arduino.h" // for delayMicroseconds, digitalPinToBitMask, etc
|
||||||
|
//#else
|
||||||
|
//#include "WProgram.h" // for delayMicroseconds
|
||||||
|
//#include "pins_arduino.h" // for digitalPinToBitMask, etc
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
// You can exclude certain features from OneWire. In theory, this
|
||||||
|
// might save some space. In practice, the compiler automatically
|
||||||
|
// removes unused code (technically, the linker, using -fdata-sections
|
||||||
|
// and -ffunction-sections when compiling, and Wl,--gc-sections
|
||||||
|
// when linking), so most of these will not result in any code size
|
||||||
|
// reduction. Well, unless you try to use the missing features
|
||||||
|
// and redesign your program to not need them! ONEWIRE_CRC8_TABLE
|
||||||
|
// is the exception, because it selects a fast but large algorithm
|
||||||
|
// or a small but slow algorithm.
|
||||||
|
|
||||||
|
// you can exclude onewire_search by defining that to 0
|
||||||
|
#ifndef ONEWIRE_SEARCH
|
||||||
|
#define ONEWIRE_SEARCH 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// You can exclude CRC checks altogether by defining this to 0
|
||||||
|
#ifndef ONEWIRE_CRC
|
||||||
|
#define ONEWIRE_CRC 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Select the table-lookup method of computing the 8-bit CRC
|
||||||
|
// by setting this to 1. The lookup table enlarges code size by
|
||||||
|
// about 250 bytes. It does NOT consume RAM (but did in very
|
||||||
|
// old versions of OneWire). If you disable this, a slower
|
||||||
|
// but very compact algorithm is used.
|
||||||
|
#ifndef ONEWIRE_CRC8_TABLE
|
||||||
|
#define ONEWIRE_CRC8_TABLE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// You can allow 16-bit CRC checks by defining this to 1
|
||||||
|
// (Note that ONEWIRE_CRC must also be 1.)
|
||||||
|
#ifndef ONEWIRE_CRC16
|
||||||
|
#define ONEWIRE_CRC16 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE 1
|
||||||
|
|
||||||
|
// Platform specific I/O definitions
|
||||||
|
|
||||||
|
#if defined(__AVR__)
|
||||||
|
#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin)))
|
||||||
|
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
||||||
|
#define IO_REG_TYPE uint8_t
|
||||||
|
#define IO_REG_ASM asm("r30")
|
||||||
|
#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask))
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask))
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask))
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask))
|
||||||
|
|
||||||
|
#elif defined(__MK20DX128__) || defined(__MK20DX256__)
|
||||||
|
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
|
||||||
|
#define PIN_TO_BITMASK(pin) (1)
|
||||||
|
#define IO_REG_TYPE uint8_t
|
||||||
|
#define IO_REG_ASM
|
||||||
|
#define DIRECT_READ(base, mask) (*((base)+512))
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0)
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1)
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1)
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1)
|
||||||
|
|
||||||
|
#elif defined(__MKL26Z64__)
|
||||||
|
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
|
||||||
|
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
||||||
|
#define IO_REG_TYPE uint8_t
|
||||||
|
#define IO_REG_ASM
|
||||||
|
#define DIRECT_READ(base, mask) ((*((base)+16) & (mask)) ? 1 : 0)
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) (*((base)+20) &= ~(mask))
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+20) |= (mask))
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) (*((base)+8) = (mask))
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) (*((base)+4) = (mask))
|
||||||
|
|
||||||
|
#elif defined(__SAM3X8E__)
|
||||||
|
// Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due.
|
||||||
|
// http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268
|
||||||
|
// If you have trouble with OneWire on Arduino Due, please check the
|
||||||
|
// status of delayMicroseconds() before reporting a bug in OneWire!
|
||||||
|
#define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->PIO_PER))
|
||||||
|
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
||||||
|
#define IO_REG_TYPE uint32_t
|
||||||
|
#define IO_REG_ASM
|
||||||
|
#define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0)
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask))
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask))
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask))
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask))
|
||||||
|
#ifndef PROGMEM
|
||||||
|
#define PROGMEM
|
||||||
|
#endif
|
||||||
|
#ifndef pgm_read_byte
|
||||||
|
#define pgm_read_byte(addr) (*(const uint8_t *)(addr))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__PIC32MX__)
|
||||||
|
#define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin)))
|
||||||
|
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
||||||
|
#define IO_REG_TYPE uint32_t
|
||||||
|
#define IO_REG_ASM
|
||||||
|
#define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) //PORTX + 0x10
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) //TRISXSET + 0x08
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) //TRISXCLR + 0x04
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) //LATXCLR + 0x24
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) //LATXSET + 0x28
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define PIN_TO_BASEREG(pin) (0)
|
||||||
|
#define PIN_TO_BITMASK(pin) (pin)
|
||||||
|
#define IO_REG_TYPE unsigned int
|
||||||
|
#define IO_REG_ASM
|
||||||
|
#define DIRECT_READ(base, pin) digitalRead(pin)
|
||||||
|
#define DIRECT_WRITE_LOW(base, pin) digitalWrite(pin, LOW)
|
||||||
|
#define DIRECT_WRITE_HIGH(base, pin) digitalWrite(pin, HIGH)
|
||||||
|
#define DIRECT_MODE_INPUT(base, pin) pinMode(pin,INPUT)
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, pin) pinMode(pin,OUTPUT)
|
||||||
|
#warning "OneWire. Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite. Operation of this library is not guaranteed on this architecture."
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
class OneWire
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
IO_REG_TYPE bitmask;
|
||||||
|
volatile IO_REG_TYPE *baseReg;
|
||||||
|
|
||||||
|
#if ONEWIRE_SEARCH
|
||||||
|
// global search state
|
||||||
|
unsigned char ROM_NO[8];
|
||||||
|
uint8_t LastDiscrepancy;
|
||||||
|
uint8_t LastFamilyDiscrepancy;
|
||||||
|
uint8_t LastDeviceFlag;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
OneWire( uint8_t pin);
|
||||||
|
|
||||||
|
// Perform a 1-Wire reset cycle. Returns 1 if a device responds
|
||||||
|
// with a presence pulse. Returns 0 if there is no device or the
|
||||||
|
// bus is shorted or otherwise held low for more than 250uS
|
||||||
|
uint8_t reset(void);
|
||||||
|
|
||||||
|
// Issue a 1-Wire rom select command, you do the reset first.
|
||||||
|
void select(const uint8_t rom[8]);
|
||||||
|
|
||||||
|
// Issue a 1-Wire rom skip command, to address all on bus.
|
||||||
|
void skip(void);
|
||||||
|
|
||||||
|
// Write a byte. If 'power' is one then the wire is held high at
|
||||||
|
// the end for parasitically powered devices. You are responsible
|
||||||
|
// for eventually depowering it by calling depower() or doing
|
||||||
|
// another read or write.
|
||||||
|
void write(uint8_t v, uint8_t power = 0);
|
||||||
|
|
||||||
|
void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0);
|
||||||
|
|
||||||
|
// Read a byte.
|
||||||
|
uint8_t read(void);
|
||||||
|
|
||||||
|
void read_bytes(uint8_t *buf, uint16_t count);
|
||||||
|
|
||||||
|
// Write a bit. The bus is always left powered at the end, see
|
||||||
|
// note in write() about that.
|
||||||
|
void write_bit(uint8_t v);
|
||||||
|
|
||||||
|
// Read a bit.
|
||||||
|
uint8_t read_bit(void);
|
||||||
|
|
||||||
|
// Stop forcing power onto the bus. You only need to do this if
|
||||||
|
// you used the 'power' flag to write() or used a write_bit() call
|
||||||
|
// and aren't about to do another read or write. You would rather
|
||||||
|
// not leave this powered if you don't have to, just in case
|
||||||
|
// someone shorts your bus.
|
||||||
|
void depower(void);
|
||||||
|
|
||||||
|
#if ONEWIRE_SEARCH
|
||||||
|
// Clear the search state so that if will start from the beginning again.
|
||||||
|
void reset_search();
|
||||||
|
|
||||||
|
// Setup the search to find the device type 'family_code' on the next call
|
||||||
|
// to search(*newAddr) if it is present.
|
||||||
|
void target_search(uint8_t family_code);
|
||||||
|
|
||||||
|
// Look for the next device. Returns 1 if a new address has been
|
||||||
|
// returned. A zero might mean that the bus is shorted, there are
|
||||||
|
// no devices, or you have already retrieved all of them. It
|
||||||
|
// might be a good idea to check the CRC to make sure you didn't
|
||||||
|
// get garbage. The order is deterministic. You will always get
|
||||||
|
// the same devices in the same order.
|
||||||
|
uint8_t search(uint8_t *newAddr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ONEWIRE_CRC
|
||||||
|
// Compute a Dallas Semiconductor 8 bit CRC, these are used in the
|
||||||
|
// ROM and scratchpad registers.
|
||||||
|
static uint8_t crc8(const uint8_t *addr, uint8_t len);
|
||||||
|
|
||||||
|
#if ONEWIRE_CRC16
|
||||||
|
// Compute the 1-Wire CRC16 and compare it against the received CRC.
|
||||||
|
// Example usage (reading a DS2408):
|
||||||
|
// // Put everything in a buffer so we can compute the CRC easily.
|
||||||
|
// uint8_t buf[13];
|
||||||
|
// buf[0] = 0xF0; // Read PIO Registers
|
||||||
|
// buf[1] = 0x88; // LSB address
|
||||||
|
// buf[2] = 0x00; // MSB address
|
||||||
|
// WriteBytes(net, buf, 3); // Write 3 cmd bytes
|
||||||
|
// ReadBytes(net, buf+3, 10); // Read 6 data bytes, 2 0xFF, 2 CRC16
|
||||||
|
// if (!CheckCRC16(buf, 11, &buf[11])) {
|
||||||
|
// // Handle error.
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @param input - Array of bytes to checksum.
|
||||||
|
// @param len - How many bytes to use.
|
||||||
|
// @param inverted_crc - The two CRC16 bytes in the received data.
|
||||||
|
// This should just point into the received data,
|
||||||
|
// *not* at a 16-bit integer.
|
||||||
|
// @param crc - The crc starting value (optional)
|
||||||
|
// @return True, iff the CRC matches.
|
||||||
|
static bool check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc = 0);
|
||||||
|
|
||||||
|
// Compute a Dallas Semiconductor 16 bit CRC. This is required to check
|
||||||
|
// the integrity of data received from many 1-Wire devices. Note that the
|
||||||
|
// CRC computed here is *not* what you'll get from the 1-Wire network,
|
||||||
|
// for two reasons:
|
||||||
|
// 1) The CRC is transmitted bitwise inverted.
|
||||||
|
// 2) Depending on the endian-ness of your processor, the binary
|
||||||
|
// representation of the two-byte return value may have a different
|
||||||
|
// byte order than the two bytes you get from 1-Wire.
|
||||||
|
// @param input - Array of bytes to checksum.
|
||||||
|
// @param len - How many bytes to use.
|
||||||
|
// @param crc - The crc starting value (optional)
|
||||||
|
// @return The CRC16, as defined by Dallas Semiconductor.
|
||||||
|
static uint16_t crc16(const uint8_t* input, uint16_t len, uint16_t crc = 0);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
11
examples/osd/arduino-dallastemp/README.md
Normal file
11
examples/osd/arduino-dallastemp/README.md
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
Arduino compatibility example
|
||||||
|
=============================
|
||||||
|
|
||||||
|
This example shows that it is now possible to re-use arduino sketches in
|
||||||
|
Contiki. This example documents the necessary magic. Arduino specifies
|
||||||
|
two routines, `setup` and `loop`. Before `setup` is called, the
|
||||||
|
framework initializes hardware. In original Arduino, all this is done in
|
||||||
|
a `main` function (in C). For contiki we define a process that does the
|
||||||
|
same.
|
||||||
|
|
||||||
|
See the documentation file in apps/contiki-compat/README.md
|
2
examples/osd/arduino-dallastemp/arduino-example.c
Normal file
2
examples/osd/arduino-dallastemp/arduino-example.c
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#include <arduino-process.h>
|
||||||
|
AUTOSTART_PROCESSES(&arduino_sketch);
|
2
examples/osd/arduino-dallastemp/flash.sh
Executable file
2
examples/osd/arduino-dallastemp/flash.sh
Executable file
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/bash
|
||||||
|
make TARGET=osd-merkur flash
|
106
examples/osd/arduino-dallastemp/project-conf.h
Normal file
106
examples/osd/arduino-dallastemp/project-conf.h
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, Swedish Institute of Computer Science.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PROJECT_RPL_WEB_CONF_H_
|
||||||
|
#define PROJECT_RPL_WEB_CONF_H_
|
||||||
|
|
||||||
|
#define PLATFORM_HAS_LEDS 1
|
||||||
|
//#define PLATFORM_HAS_BUTTON 1
|
||||||
|
#define PLATFORM_HAS_BATTERY 1
|
||||||
|
|
||||||
|
#define SICSLOWPAN_CONF_FRAG 1
|
||||||
|
|
||||||
|
#define LOOP_INTERVAL (10 * CLOCK_SECOND)
|
||||||
|
|
||||||
|
/* Save energy */
|
||||||
|
//#define RDC_CONF_PT_YIELD_OFF
|
||||||
|
|
||||||
|
/* For Debug: Dont allow MCU sleeping between channel checks */
|
||||||
|
//#undef RDC_CONF_MCU_SLEEP
|
||||||
|
//#define RDC_CONF_MCU_SLEEP 0
|
||||||
|
|
||||||
|
/* Disabling RDC for demo purposes. Core updates often require more memory. */
|
||||||
|
/* For projects, optimize memory and enable RDC again. */
|
||||||
|
// #undef NETSTACK_CONF_RDC
|
||||||
|
//#define NETSTACK_CONF_RDC nullrdc_driver
|
||||||
|
|
||||||
|
/* Increase rpl-border-router IP-buffer when using more than 64. */
|
||||||
|
#undef REST_MAX_CHUNK_SIZE
|
||||||
|
#define REST_MAX_CHUNK_SIZE 64
|
||||||
|
|
||||||
|
/* Estimate your header size, especially when using Proxy-Uri. */
|
||||||
|
/*
|
||||||
|
#undef COAP_MAX_HEADER_SIZE
|
||||||
|
#define COAP_MAX_HEADER_SIZE 70
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* The IP buffer size must fit all other hops, in particular the border router. */
|
||||||
|
|
||||||
|
#undef UIP_CONF_BUFFER_SIZE
|
||||||
|
#define UIP_CONF_BUFFER_SIZE 256
|
||||||
|
|
||||||
|
|
||||||
|
/* Multiplies with chunk size, be aware of memory constraints. */
|
||||||
|
#undef COAP_MAX_OPEN_TRANSACTIONS
|
||||||
|
#define COAP_MAX_OPEN_TRANSACTIONS 4
|
||||||
|
|
||||||
|
/* Must be <= open transaction number, default is COAP_MAX_OPEN_TRANSACTIONS-1. */
|
||||||
|
/*
|
||||||
|
#undef COAP_MAX_OBSERVERS
|
||||||
|
#define COAP_MAX_OBSERVERS 2
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Filtering .well-known/core per query can be disabled to save space. */
|
||||||
|
/*
|
||||||
|
#undef COAP_LINK_FORMAT_FILTERING
|
||||||
|
#define COAP_LINK_FORMAT_FILTERING 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Save some memory for the sky platform. */
|
||||||
|
/*
|
||||||
|
#undef NBR_TABLE_CONF_MAX_NEIGHBORS
|
||||||
|
#define NBR_TABLE_CONF_MAX_NEIGHBORS 10
|
||||||
|
#undef UIP_CONF_MAX_ROUTES
|
||||||
|
#define UIP_CONF_MAX_ROUTES 10
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Reduce 802.15.4 frame queue to save RAM. */
|
||||||
|
/*
|
||||||
|
#undef QUEUEBUF_CONF_NUM
|
||||||
|
#define QUEUEBUF_CONF_NUM 4
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
#undef SICSLOWPAN_CONF_FRAG
|
||||||
|
#define SICSLOWPAN_CONF_FRAG 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* PROJECT_RPL_WEB_CONF_H_ */
|
80
examples/osd/arduino-dallastemp/resources/res-htu21dhum.c
Normal file
80
examples/osd/arduino-dallastemp/resources/res-htu21dhum.c
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Moisture resource
|
||||||
|
* \author
|
||||||
|
* Harald Pichler <harald@the-develop.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "contiki.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "rest-engine.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
|
||||||
|
|
||||||
|
/* A simple getter example. Returns the reading from the sensor with a simple etag */
|
||||||
|
RESOURCE(res_htu21dhum,
|
||||||
|
"title=\"Moisture status\";rt=\"Moisture\"",
|
||||||
|
res_get_handler,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
extern char htu21d_hum_s[8];
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned int accept = -1;
|
||||||
|
REST.get_header_accept(request, &accept);
|
||||||
|
|
||||||
|
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
|
||||||
|
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
|
||||||
|
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", htu21d_hum_s);
|
||||||
|
|
||||||
|
REST.set_response_payload(response, buffer, strlen((char *)buffer));
|
||||||
|
} else if(accept == REST.type.APPLICATION_JSON) {
|
||||||
|
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
|
||||||
|
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'moisture':%s}", htu21d_hum_s);
|
||||||
|
|
||||||
|
REST.set_response_payload(response, buffer, strlen((char *)buffer));
|
||||||
|
} else {
|
||||||
|
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
|
||||||
|
const char *msg = "Supporting content-types text/plain and application/json";
|
||||||
|
REST.set_response_payload(response, msg, strlen(msg));
|
||||||
|
}
|
||||||
|
}
|
79
examples/osd/arduino-dallastemp/resources/res-htu21dtemp.c
Normal file
79
examples/osd/arduino-dallastemp/resources/res-htu21dtemp.c
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* This file is part of the Contiki operating system.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* Moisture resource
|
||||||
|
* \author
|
||||||
|
* Harald Pichler <harald@the-develop.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "contiki.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "rest-engine.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset);
|
||||||
|
|
||||||
|
/* A simple getter example. Returns the reading from the sensor with a simple etag */
|
||||||
|
RESOURCE(res_htu21dtemp,
|
||||||
|
"title=\"Moisture status\";rt=\"Moisture\"",
|
||||||
|
res_get_handler,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
extern char d_temp_s[8];
|
||||||
|
|
||||||
|
static void
|
||||||
|
res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned int accept = -1;
|
||||||
|
REST.get_header_accept(request, &accept);
|
||||||
|
|
||||||
|
if(accept == -1 || accept == REST.type.TEXT_PLAIN) {
|
||||||
|
REST.set_header_content_type(response, REST.type.TEXT_PLAIN);
|
||||||
|
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", d_temp_s);
|
||||||
|
|
||||||
|
REST.set_response_payload(response, buffer, strlen((char *)buffer));
|
||||||
|
} else if(accept == REST.type.APPLICATION_JSON) {
|
||||||
|
REST.set_header_content_type(response, REST.type.APPLICATION_JSON);
|
||||||
|
snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'moisture':%s}", d_temp_s);
|
||||||
|
|
||||||
|
REST.set_response_payload(response, buffer, strlen((char *)buffer));
|
||||||
|
} else {
|
||||||
|
REST.set_response_status(response, REST.status.NOT_ACCEPTABLE);
|
||||||
|
const char *msg = "Supporting content-types text/plain and application/json";
|
||||||
|
REST.set_response_payload(response, msg, strlen(msg));
|
||||||
|
}
|
||||||
|
}
|
5
examples/osd/arduino-dallastemp/run.sh
Executable file
5
examples/osd/arduino-dallastemp/run.sh
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# For the new bootloader (using a jump-table) you want to use
|
||||||
|
# BOOTLOADER_GET_MAC=0x0001ff80 (which is the current default)
|
||||||
|
make clean TARGET=osd-merkur
|
||||||
|
make TARGET=osd-merkur BOOTLOADER_GET_MAC=0x0001f3a0
|
172
examples/osd/arduino-dallastemp/sketch.pde
Normal file
172
examples/osd/arduino-dallastemp/sketch.pde
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
* Sample arduino sketch using contiki features.
|
||||||
|
* We turn the LED off
|
||||||
|
* We allow read the moisture sensor
|
||||||
|
* Unfortunately sleeping for long times in loop() isn't currently
|
||||||
|
* possible, something turns off the CPU (including PWM outputs) if a
|
||||||
|
* Proto-Thread is taking too long. We need to find out how to sleep in
|
||||||
|
* a Contiki-compatible way.
|
||||||
|
* Note that for a normal arduino sketch you won't have to include any
|
||||||
|
* of the contiki-specific files here, the sketch should just work.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <OneWire.h>
|
||||||
|
#include "DallasTemperature.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
|
||||||
|
#include "rest-engine.h"
|
||||||
|
|
||||||
|
extern volatile uint8_t mcusleepcycle; // default 16
|
||||||
|
|
||||||
|
// Data wire is plugged into port 2 on the Arduino
|
||||||
|
#define ONE_WIRE_BUS 3
|
||||||
|
#define TEMPERATURE_PRECISION 9
|
||||||
|
|
||||||
|
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
|
||||||
|
OneWire oneWire(ONE_WIRE_BUS);
|
||||||
|
|
||||||
|
// Pass our oneWire reference to Dallas Temperature.
|
||||||
|
DallasTemperature dsensors(&oneWire);
|
||||||
|
|
||||||
|
// arrays to hold device addresses
|
||||||
|
DeviceAddress insideThermometer, outsideThermometer;
|
||||||
|
|
||||||
|
extern resource_t res_htu21dtemp, res_htu21dhum, res_battery;
|
||||||
|
float htu21d_hum;
|
||||||
|
float d_temp;
|
||||||
|
char htu21d_hum_s[8];
|
||||||
|
char d_temp_s[8];
|
||||||
|
|
||||||
|
#define LED_PIN 4
|
||||||
|
}
|
||||||
|
|
||||||
|
// main functions to print information about a device
|
||||||
|
void printAddress(uint8_t* adress)
|
||||||
|
{
|
||||||
|
printf("%02X",adress[0]);
|
||||||
|
printf("%02X",adress[1]);
|
||||||
|
printf("%02X",adress[2]);
|
||||||
|
printf("%02X",adress[3]);
|
||||||
|
printf("%02X",adress[4]);
|
||||||
|
printf("%02X",adress[5]);
|
||||||
|
printf("%02X",adress[6]);
|
||||||
|
printf("%02X",adress[7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// function to print the temperature for a device
|
||||||
|
void printTemperature(DeviceAddress deviceAddress)
|
||||||
|
{
|
||||||
|
d_temp = dsensors.getTempC(deviceAddress);
|
||||||
|
dtostrf(d_temp , 6, 2, d_temp_s );
|
||||||
|
printf("Temp C: ");
|
||||||
|
printf("%s",d_temp_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printData(DeviceAddress deviceAddress)
|
||||||
|
{
|
||||||
|
printf("Device Address: ");
|
||||||
|
printAddress(deviceAddress);
|
||||||
|
printf(" ");
|
||||||
|
printTemperature(deviceAddress);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup (void)
|
||||||
|
{
|
||||||
|
// switch off the led
|
||||||
|
pinMode(LED_PIN, OUTPUT);
|
||||||
|
digitalWrite(LED_PIN, HIGH);
|
||||||
|
|
||||||
|
printf("Dallas Temperature IC Control Library Demo");
|
||||||
|
|
||||||
|
// Start up the library
|
||||||
|
dsensors.begin();
|
||||||
|
|
||||||
|
// locate devices on the bus
|
||||||
|
printf("Locating devices...\n");
|
||||||
|
printf("Found ");
|
||||||
|
printf("%d",dsensors.getDeviceCount());
|
||||||
|
printf(" devices.\n");
|
||||||
|
|
||||||
|
// report parasite power requirements
|
||||||
|
printf("Parasite power is: ");
|
||||||
|
if (dsensors.isParasitePowerMode()) printf("ON\n");
|
||||||
|
else printf("OFF\n");
|
||||||
|
|
||||||
|
// assign address manually. the addresses below will beed to be changed
|
||||||
|
// to valid device addresses on your bus. device address can be retrieved
|
||||||
|
// by using either oneWire.search(deviceAddress) or individually via
|
||||||
|
// dsensors.getAddress(deviceAddress, index)
|
||||||
|
//insideThermometer = { 0x28, 0x1D, 0x39, 0x31, 0x2, 0x0, 0x0, 0xF0 };
|
||||||
|
//outsideThermometer = { 0x28, 0x3F, 0x1C, 0x31, 0x2, 0x0, 0x0, 0x2 };
|
||||||
|
|
||||||
|
// search for devices on the bus and assign based on an index. ideally,
|
||||||
|
// you would do this to initially discover addresses on the bus and then
|
||||||
|
// use those addresses and manually assign them (see above) once you know
|
||||||
|
// the devices on your bus (and assuming they don't change).
|
||||||
|
//
|
||||||
|
// method 1: by index
|
||||||
|
if (!dsensors.getAddress(insideThermometer, 0)) printf("Unable to find address for Device 0\n");
|
||||||
|
if (!dsensors.getAddress(outsideThermometer, 1)) printf("Unable to find address for Device 1\n");
|
||||||
|
|
||||||
|
// method 2: search()
|
||||||
|
// search() looks for the next device. Returns 1 if a new address has been
|
||||||
|
// returned. A zero might mean that the bus is shorted, there are no devices,
|
||||||
|
// or you have already retrieved all of them. It might be a good idea to
|
||||||
|
// check the CRC to make sure you didn't get garbage. The order is
|
||||||
|
// deterministic. You will always get the same devices in the same order
|
||||||
|
//
|
||||||
|
// Must be called before search()
|
||||||
|
//oneWire.reset_search();
|
||||||
|
// assigns the first address found to insideThermometer
|
||||||
|
//if (!oneWire.search(insideThermometer)) Serial.println("Unable to find address for insideThermometer");
|
||||||
|
// assigns the seconds address found to outsideThermometer
|
||||||
|
//if (!oneWire.search(outsideThermometer)) Serial.println("Unable to find address for outsideThermometer");
|
||||||
|
|
||||||
|
// show the addresses we found on the bus
|
||||||
|
printf("Device 0 Address: ");
|
||||||
|
printAddress(insideThermometer);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Device 1 Address: ");
|
||||||
|
printAddress(outsideThermometer);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// set the resolution to 9 bit
|
||||||
|
dsensors.setResolution(insideThermometer, 9);
|
||||||
|
dsensors.setResolution(outsideThermometer, 9);
|
||||||
|
|
||||||
|
printf("Device 0 Resolution: ");
|
||||||
|
printf("%d",dsensors.getResolution(insideThermometer));
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Device 1 Resolution: ");
|
||||||
|
printf("%d",dsensors.getResolution(outsideThermometer));
|
||||||
|
printf("\n");
|
||||||
|
// init coap resourcen
|
||||||
|
rest_init_engine ();
|
||||||
|
rest_activate_resource (&res_htu21dtemp, "s/temp");
|
||||||
|
rest_activate_resource (&res_htu21dhum, "s/hum");
|
||||||
|
rest_activate_resource (&res_battery, "s/batter");
|
||||||
|
}
|
||||||
|
|
||||||
|
// at project-conf.h
|
||||||
|
// LOOP_INTERVAL (10 * CLOCK_SECOND)
|
||||||
|
void loop (void)
|
||||||
|
{
|
||||||
|
mcusleepcycle=0; // dont sleep
|
||||||
|
// call sensors.requestTemperatures() to issue a global temperature
|
||||||
|
// request to all devices on the bus
|
||||||
|
printf("Requesting temperatures...");
|
||||||
|
dsensors.requestTemperatures();
|
||||||
|
printf("DONE\n");
|
||||||
|
|
||||||
|
// print the device information
|
||||||
|
printData(insideThermometer);
|
||||||
|
printData(outsideThermometer);
|
||||||
|
mcusleepcycle=32; // sleep, wakeup every 32 cycles
|
||||||
|
|
||||||
|
// debug only
|
||||||
|
}
|
Loading…
Reference in a new issue