diff --git a/OneWireIO.ino b/OneWireIO.ino index dff1446..c3a1ecb 100644 --- a/OneWireIO.ino +++ b/OneWireIO.ino @@ -9,13 +9,30 @@ Pin oneWireData(2); Pin led(13); // This is the ROM the arduino will respond to, make sure it doesn't conflict with another device -const byte owROM[7] = { 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; +const byte owROM[7] = { 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; -const byte acknowledge = 0x42; +// 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; -// This sample implements a simple protocol : sending match ROM, then the ROM, then 0x01 will turn the arduino light on. Sending 0x02 will turn it off. In each case, the byte 0x42 is sent as acknowledgement. -const byte CMD_TurnOn = 0x01; -const byte CMD_TurnOff = 0x02; +// TODO: +// - handle configuration (resolution, alarms) +// - send 0 bits while conversion is in progress, 1 bits when it's done (until reset) + +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; // 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); @@ -32,14 +49,32 @@ void setup() void loop() { - delay(1); - - // You can do anything you want here, the OneWire library works entirely in background, using interrupts. + delay(10); 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. + DeviceState localState = state; + unsigned long localConversionStartTime = conversionStartTime; sei();//enable interrupts + + 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; + sei(); + } } void owReceive(OneWireSlave::ReceiveEvent evt, byte data) @@ -47,27 +82,35 @@ void owReceive(OneWireSlave::ReceiveEvent evt, byte data) switch (evt) { case OneWireSlave::RE_Byte: - if (data == CMD_TurnOn) - { - led.writeHigh(); - } - else if (data == CMD_TurnOff) - { - led.writeLow(); - } - else + switch (state) { + case DS_WaitingCommand: + switch (data) + { + case DS18B20_START_CONVERSION: + state = DS_ConvertingTemperature; + conversionStartTime = millis(); + break; + + case DS18B20_READ_SCRATCHPAD: + state = DS_WaitingReset; + OWSlave.write((const byte*)scratchpad, 9, 0); + break; + + case DS18B20_WRITE_SCRATCHPAD: + + break; + } break; } + break; - // in this simple example we just reply with one byte to say we've processed the command - // a real application should have a CRC system to ensure messages are not corrupt, for both directions - // you can use the static OneWireSlave::crc8 method to add CRC checks in your communication protocol (it conforms to standard one-wire CRC checks, that is used to compute the ROM last byte for example) - OWSlave.write(&acknowledge, 1, NULL); + case OneWireSlave::RE_Reset: + state = DS_WaitingCommand; + break; + case OneWireSlave::RE_Error: + state = DS_WaitingReset; break; - - default: - ; // we could also react to reset and error notifications, but not in this sample } }