You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.5 KiB
121 lines
3.5 KiB
7 years ago
|
// This examples demonstrates how to use the OneWireSlave library to implement a fake DS18B20 (temperature sensor) with an arduino board.
|
||
|
// The example always ever responds to requests with the same temperature
|
||
|
|
||
|
#include <Arduino.h>
|
||
|
#include <LowLevel.h>
|
||
|
#include <OneWireSlave.h>
|
||
9 years ago
|
|
||
|
// This is the pin that will be used for one-wire data (depending on your arduino model, you are limited to a few choices, because some pins don't have complete interrupt support)
|
||
|
// On Arduino Uno, you can use pin 2 or pin 3
|
||
9 years ago
|
Pin oneWireData(2);
|
||
9 years ago
|
|
||
9 years ago
|
Pin led(13);
|
||
9 years ago
|
|
||
|
// This is the ROM the arduino will respond to, make sure it doesn't conflict with another device
|
||
9 years ago
|
const byte owROM[7] = { 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 };
|
||
9 years ago
|
|
||
9 years ago
|
// This sample emulates a DS18B20 device (temperature sensor), so we start by defining the available commands
|
||
|
const byte DS18B20_START_CONVERSION = 0x44;
|
||
|
const byte DS18B20_READ_SCRATCHPAD = 0xBE;
|
||
|
const byte DS18B20_WRITE_SCRATCHPAD = 0x4E;
|
||
9 years ago
|
|
||
9 years ago
|
// TODO:
|
||
|
// - handle configuration (resolution, alarms)
|
||
|
|
||
|
enum DeviceState
|
||
|
{
|
||
|
DS_WaitingReset,
|
||
|
DS_WaitingCommand,
|
||
|
DS_ConvertingTemperature,
|
||
|
DS_TemperatureConverted,
|
||
|
};
|
||
|
volatile DeviceState state = DS_WaitingReset;
|
||
|
|
||
|
// scratchpad, with the CRC byte at the end
|
||
|
volatile byte scratchpad[9];
|
||
|
|
||
|
volatile unsigned long conversionStartTime = 0;
|
||
9 years ago
|
|
||
|
// This function will be called each time the OneWire library has an event to notify (reset, error, byte received)
|
||
|
void owReceive(OneWireSlave::ReceiveEvent evt, byte data);
|
||
|
|
||
|
void setup()
|
||
|
{
|
||
|
led.outputMode();
|
||
|
led.writeLow();
|
||
|
|
||
|
// Setup the OneWire library
|
||
9 years ago
|
OWSlave.setReceiveCallback(&owReceive);
|
||
|
OWSlave.begin(owROM, oneWireData.getPinNumber());
|
||
9 years ago
|
}
|
||
|
|
||
|
void loop()
|
||
|
{
|
||
9 years ago
|
delay(10);
|
||
9 years ago
|
|
||
|
cli();//disable interrupts
|
||
|
// Be sure to not block interrupts for too long, OneWire timing is very tight for some operations. 1 or 2 microseconds (yes, microseconds, not milliseconds) can be too much depending on your master controller, but then it's equally unlikely that you block exactly at the moment where it matters.
|
||
|
// This can be mitigated by using error checking and retry in your high-level communication protocol. A good thing to do anyway.
|
||
9 years ago
|
DeviceState localState = state;
|
||
|
unsigned long localConversionStartTime = conversionStartTime;
|
||
9 years ago
|
sei();//enable interrupts
|
||
9 years ago
|
|
||
|
if (localState == DS_ConvertingTemperature && millis() > localConversionStartTime + 750)
|
||
|
{
|
||
|
float temperature = 42.0f; // here you could plug any logic you want to return the emulated temperature
|
||
|
int16_t raw = (int16_t)(temperature * 16.0f + 0.5f);
|
||
|
|
||
|
byte data[9];
|
||
|
data[0] = (byte)raw;
|
||
|
data[1] = (byte)(raw >> 8);
|
||
|
for (int i = 2; i < 8; ++i)
|
||
|
data[i] = 0;
|
||
|
data[8] = OWSlave.crc8(data, 8);
|
||
|
|
||
|
cli();
|
||
|
memcpy((void*)scratchpad, data, 9);
|
||
|
state = DS_TemperatureConverted;
|
||
9 years ago
|
OWSlave.beginWriteBit(1, true); // now that conversion is finished, start sending ones until reset
|
||
9 years ago
|
sei();
|
||
|
}
|
||
9 years ago
|
}
|
||
|
|
||
|
void owReceive(OneWireSlave::ReceiveEvent evt, byte data)
|
||
|
{
|
||
|
switch (evt)
|
||
|
{
|
||
|
case OneWireSlave::RE_Byte:
|
||
9 years ago
|
switch (state)
|
||
9 years ago
|
{
|
||
9 years ago
|
case DS_WaitingCommand:
|
||
|
switch (data)
|
||
|
{
|
||
|
case DS18B20_START_CONVERSION:
|
||
|
state = DS_ConvertingTemperature;
|
||
|
conversionStartTime = millis();
|
||
9 years ago
|
OWSlave.beginWriteBit(0, true); // send zeros as long as the conversion is not finished
|
||
9 years ago
|
break;
|
||
|
|
||
|
case DS18B20_READ_SCRATCHPAD:
|
||
|
state = DS_WaitingReset;
|
||
9 years ago
|
OWSlave.beginWrite((const byte*)scratchpad, 9, 0);
|
||
9 years ago
|
break;
|
||
|
|
||
|
case DS18B20_WRITE_SCRATCHPAD:
|
||
|
|
||
|
break;
|
||
|
}
|
||
9 years ago
|
break;
|
||
|
}
|
||
9 years ago
|
break;
|
||
9 years ago
|
|
||
9 years ago
|
case OneWireSlave::RE_Reset:
|
||
|
state = DS_WaitingCommand;
|
||
|
break;
|
||
9 years ago
|
|
||
9 years ago
|
case OneWireSlave::RE_Error:
|
||
|
state = DS_WaitingReset;
|
||
9 years ago
|
break;
|
||
|
}
|
||
|
}
|