void SleepClass::sleep(uint8_t modules,uint8_t sm){ // power_adc_disable(); cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF // ACSR = (1<<ACD); //Disable the analog comparator if(!(modules & SPI_ON)) power_spi_disable(); if(!(modules & TWI_ON)) power_twi_disable(); if(!(modules & USART0_ON)) power_usart0_disable(); if(!(modules & TIMER0_ON)) power_timer0_disable(); if(!(modules & TIMER1_ON)) power_timer1_disable(); if(!(modules & TIMER2_ON)) power_timer2_disable(); set_sleep_mode(sm); cli(); do{ sleep_enable(); #if defined __AVR_ATmega328P__ sleep_bod_disable(); #endif sei(); sleep_cpu(); // System sleeps here sleep_disable(); // System continues execution here when an interrupt woke up the divice } while(0); sei(); power_all_enable(); sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON }
void sleep_until_eswitch_pressed() { WDT_off(); ADC_off(); // make sure switch isn't currently pressed while (button_is_pressed()) {} empty_event_sequence(); // cancel pending input on suspend //PCINT_since_WDT = 0; // ensure PCINT won't ignore itself PCINT_on(); // wake on e-switch event // configure sleep mode set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_bod_disable(); sleep_cpu(); // wait here // something happened; wake up sleep_disable(); #ifdef USE_THERMAL_REGULATION // forget what the temperature was last time we were on reset_thermal_history = 1; #endif // go back to normal running mode //PCINT_on(); // should be on already // FIXME? if button is down, make sure a button press event is added to the current sequence ADC_on(); WDT_on(); }
/*! Sleep function. * * Which IO line is in use is recorded in the progs struct. * * \note Incompatible with MONOSTABLE valve. */ void go_to_sleep(uint8_t valve, struct debug_t *debug) { if (valve == BISTABLE) { set_sleep_mode(SLEEP_MODE_PWR_SAVE); /* shut down everything */ i2c_shut(); io_shut(); led_shut(); /* start sleep procedure */ sleep_enable(); sleep_bod_disable(); sleep_cpu(); sleep_disable(); /* restart everything */ led_init(); io_init(); i2c_init(); } else { set_sleep_mode(SLEEP_MODE_IDLE); /* start sleep procedure */ sleep_enable(); sleep_cpu(); sleep_disable(); } }
void sleep(void) { sleep_enable(); sleep_bod_disable(); sei(); sleep_cpu(); sleep_disable(); }
static inline void enterSleep(void) { sleep_enable(); sleep_bod_disable(); sleep_cpu(); sleep_disable(); } // End of enterSleep().
// repeatedly enter power save mode until power restored void system_sleep_loop(void) { sleep_enable(); // permit sleep mode system.status |= SYSTEM_SLEEP; // set sleep flag wdt_disable(); // disable watchdog ACSR = _BV(ACD) | _BV(ACI); // disable analog comparator and // clear analog comparator interrupt do { do { // check battery status after specified delay if(system.sleep_timer == SYSTEM_BATTERY_CHECK_DELAY) { system_check_battery(); } // disable analog comparator to save power; analog comparator // will be enabled in system_tick() or system_wake() ACSR = _BV(ACD); // wait until asynchronous updates are complete // or system might fail to wake from sleep while(ASSR & ( _BV(TCN2UB) | _BV(OCR2AUB) | _BV(OCR2BUB) | _BV(TCR2AUB) | _BV(TCR2BUB) )); if(system.status & SYSTEM_ALARM_SOUNDING) { // if the alarm buzzer is active, remain in idle mode // so buzzer continues sounding for next second set_sleep_mode(SLEEP_MODE_IDLE); } else { // otherwise, sleep with BOD disabled to save power set_sleep_mode(SLEEP_MODE_PWR_SAVE); sleep_bod_disable(); } // enter sleep mode sei(); sleep_cpu(); cli(); // analog comparator will have already been enabled // in the TIMER2_COMPB_vect interrupt (icetube.c) } while(system_power() == SYSTEM_BATTERY); // debounce power-restored signal; delay is actually 100 ms _delay_ms(25); // because system clock is divided by four } while(system_power() == SYSTEM_BATTERY); wdt_enable(WDTO_8S); wdt_reset(); // enable analog comparator interrupt ACSR = _BV(ACBG) | _BV(ACIE) | _BV(ACI); system.status &= ~SYSTEM_SLEEP; // clear sleep flag }
void hibernate(void) { set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_bod_disable(); softuart_turn_rx_off(); TIMSK = 0; sei(); // Enable global interrupts sleep_mode(); sleep_disable(); setup(); }
void go_sleep() { cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF set_sleep_mode(SLEEP_MODE_PWR_DOWN); cli(); sleep_enable(); sleep_bod_disable(); sei(); sleep_cpu(); //sleep_mode(); /* wake up here */ sleep_disable(); sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON initvars(); setup(); }
void standbyTimerDone(uint32_t avgInputVolt) { if (avgInputVolt > 768) { // high level means NO bat. loading! now we can really go to sleep // shut down everything led_fader_disable(); DIGIWRITE_L(PORTB, PIN_LED); DIGIWRITE_L(PORTB, PIN_AUDIO_TRIGGER); // stop giving signal to audio playback DIGIWRITE_L(PORTB, ACCEL_PIN_X); // prepare going to sleep GIMSK |= (1 << INT0); // enable external interrupt on PB2 // NOTE: only LOW level will wake the MCU up again! // this does not work somehow: // MCUCR |= (1 << ISC01) | (1 << ISC00); // The rising edge of INT0 generates an interrupt request. // MCUCR |= (1 << ISC00); // Any logical change on INT0 generates an interrupt request. // wdt_disable(); // go to sleep sleep_enable(); sei(); sleep_bod_disable(); sleep_cpu(); // woken up! cli(); sleep_disable(); GIMSK &= ~(1 << INT0); // disable external interrupt on PB2 // test LEDs. 2 times blinking means "woken up" blinkLED(&PORTB, PIN_LED, 50); long_delay_ms(50); blinkLED(&PORTB, PIN_LED, 50); // start LED fading again startLEDDefaultMode(); shakeEnded(); // reset states // wake up watch dog // wdt_enable(WTD_TIME); } else { standby_timer_reset(); // try it again } // standby_timer_enable(); }
// go to sleep until the MCU is reset void sleepNow(void) { // configure sleep mode and enable it set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_bod_disable(); // disable interupts cli(); // set ports to inputs and disabled pullups DDRB = 0; PORTB = 0; // sleep sleep_mode(); }
void enterSleep() { // Disabling ADC ADCSRA = 0; // Disabling all peripherals PORTB = 0; // Disable Brown out Detection sleep_bod_disable(); wdt_reset(); /* Now enter sleep mode. */ sleep_mode(); /* Re-enable the peripherals. */ power_all_enable(); }
void yackpower(byte n) /*! @brief Manages the power saving mode This is called in yackbeat intervals with either a TRUE or FALSE as parameter. Whenever the parameter is TRUE a beat counter is advanced until the timeout level is reached. When timeout is reached, the chip shuts down and will only wake up again when issued a level change interrupt on either of the input pins. When the parameter is FALSE, the counter is reset. @param n TRUE: OK to sleep, FALSE: Can not sleep now */ { static uint32_t shdntimer=0; if (n) // True = we could go to sleep { if(shdntimer++ == YACKSECS(PSTIME)) { shdntimer=0; // So we do not go to sleep right after waking up.. set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_bod_disable(); sleep_enable(); sei(); sleep_cpu(); cli(); // There is no technical reason to CLI here but it avoids hitting the ISR every time // the paddles are touched. If the remaining code needs the interrupts this is OK to remove. } } else // Passed parameter is FALSE { shdntimer=0; } }
void hwPowerDown(const uint8_t wdto) { // Let serial prints finish (debug, log etc) #ifndef MY_DISABLED_SERIAL MY_SERIALDEVICE.flush(); #endif // disable ADC for power saving ADCSRA &= ~(1 << ADEN); // save WDT settings const uint8_t WDTsave = WDTCSR; if (wdto != WDTO_SLEEP_FOREVER) { wdt_enable(wdto); // enable WDT interrupt before system reset WDTCSR |= (1 << WDCE) | (1 << WDIE); } else { // if sleeping forever, disable WDT wdt_disable(); } set_sleep_mode(SLEEP_MODE_PWR_DOWN); cli(); sleep_enable(); #if defined(__AVR_ATmega328P__) sleep_bod_disable(); #endif // Enable interrupts & sleep until WDT or ext. interrupt sei(); // Directly sleep CPU, to prevent race conditions! // Ref: chapter 7.7 of ATMega328P datasheet sleep_cpu(); sleep_disable(); // restore previous WDT settings cli(); wdt_reset(); // enable WDT changes WDTCSR |= (1 << WDCE) | (1 << WDE); // restore saved WDT settings WDTCSR = WDTsave; sei(); // enable ADC ADCSRA |= (1 << ADEN); }
// Sleep until the timer match interrupt fired. If interruptible is // true, this can return before if some other interrupt wakes us up // from sleep. If this happens, true is returned. bool SleepHandler::sleepUntilMatch(bool interruptible) { // When the timer is in asynchronous mode, it takes up to two // 32kHz clock cycles for register writes to take effect. Wait // until that's done before sleeping. while (ASSR & ASSR_BUSY_MASK) /* wait */; while (true) { #ifdef sleep_bod_disable // On 256rfr2, BOD is automatically disabled in deep sleep, but // some other MCUs need explicit disabling. This should happen shortly // before actually sleeping. It's always automatically re-enabled. sleep_bod_disable(); #endif sei(); // AVR guarantees that the instruction after sei is executed, so // there is no race condition here sleep_cpu(); // Immediately disable interrupts again, to ensure that // exactly one interrupt routine runs after wakeup, so // we prevent race conditions and can properly detect if // another interrupt than overflow occurred. cli(); if (!timer_match && interruptible) { // We were woken up, but the overflow interrupt // didn't run, so another interrupt must have // triggered. Note that if the overflow // interrupt did run, but also another (lower // priority) interrupt occured, its flag will // remain set and it will immediately wake us up // on the next sleep attempt. return false; } // See if overflow happened. Also check the TOV2 flag, // for the case where the overflow happens together with // another (higher priority) interrupt. if (timer_match || TIFR2 & (1 << TOV2)) { TIFR2 = (1 << TOV2); timer_match = false; return true; } } }
//#START_FUNCTION_HEADER////////////////////////////////////////////////////// //# //# Description: Puts the unit into sleep while enabling proper interrupts to //# exit sleep mode. In normal mode, we want to sleep in between //# data ready aquisitions to maximize power. When no motion is present, //# we only want to be woken up by BLE or movement again, not data //# ready. //# //# Parameters: still --> true = disable acc data interrupts //# false = enable acc data interrupts //# //# Returns: Nothing //# //#//END_FUNCTION_HEADER//////////////////////////////////////////////////////// void sleep_handler(bool still) { got_slp_wake = false; got_data_acc = false; got_int_ble = false; factory_sleep = false; set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); cli(); sleep_bod_disable(); enable_int(PCIE0); enable_int(PCIE1); still ? disable_int(PCIE2) : enable_int(PCIE2); //if we want to sleep in between data reads AND when no motion occurs clear_acc_ints(); sei(); sleep_cpu(); sleep_disable(); enable_int(PCIE2); }
//#START_FUNCTION_HEADER////////////////////////////////////////////////////// //# //# Description: //# Puts the sensor into factory mode. This mode //# is essentially an ultra deep sleep mode that is only brought out //# of sleep by one specific interrupt generated by the BLE unit. //# //# Parameters: None //# //# Returns: Nothing //# //#//END_FUNCTION_HEADER//////////////////////////////////////////////////////// void set_factory_mode() { got_slp_wake = false; got_data_acc = false; got_int_ble = false; factory_sleep = true; enable_int(PCIE0); disable_int(PCIE1); disable_int(PCIE2); acc1.MMA8452Standby(); acc2.MMA8452Standby(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); cli(); sleep_bod_disable(); sei(); sleep_cpu(); sleep_disable(); clear_acc_ints(); }
int main(void) { initSPI(); initNRF24L01(); //initUSART(); //Init LEDs and flash once to show script running LED_DDR|=(1 << LED_RED)|(1 << LED_GREEN); // set LED pins for output LED_DDR2|=(1 << LED_BLUE); // set blue LED pin for output flashLED(); //Flash to show initiated initADC(); ADCSRA |= (1<<ADSC); // Start conversion - didn't do earlier as not all bits set //Reduce power power_timer0_disable(); power_timer1_disable(); power_timer2_disable(); power_twi_disable(); //Sleep modes set_sleep_mode(SLEEP_MODE_ADC); sleep_enable(); sleep_bod_disable(); sleep_cpu(); sleep_mode(); //Power down nrf24 // Mainloop - use asm to stop empty infinite loop being optimised out. while(1) { asm(""); } return 0; }
void goToSleep(void) { // Delay for button debouncing - we're giving this to you _delay_ms(1000); // Set the sleep mode (could be done in the initSystem as well - only needs to be done once) set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set LED outputs to inputs DDRB &= ~_BV(RED); DDRA &= ~_BV(GREEN); DDRA &= ~_BV(BLUE); // Allow stuff to trigger sleep mode but don't go to sleep yet sleep_enable(); // Turn off brown-out detect. This means that the power is on but low, so // the light bulb turns brown. sleep_bod_disable(); // Send the sleep instruction sleep_cpu(); // Inline assembly. // When we get here we've just woken up again, so disable the ability to sleep - brown-out detect automatically comes back sleep_disable(); // Set LED pins back to ouputs DDRB |= _BV(RED); DDRA |= _BV(GREEN); DDRA |= _BV(BLUE); // Delay for a second so that you don't accidentally go to sleep _delay_ms(1000); // Make it so the button can send us back to sleep (set sleep_status to 0) sleep_status = 0; }
void habilitarWDT (void) { MCUSR = 0; // Limpa o Status Register de inicio da MCU WDTCSR = _BV (WDCE) | _BV (WDE); // Bit 4 – WDCE: Watchdog Change Enable // Bit 3 – WDE: Watchdog System Reset Enable WDTCSR = _BV (WDIE) | _BV (WDP3) | _BV (WDP0); // set WDIE, and 8 seconds delay /* Bit 6 – WDIE: Watchdog Interrupt Enable WDP[3:0]: Watchdog Timer Prescaler 3, 2, 1 and 0 0 0 0 0 2K (2048) cycles 16 ms 0 0 0 1 4K (4096) cycles 32 ms 0 0 1 0 8K (8192) cycles 64 ms 0 0 1 1 16K (16384) cycles 0.125 s 0 1 0 0 32K (32768) cycles 0.25 s 0 1 0 1 64K (65536) cycles 0.5 s 0 1 1 0 128K (131072) cycles 1.0 s 0 1 1 1 256K (262144) cycles 2.0 s 1 0 0 0 512K (524288) cycles 4.0 s 1 0 0 1 1024K (1048576) cycles 8.0 */ wdt_reset(); // Limpa o Status do WDT ADCSRA = 0; // Desabilita o ADC set_sleep_mode (SLEEP_MODE_PWR_DOWN); // Modo de Sleep como Power Down sleep_enable(); // Habilita o Sleep // turn off brown-out enable in software //MCUCR = _BV (BODS) | _BV (BODSE); //MCUCR = _BV (BODS); sleep_bod_disable(); // Faz o mesmo que as intrucoes acima sleep_cpu (); // Coloca para dormir por 8 segundos sleep_disable(); // Na volta ou ACORDADA, desabilita o sleep }
void hwPowerDown(period_t period) { // disable ADC for power saving ADCSRA &= ~(1 << ADEN); // save WDT settings uint8_t WDTsave = WDTCSR; if (period != SLEEP_FOREVER) { wdt_enable(period); // enable WDT interrupt before system reset WDTCSR |= (1 << WDCE) | (1 << WDIE); } else { // if sleeping forever, disable WDT wdt_disable(); } set_sleep_mode(SLEEP_MODE_PWR_DOWN); cli(); sleep_enable(); #if defined __AVR_ATmega328P__ sleep_bod_disable(); #endif // Enable interrupts & sleep until WDT or ext. interrupt sei(); // Directly sleep CPU, to prevent race conditions! (see chapter 7.7 of ATMega328P datasheet) sleep_cpu(); sleep_disable(); // restore previous WDT settings cli(); wdt_reset(); // enable WDT changes WDTCSR |= (1 << WDCE) | (1 << WDE); // restore saved WDT settings WDTCSR = WDTsave; sei(); // enable ADC ADCSRA |= (1 << ADEN); }
int main(void) { /* default state to conf */ snrf_state = SNRF_STATE_CONF; nrf_setup(); nrf_set_powerdown_mode(); nrf_setup_rx_irq(); uart_setup(); uart_enable_rx_int(); /* uart and pinchange int wakeup sources */ set_sleep_mode(SLEEP_MODE_IDLE); /* enable interrupts before looping */ sei(); while (1) { sleep_disable(); /* note: keep uart interrupt enabled */ /* disable pcint interrupt since we are already awake */ /* and entering the handler perturbates the execution */ nrf_disable_rx_irq(); /* alternate do_{uart,nrf} to avoid starvation */ while (1) { uint8_t is_msg = do_uart(); if (snrf_state != SNRF_STATE_CONF) is_msg |= do_nrf(); if (is_msg == 0) break ; } /* reenable pcint interrupts */ nrf_enable_rx_irq(); /* the following procedure is used to not miss interrupts */ /* disable interrupts, check if something available */ /* otherwise, enable interrupt and sleep (sei, sleep) */ /* the later ensures now interrupt is missed */ sleep_enable(); sleep_bod_disable(); cli(); if ((uart_pos == sizeof(snrf_msg_t)) || nrf_peek_rx_irq()) { /* continue, do not sleep */ sei(); } else { /* warning: keep the 2 instructions in the same block */ /* atomic, no int schedule between sei and sleep_cpu */ sei(); sleep_cpu(); } } return 0; }
void vApplicationIdleHook( void ) { // Digital Input Disable on Analogue Pins // When this bit is written logic one, the digital input buffer on the corresponding ADC pin is disabled. // The corresponding PIN Register bit will always read as zero when this bit is set. When an // analogue signal is applied to the ADC7..0 pin and the digital input from this pin is not needed, this // bit should be written logic one to reduce power consumption in the digital input buffer. #if defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) // Mega with 2560 DIDR0 = 0xFF; DIDR2 = 0xFF; #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284PA__) // Goldilocks with 1284p DIDR0 = 0xFF; #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) // assume we're using an Arduino with 328p DIDR0 = 0x3F; #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) // assume we're using an Arduino Leonardo with 32u4 DIDR0 = 0xF3; DIDR2 = 0x3F; #endif // Analogue Comparator Disable // When the ACD bit is written logic one, the power to the Analogue Comparator is switched off. // This bit can be set at any time to turn off the Analogue Comparator. // This will reduce power consumption in Active and Idle mode. // When changing the ACD bit, the Analogue Comparator Interrupt must be disabled by clearing the ACIE bit in ACSR. // Otherwise an interrupt can occur when the ACD bit is changed. ACSR &= ~_BV(ACIE); ACSR |= _BV(ACD); // There are several macros provided in this header file to actually put the device into sleep mode. // The simplest way is to optionally set the desired sleep mode using set_sleep_mode() // (it usually defaults to idle mode where the CPU is put on sleep but all peripheral clocks are still running), // and then call sleep_mode(). This macro automatically sets the sleep enable bit, // goes to sleep, and clears the sleep enable bit. // SLEEP_MODE_IDLE (0) // SLEEP_MODE_ADC _BV(SM0) // SLEEP_MODE_PWR_DOWN _BV(SM1) // SLEEP_MODE_PWR_SAVE (_BV(SM0) | _BV(SM1)) // SLEEP_MODE_STANDBY (_BV(SM1) | _BV(SM2)) // SLEEP_MODE_EXT_STANDBY (_BV(SM0) | _BV(SM1) | _BV(SM2)) set_sleep_mode( SLEEP_MODE_IDLE ); portENTER_CRITICAL(); sleep_enable(); #if defined(BODS) && defined(BODSE) // only if there is support to disable the BOD. sleep_bod_disable(); #endif portEXIT_CRITICAL(); sleep_cpu(); // good night. sleep_reset(); // reset the sleep_mode() faster than sleep_disable(); }
void pwrmgr_update() { bool idle = false; LOOPR(PWR_ACTIVE_COUNT, i) { if(active[i] == PWR_STATE_BSY) // Something busy, no sleep stuff return; else if(active[i] == PWR_STATE_IDLE) idle = true; } bool buttonsActive = buttons_isActive(); if(idle || buttonsActive) { if(systemState == SYS_CRTANIM && buttonsActive) // Cancel CRT anim if a button is pressed { display_startCRTAnim(DISPLAY_CRTANIM_OPEN); systemState = SYS_AWAKE; } else // Idle sleep mode { debugPin_sleepIdle(HIGH); sleep_mode(); debugPin_sleepIdle(LOW); } } else { if(systemState == SYS_AWAKE) // Begin CRT anim { systemState = SYS_CRTANIM; display_startCRTAnim(DISPLAY_CRTANIM_CLOSE); } else if(systemState == SYS_CRTANIM) { // Shutdown if(userState == USER_ACTIVE) userSleep(); systemState = SYS_SLEEP; set_sleep_mode(SLEEP_MODE_PWR_DOWN); time_sleep(); debugPin_sleepPowerDown(HIGH); // need to make sure no interrupts fired here! cli(); sleep_enable(); sleep_bod_disable(); sei(); sleep_cpu(); sleep_disable(); debugPin_sleepPowerDown(LOW); systemState = SYS_AWAKE; if(time_wake() != RTCWAKE_SYSTEM) // Woken by button press, USB plugged in or by RTC user alarm userWake(); set_sleep_mode(SLEEP_MODE_IDLE); } } }
int main(void) { char buf[7]; // antes apenas 7 era o suficiente uint8_t contador; uint8_t ciclosWDTSono, min5s300; iniciaPORTAS(); PORTD |= (1<<PD7); // liga MOSFET _delay_ms(20); // espera 20ms para energizar os circuitos // MCUSR – MCU Status Register // The MCU Status Register provides information on which reset source caused an MCU reset. printString("MCU Status Register:"); printHexByte( ((MCUSR | WDRF) &0b1000 >> 3) ); printString(","); printHexByte( ((MCUSR | BORF) &0b0100 >> 2) ); printString(","); printHexByte( ((MCUSR | EXTRF) &0b0010 >> 1) ); printString(","); printHexByte( ((MCUSR | PORF) &0b0001 ) ); printString("\r\nProj 07B v1.1b PSW (sem RTC)"); //WDTCSR – Watchdog Timer Control Register /* When the Brown-out Detector (BOD) is enabled by BODLEVEL fuses, Table 28-6 on page 293, the BOD is actively monitoring the power supply voltage during a sleep period. To save power, it is possible to disable the BOD by software for some of the sleep modes, see Table 10-1 on page 40. The sleep mode power consumption will then be at the same level as when BOD is globally disabled by fuses. If BOD is disabled in software, the BOD function is turned off immediately after entering the sleep mode. Upon wake-up from sleep, BOD is automatically enabled again. This ensures safe operation in case the VCC level has dropped during the sleep period. When the BOD has been disabled,the wake-up time from sleep mode will be approximately 60 µs to ensure that the BOD is working correctly before the MCU continues executing code. BOD disable is controlled by bit 6, BODS (BOD Sleep) in the control register MCUCR, see ”MCUCR – MCU Control Register” on page 45. Writing this bit to one turns off the BOD in relevant sleep modes, while a zero in this bit keeps BOD active. Default setting keeps BOD active, i.e. BODS set to zero. */ //sleep_bod_disable(); /* faz o mesmo que abaixo */ //MCUCR |= (1<<BODS) | (1<<BODSE); // desabilita o BOD para o sleep mode //MCUCR |= (1<<BODS); // desabilita o BOD //MCUCR &= ~(1<<BODSE); // //SMCR |= (1<<SE); // Sleep Enable //SMCR |= (1<<SM2) | (1<<SM1) | (1<<SM0); // IDLE //power_tx_modulator_enable(); // disable ADC //ADCSRA = 0; // With that there the power consumption drops a large amount, down from 335 µA to 0.355 µA! (that is, 355 nA) /* 20.7.3 Receive Compete Flag and Interrupt The USART Receiver has one flag that indicates the Receiver state. The Receive Complete (RXCn) Flag indicates if there are unread data present in the receive buffer. This flag is one when unread data exist in the receive buffer, and zero when the receive buffer is empty (i.e., does not contain any unread data). If the Receiver is disabled (RXENn = 0), the receive buffer will be flushed and consequently the RXCn bit will become zero. When the Receive Complete Interrupt Enable (RXCIEn) in UCSRnB is set, the USART Receive Complete interrupt will be executed as long as the RXCn Flag is set (provided thatglobal interrupts are enabled). When interrupt-driven data reception is used, the receive complete routine must read the received data from UDRn in order to clear the RXCn Flag, otherwise a new interrupt will occur once the interrupt routine terminates. */ UCSR0B |= (1<<RXCIE0); // Habilita a Interrupcao de RX no controle da USART sei(); _delay_ms(10000); printString("\r\nLoop Sleep Indefinido - RXINT.\r\n"); while(1) { cli(); for (contador=0;contador<3;contador++) { getEnv(); _delay_ms(3333); } if(MODO=='0') // o MODO 0 caracteriza-se por dormir indefinidamente // ate que uma interrupcao na USART acorde o MCU { set_sleep_mode(SLEEP_MODE_IDLE); // configura o MODO de sleep sei(); // habilita todos interrupts liga_mcp23008(); seqLed_mcp23008(); //printString("Habilitando Sleep.\r\n"); sleep_enable(); // habilita a dormirda power_adc_disable(); power_spi_disable(); power_timer0_disable(); power_timer1_disable(); power_timer2_disable(); power_twi_disable(); sleep_bod_disable(); // desliga o comparador de voltagem do BOD PORTD &= ~(1<<PD7); // desliga MOSFET printString("dormindo..."); sleep_mode(); // realmente coloca para dormir /*--------------------------------------------------------------*/ printString("...Acordou!\r\n"); sleep_disable(); PORTD |= (1<<PD7); // liga MOSFET _delay_ms(20); // espera 20ms para energizar os circuitos power_all_enable(); } else { printString("\r\nLoop Sono de 1h/5m (64s/64s).\r\n_"); // Marca ZERO ciclos de Sleep com WDT ciclosWDTSono=0; min5s300=0; // contador multiplo de 5 minutos (ou 300 seg) while ( (MODO=='1') | (MODO=='2') ) // o Modo 1 eh o Sleep com WDT de no maximo 1h // o Modo 2 eh o Sleep com WDT sem hora para realmente acordar { //UCSR0B &= ~(1<<RXCIE0); // Deabilita a Interrupcao de RX no controle da USART sei(); // Habilita interrupcoes, por causa do WDT PORTD &= ~(1<<PD7); // desliga MOSFET habilitarWDT(); // coloca a CPU para dormir em SLEEP_MODE_PWR_DOWN // sendo acordada 8 segundos depois pelo WDT ciclosWDTSono++; // computa mais um ciclo de WDT de 8 segundos if (ciclosWDTSono >= 37) // ciclos de sleep+WDT forem maiores que 37 (8s*37 = 300s = 5min ) { ciclosWDTSono=0; // zera o contador de ciclos a cada "minuto" (ou mais segundos) de sono min5s300++; // incrementa o contador de 5 minutos PORTD |= (1<<PD7); // liga MOSFET _delay_ms(20); // espera 20ms para energizar os circuitos liga_mcp23008(); seqLed_mcp23008(); //////////////////////////////////////////////////// printString( itoa(( min5s300 * 5) ,buf,10) ); printString("min _ \r\n"); getEnv(); _delay_ms(2000); //////////////////////////////////////////////////// if ( (min5s300 == 12) & (MODO=='1')) // testa se ja faz 1 hora que dormi { MODO='0'; // forcar para sair do MODO 1 (WDT) e voltar para o MODO 0 (USART RX INT) printString("Saindo do Modo Sono de 1 hora.\r\n_"); } //////////////////////////////////////////////////// _delay_ms(2000); } } } } }
void BeanClass::sleep(uint32_t duration_ms){ // ensure that our interrupt line is an input DDRD &= ~(_BV(3)); // There's no point in sleeping if the duration is <= 10ms if ( duration_ms < MIN_SLEEP_TIME ) { delay( duration_ms ); return; } // poll and wait for interrupt line to go HIGH (sleep) // attempt sleep, if it fails, waited a total of 10ms bool sleeping = false; sleeping = attemptSleep( duration_ms ); if ( !sleeping && duration_ms > MAX_DELAY ) { // keep trying until the end of delay period while( duration_ms > 0 && false == sleeping ) { duration_ms = ( duration_ms >= MAX_SLEEP_POLL ) ? duration_ms - MAX_SLEEP_POLL : 0; sleeping = attemptSleep( duration_ms ); } } else if ( !sleeping && duration_ms > MAX_SLEEP_POLL ) { // take out the time we've already delayed delay( duration_ms - MAX_SLEEP_POLL ); sleeping = false; } // if we never slept, don't set interrupts if ( sleeping == false ) { return; } // set our interrupt pin to input: const int interruptNum = 1; bool adc_was_set = bit_is_set(ADCSRA, ADEN); if(adc_was_set){ // disable ADC ADCSRA &= ~(_BV(ADEN)); } bool ac_was_set = bit_is_set(ACSR, ACD); if(ac_was_set){ // disable ADC ACSR &= ~(_BV(ACD)); } // Details on how to manage sleep mode with AVR gotten from the avr-libc // manual, found here: http://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html // (block quote below) // Note that unless your purpose is to completely lock the CPU (until a // hardware reset), interrupts need to be enabled before going to sleep. // As the sleep_mode() macro might cause race conditions in some situations, // the individual steps of manipulating the sleep enable (SE) bit, and // actually issuing the SLEEP instruction, are provided in the macros // sleep_enable(), sleep_disable(), and sleep_cpu(). This also allows for // test-and-sleep scenarios that take care of not missing the interrupt // that will awake the device from sleep. // Example: // #include <avr/interrupt.h> // #include <avr/sleep.h> // ... // set_sleep_mode(<mode>); // cli(); // if (some_condition) // { // sleep_enable(); // sei(); // sleep_cpu(); // sleep_disable(); // } // sei(); // This sequence ensures an atomic test of some_condition with interrupts // being disabled. If the condition is met, sleep mode will be prepared, // and the SLEEP instruction will be scheduled immediately after an SEI // instruction. As the intruction right after the SEI is guaranteed to be // executed before an interrupt could trigger, it is sure the device will // really be put to sleep. // Some devices have the ability to disable the Brown Out Detector (BOD) // before going to sleep. This will also reduce power while sleeping. // If the specific AVR device has this ability then an additional macro // is defined: sleep_bod_disable(). This macro generates inlined assembly // code that will correctly implement the timed sequence for disabling the // BOD before sleeping. However, there is a limited number of cycles after // the BOD has been disabled that the device can be put into sleep mode, // otherwise the BOD will not truly be disabled. Recommended practice is // to disable the BOD (sleep_bod_disable()), set the interrupts (sei()), // and then put the device to sleep (sleep_cpu()), like so: // #include <avr/interrupt.h> // #include <avr/sleep.h> // ... // set_sleep_mode(<mode>); // cli(); // if (some_condition) // { // sleep_enable(); // sleep_bod_disable(); // sei(); // sleep_cpu(); // sleep_disable(); // } // sei(); /* In the function call attachInterrupt(A, B, C) * A can be either 0 or 1 for interrupts on pin 2 or 3. * * B Name of a function you want to execute at interrupt for A. * * C Trigger mode of the interrupt pin. can be: * LOW a low level triggers * CHANGE a change in level triggers * RISING a rising edge of a level triggers * FALLING a falling edge of a level triggers * * In all but the IDLE sleep modes only LOW can be used. */ attachInterrupt(interruptNum,wakeUp, LOW); set_sleep_mode(SLEEP_MODE_PWR_DOWN); cli(); if (bit_is_set(PIND, 3)) { sleep_enable(); sleep_bod_disable(); sei(); sleep_cpu(); sleep_disable(); } sei(); detachInterrupt(interruptNum); if(adc_was_set){ //re-enable adc ADCSRA |= _BV(ADEN); } if(ac_was_set){ //re-enable analog compareter ACSR |= _BV(ACD); } }
int main(void) { //disable interrupts before setup cli(); //############## begin setup ############## if(MCUSR & (1<<WDRF)){ // If a reset was caused by the Watchdog Timer.. // (highly unlikely, but just in case) MCUSR &= ~(1<<WDRF); // Clear the WDT reset flag WDTCR |= (1<<WDCE) | (1<<WDE); // Enable the WD Change Bit WDTCR = 0x00; // Disable the WDT } //setup the WDT properly now WDTCR |= (1<<WDCE) | (1<<WDE); // Enable the WDT Change Bit WDTCR = (1<<WDTIE) | //Enable WDT Interrupt //(1<<WDP1) | (1<<WDP2); // Set Timeout to ~1s (1<<WDP1)|(1<<WDP0); //.125s (8x, for debug) //0; //speed up 64x for debug //set i/o pin modes DDRB |= (1<<POT_ENABLE_PIN) | (1<<BUZZ_PIN) | (1<<SHIFT_PIN); //out DDRB &= ~(1<<POT_PIN) & ~(1<<BTN_PIN); //in PORTB |= (1<<BTN_PIN); //enable the internal pullup for the button //setup the timer timsetup(); //setup the ADC adcsetup(); //enable the INT0 interrupt for button capture EIMSK |= (1<<INT0); //enable MCUCR &= ~((1<<ISC01)|(1<<ISC00)); //set INT0 mode to level-triggered //setup sleep //we want the deepest (powerdown) sleep mode set_sleep_mode(SLEEP_MODE_PWR_DOWN); //init globals delay_ctr = 0; buzz_pattern = 0; //########## setup complete; re-enable interrupts ########## sei(); //do the sleepyloop while(1) { if ( //sleep-allowed conditions (all at once): !(ADCSRA & (1<<ADSC)) // ADC not currently converting && MCUCR & (1<<SE) // sleep-enable bit is set (=WDT routine finished) && !buzz_pattern // buzzed everything already && PORTB & (1<<BTN_PIN) // button is not pressed ){ cli(); //turn everything off, to be sure PORTB &= ~( (1<<BUZZ_PIN) | (1<<POT_ENABLE_PIN) ) ; // Disable BOD sleep_bod_disable(); sei(); //set INT0 mode to level-triggered //(otherwise it couldn't wake the MCU) MCUCR &= ~((1<<ISC01)|(1<<ISC00)); // Go to Sleep sleep_cpu(); } } }
int main(void){ // PA0 - ADC IN // PA2 - RED // PA3 - GREEN // PA4 - BLUE // PA7(OC0B) - PWM output. // PB0 - out (EN) // PB1 - hall1, PB2 - hall2 DDRA = 0b11111110; PORTA = 0b00000000; DDRB = 0b0001; PORTB = 0b0110; TCCR0A = (1 << COM0B1) | (1 << WGM00);// | (1 << WGM01); // PWM mode TCCR0B = (1 << CS01); // clock source = CLK/8, start PWM PCMSK1 = (1<<PCINT9) | (1<<PCINT10); GIMSK = (1<<PCIE1);//interrupt on pin change0 ADMUX = 0b10000000; // ADC0 - int apply_led(1); DRIVER_ON; OCR0B = 8; _delay_ms(500); all_off(); eeprom_read_block(&seconds_on, &nv_seconds_on, sizeof(seconds_on)); eeprom_read_block(×_on, &nv_times_on, sizeof(times_on) ); eeprom_read_block(&max_on, &nv_max_on, sizeof(max_on) ); prev_power_mode = MODE_OFF; sei(); while(1){ // ADC8 = 330 - ~70 degrees Celcium // 9V = 714 // 10V = 793 // 11V = 872 // 12V = 951 // 12.6V = 999 if(power_mode==MODE_OFF && unlock_stage==0){ seconds = 0; d_seconds = 0; stop_timer(); disable_adc(); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_bod_disable(); sleep_cpu(); sleep_disable(); } if(seconds>1 && power_mode==MODE_OFF){ all_off(); } if(unlock_stage==0 && power_mode!=MODE_OFF){ if(d_seconds==0){ adc_channel = 0; ADMUX = 0b10000000; // ADC0 - int } if(d_seconds==5){ adc_channel = 1; ADMUX = 0b10100010; // int reference and temp sensor } if(seconds%2==0){ if(power_mode==MODE_LOW_VOLTAGE){ RED_ON;GREEN_OFF;BLUE_OFF; } if(power_mode==MODE_OVERTEMP){ RED_ON;GREEN_ON;BLUE_OFF; } }else{ if(power_mode==MODE_OVERTEMP||power_mode==MODE_LOW_VOLTAGE){ apply_led(0); } } // if((seconds%5==0) && ADMUX == 0b10000000){ //measure voltage in active mode if(adc_channel ==0 && d_seconds == 4){ //measure voltage in active mode if(val<LIMIT_9V){ if(check_and_set_times(0)){ all_off();//completely discharged. turning off } } else if(power_mode!=MODE_OVERTEMP && power_mode!=MODE_LOW_VOLTAGE && power_mode>=MODE_IDLE){ //show voltage always, except overtemp if(val<((LIMIT_9V+LIMIT_10V)/2)){ if(power_mode>=MODE_LOW && check_and_set_times(1)){ // усвловие нужно, чтобы не задалбывать функцию - в ней будут логи apply_led(0); power_mode = MODE_LOW_VOLTAGE;//low voltage apply_power(); } }else if(val<LIMIT_10V){ if(led_selected==0 || check_and_set_times(2) ){ apply_led(1); } led_selected = 1; }else if(val<LIMIT_11V){ if(led_selected==0 || check_and_set_times(3)){ apply_led(2); } led_selected = 2; }else{ if(led_selected==0 || check_and_set_times(4)){ apply_led(3); } led_selected = 3; } } } while(d_seconds==4){} if(adc_channel ==1 && d_seconds == 8){ //measure temp in active mode if(val>330 && power_mode>=MODE_LOW && check_and_set_times(5)){// усвловие нужно, чтобы не задалбывать функцию - в ней будут логи power_mode = MODE_OVERTEMP; apply_power(); //overtemp. reduce current cunsumption } } while(d_seconds==8){} if(power_mode==MODE_IDLE && seconds>=7200){ //выключение через два часа из режима простоя all_off(); } // if(seconds==0 && d_seconds<5 && power_mode>=MODE_LOW){ // GIMSK = 0;//вырубим прерывания на первые 500мс, чтобы не кнопать кнопкой сильно часто // }else{ // GIMSK = (1<<PCIE1);//interrupt on pin change0 // } } } }
int main() { if (_is_docked()){ for(int j=0;(j<10);j++) for(int i=0;(i<200);i++) _delay_ms(5); } scounter=0; //Initialized data buffer dataIndex=0; dataSubindex=0; // Blink green for 5 seconds _wocket_initialize(); AC_NUMS=_SAMPLING_RATE *60; power_adc_disable(); power_spi_disable(); power_timer0_disable(); power_timer1_disable(); power_twi_disable(); while(1){ //Sample only in the main loop because of p if(sampleFlag){ power_adc_enable(); _atmega_adc_turn_on(); sampleFlag=0; #ifdef _VERSION ==3 x=_atmega_a2dConvert10bit(ADC0); y=_atmega_a2dConvert10bit(ADC1); z=_atmega_a2dConvert10bit(ADC2); //x=y=z=cc++; //if (cc>=1024) // cc=0; vmag+=Filter(x,0)+Filter(y,1)+Filter(z,2); if (_wPC>40){ //Skip the first samples if (summary_count==0) { vmag=vmag/24; if (vmag>65535) acount[ci]=65535; else acount[ci]=(unsigned short) vmag; vmag=0; ++ci; if (ci==AC_BUFFER_SIZE) ci=0; cseq++; if (ci==si) { si++; if (si==AC_BUFFER_SIZE) si=0; sseq++; } acount[ci]=0; summary_count=AC_NUMS; }else summary_count--; } else if (_wPC==40) vmag=0; #else //x=_atmega_a2dConvert10bit(ADC3); //y=_atmega_a2dConvert10bit(ADC2); //z=_atmega_a2dConvert10bit(ADC1); #endif m_SET_X(data[dataIndex],x,dataSubindex); m_SET_Y(data[dataIndex],y,dataSubindex); m_SET_Z(data[dataIndex],z,dataSubindex); dataSubindex++; if (dataSubindex>=4) dataSubindex=0; //Most of the time the data buffer with 750 will not overflow //and will be enough to transmit the data, data will go from 0 up to a specific //value if (_wTM==_TM_Continuous) { switch(dataSubindex){ case 1: m_GET_X(x,data[dataIndex].byte1,data[dataIndex].byte2,0); m_GET_Y(y,data[dataIndex].byte2,data[dataIndex].byte3,0); m_GET_Z(z,data[dataIndex].byte3,data[dataIndex].byte4,0); break; case 2: m_GET_X(x,data[dataIndex].byte4,data[dataIndex].byte5,1); m_GET_Y(y,data[dataIndex].byte6,data[dataIndex].byte7,1); m_GET_Z(z,data[dataIndex].byte7,data[dataIndex].byte8,1); break; case 3: m_GET_X(x,data[dataIndex].byte8,data[dataIndex].byte9,2); m_GET_Y(y,data[dataIndex].byte9,data[dataIndex].byte10,2); m_GET_Z(z,data[dataIndex].byte11,data[dataIndex].byte12,2); break; case 0: m_GET_X(x,data[dataIndex].byte12,data[dataIndex].byte13,3); m_GET_Y(y,data[dataIndex].byte13,data[dataIndex].byte14,3); m_GET_Z(z,data[dataIndex].byte14,data[dataIndex].byte15,3); break; } if (justconnected==1) { _send_tm(); justconnected=2; } //_send_pdu(x,y,z); _send_uncompressed_pdu(x, y, z); //Send summary activity count /* for (int i=0;(i<summaryindex);i++){ _send_summary_count(acount[i]); acount[i]=0; } if (summaryindex<AC_BUFFER_SIZE){ acount[0]=acount[summaryindex]; summaryindex=0; }*/ } else { if ((dataSubindex==0) && (batch_counter<750)) batch_counter++; if (connected){ _greenled_turn_on(); gotack=1; tester=0; if (_wTM==_TM_Continuous) continue; for (int ixz=0;(ixz<100);ixz++) { _bluetooth_transmit_uart0_byte(0xff); if (sampleFlag) { sampleFlag=0; x=_atmega_a2dConvert10bit(ADC0); y=_atmega_a2dConvert10bit(ADC1); z=_atmega_a2dConvert10bit(ADC2); vmag+=Filter(x,0)+Filter(y,1)+Filter(z,2); if (_wPC>40){ //Skip the first samples if (summary_count==0) { vmag=vmag/24; if (vmag>65535) acount[ci]=65535; else acount[ci]=(unsigned short) vmag; vmag=0; ++ci; if (ci==AC_BUFFER_SIZE) ci=0; cseq++; if (ci==si) { si++; if (si==AC_BUFFER_SIZE) si=0; sseq++; } acount[ci]=0; summary_count=AC_NUMS; }else summary_count--; } else if (_wPC==40) vmag=0; m_SET_X(data[dataIndex],x,dataSubindex); m_SET_Y(data[dataIndex],y,dataSubindex); m_SET_Z(data[dataIndex],z,dataSubindex); dataSubindex++; if (dataSubindex>=4) dataSubindex=0; } } _send_fv(); _send_sr(); _send_tm(); _send_batch_count((batch_counter-1)*4); _send_acs(); //Send summary activity count /*for (int i=0;(i<summaryindex);i++){ _send_summary_count(acount[i]); acount[i]=0; } if (summaryindex<AC_BUFFER_SIZE){ acount[0]=acount[summaryindex]; summaryindex=0; }*/ if ((batch_counter>0) && (batch_counter<750)) // Go from 0 up to batch_counter { for (int i=0;(i<(batch_counter-1));i++) { m_GET_X(x,data[i].byte1,data[i].byte2,0); m_GET_Y(y,data[i].byte2,data[i].byte3,0); m_GET_Z(z,data[i].byte3,data[i].byte4,0); //_send_uncompressed_pdu(x, y, z); _send_pdu(x,y,z); m_GET_X(x,data[i].byte4,data[i].byte5,1); m_GET_Y(y,data[i].byte6,data[i].byte7,1); m_GET_Z(z,data[i].byte7,data[i].byte8,1); //_send_uncompressed_pdu(x,y, z); _send_pdu(x,y,z); m_GET_X(x,data[i].byte8,data[i].byte9,2); m_GET_Y(y,data[i].byte9,data[i].byte10,2); m_GET_Z(z,data[i].byte11,data[i].byte12,2); //_send_uncompressed_pdu(x, y, z); _send_pdu(x,y,z); m_GET_X(x,data[i].byte12,data[i].byte13,3); m_GET_Y(y,data[i].byte13,data[i].byte14,3); m_GET_Z(z,data[i].byte14,data[i].byte15,3); //_send_uncompressed_pdu(x, y, z); _send_pdu(x,y,z); _receive_data(); if (sampleFlag) { sampleFlag=0; x=_atmega_a2dConvert10bit(ADC0); y=_atmega_a2dConvert10bit(ADC1); z=_atmega_a2dConvert10bit(ADC2); vmag+=Filter(x,0)+Filter(y,1)+Filter(z,2); if (_wPC>40){ //Skip the first samples if (summary_count==0) { vmag=vmag/24; if (vmag>65535) acount[ci]=65535; else acount[ci]=(unsigned short) vmag; vmag=0; ++ci; if (ci==AC_BUFFER_SIZE) ci=0; cseq++; if (ci==si) { si++; if (si==AC_BUFFER_SIZE) si=0; sseq++; } acount[ci]=0; summary_count=AC_NUMS; }else summary_count--; } else if (_wPC==40) vmag=0; m_SET_X(data[dataIndex],x,dataSubindex); m_SET_Y(data[dataIndex],y,dataSubindex); m_SET_Z(data[dataIndex],z,dataSubindex); dataSubindex++; if (dataSubindex>=4) dataSubindex=0; } } if (batch_counter>0){ //copy end item into start data[0].byte1=data[batch_counter].byte1; data[0].byte2=data[batch_counter].byte2; data[0].byte3=data[batch_counter].byte3; data[0].byte4=data[batch_counter].byte4; data[0].byte5=data[batch_counter].byte5; data[0].byte6=data[batch_counter].byte6; data[0].byte7=data[batch_counter].byte7; data[0].byte8=data[batch_counter].byte8; data[0].byte9=data[batch_counter].byte9; data[0].byte10=data[batch_counter].byte10; data[0].byte11=data[batch_counter].byte11; data[0].byte12=data[batch_counter].byte12; data[0].byte13=data[batch_counter].byte13; data[0].byte14=data[batch_counter].byte14; data[0].byte15=data[batch_counter].byte15; } }else{ int current=dataIndex+1; int end =dataIndex; if (current>=750) current=0; while(current!=end) { m_GET_X(x,data[current].byte1,data[current].byte2,0); m_GET_Y(y,data[current].byte2,data[current].byte3,0); m_GET_Z(z,data[current].byte3,data[current].byte4,0); //_send_uncompressed_pdu(x, y, z); _send_pdu(x,y,z); m_GET_X(x,data[current].byte4,data[current].byte5,1); m_GET_Y(y,data[current].byte6,data[current].byte7,1); m_GET_Z(z,data[current].byte7,data[current].byte8,1); //_send_uncompressed_pdu(x, y, z); _send_pdu(x,y,z); m_GET_X(x,data[current].byte8,data[current].byte9,2); m_GET_Y(y,data[current].byte9,data[current].byte10,2); m_GET_Z(z,data[current].byte11,data[current].byte12,2); //_send_uncompressed_pdu(x, y, z); _send_pdu(x,y,z); m_GET_X(x,data[current].byte12,data[current].byte13,3); m_GET_Y(y,data[current].byte13,data[current].byte14,3); m_GET_Z(z,data[current].byte14,data[current].byte15,3); //_send_uncompressed_pdu(x,y, z); _send_pdu(x,y,z); current++; if (current==750) current=0; _receive_data(); if (sampleFlag) { sampleFlag=0; x=_atmega_a2dConvert10bit(ADC0); y=_atmega_a2dConvert10bit(ADC1); z=_atmega_a2dConvert10bit(ADC2); vmag+=Filter(x,0)+Filter(y,1)+Filter(z,2); if (_wPC>40){ //Skip the first samples if (summary_count==0) { vmag=vmag/24; if (vmag>65535) acount[ci]=65535; else acount[ci]=(unsigned short) vmag; vmag=0; ++ci; if (ci==AC_BUFFER_SIZE) ci=0; cseq++; if (ci==si) { si++; if (si==AC_BUFFER_SIZE) si=0; sseq++; } acount[ci]=0; summary_count=AC_NUMS; }else summary_count--; } else if (_wPC==40) vmag=0; m_SET_X(data[dataIndex],x,dataSubindex); m_SET_Y(data[dataIndex],y,dataSubindex); m_SET_Z(data[dataIndex],z,dataSubindex); dataSubindex++; if (dataSubindex>=4) dataSubindex=0; } } //copy end item into start data[0].byte1=data[end].byte1; data[0].byte2=data[end].byte2; data[0].byte3=data[end].byte3; data[0].byte4=data[end].byte4; data[0].byte5=data[end].byte5; data[0].byte6=data[end].byte6; data[0].byte7=data[end].byte7; data[0].byte8=data[end].byte8; data[0].byte9=data[end].byte9; data[0].byte10=data[end].byte10; data[0].byte11=data[end].byte11; data[0].byte12=data[end].byte12; data[0].byte13=data[end].byte13; data[0].byte14=data[end].byte14; data[0].byte15=data[end].byte15; } batch_counter=0; dataIndex=0; seconds_passed=0; while (seconds_passed<400) { _delay_ms(5); seconds_passed++; _receive_data(); if (sampleFlag) { sampleFlag=0; x=_atmega_a2dConvert10bit(ADC0); y=_atmega_a2dConvert10bit(ADC1); z=_atmega_a2dConvert10bit(ADC2); vmag+=Filter(x,0)+Filter(y,1)+Filter(z,2); if (_wPC>40){ //Skip the first samples if (summary_count==0) { vmag=vmag/24; if (vmag>65535) acount[ci]=65535; else acount[ci]=(unsigned short) vmag; vmag=0; ++ci; if (ci==AC_BUFFER_SIZE) ci=0; cseq++; if (ci==si) { si++; if (si==AC_BUFFER_SIZE) si=0; sseq++; } acount[ci]=0; summary_count=AC_NUMS; }else summary_count--; } else if (_wPC==40) vmag=0; m_SET_X(data[dataIndex],x,dataSubindex); m_SET_Y(data[dataIndex],y,dataSubindex); m_SET_Z(data[dataIndex],z,dataSubindex); dataSubindex++; if (dataSubindex>=4) dataSubindex=0; } } //connected=0; //Don't turn off the radio if a request to switch mode has been received if (_wTM==_TM_Continuous) _bluetooth_turn_on(); else _bluetooth_turn_off(); command_counter=0; seconds_disconnected=0; _greenled_turn_off(); } } _atmega_adc_turn_off(); power_adc_disable(); if ((dataSubindex==0) && (!connected)) dataIndex++; if (dataIndex==750) dataIndex=0; connected=0; } cli(); set_sleep_mode(SLEEP_MODE_IDLE); //set_sleep_mode(SLEEP_MODE_PWR_SAVE); sleep_enable(); sleep_bod_disable(); sei(); sleep_cpu(); sleep_disable(); } return 0; }