// 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(); }
// 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(); } }