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(); }
// Read the state, returns -1 on failure int8_t OwRelay::rawRead(uint64_t addr) { OneWire ds = os->getOneWire(); byte data[12]; ds.reset(); ds.select((uint8_t *)&addr); uint8_t value = ds.read_bit() ^ 1; // read the switch value #if DEBUG Serial.print(F("OWR: Good data for ")); printAddr(&Serial, addr); Serial.print("->"); Serial.print(value); Serial.println(); #endif return value; }
///<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; }
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; }
/** * 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; }
void setup() { memset(voltsChr,0,sizeof(voltsChr)); memset(amps0Chr,0,sizeof(amps0Chr)); memset(amps1Chr,0,sizeof(amps1Chr)); memset(tmpChr,0,sizeof(tmpChr)); // if the program crashed, skip things that might make it crash String rebootMsg = ESP.getResetReason(); if (rebootMsg=="Exception") safeMode=true; else if (rebootMsg=="Hardware Watchdog") safeMode=true; else if (rebootMsg=="Unknown") safeMode=true; else if (rebootMsg=="Software Watchdog") safeMode=true; if (sw1>=0) { pinMode(sw1, OUTPUT); } if (sw2>=0) { pinMode(sw2, OUTPUT); } if (sw3>=0) { pinMode(sw3, OUTPUT); } if (sw4>=0) { pinMode(sw4, OUTPUT); } // "mount" the filesystem bool success = SPIFFS.begin(); if (!success) SPIFFS.format(); if (!safeMode) fsConfig(); // read node config from FS #ifdef _TRAILER wifiMulti.addAP("DXtrailer", "2317239216"); #else wifiMulti.addAP("Tell my WiFi I love her", "2317239216"); #endif int wifiConnect = 240; while ((wifiMulti.run() != WL_CONNECTED) && (wifiConnect-- > 0)) { // spend 2 minutes trying to connect to wifi // connecting to wifi delay(1000); } if (wifiMulti.run() != WL_CONNECTED ) { // still not connected? reboot! ESP.reset(); delay(5000); } if (hasHostname) { // valid config found on FS, set network name WiFi.hostname(String(nodename)); // set network hostname ArduinoOTA.setHostname(nodename); // OTA hostname defaults to esp8266-[ChipID] MDNS.begin(nodename); // set mDNS hostname } WiFi.macAddress(mac); // get esp mac address, store it in memory, build fw update url sprintf(macStr,"%x%x%x%x%x%x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); sprintf(theURL,"/iotfw?mac=%s", macStr); // request latest config from web api if (!safeMode) getConfig(); // check web api for new firmware if (!safeMode) httpUpdater(); // start UDP for ntp client udp.begin(localPort); updateNTP(); setSyncProvider(getNtptime); // use NTP to get current time setSyncInterval(600); // refresh clock every 10 min #ifndef _MINI // start the webserver httpd.onNotFound(handleNotFound); httpd.begin(); // Add service to MDNS-SD MDNS.addService("http", "tcp", 80); #endif // start websockets server webSocket.begin(); webSocket.onEvent(webSocketEvent); // setup other things setupOTA(); setupMQTT(); // setup i2c if configured, basic sanity checking on configuration if (hasI2C && iotSDA>=0 && iotSCL>=0 && iotSDA!=iotSCL) { sprintf(str,"I2C enabled, using SDA=%u SCL=%u", iotSDA, iotSCL); mqtt.publish(mqttpub, str); Wire.begin(iotSDA, iotSCL); // from api config file //Wire.begin(12, 14); // from api config file i2c_scan(); printConfig(); if (hasRGB) setupRGB(); if (hasIout) setupADS(); if (hasSpeed) setupSpeed(); } // OWDAT = 4; if (OWDAT>0) { // setup onewire if data line is using pin 1 or greater sprintf(str,"Onewire Data OWDAT=%u", OWDAT); mqtt.publish(mqttpub, str); oneWire.begin(OWDAT); if (hasTout) { ds18b20 = DallasTemperature(&oneWire); ds18b20.begin(); // start one wire temp probe } if (hasTpwr>0) { pinMode(hasTpwr, OUTPUT); // onewire power pin as output digitalWrite(hasTpwr, LOW); // ow off } } if (useMQTT) { String rebootReason = String("Last reboot cause was ") + rebootMsg; rebootReason.toCharArray(str, rebootReason.length()+1); mqtt.publish(mqttpub, str); } }
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"); }
///<summary>Go through the collection of sensors and validate that we have the ///requested sensor on the system.</summary> ///<param name="Sensors"> The OneWire bus that contains the temperature sensors</param> ///<return> True if found, false otherwise</return> bool TemperatureSensor::DoesSensorExist(OneWire Sensors) { bool retVal = false; byte foundSensorAddress[8]; Logger::PrependLogStatement(DEB); Logger::LogStatement(F("Searching for "), DEB); Logger::LogStatement(m_SensorAddress, DEB); Logger::EndLogStatement(DEB); while(true == Sensors.search(foundSensorAddress)) { bool found = true; //Print out the data Logger::PrependLogStatement(DEB); Logger::LogStatement(F("Found sensor "), DEB); Logger::LogStatement(foundSensorAddress, DEB); Logger::EndLogStatement(DEB); //See if this is a valid address if ( OneWire::crc8( foundSensorAddress, 7) != foundSensorAddress[7]) { Logger::Log(F("CRC is not valid!"), WAR); Sensors.reset(); Sensors.reset_search(); break; } if ( foundSensorAddress[0] != 0x10 && foundSensorAddress[0] != 0x28) { Logger::Log(F("Device is not recognized"), WAR); continue; } //We found a valid device on the wire. See if it's a match for(int i = 0; i < 8; i++) { if(m_SensorAddress[i] != foundSensorAddress[i]) { found = false; break; } } //See if we found a match if(true == found) { //This is the sensor we're looking for Logger::Log(F("Found sensor"), DEB); retVal = true; break; } } Logger::Log(F("Done searching for sensors"), DEB); cleanup: //Reset the temperature sensor search for subsequent invocations Sensors.reset_search(); return retVal; }
/** * 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; }