// SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2012-2024 Scott Penrose and WII5 Buoy contributors // // This file is part of WII5 Buoy firmware. // See LICENSE for full terms. /** * @file WII5Weather_18B20.cpp * @brief Dallas DS18B20 temperature sensor driver (OneWire). */ /* WII5Weather_18B20 TODO 2024 - Check when this is running as it blocks all other use TODO: Should be Weather / Temperature then drivers. WII5Weather WII5Weather::Temperature age() value(); value({n}) - which sensor? WII5Weather::Pressure WII5Weather::Humidity ... */ #include #include OneWire ds(WEATHER_18B20_DATA); void WII5Weather_18B20::begin() { powerSetPin(POWER_WEATHER_18B20_PIN, POWER_WEATHER_18B20_ON); powerOff(true); // Force power off at boot stepWait = 300001; age = WII5TIME_1WEEK * 1000; } void WII5Weather_18B20::loop() { // WII5 - removing this loop for now, temperature has to be an active decision. /* // If at lest been 5 minutes (maybe make this bigger later) if (stepWait > 300000) { if ( (minute() > 0) && ((minute() % 7) == 0) ) { if (wii5Sparton.captureRunning()) { console.log(LOG_DEBUG, F("Weather: Skipped - capture running. Min=%d"), minute()); } else { // REMEMBER - This blocks a bit. if (temperatureRead()) { console.log(LOG_DEBUG, F("Weather: Temperature Read. Min=%d"), minute()); } else { console.log(LOG_DEBUG, F("Weather: Failed to read temperature (unknown). Min=%d"), minute()); } } stepWait = 0; } } */ } // TODO - This is a blocking libary. Fix it. bool WII5Weather_18B20::temperatureRead() { // (check we have nothing else on) return false; powerOn(); // Give power time delay(250); currentTemperature = 2000; console.log(LOG_DEBUG, F("currentTemperature=%d"), int(currentTemperature)); ds.reset_search(); // TODO Rework code - make it so it will seaerch over 10 minutes or so // But then just queries those, no more searching, or maybe research and // try and find more devices once every hour. // What about lost devices? /* inside OneWire seems to be only small delayMicroseconds. With the exception of one 400 - (half 1 millisecond) This means that we could easily write a state machine here with a 1ms loop time Is that fast enough for other things - then this can be non blocking, even for large number of temperature sensors. */ for(byte count = 0; count < 3; count++) { if ( ds.search(addr)) { ds.reset(); ds.select(addr); ds.write(0x44, 1); // start conversion, with parasite power on at the end // TODO Gah... this should be background ! // wii5Controller.safeDelay(1000); // maybe 750ms is enough, maybe not delay(1000); ds.reset(); ds.select(addr); ds.write(0xBE); // Read Scratchpad for ( byte i = 0; i < 9; i++) // we need 9 bytes data[i] = ds.read(); int16_t raw = (data[1] << 8) | data[0]; byte cfg = (data[4] & 0x60); 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 currentTemperature = (float)raw / 16.0; // FIND and STORE them /* bool found = false; for (byte i = 0; i < countTemperature; i++) { if (ByteArrayCompare(addr, lastTemperature[i].addr, 8)) { found = true; lastTemperature[i].age = 0; // Convert to Decidegrees lastTemperature[i].celsius = currentTemperature; } } */ /* if (!found) { if (countTemperature < maxTemperature) { lastTemperature[countTemperature].age = 0; // Convert to Decidegrees lastTemperature[countTemperature].celsius = currentTemperature; memcpy( lastTemperature[countTemperature].addr, addr, 8 ); // TODO length? countTemperature++; } else { console.printf(F("ERROR: Maximum temperature probes found\r\n")); // TODO Too many errors this requires a complete reset // TODO Make it so if we get this 10 times, we reset the // whole list and start again. e.g. change countTemperature = 0 // Reset for next time... countTemperature = 0; return true; } } */ // Temporary hard coded to one sensor if (count == 0) { console.log(LOG_DEBUG, F("Temperature: %02x%02x%02x%02x%02x%02x%02x%02x count=%d currentTemperature=%d.%02d*"), addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], count, int(currentTemperature), abs(int(currentTemperature * 100) % 100) ); } } } // copy to rest of places powerOff(); console.log(LOG_DEBUG, F("currentTemperature=%d"), int(currentTemperature)); // TODO value is int32_t, but int16_t should be heaps? value = int(currentTemperature * 100); age = 0; wii5Display.atCommandSend(F("status"), F("temperature=%d"), int(value) ); wii5Display.atCommandSend(F("status"), F("update")); // TODO ?Move return true; } WII5Weather_18B20 wii5Weather_18B20;