bool OwRelay::rawWrite(uint64_t addr, bool value) { OneWire ds = os->getOneWire(); uint8_t *a = (uint8_t *)&addr; ds.reset(); ds.write(0x55, 1); // ROM select for(int i = 0; i < 8; i++) ds.write(a[i], 1); uint8_t bit = ds.read_bit(); ds.reset(); bool oops = false; value ^= 1; if ((bit&1) ^ value) { oops = true; // toggled the wrong way, toggle again... ds.write(0x55, 1); // ROM select for(int i = 0; i < 8; i++) ds.write(a[i], 1); bit = ds.read_bit(); ds.reset(); } #if DEBUG Serial.print(F("OWR: Write ")); printAddr(&Serial, addr); Serial.print("<-"); Serial.print(value); if (oops) Serial.print(" 2xtoggle"); Serial.print(" bit="); Serial.print(bit); Serial.println(); #endif return !((bit&1) ^ value); }
float getTemp(OneWire ds){ //returns the temperature from one DS18S20 in DEG Celsius unsigned long currentMillis = millis(); static long previousMillis = 0; if(currentMillis - previousMillis > TempSampleInterval) { // save the last time you blinked the LED previousMillis = currentMillis; byte data[12]; byte addr[8]; if ( !ds.search(addr)) { //no more sensors on chain, reset search ds.reset_search(); return -1000; } if ( OneWire::crc8( addr, 7) != addr[7]) { Serial.println("CRC is not valid!"); return -1000; } if ( addr[0] != 0x10 && addr[0] != 0x28) { Serial.print("Device is not recognized"); return -1000; } ds.reset(); ds.select(addr); ds.write(0x44,1); // start conversion, with parasite power on at the end byte present = ds.reset(); ds.select(addr); ds.write(0xBE); // Read Scratchpad for (int i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); } ds.reset_search(); byte MSB = data[1]; byte LSB = data[0]; float tempRead = ((MSB << 8) | LSB); //using two's compliment float TemperatureSum = tempRead / 16; // Serial.print("Temperature: "); // Serial.print(TemperatureSum); // Serial.print('\n'); return TemperatureSum; } }
void loop(void) { byte i; byte present = 0; byte data[12]; byte addr[8]; if ( !ds.search(addr)) { Serial.print("No more addresses.\n"); ds.reset_search(); delay(1250); return; } Serial.print("R="); for( i = 0; i < 8; i++) { Serial.print(addr[i], HEX); Serial.print(" "); } if ( OneWire::crc8( addr, 7) != addr[7]) { Serial.print("CRC is not valid!\n"); return; } if ( addr[0] != 0x28) { Serial.print("Device is not a DS18B20 family device.\n"); return; } // The DallasTemperature library can do all this work for you! ds.reset(); ds.select(addr); ds.write(0x44,1); // start conversion, with parasite power on at the end delay(1000); // maybe 750ms is enough, maybe not // we might do a ds.depower() here, but the reset will take care of it. present = ds.reset(); ds.select(addr); ds.write(0xBE); // Read Scratchpad Serial.print("P="); Serial.print(present,HEX); Serial.print(" "); for ( i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); Serial.print(data[i], HEX); Serial.print(" "); } Serial.print(" CRC="); Serial.print( OneWire::crc8( data, 8), HEX); Serial.println(); }
///<summary> Retrieve the temperature from the OneWire sensor</summary> ///<param name="Sensors">Location of the bus for the OneWire sensors</param> ///<return>True if successful, false otherwise</return> bool TemperatureSensor::RetrieveTemperatureFromSensor(OneWire Sensors) { float retVal = INVALID_DATA; byte data[2]; //Found the sensor we were looking for, read the data from it if(0 == Sensors.reset()) { Logger::Log(F("Unable to reset the bus"), ERR); goto cleanup; } Sensors.select(m_SensorAddress); //Send the 0x44 command, which is the convert command Sensors.write(0x44); //TODO: Can only do this when not in parasitic power mode while(Sensors.read() == 0) { //Chill for 5 ms to see if it's all done delay(5); } //TODO: This might not be needed for non-parasite powered sensors if(0 == Sensors.reset()) { Logger::Log(F("Unable to reset the bus after converting temperature"), ERR); goto cleanup; } Sensors.select(m_SensorAddress); //Send the 0xBE command, which is read the scratchpad Sensors.write(0xBE); //The data is of the format LSB, MSB data[0] = Sensors.read(); data[1] = Sensors.read(); retVal = ((data[1] << 8) | data[0]); //using two's compliment retVal = retVal / 16.0; retVal = Utility::ToFahrenheit(retVal); //Reset the communication Sensors.reset(); //Assign our temperature data m_Temperature = retVal; cleanup: return retVal; }
/** * Set the temperature resolution. While this speeds up conversion, it also * reduces accuracy. * * @param ds OneWire instance configured for communication with the DS18B20. * @param res One of the resolution constants to set the appropriate resolution. * @return Success or failure */ bool DS18B20::setResolution(OneWire ds, byte res) { byte addr[8]; // address buffer int deviceCount = 0; // track number of devices serviced // Make sure the resolution byte sent in is valid. if (res != RES_9BIT && res != RES_10BIT && res != RES_11BIT && res != RES_12BIT) return false; // Do this while devices are available ds.reset_search(); while (ds.search(addr)) { // Count this device deviceCount++; // Verify the CRC of the address if ( OneWire::crc8( addr, 7) != addr[7]) { return false; } // Verify the device is recognized by looking at the device ID in the // first byte of the address (=0x28). if (addr[0] != DS18B20_CODE) { return false; } // Write to the scratchpad register. See pg. 11 of datasheet. This // requires sending the write command and then 3 bytes. The first two // set alarms...these are not used. The third is the resolution. ds.reset(); ds.select(addr); ds.write(CMD_WRITE_SPAD); // 0x4E = write scratchpad ds.write(ALARM_DISABLED); // alarm low setting = 0 (not used) ds.write(ALARM_DISABLED); // alarm high setting = 0 (not used) ds.write(res); // resolution } // If we didn't catch any devices, return false if (deviceCount == 0) return false; // If we did, return true else return true; }
float Temperature::getTemp(OneWire ds){ if ( !ds.search(_addr)) { //no more sensors on chain, reset search ds.reset_search(); return -1000; } if ( OneWire::crc8( _addr, 7) != _addr[7]) { Serial.println("CRC is not valid!"); return -1000; } if ( _addr[0] != 0x10 && _addr[0] != 0x28) { Serial.print("Device is not recognized"); return -1000; } ds.reset(); ds.select(_addr); ds.write(0x44,1); // start conversion, with parasite power on at the end _present = ds.reset(); ds.select(_addr); ds.write(0xBE); // Read Scratchpad for (int i = 0; i < 9; i++) { // we need 9 bytes _data[i] = ds.read(); } ds.reset_search(); _MSB = _data[1]; _LSB = _data[0]; _tempRead = ((_MSB << 8) | _LSB); //using two's compliment _TemperatureSum = _tempRead / 16; return _TemperatureSum; }
void ReadTemp(Temp& reading) { byte i; byte present = 0; byte type_s; byte data[12]; if ( !ds.search(reading.addr)) { ds.reset_search(); delay(250); return; } if (OneWire::crc8(reading.addr, 7) != reading.addr[7]) { Serial.println("CRC is not valid!"); return; } // the first ROM byte indicates which chip switch (reading.addr[0]) { case 0x10: type_s = 1; break; case 0x28: type_s = 0; break; case 0x22: type_s = 0; break; default: Serial.println("Device is not a DS18x20 family device."); return; } ds.reset(); ds.select(reading.addr); ds.write(0x44, 1); // start conversion, with parasite power on at the end delay(750); // maybe 750ms is enough, maybe not // we might do a ds.depower() here, but the reset will take care of it. present = ds.reset(); ds.select(reading.addr); ds.write(0xBE); // Read Scratchpad for ( i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); } // Convert the data to actual temperature // because the result is a 16 bit signed integer, it should // be stored to an "int16_t" type, which is always 16 bits // even when compiled on a 32 bit processor. int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // 9 bit resolution default if (data[7] == 0x10) { // "count remain" gives full 12 bit resolution raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); // at lower res, the low bits are undefined, so let's zero them if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms //// default is 12 bit resolution, 750 ms conversion time } reading.celsius = (raw / 16.0) * 100; reading.didRead = true; }
void loop(void) { byte i; byte present = 0; byte type_s; byte data[12]; byte addr[8]; float celsius, fahrenheit; if ( !ds.search(addr)) { Serial.println("No more addresses."); Serial.println(); ds.reset_search(); delay(250); return; } Serial.print("ROM ="); for( i = 0; i < 8; i++) { Serial.write(' '); Serial.print(addr[i], HEX); } if (OneWire::crc8(addr, 7) != addr[7]) { Serial.println("CRC is not valid!"); return; } Serial.println(); // the first ROM byte indicates which chip switch (addr[0]) { case 0x10: Serial.println(" Chip = DS18S20"); // or old DS1820 type_s = 1; break; case 0x28: Serial.println(" Chip = DS18B20"); type_s = 0; break; case 0x22: Serial.println(" Chip = DS1822"); type_s = 0; break; default: Serial.println("Device is not a DS18x20 family device."); return; } ds.reset(); ds.select(addr); ds.write(0x44, 1); // start conversion, with parasite power on at the end delay(1000); // maybe 750ms is enough, maybe not // we might do a ds.depower() here, but the reset will take care of it. present = ds.reset(); ds.select(addr); ds.write(0xBE); // Read Scratchpad Serial.print(" Data = "); Serial.print(present, HEX); Serial.print(" "); for ( i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); Serial.print(data[i], HEX); Serial.print(" "); } Serial.print(" CRC="); Serial.print(OneWire::crc8(data, 8), HEX); Serial.println(); // Convert the data to actual temperature // because the result is a 16 bit signed integer, it should // be stored to an "int16_t" type, which is always 16 bits // even when compiled on a 32 bit processor. int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // 9 bit resolution default if (data[7] == 0x10) { // "count remain" gives full 12 bit resolution raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); // at lower res, the low bits are undefined, so let's zero them if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms //// default is 12 bit resolution, 750 ms conversion time } celsius = (float)raw / 16.0; fahrenheit = celsius * 1.8 + 32.0; Serial.print(" Temperature = "); Serial.print(celsius); Serial.print(" Celsius, "); Serial.print(fahrenheit); Serial.println(" Fahrenheit"); }
/** * Get a float representing the temperature from the DS18B20. * * @param ds OneWire instance configured for communication with the DS18B20. * @return The average temperature in Fahrenheit of all devices, or 0 if fail. */ float DS18B20::getTemperature(OneWire ds) { byte data[12]; // data buffer byte addr[8]; // address buffer byte deviceCount = 0; // number of devices taken care of float avgTemp = 0.0; // the average temperature to be returned // Search for a new device on the bus. If 1, a new device is available. If 0, // the bus may be in error, nothing may be connected, or all devices have been // read. This should allow for multiple sensors on the same bus (must remove // else block). The address of the next device will be stored in addr. ds.reset_search(); while (ds.search(addr)) { // Count this device deviceCount++; // Verify the CRC of the address if ( OneWire::crc8( addr, 7) != addr[7]) { //Serial.println("CRC is not valid!"); return 0.0; } // Verify the device is recognized by looking at the device ID in the // first byte of the address (=0x28). if (addr[0] != DS18B20_CODE) { //Serial.println("Device not recognized!"); return 0.0; } // Begin a temperature conversion ds.reset(); ds.select(addr); ds.write(CMD_CONVERT_TEMP); // 0x44 = start conversion // Hard delay to get the most up-to-date reading. This gives the most time accurate reading // but locks the processor up from doing anything else. The existing method where we read // the *previous* reading every 1 second is suitable and increases utilization. //delay(1000); // Request to read the temperature sensor's scratchpad for the converted temperature ds.reset(); ds.select(addr); ds.write(CMD_READ_SPAD); // 0xBE = read scratchpad // Read data (9 bytes total in register, only the first two bytes contain the temperature) for (int i = 0; i < 9; i++) { data[i] = ds.read(); } // Convert read data (16 bit signed integer) to a float int16_t temp_raw = (data[1] << 8) | data[0]; float temp_celsius = (float)temp_raw/16.0; // Convert temperature to Fahrenheit and add it to our running average float temp_fahrenheit = temp_celsius * 1.8 + 32.0; avgTemp += temp_fahrenheit; } // If we didn't catch any devices, return 0.0 if (deviceCount == 0) return 0.0; // Compute and return the average avgTemp /= deviceCount; return avgTemp; }
//------------------------------------------------------------------------- float ReadSingleOneWireSensor(OneWire ds) { //--- 18B20 stuff byte i; byte type_s; byte data[12]; byte addr[8]; float celsius = 12.3; if (!ds.search(addr)) { ds.reset_search(); delay(250); return celsius; } if (OneWire::crc8(addr, 7) != addr[7]) { return celsius; } //--- the first ROM byte indicates which chip switch (addr[0]) { case 0x10: //Serial.println(" Chip = DS18S20"); // or old DS1820 type_s = 1; break; case 0x28: // Serial.println(" Chip = DS18B20"); type_s = 0; break; case 0x22: // Serial.println(" Chip = DS1822"); type_s = 0; break; default: // Serial.println("Device is not a DS18x20 family device."); return celsius; } ds.reset(); ds.select(addr); ds.write(0x44,1 ); //--- start conversion, use alternatively ds.write(0x44,1) with parasite power on at the end delay(1000); //--- maybe 750ms is enough, maybe not //--- we might do a ds.depower() here, but the reset will take care of it. ds.reset(); //--- DS18B20 responds with presence pulse //--- match ROM 0x55, sensor sends ROM-code command ommitted here. ds.select(addr); ds.write(0xBE); //--- read scratchpad for (i = 0; i < 9; i++) { //--- we need 9 bytes, 9th byte is CRC, first 8 are data data[i] = ds.read(); } //--- Convert the data to actual temperature //--- because the result is a 16 bit signed integer, it should //--- be stored to an "int16_t" type, which is always 16 bits //--- even when compiled on a 32 bit processor. int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; //--- 9 bit resolution default if (data[7] == 0x10) { //--- "count remain" gives full 12 bit resolution raw = (raw & 0xFFF0) + 12 - data[6]; }; } else { byte cfg = (data[4] & 0x60); // at lower res, the low bits are undefined, so let's zero them // default is 12 bit resolution, 750 ms conversion time if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms }; celsius = (float)raw / 16.0; //fahrenheit = celsius * 1.8 + 32.0; //---- Check if any reads failed and exit early (to try again). if (isnan(celsius)) { //--- signalize error condition celsius = -99.9; }; return celsius; }