// Called from startup() after some initial setup has been done. // Can abort with panic() if need be. void POSTalt() { #ifdef USE_MODULE_RFM22RADIOSIMPLE #if !defined(RFM22_IS_ACTUALLY_RFM23) && defined(DEBUG) DEBUG_SERIAL_PRINTLN_FLASHSTRING("(Using RFM22.)"); #endif // Initialise the radio, if configured, ASAP because it can suck a lot of power until properly initialised. RFM22PowerOnInit(); // Check that the radio is correctly connected; panic if not... if(!RFM22CheckConnected()) { panic(); } // Configure the radio. RFM22RegisterBlockSetup(FHT8V_RFM22_Reg_Values); // Put the radio in low-power standby mode. RFM22ModeStandbyAndClearState(); #endif DEBUG_SERIAL_PRINTLN_FLASHSTRING("Setting up interrupts"); cli(); PCICR = 0x05; PCMSK0 = 0b00000011; // PB; PCINT 0--7 (LEARN1 and Radio) PCMSK1 = 0b00000000; // PC; PCINT 8--15 PCMSK2 = 0b00101001; // PD; PCINT 16--24 (LEARN2 and MODE, RX) sei(); }
// Clears the RFM22 TX FIFO and queues up ready to send via the TXFIFO the 0xff-terminated bytes starting at bptr. // This routine does not change the command area. // This uses an efficient burst write. // For DEBUG can abort after (over-)filling the 64-byte FIFO at no extra cost with a check before spinning waiting for SPI byte to be sent. void RFM22QueueCmdToFF(const uint8_t *bptr) { #if 0 && defined(DEBUG) if(0 == *bptr) { DEBUG_SERIAL_PRINTLN_FLASHSTRING("RFM22QueueCmdToFF: buffer uninitialised"); panic(); } #endif const bool neededEnable = powerUpSPIIfDisabled(); // Clear the TX FIFO. _RFM22ClearTXFIFO(); _RFM22_SELECT(); _RFM22_wr(RFM22REG_FIFO | 0x80); // Start burst write to TX FIFO. uint8_t val; #if 1 && defined(DEBUG) for(int8_t i = 64; ((uint8_t)0xff) != (val = *bptr++); ) { // DEBUG_SERIAL_PRINTFMT(val, HEX); DEBUG_SERIAL_PRINTLN(); SPDR = val; if(--i < 0) { DEBUG_SERIAL_PRINTLN_FLASHSTRING("RFM22QueueCmdToFF: buffer unterminated"); panic(); } while (!(SPSR & _BV(SPIF))) { } //val = SPDR; // Not clear if SPDR has to be read... } #else while((uint8_t)0xff != (val = *bptr++)) { _RFM22_wr(val); } #endif _RFM22_DESELECT(); if(neededEnable) { powerDownSPI(); } }
// Returns true iff RFM22 (or RFM23) appears to be correctly connected. bool RFM22CheckConnected() { const bool neededEnable = powerUpSPIIfDisabled(); bool isOK = false; const uint8_t rType = _RFM22ReadReg8Bit(0); // May read as 0 if not connected at all. if(RFM22_SUPPORTED_DEVICE_TYPE == rType) { const uint8_t rVersion = _RFM22ReadReg8Bit(1); if(RFM22_SUPPORTED_DEVICE_VERSION == rVersion) { isOK = true; } #if 0 && defined(DEBUG) else { DEBUG_SERIAL_PRINT_FLASHSTRING("RFM22 bad version: "); DEBUG_SERIAL_PRINTFMT(rVersion, HEX); DEBUG_SERIAL_PRINTLN(); } #endif } #if 0 && defined(DEBUG) else { DEBUG_SERIAL_PRINT_FLASHSTRING("RFM22 bad type: "); DEBUG_SERIAL_PRINTFMT(rType, HEX); DEBUG_SERIAL_PRINTLN(); } #endif #if 1 && defined(DEBUG) if(!isOK) { DEBUG_SERIAL_PRINTLN_FLASHSTRING("RFM22 bad"); } #endif if(neededEnable) { powerDownSPI(); } return(isOK); }
// Enter receive mode. // SPI must already be configured and running. static void _RFM22ModeRX() { _RFM22WriteReg8Bit(RFM22REG_OP_CTRL1, 5); #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINTLN_FLASHSTRING("Rx"); #endif } // RXON | XTON
// Minimal set-up of I/O (etc) after system power-up. // Performs a software reset and leaves the radio deselected and in a low-power and safe state. // Will power up SPI if needed. void RFM22PowerOnInit() { #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINTLN_FLASHSTRING("RFM22 reset..."); #endif const bool neededEnable = powerUpSPIIfDisabled(); _RFM22WriteReg8Bit(RFM22REG_OP_CTRL1, RFM22REG_OP_CTRL1_SWRES); _RFM22ModeStandby(); if(neededEnable) { powerDownSPI(); } }
// Called from loop(). void loopAlt() { // Sleep in low-power mode (waiting for interrupts) until seconds roll. // NOTE: sleep at the top of the loop to minimise timing jitter/delay from Arduino background activity after loop() returns. // DHD20130425: waking up from sleep and getting to start processing below this block may take >10ms. #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINTLN_FLASHSTRING("*E"); // End-of-cycle sleep. #endif powerDownSerial(); // Ensure that serial I/O is off. // Power down most stuff (except radio for hub RX). minimisePowerWithoutSleep(); static uint_fast8_t TIME_LSD; // Controller's notion of seconds within major cycle. uint_fast8_t newTLSD; while(TIME_LSD == (newTLSD = getSecondsLT())) { sleepUntilInt(); // Normal long minimal-power sleep until wake-up interrupt. } TIME_LSD = newTLSD; #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINTLN_FLASHSTRING("*S"); // Start-of-cycle wake. #endif // START LOOP BODY // =============== DEBUG_SERIAL_PRINTLN_FLASHSTRING("tick..."); DEBUG_SERIAL_PRINTLN_FLASHSTRING("int count: "); DEBUG_SERIAL_PRINT(interruptCount); DEBUG_SERIAL_PRINTLN(); }
// Get approximate internal temperature in nominal C/16. // Only accurate to +/- 10C uncalibrated. // May set sleep mode to SLEEP_MODE_ADC, and disables sleep on exit. int readInternalTemperatureC16() { // Measure internal temperature sensor against internal voltage source. // Response is ~1mv/C with 0C at ~289mV according to the data sheet. const uint16_t raw = OTV0P2BASE::_analogueNoiseReducedReadM(_BV(REFS1) | _BV(REFS0) | _BV(MUX3), 1); #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINT_FLASHSTRING("Int temp raw: "); DEBUG_SERIAL_PRINT(raw); DEBUG_SERIAL_PRINTLN_FLASHSTRING(""); #endif //const int degC = (raw - 328) ; // Crude fast adjustment for one sensor at ~20C (DHD20130429). const int degC = ((((int)raw) - 324) * 210) >> 4; // Slightly less crude adjustment, see http://playground.arduino.cc//Main/InternalTemperatureSensor return(degC); }
// Send the underlying stats binary/text 'whitened' message. // This must be terminated with an 0xff (which is not sent), // and no longer than STATS_MSG_MAX_LEN bytes long in total (excluding the terminating 0xff). // This must not contain any 0xff and should not contain long runs of 0x00 bytes. // The message to be sent must be written at an offset of STATS_MSG_START_OFFSET from the start of the buffer. // This routine will alter the content of the buffer for transmission, // and the buffer should not be re-used as is. // * doubleTX double TX to increase chance of successful reception // * RFM23BfriendlyPremable if true then add an extra preamble // to allow RFM23B-based receiver to RX this // This will use whichever transmission medium/carrier/etc is available. //#define STATS_MSG_START_OFFSET (RFM22_PREAMBLE_BYTES + RFM22_SYNC_MIN_BYTES) //#define STATS_MSG_MAX_LEN (64 - STATS_MSG_START_OFFSET) void RFM22RawStatsTXFFTerminated(uint8_t * const buf, const bool doubleTX, bool RFM23BFramed) { if(RFM23BFramed) RFM22RXPreambleAdd(buf); // Only needed for RFM23B. This should be made more clear when refactoring const uint8_t buflen = OTRadioLink::frameLenFFTerminated(buf); #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINT_FLASHSTRING("buflen="); DEBUG_SERIAL_PRINT(buflen); DEBUG_SERIAL_PRINTLN(); #endif // DEBUG if(!PrimaryRadio.queueToSend(buf, buflen, 0, (doubleTX ? OTRadioLink::OTRadioLink::TXmax : OTRadioLink::OTRadioLink::TXnormal))) { #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINTLN_FLASHSTRING("!TX failed"); #endif } // DEBUG //DEBUG_SERIAL_PRINTLN_FLASHSTRING("RS"); }
// Called from startup() after some initial setup has been done. // Can abort with panic() if need be. void POSTalt() { #ifdef USE_MODULE_RFM22RADIOSIMPLE #if !defined(RFM22_IS_ACTUALLY_RFM23) && defined(DEBUG) DEBUG_SERIAL_PRINTLN_FLASHSTRING("(Using RFM22.)"); #endif // Initialise the radio, if configured, ASAP, because it can suck a lot of power until properly initialised. RFM22PowerOnInit(); // Check that the radio is correctly connected; panic if not... if(!RFM22CheckConnected()) { panic(); } // Configure the radio. RFM22RegisterBlockSetup(FHT8V_RFM22_Reg_Values); // Put the radio in low-power standby mode. RFM22ModeStandbyAndClearState(); #endif // Force initialisation into low-power state. const int heat = TemperatureC16.read(); #if 1 && defined(DEBUG) DEBUG_SERIAL_PRINT_FLASHSTRING("temp: "); DEBUG_SERIAL_PRINT(heat); DEBUG_SERIAL_PRINTLN(); #endif const int light = AmbLight.read(); #if 1 && defined(DEBUG) DEBUG_SERIAL_PRINT_FLASHSTRING("light: "); DEBUG_SERIAL_PRINT(light); DEBUG_SERIAL_PRINTLN(); #endif // Trailing setup for the run // -------------------------- // const bool foundSlaves = MinOW.reset(); }
// Initialise the device (if any) before first use. // Returns true iff successful. // Uses specified order DS18B20 found on bus. // May need to be reinitialised if precision changed. bool TemperatureC16_DS18B20::init() { // DEBUG_SERIAL_PRINTLN_FLASHSTRING("DS18B20 init..."); bool found = false; // Ensure no bad search state. minOW.reset_search(); for( ; ; ) { if(!minOW.search(address)) { minOW.reset_search(); // Be kind to any other OW search user. break; } #if 0 && defined(DEBUG) // Found a device. DEBUG_SERIAL_PRINT_FLASHSTRING("addr:"); for(int i = 0; i < 8; ++i) { DEBUG_SERIAL_PRINT(' '); DEBUG_SERIAL_PRINTFMT(address[i], HEX); } DEBUG_SERIAL_PRINTLN(); #endif if(0x28 != address[0]) { #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINTLN_FLASHSTRING("Not a DS18B20, skipping..."); #endif continue; } #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINTLN_FLASHSTRING("Setting precision..."); #endif minOW.reset(); // Write scratchpad/config minOW.select(address); minOW.write(0x4e); minOW.write(0); // Th: not used. minOW.write(0); // Tl: not used. // MinOW.write(DS1820_PRECISION | 0x1f); // Config register; lsbs all 1. minOW.write(((precision - 9) << 6) | 0x1f); // Config register; lsbs all 1. // Found one and configured it! found = true; } // Search has been run (whether DS18B20 was found or not). initialised = true; if(!found) { // DEBUG_SERIAL_PRINTLN_FLASHSTRING("DS18B20 not found"); address[0] = 0; // Indicate that no DS18B20 was found. } return(found); }
// Called from loop(). void loopAlt() { // Sleep in low-power mode (waiting for interrupts) until seconds roll. // NOTE: sleep at the top of the loop to minimise timing jitter/delay from Arduino background activity after loop() returns. // DHD20130425: waking up from sleep and getting to start processing below this block may take >10ms. #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINTLN_FLASHSTRING("*E"); // End-of-cycle sleep. #endif #if !defined(ENABLE_MIN_ENERGY_BOOT) OTV0P2BASE::powerDownSerial(); // Ensure that serial I/O is off. // Power down most stuff (except radio for hub RX). minimisePowerWithoutSleep(); #endif static uint_fast8_t TIME_LSD; // Controller's notion of seconds within major cycle. uint_fast8_t newTLSD; while(TIME_LSD == (newTLSD = OTV0P2BASE::getSecondsLT())) { // Poll I/O and process message incrementally (in this otherwise idle time) // before sleep and on wakeup in case some IO needs further processing now, // eg work was accrued during the previous major slow/outer loop // or the in a previous orbit of this loop sleep or nap was terminated by an I/O interrupt. // Come back and have another go if work was done, until the next tick at most. if(handleQueuedMessages(&Serial, true, &PrimaryRadio)) { continue; } // If missing h/w interrupts for anything that needs rapid response // then AVOID the lowest-power long sleep. #if defined(ENABLE_CONTINUOUS_RX) && !defined(PIN_RFM_NIRQ) #define MUST_POLL_FREQUENTLY true #else #define MUST_POLL_FREQUENTLY false #endif if(MUST_POLL_FREQUENTLY /** && in hub mode */ ) { // No h/w interrupt wakeup on receipt of frame, // so can only sleep for a short time between explicit poll()s, // though allow wake on interrupt anyway to minimise loop timing jitter. OTV0P2BASE::nap(WDTO_15MS, true); } else { // Normal long minimal-power sleep until wake-up interrupt. // Rely on interrupt to force fall through to I/O poll() below. OTV0P2BASE::sleepUntilInt(); } // DEBUG_SERIAL_PRINTLN_FLASHSTRING("w"); // Wakeup. // idle15AndPoll(); // Attempt to crash the board! } TIME_LSD = newTLSD; #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINTLN_FLASHSTRING("*S"); // Start-of-cycle wake. #endif // START LOOP BODY // =============== // DEBUG_SERIAL_PRINTLN_FLASHSTRING("*"); // // Power up serial for the loop body. // // May just want to turn it on in POSTalt() and leave it on... // const bool neededWaking = powerUpSerialIfDisabled(); //#if defined(ENABLE_FHT8VSIMPLE) // // Try for double TX for more robust conversation with valve? // const bool doubleTXForFTH8V = false; // // FHT8V is highest priority and runs first. // // ---------- HALF SECOND #0 ----------- // bool useExtraFHT8VTXSlots = localFHT8VTRVEnabled() && FHT8VPollSyncAndTX_First(doubleTXForFTH8V); // Time for extra TX before UI. //// if(useExtraFHT8VTXSlots) { DEBUG_SERIAL_PRINTLN_FLASHSTRING("ES@0"); } //#endif switch(TIME_LSD) { #ifdef ENABLE_STATS_TX // Regular transmission of stats if NOT driving a local valve (else stats can be piggybacked onto that). case 10: { // if((OTV0P2BASE::getMinutesLT() & 0x3) == 0) // Send once every 4 minutes. { // Send it! // Try for double TX for extra robustness unless: // * this is a speculative 'extra' TX // * battery is low // * this node is a hub so needs to listen as much as possible // This doesn't generally/always need to send binary/both formats // if this is controlling a local FHT8V on which the binary stats can be piggybacked. // Ie, if doesn't have a local TRV then it must send binary some of the time. // Any recently-changed stats value is a hint that a strong transmission might be a good idea. const bool doBinary = false; // !localFHT8VTRVEnabled() && OTV0P2BASE::randRNG8NextBoolean(); bareStatsTX(false, false, false); } break; } #endif // Poll ambient light level at a fixed rate. // This allows the unit to respond consistently to (eg) switching lights on (eg TODO-388). case 20: { AmbLight.read(); break; } #if defined(ENABLE_PRIMARY_TEMP_SENSOR_DS18B20) case 30: { TemperatureC16.read(); break; } #endif // ENABLE_PRIMARY_TEMP_SENSOR_DS18B20 #if defined(ENABLE_VOICE_SENSOR) // read voice sensor case 40: { Voice.read(); break; } #endif // (ENABLE_VOICE_SENSOR) #ifdef ENABLE_OCCUPANCY_SUPPORT case 50: { Occupancy.read(); // Needs regular poll. break; } #endif // ENABLE_OCCUPANCY_SUPPORT } PrimaryRadio.poll(); //#if defined(ENABLE_FHT8VSIMPLE) // if(useExtraFHT8VTXSlots) // { // // Time for extra TX before other actions, but don't bother if minimising power in frost mode. // // ---------- HALF SECOND #1 ----------- // useExtraFHT8VTXSlots = localFHT8VTRVEnabled() && FHT8VPollSyncAndTX_Next(doubleTXForFTH8V); //// if(useExtraFHT8VTXSlots) { DEBUG_SERIAL_PRINTLN_FLASHSTRING("ES@1"); } // } //#endif //#if defined(ENABLE_FHT8VSIMPLE) && defined(V0P2BASE_TWO_S_TICK_RTC_SUPPORT) // if(useExtraFHT8VTXSlots) // { // // ---------- HALF SECOND #2 ----------- // useExtraFHT8VTXSlots = localFHT8VTRVEnabled() && FHT8VPollSyncAndTX_Next(doubleTXForFTH8V); //// if(useExtraFHT8VTXSlots) { DEBUG_SERIAL_PRINTLN_FLASHSTRING("ES@2"); } // } //#endif //#if defined(ENABLE_FHT8VSIMPLE) && defined(V0P2BASE_TWO_S_TICK_RTC_SUPPORT) // if(useExtraFHT8VTXSlots) // { // // ---------- HALF SECOND #3 ----------- // useExtraFHT8VTXSlots = localFHT8VTRVEnabled() && FHT8VPollSyncAndTX_Next(doubleTXForFTH8V); //// if(useExtraFHT8VTXSlots) { DEBUG_SERIAL_PRINTLN_FLASHSTRING("ES@3"); } // } //#endif //#ifdef HAS_DORM1_VALVE_DRIVE // // Move valve to new target every minute to try to upset it! // // Targets at key thresholds and random. // if(0 == TIME_LSD) // { // switch(OTV0P2BASE::randRNG8() & 1) // { // case 0: ValveDirect.set(OTRadValve::DEFAULT_VALVE_PC_MIN_REALLY_OPEN-1); break; // Nominally shut. // case 1: ValveDirect.set(OTRadValve::DEFAULT_VALVE_PC_MODERATELY_OPEN); break; // Nominally open. // // Random. //// default: ValveDirect.set(OTV0P2BASE::randRNG8() % 101); break; // } // } // // // Simulate human doing the right thing after fitting valve when required. // if(ValveDirect.isWaitingForValveToBeFitted()) { ValveDirect.signalValveFitted(); } // // // Provide regular poll to motor driver. // // May take significant time to run // // so don't call when timing is critical or not much left, // // eg around critical TXes. // const uint8_t pc = ValveDirect.read(); // DEBUG_SERIAL_PRINT_FLASHSTRING("Pos%: "); // DEBUG_SERIAL_PRINT(pc); // DEBUG_SERIAL_PRINTLN(); //#endif // // Reading shaft encoder. // // Measure motor count against (fixed) internal reference. // power_intermittent_peripherals_enable(true); // const uint16_t mc = analogueNoiseReducedRead(MOTOR_DRIVE_MC_AIN, INTERNAL); // void power_intermittent_peripherals_disable(); // DEBUG_SERIAL_PRINT_FLASHSTRING("Count input: "); // DEBUG_SERIAL_PRINT(mc); // DEBUG_SERIAL_PRINTLN(); // // Force any pending output before return / possible UART power-down. // flushSerialSCTSensitive(); // if(neededWaking) { OTV0P2BASE::powerDownSerial(); } }
// Called from loop(). void loopAlt() { // Sleep in low-power mode (waiting for interrupts) until seconds roll. // NOTE: sleep at the top of the loop to minimise timing jitter/delay from Arduino background activity after loop() returns. // DHD20130425: waking up from sleep and getting to start processing below this block may take >10ms. #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINTLN_FLASHSTRING("*E"); // End-of-cycle sleep. #endif #if defined(WAKEUP_32768HZ_XTAL) // Normal 32768Hz crystal driving main timing. powerDownSerial(); // Ensure that serial I/O is off. // Power down most stuff (except radio for hub RX). minimisePowerWithoutSleep(); // RFM22ModeStandbyAndClearState(); static uint_fast8_t TIME_LSD; // Controller's notion of seconds within major cycle. uint_fast8_t newTLSD; while(TIME_LSD == (newTLSD = getSecondsLT())) { sleepUntilInt(); // Normal long minimal-power sleep until wake-up interrupt. // DEBUG_SERIAL_PRINTLN_FLASHSTRING("w"); // Wakeup. } TIME_LSD = newTLSD; #else // Keep running on main RC clock, simulating normal-ish sleep length. delay(2000); #endif #if 0 && defined(DEBUG) DEBUG_SERIAL_PRINTLN_FLASHSTRING("*S"); // Start-of-cycle wake. #endif // START LOOP BODY // =============== DEBUG_SERIAL_PRINTLN_FLASHSTRING("*"); // const bool neededWaking = powerUpSerialIfDisabled(); // const int heat = TemperatureC16.read(); //#if 1 && defined(DEBUG) // DEBUG_SERIAL_PRINT_FLASHSTRING("temp: "); // DEBUG_SERIAL_PRINT(heat); // DEBUG_SERIAL_PRINTLN(); //#endif //#if defined(DIRECT_MOTOR_DRIVE_V1) && defined(ALT_MAIN_LOOP) && defined(DEBUG) // // Ensure that end-stop current-sense feedback is enabled before starting the motor. // cb.hitEndStop = false; // hd.enableFeedback(true, cb); // // Ensure that the motor is running... // static bool open = true; // if(open) { DEBUG_SERIAL_PRINTLN_FLASHSTRING("opening"); } else { DEBUG_SERIAL_PRINTLN_FLASHSTRING("closing"); } // hd.motorRun(open ? HardwareMotorDriverInterface::motorDriveOpening : HardwareMotorDriverInterface::motorDriveClosing); // // Try to ride through any start-up transients... // nap(WDTO_120MS); // nap(WDTO_120MS); // nap(WDTO_120MS); // nap(WDTO_120MS); // // Spin the motor for up to about 1.5s polling for end-stop hit, etc. // while(!cb.hitEndStop && (getSubCycleTime() < 0xc0)) // { // hd.enableFeedback(true, cb); // } // // Stop motor. // hd.motorRun(HardwareMotorDriverInterface::motorOff); // // Iff the end-stop was hit then reverse the motor. // if(cb.hitEndStop) // { // DEBUG_SERIAL_PRINTLN_FLASHSTRING("Hit end stop; reversing..."); // open = !open; // } //#endif // static bool boilerOut; // boilerOut = !boilerOut; // if(boilerOut) { LED_HEATCALL_ON() } else { LED_HEATCALL_OFF(); } // fastDigitalWrite(OUT_HEATCALL, boilerOut ? HIGH : LOW); //#if defined(LED_UI2_L) // if(boilerOut) { LED_UI2_OFF() } else { LED_UI2_ON(); } //#endif // uint8_t addr[8]; // // if(!MinOW.search(addr)) // { // Serial.println("No more slaves found..."); // MinOW.reset_search(); // return; // } // // // Found a device. // Serial.print("addr:"); // for(int i = 0; i < 8; ++i) // { // Serial.write(' '); // Serial.print(addr[i], HEX); // } // Serial.println(); // // if(0x28 != addr[0]) // { // Serial.println("Not a DS18B20..."); // return; // } // //#define DS1820_PRECISION_MASK 0x60 //#define DS1820_PRECISION_9 0x00 //#define DS1820_PRECISION_10 0x20 //#define DS1820_PRECISION_11 0x40 // 1/8C @ 375ms. //#define DS1820_PRECISION_12 0x60 // 1/16C @ 750ms. // //#define DS1820_PRECISION DS1820_PRECISION_11 // 1/8C @ 375ms. // // // // Force any pending output before return / possible UART power-down. // flushSerialSCTSensitive(); // if(neededWaking) { powerDownSerial(); } // // DEBUG_SERIAL_PRINTLN_FLASHSTRING("Setting precision..."); // MinOW.reset(); // // Write scratchpad/config // MinOW.select(addr); // MinOW.write(0x4e); // MinOW.write(0); // Th: not used. // MinOW.write(0); // Tl: not used. // MinOW.write(DS1820_PRECISION | 0x1f); // Config register; lsbs all 1. // // const unsigned long usStart = micros(); // // // Start a temperature reading. // MinOW.reset(); // MinOW.select(addr); // MinOW.write(0x44); // Start conversion without parasite power. // //delay(1000); // 750ms should be enough. // while(MinOW.read_bit() == 0) { /*nap(WDTO_30MS);*/ } // Poll for conversion complete (bus released)... // // // Fetch temperature (scratchpad read). // MinOW.reset(); // MinOW.select(addr); // MinOW.write(0xbe); // byte data[2]; // Read first two bytes of 9 available. // for(uint8_t i = 0; i < sizeof(data); ++i) // { // data[i] = MinOW.read(); //// Serial.print(data[i], HEX); //// Serial.print(" "); // } // Serial.println(); // MinOW.reset(); // // const unsigned long usEnd = micros(); // // Nominal loop time should be 2s x 1MHz clock, ie 2,000,000 if CPU running all the time. // // Should generally be <2000 (<0.1%) for leaf, <20000 (<1%) for hub. // const unsigned long usApparentTaken = usEnd - usStart; //#if 1 && defined(DEBUG) // DEBUG_SERIAL_PRINT_FLASHSTRING("us apparent: "); // DEBUG_SERIAL_PRINT(usApparentTaken); // DEBUG_SERIAL_PRINTLN(); //#endif // // if(neededWaking) { powerUpSerialIfDisabled(); } // // // Extract raw temperature, masking any undefined lsbits. // const int16_t rawC16 = (data[1] << 8) | (data[0] & ~1); // Serial.print("C16="); // Serial.print(rawC16); //// Serial.print(" = "); //// Serial.print(rawC16 / 16.0f); // Serial.println(); // // Force any pending output before return / possible UART power-down. // flushSerialSCTSensitive(); // // if(neededWaking) { powerDownSerial(); } }