/* Emulates a DS18B20 using a DHT22 * * Provided by Destroyedlolo. (http://destroyedlolo.info) * * 23/03/2018 - First version */ #include #include #include Pin oneWireData(2); // Where the 1-wire bus is connected to const byte owROM[7] = { 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; enum OW_Cmd { START_CONVERSION = 0x44, WRITE_SCRATCHPAD = 0x4e, READ_POWERSUPPLY = 0xb4, READ_SCRATCHPAD = 0xBE }; volatile byte scratchpad[9]; /* * DHT22 related */ #include // https://github.com/winlinvip/SimpleDHT SimpleDHT22 DHT; #define pinDHT 3 /* * Let's go */ #define DEBUG // Comment out to be silence enum DeviceState { WAIT4RESET, WAIT4COMMAND, CONVERTING, TEMPERATUREREADY }; volatile DeviceState state = DeviceState::WAIT4RESET; volatile unsigned long conversionStartTime = 0; void owRcv( OneWireSlave::ReceiveEvent evt, byte cmd ){ switch( evt ){ case OneWireSlave::RE_Reset: state = DeviceState::WAIT4COMMAND; #ifdef DEBUG Serial.println(F("Reset")); #endif break; case OneWireSlave::RE_Error: state = DeviceState::WAIT4RESET; #ifdef DEBUG Serial.println(F("Error")); #endif break; case OneWireSlave::RE_Byte: if( state == DeviceState::WAIT4COMMAND ) switch( cmd ){ case OW_Cmd::START_CONVERSION: // Do a new request only if enough time passed if( !conversionStartTime || millis() < conversionStartTime || millis() > conversionStartTime + 2000 ){ state = DeviceState::CONVERTING; OWSlave.beginWriteBit(0, true); // send zeros as long as the conversion is not finished } #ifdef DEBUG else Serial.println(F("Ignored StartConv")); #endif break; case OW_Cmd::READ_SCRATCHPAD: state = DeviceState::WAIT4RESET; OWSlave.beginWrite((const byte*)scratchpad, 9, 0); break; case OW_Cmd::WRITE_SCRATCHPAD: case OW_Cmd::READ_POWERSUPPLY: state = DeviceState::WAIT4RESET; // Ignore parameters break; default: state = DeviceState::WAIT4RESET; #ifdef DEBUG Serial.print(F("Unknown command :")); Serial.println( cmd, HEX ); #endif } } } void setTemperature( float temp ){ // Write given temperature to the scratchpad int16_t raw = (int16_t)(temp * 16.0f + 0.5); // We don't care about race condition as well as only one command // can be processed at a time otherwise we are failing in error/collision // condition. scratchpad[0] = (byte)raw; scratchpad[1] = (byte)(raw >> 8); scratchpad[8] = OWSlave.crc8((const byte*)scratchpad, 8); } void setup(){ Serial.begin(115200); // debugging for(int i = 2; i<8; i++) scratchpad[i] = 0; setTemperature( 85 ); OWSlave.setReceiveCallback(&owRcv); OWSlave.begin(owROM, oneWireData.getPinNumber()); } void loop(){ delay(10); if(state == DeviceState::CONVERTING){ // start conversion float temperature = 0; float humidite = 0; int err; conversionStartTime = millis(); if((err = DHT.read2(pinDHT, &temperature, &humidite, NULL)) != SimpleDHTErrSuccess){ #ifdef DEBUG Serial.print("\nError while reading, err="); Serial.println(err); #endif temperature = 85; } else { #ifdef DEBUG Serial.print("Temperature :"); Serial.println(temperature); #endif } setTemperature( temperature ); state = DeviceState::TEMPERATUREREADY; OWSlave.beginWriteBit(1, true); } }