void goto_sleep(void) { // Disable the watchdog timer's interrupt vector, WDIE // On the Arduino (ATmega328p at least), it suffices to // just set WDTCSR = 0. So what follows may be overkill // on some AVRs asm("cli"); asm("wdr"); // Make sure that the watchdog interrupt is not renewed by the // watchdog interrupt sleeping = 1; MCUSR = 0; WDTCSR |= (1 << WDCE) | (1 << WDE); WDTCSR = 0; // Again, enable the pull up resistor on the input port BUTTON_PORT = (1 << BUTTON_BIT); // Shut down the LEDs leds_on = 0; old_leds_on = 0; LED_PORT &= ~(LED_1 | LED_2 | LED_3 | LED_4 | LED_5 | LED_6 | LED_7); // Set the sleep mode set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Use INT0 and run the INT0 interrupt routine when pin 2 goes LOW // When the external interrupt INT0 is enabled, we will // trigger when the pin goes to a logical low INTERRUPT_CONT &= ~((1 << ISC00) | (1 <<ISC01)); INTERRUPT_MASK = (1 << INT0); // Enable the sleep bit in MCUCR register sleep_enable(); // And now go to sleep asm("sei"); sleep_mode(); // We will resume here when awoken... // Disable sleep... sleep_disable(); // Disable INT0 thus preventing the INT0 interrupt from being // executed during normal operation INTERRUPT_MASK &= ~(1 << INT0); // Allow the watchdog interrupt to renew itself sleeping = 0; // Re-enable the watchdog timer's interrupt vector // The following is overkill on some AVRs. For instance, on the // ATmege328p, just doing "WDTCSR = 1 << WDIE" is sufficient. WDTCSR = (1 << WDCE) | (1 << WDE); WDTCSR = (1 << WDE) | (1 << WDIE); // Run throught the LED test led_test(); }
int main(void) { uint16_t adcPVoltages[BUFSIZE] = {0UL}; uint16_t adcNVoltages[BUFSIZE] = {0UL}; uint16_t adcCurrents[BUFSIZE] = {0UL}; uint16_t adcGNDs[BUFSIZE] = {0UL}; uint16_t adcValue; int16_t gndValue; int16_t mVoltage, mCurrent; uint8_t idx; float fv, fa; // ポートの初期化 DDRD = _BV(2); // RSTピンを出力に PORTC = _BV(4) | _BV(5); // SCL, SDA内蔵プルアップを有効 // デバイスの初期化 i2c_init(); // AVR内蔵I2Cモジュールの初期化 wait_ms(500); PORTD &= ~_BV(2); // RSTをLにします。リセット wait_ms(1); PORTD |= _BV(2); // RSTをHにします。リセット解除 wait_ms(10); lcdInit(); //LCD初期表示 lcdSetPos(0, 0); lcdPutStr("Volt + / Current"); lcdSetPos(0, 1); lcdPutStr("Volt - / GND"); wait_sec(3); //消費電力削減のためADC使用ピンをデジタル入力禁止にする(ADC入力(アナログ)専用となる) DIDR0 |= (1 << ADC0D) | (1 << ADC1D) | (1 << ADC2D) | (1 << ADC3D); //PC0,PC1,PC2,PC3 //ADC動作設定 ADCSRA = 0b10000110 //bit2-0: 110 = 64分周 8MHz/64=125kHz (50k〜200kHzであること) | (1 << ADIE); //割り込み許可(スリープ対応) //ADCの基準電圧(AVCC)と入力ピンを設定する ADMUX = (1 << REFS0) | ADC_SET_PVOLTAGE; //A/D変換ノイズ低減のスリープモードを設定する set_sleep_mode(SLEEP_MODE_ADC); sei(); //割り込み許可 sleep_mode(); //A/Dコンバータ初期化として初回変換開始…変換中…変換完了 adcValue = ADC; //値の読み捨て idx = 0; while(1) { //===== GND電圧を測定する =================================================== // ADMUX = ADC_SET_GND; wait_ms(10); //安定待ち sleep_mode(); //スリープモード突入…変換中…変換完了 adcGNDs[idx] = ADC; adcValue = total(adcGNDs); gndValue = (float)adcValue / BUFSIZE; fv = gndValue * F_VCC * 1000 / 1024; // mV単位 //電圧を表示する mVoltage = (int16_t)fv; lcdPutVoltage(mVoltage, 1, 1); //===== 正電圧を測定する =================================================== // ADMUX = ADC_SET_PVOLTAGE; wait_ms(10); //安定待ち sleep_mode(); //スリープモード突入…変換中…変換完了 adcPVoltages[idx] = ADC; adcValue = total(adcPVoltages); //A/D変換値から電圧を求める fv = (((float)adcValue / BUFSIZE) - gndValue) * F_VCC * 1000 / (1024 * F_POSITIVE_V_RATE); // mV単位 //電圧を表示する mVoltage = (int16_t)fv; lcdPutVoltage(mVoltage, 0, 0); //===== 負電圧を測定する =================================================== // ADMUX = ADC_SET_NVOLTAGE; wait_ms(10); //安定待ち sleep_mode(); //スリープモード突入…変換中…変換完了 adcNVoltages[idx] = ADC; adcValue = total(adcNVoltages); //A/D変換値から電圧を求める fv = (((float)adcValue / BUFSIZE) - gndValue) * F_VCC * 1000 / (1024 * F_NEGATIVE_V_RATE); // mV単位 //電圧を表示する mVoltage = (int16_t)fv; lcdPutVoltage(mVoltage, 0, 1); //===== 電流を測定する ==================================================== // ADMUX = ADC_SET_CURRENT; wait_ms(10); //安定待ち sleep_mode(); //スリープモード突入…変換中…変換完了 adcCurrents[idx] = ADC; adcValue = total(adcCurrents); // ADCの読み取り値が1000以上の場合測定不可とする if ((float)adcValue / BUFSIZE < 1000) { //A/D変換値から電圧を求め、電流を算出する fv = (((float)adcValue / BUFSIZE) - gndValue) * F_VCC * 1000 / (1024 * F_CURRENT_AMP); // mV単位 fa = fv / F_SHUNT_R; //mA単位 //電流を表示する mCurrent = (int16_t)(fa * 10.0); //0.1mA単位 lcdPutCurrent(mCurrent, 1, 0); } else { lcdLineClear(1, 0); lcdSetPos(8, 0); lcdPutStr(" OVER"); } //次のループの準備 if (++idx == BUFSIZE) idx = 0; } return 0; }
int main(void) { int seq[SEQMAX]; word adc1val, sinceTriggered; int dumax = 0; byte q = 0; boolean listening = false; init(); sei(); music(0); for (;;){ adc1val = 0; // set_sleep_mode(0); sleep_mode(); if ( ! bitRead(ADCSRA, ADSC) ) // adc completed. { adc1val = ADCL + (ADCH<<8); if ( adc1val > 10 ) { sinceTriggered = t0compa_cnt; } } if ( adc1val > 10 && (sinceTriggered > 48)) { if ( listening ) { seq[q++] = t0compa_cnt; seq[q] = 0; dumax = max(dumax, t0compa_cnt); t0compa_cnt = 0; } else { listening = true; q = 0; seq[q] = 0; dumax = 0; t0compa_cnt = 0; } } if (listening ) { if (q >= SEQMAX) { listening = false; } else if ( (dumax != 0) && (t0compa_cnt > dumax*4) ) { listening = false; } else if ( t0compa_cnt > 400 ) { listening = false; } } if ( (!listening) && q > 0 ) { analyzeSeq(seq); q = 0; } else { bitClear(PORTB, PB3); } } return 0; /* never reached */ }
int main(void) { // All ports default to input, but turn pull-up resistors on for the stars // (not the ADC input! Made that mistake already) // (stars not used) //PORTB = (1 << STAR2_PIN) | (1 << STAR3_PIN) | (1 << STAR4_PIN); // Set PWM pin to output DDRB = (1 << PWM_PIN); // Turn features on or off as needed #ifdef VOLTAGE_MON ADC_on(); #else ADC_off(); #endif ACSR |= (1<<7); //AC off // Enable sleep mode set to Idle that will be triggered by the sleep_mode() command. // Will allow us to go idle between WDT interrupts (which we're not using anyway) set_sleep_mode(SLEEP_MODE_IDLE); // Determine what mode we should fire up // Read the last mode that was saved if (noinit_decay) // not short press, forget mode { noinit_mode = 0; mode_idx = 0; } else { // short press, advance to next mode mode_idx = noinit_mode; next_mode(); noinit_mode = mode_idx; } // set noinit data for next boot noinit_decay = 0; // set PWM mode if (modes[mode_idx] < FAST_PWM_START) { // Set timer to do PWM for correct output pin and set prescaler timing TCCR0A = 0x21; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23 } else { // Set timer to do PWM for correct output pin and set prescaler timing TCCR0A = 0x23; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23 } TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...) // Now just fire up the mode PWM_LVL = modes[mode_idx]; uint8_t i = 0; uint8_t j = 0; uint8_t strobe_len = 0; #ifdef VOLTAGE_MON uint8_t lowbatt_cnt = 0; uint8_t voltage; #endif while(1) { if(mode_idx < SOLID_MODES) { // Just stay on at a given brightness sleep_mode(); } else if (mode_idx < BATT_CHECK_MODE) { PWM_LVL = 0; get_voltage(); _delay_ms(200); // the first reading is junk #ifdef BATTCHECK_VpT uint8_t result = battcheck(); blink(result >> 5, BLINK_SPEED/8); _delay_ms(BLINK_SPEED); blink(1,5); _delay_ms(BLINK_SPEED*3/2); blink(result & 0b00011111, BLINK_SPEED/8); #else blink(battcheck()); #endif // BATTCHECK_VpT _delay_ms(2000); // wait at least 2 seconds between readouts } else if (mode_idx < SINGLE_BEACON_MODES) { // heartbeat flasher
/* deepSleep(time2wake, offset, mode) - sets the microcontroller to the lowest consumption sleep mode * * It sets the microcontroller to the lowest consumption sleep mode. It enables RTC interruption to be able to * wake up the microcontroller when the RTC alarm is launched. * * 'time2wake' --> it specifies the time at which the RTC alarm will activate. It must follow the next format: * "DD:HH:MM:SS" * 'offset' --> it specifies if 'time2wake' is added to the actual time or if this time is set as the alarm * 'mode' --> it specifies the mode for RTC alarm * * It uses Alarm1 on the RTC due to this Alarm has more precision than Alarm2 * * It switches off all the switches on the Waspmote board. * * It returns nothing. */ void WaspPWR::deepSleep( const char* time2wake, uint8_t offset, uint8_t mode, uint8_t option ) { uint8_t retries=0; // Switch off both multiplexers in UART_0 and UART_1 Utils.muxOFF(); // set the XBee monitorization pin to zero pinMode(XBEE_MON,OUTPUT); digitalWrite(XBEE_MON,LOW); // switches off depending on the option selected switchesOFF(option); // mandatory delay to wait for MUX_RX stabilization // after switching off the sensor boards delay(100); // make sure interruption pin is LOW before entering a low power state // if not the interruption will never come while(digitalRead(MUX_RX)==HIGH) { // clear all detected interruption signals delay(1); PWR.clearInterruptionPin(); retries++; if(retries>10) { return (void)0; } } // RTC ON RTC.ON(); // set Alarm RTC.setAlarm1(time2wake,offset,mode); // get backup of selected Alarm uint8_t day_aux = RTC.day_alarm1; uint8_t hour_aux = RTC.hour_alarm1; uint8_t minute_aux = RTC.minute_alarm1; uint8_t second_aux = RTC.second_alarm1; // get Alarm RTC.getAlarm1(); // check Alarm was correctly set if( ( day_aux != RTC.day_alarm1 ) || ( hour_aux != RTC.hour_alarm1 ) || ( minute_aux != RTC.minute_alarm1 ) || ( second_aux != RTC.second_alarm1 ) ) { RTC.disableAlarm1(); RTC.OFF(); return (void)0; } RTC.OFF(); // set sleep mode set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_mode(); sleep_disable(); // in the case SENS_OFF was an option is mandatory to turn on the // sensor boards before setting up the I2C bus switchesON(option); // Switch on the RTC and clear the alarm signals // Disable RTC interruption after waking up RTC.ON(); RTC.disableAlarm1(); RTC.clearAlarmFlag(); RTC.OFF(); // Keep sensor supply powered down if selected if( option & SENS_OFF ) { pinMode(SENS_PW_3V3,OUTPUT); digitalWrite(SENS_PW_3V3,LOW); pinMode(SENS_PW_5V,OUTPUT); digitalWrite(SENS_PW_5V,LOW); } }
void enterSleepMode() { set_sleep_mode(SLEEP_MODE_IDLE); sleep_mode() ; }
void sleep_if_no_traffic(void) { if (serial_available()) return; sleep_mode(); }
int main() { cli(); disableWatchdog(); slowClock(); initBuzzer(); initSwitch(); initADC(); #ifdef DEBUG uint16_t v = getVoltage(); uint16_t i; for (i = 0x8000; i != 0; i >>= 1) { if (v & i) { dit(); } else { dah(); } _delay_ms(1000); } #endif // Retrieve the current warning timeout from eeprom uint8_t warn_min = eeprom_read_byte(&cfg_warn_min); if (switchPressed()) { number(warn_min); // pause between increments _delay_ms(3000); } // If switch is depressed (at power up), begin increasing // warning time, in 5-minute increments, max 30 minutes // SOS time is 2 x warning time. // while (switchPressed()) { if (switchPressed()) { // Increment warning time by 5 minutes warn_min += 5; // Maximum warning time is 30 minutes if (warn_min > 30) warn_min = 5; // Save the new warning time eeprom_update_byte(&cfg_warn_min, warn_min); } number(warn_min); // pause between increments _delay_ms(3000); } // Compute the number of seconds for warning and SOS warn_sec = warn_min * 60; sos_sec = warn_sec * 2; if (checkVoltage()) { ok(); } else { sos(); } enableWatchdog(); sei(); while (1) { set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_mode(); } }
// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in // millimaters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed // rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes. //void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t invert_feed_rate) void plan_buffer_line (tActionRequest *pAction) { double x; double y; double z; double feed_rate; uint8_t invert_feed_rate; bool e_only = false; double speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis x = pAction->target.x; y = pAction->target.y; z = pAction->target.z; feed_rate = pAction->target.feed_rate; invert_feed_rate = pAction->target.invert_feed_rate; // Calculate target position in absolute steps int32_t target[NUM_AXES]; target[X_AXIS] = lround(x*(double)config.steps_per_mm_x); target[Y_AXIS] = lround(y*(double)config.steps_per_mm_y); target[Z_AXIS] = lround(z*(double)config.steps_per_mm_z); target[E_AXIS] = lround(pAction->target.e*(double)config.steps_per_mm_e); // Calculate the buffer head after we push this byte int next_buffer_head = next_block_index( block_buffer_head ); // If the buffer is full: good! That means we are well ahead of the robot. // Rest here until there is room in the buffer. while(block_buffer_tail == next_buffer_head) { sleep_mode(); } // Prepare to set up new block block_t *block = &block_buffer[block_buffer_head]; block->action_type = AT_MOVE; // Compute direction bits for this block block->direction_bits = 0; if (target[X_AXIS] < position[X_AXIS]) { block->direction_bits |= X_DIR_BIT; } if (target[Y_AXIS] < position[Y_AXIS]) { block->direction_bits |= Y_DIR_BIT; } if (target[Z_AXIS] < position[Z_AXIS]) { block->direction_bits |= Z_DIR_BIT; } if (target[E_AXIS] < position[E_AXIS]) { block->direction_bits |= E_DIR_BIT; } // Number of steps for each axis block->steps_x = labs(target[X_AXIS]-position[X_AXIS]); block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); block->steps_e = labs(target[E_AXIS]-position[E_AXIS]); block->step_event_count = max(block->steps_x, max(block->steps_y, block->steps_z)); block->step_event_count = max(block->step_event_count, block->steps_e); // Bail if this is a zero-length block if (block->step_event_count == 0) { return; }; // Compute path vector in terms of absolute step target and current positions double delta_mm[NUM_AXES]; delta_mm[X_AXIS] = (target[X_AXIS]-position[X_AXIS])/(double)config.steps_per_mm_x; delta_mm[Y_AXIS] = (target[Y_AXIS]-position[Y_AXIS])/(double)config.steps_per_mm_y; delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/(double)config.steps_per_mm_z; delta_mm[E_AXIS] = (target[E_AXIS]-position[E_AXIS])/(double)config.steps_per_mm_e; block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS])); if (block->millimeters == 0) { e_only = true; block->millimeters = fabs(delta_mm[E_AXIS]); } double inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides // // Speed limit code from Marlin firmware // //TODO: handle invert_feed_rate double microseconds; //if(feedrate<minimumfeedrate) // feedrate=minimumfeedrate; microseconds = lround((block->millimeters/feed_rate*60.0)*1000000.0); // Calculate speed in mm/minute for each axis double multiplier = 60.0*1000000.0/(double)microseconds; speed_x = delta_mm[X_AXIS] * multiplier; speed_y = delta_mm[Y_AXIS] * multiplier; speed_z = delta_mm[Z_AXIS] * multiplier; speed_e = delta_mm[E_AXIS] * multiplier; // Limit speed per axis double speed_factor = 1; //factor <=1 do decrease speed if(fabs(speed_x) > config.maximum_feedrate_x) { speed_factor = (double)config.maximum_feedrate_x / fabs(speed_x); } if(fabs(speed_y) > config.maximum_feedrate_y) { double tmp_speed_factor = (double)config.maximum_feedrate_y / fabs(speed_y); if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; } if(fabs(speed_z) > config.maximum_feedrate_z) { double tmp_speed_factor = (double)config.maximum_feedrate_z / fabs(speed_z); if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; } if(fabs(speed_e) > config.maximum_feedrate_e) { double tmp_speed_factor = (double)config.maximum_feedrate_e / fabs(speed_e); if(speed_factor > tmp_speed_factor) speed_factor = tmp_speed_factor; } multiplier = multiplier * speed_factor; speed_x = delta_mm[X_AXIS] * multiplier; speed_y = delta_mm[Y_AXIS] * multiplier; speed_z = delta_mm[Z_AXIS] * multiplier; speed_e = delta_mm[E_AXIS] * multiplier; block->nominal_speed = block->millimeters * multiplier; // mm per min block->nominal_rate = ceil(block->step_event_count * multiplier); // steps per minute //--- #if 0 // Calculate speed in mm/minute for each axis. No divide by zero due to previous checks. // NOTE: Minimum stepper speed is limited by MINIMUM_STEPS_PER_MINUTE in stepper.c double inverse_minute; if (!invert_feed_rate) { inverse_minute = feed_rate * inverse_millimeters; } else { inverse_minute = 1.0 / feed_rate; } block->nominal_speed = block->millimeters * inverse_minute; // (mm/min) Always > 0 block->nominal_rate = ceil(block->step_event_count * inverse_minute); // (step/min) Always > 0 #endif #if 0 double axis_speed; axis_speed = delta_mm[Z_AXIS] * inverse_minute; if (axis_speed > config.maximum_feedrate_z) { inverse_millimeters = 1.0 / delta_mm[Z_AXIS]; inverse_minute = calc_inverse_minute (false, config.maximum_feedrate_z, inverse_millimeters); block->nominal_speed = delta_mm[Z_AXIS] * inverse_minute; // (mm/min) Always > 0 block->nominal_rate = ceil(block->step_event_count * inverse_minute); // (step/min) Always > 0 } #endif // Compute the acceleration rate for the trapezoid generator. Depending on the slope of the line // average travel per step event changes. For a line along one axis the travel per step event // is equal to the travel/step in the particular axis. For a 45 degree line the steppers of both // axes might step for every step event. Travel per step event is then sqrt(travel_x^2+travel_y^2). // To generate trapezoids with contant acceleration between blocks the rate_delta must be computed // specifically for each line to compensate for this phenomenon: // Convert universal acceleration for direction-dependent stepper rate change parameter block->rate_delta = ceil( block->step_event_count*inverse_millimeters * config.acceleration*60.0 / ACCELERATION_TICKS_PER_SECOND ); // (step/min/acceleration_tick) #if 0 double rate_calc; if (delta_mm[Z_AXIS] > 0) { rate_calc = ceil( block->step_event_count / delta_mm[Z_AXIS] * 50*60.0 / ACCELERATION_TICKS_PER_SECOND ); // (step/min/acceleration_tick) if (rate_calc < block->rate_delta) block->rate_delta = rate_calc; } #endif // Perform planner-enabled calculations if (acceleration_manager_enabled /*&& !e_only*/ ) { // Compute path unit vector double unit_vec[NUM_AXES]; unit_vec[X_AXIS] = delta_mm[X_AXIS]*inverse_millimeters; unit_vec[Y_AXIS] = delta_mm[Y_AXIS]*inverse_millimeters; unit_vec[Z_AXIS] = delta_mm[Z_AXIS]*inverse_millimeters; // Compute maximum allowable entry speed at junction by centripetal acceleration approximation. // Let a circle be tangent to both previous and current path line segments, where the junction // deviation is defined as the distance from the junction to the closest edge of the circle, // colinear with the circle center. The circular segment joining the two paths represents the // path of centripetal acceleration. Solve for max velocity based on max acceleration about the // radius of the circle, defined indirectly by junction deviation. This may be also viewed as // path width or max_jerk in the previous grbl version. This approach does not actually deviate // from path, but used as a robust way to compute cornering speeds, as it takes into account the // nonlinearities of both the junction angle and junction velocity. double vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed // Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles. if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) { // Compute cosine of angle between previous and current path. (prev_unit_vec is negative) // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity. double cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS] - previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS] - previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ; // Skip and use default max junction speed for 0 degree acute junction. if (cos_theta < 0.95) { vmax_junction = min(previous_nominal_speed,block->nominal_speed); // Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds. if (cos_theta > -0.95) { // Compute maximum junction velocity based on maximum acceleration and junction deviation double sin_theta_d2 = sqrt(0.5*(1.0-cos_theta)); // Trig half angle identity. Always positive. vmax_junction = min(vmax_junction, sqrt(config.acceleration*60*60 * config.junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) ); } } } block->max_entry_speed = vmax_junction; // Initialize block entry speed. Compute based on deceleration to user-defined MINIMUM_PLANNER_SPEED. double v_allowable = max_allowable_speed(-config.acceleration,MINIMUM_PLANNER_SPEED,block->millimeters); block->entry_speed = min(vmax_junction, v_allowable); // Initialize planner efficiency flags // Set flag if block will always reach maximum junction speed regardless of entry/exit speeds. // If a block can de/ac-celerate from nominal speed to zero within the length of the block, then // the current block and next block junction speeds are guaranteed to always be at their maximum // junction speeds in deceleration and acceleration, respectively. This is due to how the current // block nominal speed limits both the current and next maximum junction speeds. Hence, in both // the reverse and forward planners, the corresponding block junction speed will always be at the // the maximum junction speed and may always be ignored for any speed reduction checks. if (block->nominal_speed <= v_allowable) { block->nominal_length_flag = true; } else { block->nominal_length_flag = false; } block->recalculate_flag = true; // Always calculate trapezoid for new block // Update previous path unit_vector and nominal speed memcpy(previous_unit_vec, unit_vec, sizeof(unit_vec)); // previous_unit_vec[] = unit_vec[] previous_nominal_speed = block->nominal_speed; } else { // Acceleration planner disabled. Set minimum that is required. // block->entry_speed = block->nominal_speed; block->initial_rate = block->nominal_rate; block->final_rate = block->nominal_rate; block->accelerate_until = 0; block->decelerate_after = block->step_event_count; block->rate_delta = 0; } if (pAction->ActionType == AT_MOVE) block->check_endstops = false; else block->check_endstops = true; pAction->ActionType = AT_MOVE; // Move buffer head block_buffer_head = next_buffer_head; // Update position memcpy(position, target, sizeof(target)); // position[] = target[] startpoint = pAction->target; if (acceleration_manager_enabled) { planner_recalculate(); } st_wake_up(); }
void sleep_if_no_traffic(void) { if (zcl_receiver_has_data()) return; sleep_mode(); }
/*this mode turns off everything not needed during the time in which only the main counter is running The only things needed during simple sleep are the operation of basic pins and the timer1 interrupt */ void Radian_power_saver::EnterSimpleSleep(unsigned int IdlePWM ){ /* //Disable ADC and internal Vref POWER_OFF; ADMUX &= ~( (1<<REFS1) | (1<<REFS0)); ADCSRA &= ~( (1<<ADEN) ); //Disable AnalogComparator ACSR |= (1<<ACD); SMCR = 1; //go into idle mode sleep_mode(); POWER_ON; set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); interrupts(); // attachInterrupt(0,sleepHandler, FALLING); sleep_mode(); //sleep now //--------------- ZZZZZZ sleeping here sleep_disable(); //fully awake now POWER_ON; //turn the power back on */ if(DEBUG) Serial.println("Entering simple Sleep Mode"); if(IdlePWM == 0) SetIdlePins(PAN); else SetIdlePins(TILT); // power_all_disable(); //turn off all modules //turn necessary idle ports back on power_usart0_enable(); power_timer1_enable(); // power_timer4_enable(); //leave PWM module on, should make something smarter for future set_sleep_mode(SLEEP_MODE_IDLE); sleep_enable(); // interrupts(); // attachInterrupt(0,sleepHandler, FALLING); sleep_mode(); //sleep now //--------------- ZZZZZZ sleeping here sleep_disable(); //fully awake now // Serial.println("Woke up"); POWER_ON; power_all_enable(); if(IdlePWM == 0) WakeUpPins(PAN); else WakeUpPins(TILT); /*power_adc_enable(); power_timer0_enable(); power_usart1_enable(); power_useart0_enable(); */ }
void sleep_after_exit() { cli(); sleep_mode(); }
int main(void) { LCD_Initalize(); LCD_GoTo(0, 0); // Set cursor to first char in first line LCD_WriteText("-= LCD READY =-"); // Display sample text #ifdef HEART_BEAT SET_BIT(DDRB, PB0); SET_BIT(PORTB, PB0); #endif // g_clock.handle_milisec = milisec_handler; g_clock.handle_second = second_handler; init_clock(); init_keypad(); sei(); msg_t* msg = 0; int screen = DEFAULT_SCREEN; char screen_changed = 1; while(1) { while((msg = get_msg())) { switch(msg->type) { case MSG_INPUT: if (msg->size == BTN_0) { if (screen == SETUP_TIME_SCREEN) { set_clock(g_time_screen.hour, g_time_screen.minute); } ++screen; screen %= SCREEN_COUNT; screen_changed = 1; } break; default: break; } if (screen_changed) { clear_screen(); } switch (screen) { case 0: show_default_screen(msg); break; case 1: show_setup_time_screen(screen_changed, msg); break; case -1: show_setup_diameter_screen(); break; default: break; } screen_changed = 0; free_msg(&msg); } sleep_mode(); } return 0; }
int main(void) { { // Set up timers, sleep and such cli(); set_sleep_mode(SLEEP_MODE_IDLE); PRR = ((1 << PRTIM1) | (1 << PRUSI) | (1 << PRADC)); // TIMER0 TCCR0A = (1 << WGM01); TCCR0B = ((1 << CS01) | (1 << CS00)); OCR0A = 61; OCR0B = 0; TIMSK = (1 << OCIE0A); // INT0 MCUCR |= (1 << ISC01); GIMSK = (1 << INT0); PORTB = PORTB_NULL; counter = leds = 0; counter_max = MAXIMUM; piezo = 0; stopped = 1; sei(); } { // Set up the counter and start while (stopped < 3) { leds = counter_max; sleep_mode(); } leds = LED_ON; } { // Prepare for the timer cli(); GIMSK = 0; // Stop INT0 stopped = 0; TCNT0 = 0; // Clear TIMER0 sei(); } { // Display the timer while it's running while (counter < counter_max) { leds = counter | LED_ON; sleep_mode(); } stopped = 4; leds = counter; } { // Yell! cli(); GIMSK = (1 << INT0); // Start INT0 sei(); while (stopped == 4) // Sleep! sleep_mode(); GIMSK = 0; // Stop INT0 TCCR0A &= ~((1 << COM0B1) | (1 << COM0B0)); // Stop yelling! } { // Timer finished, sleep forever! cli(); TIMSK = 0; PORTB = 0; // Everything off set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_mode(); } return 0; }
int main(void) { // All ports default to input, but turn pull-up resistors on for the stars (not the ADC input! Made that mistake already) PORTB = (1 << STAR2_PIN) | (1 << STAR3_PIN) | (1 << STAR4_PIN); // Set PWM pin to output DDRB = (1 << PWM_PIN); // Set timer to do PWM for correct output pin and set prescaler timing TCCR0A = 0x23; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23 TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...) // Turn features on or off as needed #ifdef ENABLE_VOLTAGE_MONITORING ADC_on(); #else ADC_off(); #endif ACSR |= (1<<7); //AC off #ifdef ENABLE_TURNING_OFF_MEMORY // Soldering Star 4 disables memory #ifdef MEMORY_ON_BY_DEFAULT memory_enabled = ((PINB & (1 << STAR4_PIN)) > 0) ? 1 : 0; #else memory_enabled = ((PINB & (1 << STAR4_PIN)) == 0) ? 1 : 0; #endif #endif #ifdef ENABLE_TURNING_OFF_TURBO_TIMER turbo_timer_enabled = ((PINB & (1 << STAR2_PIN)) > 0) ? 1 : 0; #endif #ifdef ENABLE_SINGLE_MODE if((PINB & (1 << STAR2_PIN)) == 0) { modes[0] = modes[1] = #ifdef FOUR_MODES modes[2] = #endif MODE_TURBO; // Last basic mode is already MODE_TURBO - no need to waste bytes changing that } #endif #ifdef ENABLE_TACTICAL_MODE #ifdef TACTICAL_MODE_ON_BY_DEFAULT if((PINB & (1 << STAR2_PIN)) > 0) #else if((PINB & (1 << STAR2_PIN)) == 0) #endif { #ifdef ENABLE_TURNING_OFF_MEMORY if(memory_enabled) // Single mode { modes[0] = modes[1] = #ifdef FOUR_MODES modes[2] = #endif MODE_TURBO; // Last basic mode is already MODE_TURBO - no need to waste bytes changing that } else #endif { modes[0] = MODE_STROBE; modes[1] = MODE_TURBO; modes[2] = MODE_LOW; #ifdef FOUR_MODES modes[3] = MODE_LOWLOW; #endif wdt_timeout = 1; } } #endif #ifdef ENABLE_HIGH_TO_LOW #ifdef HIGH_TO_LOW_ON_BY_DEFAULT if((PINB & (1 << STAR3_PIN)) > 0) #else if((PINB & (1 << STAR3_PIN)) == 0) #endif revert_modes(); #endif // Enable sleep mode set to Idle that will be triggered by the sleep_mode() command. // Will allow us to go idle between WDT interrupts set_sleep_mode(SLEEP_MODE_IDLE); // Mode memory handling block { uint8_t short_clicks = 0; // Determine what mode we should fire up // Read the last mode that was saved mode_idx = read_stored_idx(); // Handle short press indicator short_clicks = (mode_idx & 0xf0); mode_idx &= 0x0f; if(short_clicks) // One or more short clicks { // Indicates we did a short press last time, go to the next mode next_mode(short_clicks); // Will handle wrap arounds } // else: Didn't have a short press, keep the same mode, nothing to do // Store mode with short press indicator store_mode_idx(mode_idx | ((short_clicks < HIDDEN_MODE_THRESHOLD) ? short_clicks+0x10 : short_clicks)); } // Start watchdog timer (used for storing the mode after delay, turbo timer, and voltage monitoring) WDT_on(); // Now just fire up the mode selected_pwm = modes[mode_idx]; // Note: Actual PWM can be less than selected PWM (e.g. in case of low voltage) if(selected_pwm < PWM_MIN) // Hidden blinky modes adjusted_pwm = PWM_MAX; // All blinky modes initially with full power else adjusted_pwm = selected_pwm; // block for main loop { uint8_t ii = 0; // Loop counter, used by multiple branches #ifdef ENABLE_BEACONS uint8_t beacon_background = PWM_OFF; #endif while(1) { #ifdef ENABLE_VOLTAGE_MONITORING if(adjusted_pwm == PWM_OFF) // Voltage monitoring signaled us to turn off the light -> break out of the main loop break; #endif PWM_LVL = adjusted_pwm; // must be set inside loop, is volatile & might have changed because of voltage monitoring switch(selected_pwm) { case MODE_STROBE: // Disorienting alternating strobe #ifdef NORMAL_STROBE _delay_ms(20); PWM_LVL = 0; _delay_ms(40); #endif #ifdef ALTERNATING_STROBE _delay_ms(20); PWM_LVL = 0; if(ii < 22) // 60ms = ~16.7Hz, ~33% DC _delay_ms(40); else if(ii < 36) // 111ms = ~9Hz, ~18% DC _delay_ms(90); else ii = 255; #endif #ifdef RANDOM_STROBE { // 77ms = 13Hz, 51ms = 19.5Hz / 40-60% DC ii = (5 * ii) + 128; _delay_ms(31); PWM_LVL = 0; _delay_ms(ii > 127 ? 46 : 20); } #endif break; case MODE_MOTION_STOPPING_STROBE: // 10Hz, 2% DC _delay_ms(2); PWM_LVL = 0; _delay_ms(98); break; #ifdef ENABLE_SOS case MODE_SOS: if(ii / 3 == 1) _delay_ms(600); // Dash for 'O' (3xDot) else _delay_ms(200); // Dot for 'S' PWM_LVL = 0; switch(ii) { default: _delay_ms(200); // Pause inside a letter (1xDot) break; case 2: case 5: _delay_ms(600); // Pause between letters (3xDot) break; case 8: _delay_ms(2500); // Pause between "words" (should be 7xDot, but I like it longer) ii = 255; break; } break; #endif #ifdef ENABLE_BEACONS case MODE_BEACON_WITH_BACKGROUND: case MODE_SLOW_BEACON_WITH_BACKGROUND: #ifdef FOUR_MODES beacon_background = PWM_SLOW_BEACON_BACKGROUND; #else switch(selected_pwm) { case MODE_BEACON_WITH_BACKGROUND: beacon_background = PWM_BEACON_BACKGROUND; break; case MODE_SLOW_BEACON_WITH_BACKGROUND: beacon_background = PWM_SLOW_BEACON_BACKGROUND; break; } #endif // no break - fall through to beacon code case MODE_BEACON: case MODE_ALPINE_DISTRESS_BEACON: _delay_ms(50); PWM_LVL = beacon_background; _delay_ms(950); if(selected_pwm == MODE_ALPINE_DISTRESS_BEACON) { if(ii > 5) { _delay_ms(59000); ii = 255; } else _delay_ms(9000); } else if(selected_pwm == MODE_SLOW_BEACON_WITH_BACKGROUND) _delay_ms(1500); #endif break; default: sleep_mode(); break; } ii++; // Loop counter, used by multiple branches } } #ifdef ENABLE_VOLTAGE_MONITORING // // Critically low voltage -> Turn off the light // // Disable WDT so it doesn't wake us up from sleep WDT_off(); // Would be nice to blink a couple of times with lowest brightness to notify the user, but not implemented due space restrictions // Turn the light off PWM_LVL = 0; // Disable ADC so it doesn't consume power ADC_off(); // Power down as many components as possible set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Deep sleep until powered off - consumes ~110uA during the deep sleep while(1) sleep_mode(); #endif return 0; // Standard Return Code -> would return to idle loop with interrupts disabled. }
int main(void) { SetSystemClockPrescaler(0); init(); sei(); led_blink(3); while (1) { if(SW_ACTIVE()) { // SW pressed uint8_t pressCnt = 100; // wait until released do { // long term press detected? if(pressCnt>0 && --pressCnt==0) LED_ON(); _delay_ms(10); } while(SW_ACTIVE()); // SW released LED_OFF(); if(pressCnt>0) handleSensor(1); // force transmit else { // program mode LED_ON(); fs20_resetbuffer(); fs20_rxon(); fstelegram_t t; t.type = 'U'; // undefined pressCnt = 100; // wait for next telegram // exit if button pressed or timeout occured while(!fs20_readFS20Telegram(&t) && --pressCnt>0 && !SW_ACTIVE()) _delay_ms(100); fs20_idle(); LED_OFF(); // save the result if(t.type=='F') { saveConfig(t.housecode, t.button); led_blink(2); // confirm save of config handleSensor(1); // force transmit } // wait until sw releases while(SW_ACTIVE()); } } // check long term timer if(longTimerCnt >= LONGTIMER_VAL) handleSensor(1); // finaly check if sensor value changed // this will only be the case if the current sensor value haven't been sent // during this cycle handleSensor(0); // sleep well LED_OFF(); SENS_ACTIVATE(0); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_mode(); } }
void powerdown_avr(){ set_sleep_mode(SLEEP_MODE_PWR_DOWN ); // sleep mode is set here sleep_enable(); sleep_mode(); // System sleeps here }
// **************** main() *********************************************** int main(void) { DDRD |= (1<<PD5)|(1<<PD4)|(1<<PD0)|(1<<PD1); // ustaw piny PWM1 (OC1A) oraz PWM2 (OC1B) jako wyjœcia WA¯NE !!! DDRB |= (1<<PB0); // wyjœcie do sterowania zasilaniem karty SD PORTB = 0b00000001; // podci¹gniêcie PORTB do VCC ?? set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Wybranie trybu uœpienia mikrokontrolera // init SPI DDRB |= (1<<CS)|(1<<MOSI)|(1<<SCK)|(1<<CS); PORTB |= (1<<CS); SPCR |= (1<<SPE)|(1<<MSTR); SPSR |= (1<<SPI2X); // masymalny zegar SCK // konfiguracja PWM (Timer1) TCCR1A = (1<<WGM10)|(1<<COM1A1)|(0<<COM1A0)|(1<<COM1B1);//|(1<<COM1B0); TCCR1B = (1<<CS10); // konfiguracja Timer0 (samplowanie) TCCR0 = (1<<WGM01); // tryb CTC TIMSK = (1<<OCIE0); // zezwolenie na przerwanie CompareMatch sei(); // globalne zezwolenie na przerwania OCR0 = (uint8_t)44; //bo F_CPU/8/samplerate // **************** akcelerometr ********************************** ADCSRA |= 1<<ADPS2 | 1<<ADPS1 | 1<<ADPS0; //ustawienie preskalera ADMUX |= 1<<REFS0 | 1<<REFS1; //ustawienie napiêcia referencyjnego ADCSRA |= 1<<ADIE; //w³¹czenie przerwania ADCSRA |= 1<<ADEN; //w³¹czenie modu³u konwersji // **************** pêtla g³ówna ********************************** while(1) { if (pf_mount(&Fs)) continue; //inicjalizacja FS for (;;) { if (pf_opendir(&Dir, "")) break; //otwarcie g³ównego folderu karty if (startup==1) //odtworzenie dŸwiêku w³¹czania { if (play("startup.wav")) break; startup=0; PORTD |= (1<<PIND0); } // ********************* zdarzenie SWING **************** if (hitpriority==1) { swingnumber=swing[swingcounter]; if (swingnumber==1) { play("swing.wav"); } if (swingnumber==2) { play("swing.wav"); } if (swingnumber==3) { play("swing.wav"); } hitpriority=0; breakdisablehigh=0; breakdisablelow=0; swingcounter++; if (swingcounter==9) { swingcounter=0; } } // ******************** zdarzenie HIT *********** if (hitpriority==2) { hitnumber=hit[hitcounter]; PORTD |= (1<<PIND1); //W³¹czenie dodatkowej diody ledoff=1; if (hitnumber==1) { play("clash.wav"); } if (hitnumber==2) { play("clash.wav"); } if (hitnumber==3) { play("clash.wav"); } hitpriority=0; breakdisablehigh=0; hitcounter++; if (hitcounter==9) { hitcounter=0; } } // ********************** sekwencja POWER DOWN ****************** if (shutdown==1) { play("startup.wav"); GENERAL_MAJOR_SHUTDOWN_PROCEDURE; sleep_mode(); } // ********************** tryb ja³owy ****************** else { if (play("hum.wav")) break; } } } }
int st_buffer_block(int32_t steps_x, int32_t steps_y, int32_t steps_z, int32_t pos_x, int32_t pos_y, int32_t pos_z, uint32_t microseconds, int16_t line_number) { uint8_t direction_bits = 0; uint8_t changed_dir; struct Block *block; struct Block *comp_block=NULL; uint32_t maximum_steps; maximum_steps = max(labs(steps_x), max(labs(steps_y), labs(steps_z))); // Don't process empty blocks if (maximum_steps==0) {return 0;} // Determine direction bits if (steps_x < 0) { direction_bits |= (1<<X_DIRECTION_BIT); } if (steps_y < 0) { direction_bits |= (1<<Y_DIRECTION_BIT); } if (steps_z < 0) { direction_bits |= (1<<Z_DIRECTION_BIT); } while (st_buffer_full()) { sleep_mode();} // makes sure there are two // slots left on buffer // If direction has changed, then put a backlash instruction // on the queue: if (direction_bits!=old_direction_bits){ comp_block = &block_buffer[block_buffer_head]; comp_block->backlash = 1; comp_block->direction_bits = direction_bits; comp_block->line_number = line_number; comp_block->steps_x = 0; comp_block->steps_y = 0; comp_block->steps_z = 0; comp_block->pos_x = pos_x; comp_block->pos_y = pos_y; comp_block->pos_z = pos_z; changed_dir = direction_bits^old_direction_bits; old_direction_bits = direction_bits; if (changed_dir & (1<<X_DIRECTION_BIT)) comp_block->steps_x=settings.backlash_x_count; if (changed_dir & (1<<Y_DIRECTION_BIT)) comp_block->steps_y=settings.backlash_y_count; if (changed_dir & (1<<Z_DIRECTION_BIT)) comp_block->steps_z=settings.backlash_z_count; // Use same rate for backlash compensation as for the block itself: comp_block->rate = microseconds/maximum_steps; comp_block->mode = SM_RUN; comp_block->maximum_steps = max(comp_block->steps_x, max(comp_block->steps_y, comp_block->steps_z)); // If compensation is not empty, advance the end of the queue if (comp_block->maximum_steps > 0) { block_buffer_head = (block_buffer_head + 1) % BLOCK_BUFFER_SIZE; } } // Setup block record block = &block_buffer[block_buffer_head]; block->backlash=0; block->line_number = line_number; block->steps_x = labs(steps_x); block->steps_y = labs(steps_y); block->steps_z = labs(steps_z); block->pos_x = pos_x; block->pos_y = pos_y; block->pos_z = pos_z; block->maximum_steps = maximum_steps; block->rate = microseconds/block->maximum_steps; block->mode = SM_RUN; // Compute direction bits for this block block->direction_bits = direction_bits; // Move buffer head block_buffer_head = (block_buffer_head + 1) % BLOCK_BUFFER_SIZE; //next_buffer_head; // Ensure that blocks will be processed by enabling The Stepper Driver Interrupt ENABLE_STEPPER_DRIVER_INTERRUPT(); return 1; }
void ALWBase::idle() { set_sleep_mode(SLEEP_MODE_IDLE); sleep_mode(); }
/* deepSleep(time2wake, offset, mode) - sets the microcontroller to the lowest consumption sleep mode * * It sets the microcontroller to the lowest consumption sleep mode. It enables RTC interruption to be able to * wake up the microcontroller when the RTC alarm is launched. * * 'time2wake' --> it specifies the time at which the RTC alarm will activate. It must follow the next format: * "DD:HH:MM:SS" * 'offset' --> it specifies if 'time2wake' is added to the actual time or if this time is set as the alarm * 'mode' --> it specifies the mode for RTC alarm * * It uses Alarm1 on the RTC due to this Alarm has more precision than Alarm2 * * It switches off all the switches on the MakeSuremote board. * * It returns nothing. */ void MakeSurePWR::deepSleep( const char* time2wake, uint8_t offset, uint8_t mode, uint8_t option ) { uint8_t retries=0; // set the monitorization pin to zero pinMode(XBEE_MON,INPUT); digitalWrite(XBEE_MON,LOW); // Switch off both multiplexers in UART_0 and UART_1 when // no interruption is expected through the UART1 if( !(option & UART1_OFF) ) { // keep multiplexer on } else { Utils.muxOFF(); } delay(100); // Set RTC alarm to wake up from Sleep Power Down Mode RTC.ON(); RTC.setAlarm1(time2wake,offset,mode); RTC.close(); RTC.OFF(); pinMode(I2C_SDA,OUTPUT); digitalWrite(I2C_SDA,LOW); pinMode(I2C_SCL,OUTPUT); digitalWrite(I2C_SCL,LOW); switchesOFF(option); // make sure interruption pin is LOW before entering a low power state // if not the interruption will never come while(digitalRead(MUX_RX)==HIGH) { // clear all detected interruption signals delay(1); PWR.clearInt(); retries++; if(retries>10) { return (void)0; } } set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_mode(); sleep_disable(); switchesON(option); RTC.ON(); RTC.clearAlarmFlag(); if( option & RTC_OFF ) RTC.OFF(); if( option & SENS_OFF ) { pinMode(SENS_PW_3V3,OUTPUT); digitalWrite(SENS_PW_3V3,LOW); pinMode(SENS_PW_5V,OUTPUT); digitalWrite(SENS_PW_5V,LOW); } }
// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in // mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration // calculation the caller must also provide the physical length of the line in millimeters. void plan_buffer_line(double x, double y, double z, double feed_rate, int invert_feed_rate) { // The target position of the tool in absolute steps // Calculate target position in absolute steps int32_t target[3]; target[X_AXIS] = lround(x*settings.steps_per_mm[X_AXIS]); target[Y_AXIS] = lround(y*settings.steps_per_mm[Y_AXIS]); target[Z_AXIS] = lround(z*settings.steps_per_mm[Z_AXIS]); // Calculate the buffer head after we push this byte uint8_t next_buffer_head = (block_buffer_head + 1); next_buffer_head = next_buffer_head % BLOCK_BUFFER_SIZE; // If the buffer is full: good! That means we are well ahead of the robot. // Rest here until there is room in the buffer. uint8_t bufferWasFull = block_buffer_tail == next_buffer_head; if( bufferWasFull) { //printPgmString(PSTR("::buf_full::\r\n")); } while(block_buffer_tail == next_buffer_head) { st_pause_wait_resume(); sleep_mode(); } if(bufferWasFull) { //printPgmString(PSTR("::not_full::\r\n")); } // Prepare to set up new block block_t *block = &block_buffer[block_buffer_head]; // Number of steps for each axis block->steps_x = labs(target[X_AXIS]-position[X_AXIS]); block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]); block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]); block->step_event_count = max(block->steps_x, max(block->steps_y, block->steps_z)); // Bail if this is a zero-length block if (block->step_event_count == 0) { return; }; double delta_x_mm = (target[X_AXIS]-position[X_AXIS])/settings.steps_per_mm[X_AXIS]; double delta_y_mm = (target[Y_AXIS]-position[Y_AXIS])/settings.steps_per_mm[Y_AXIS]; double delta_z_mm = (target[Z_AXIS]-position[Z_AXIS])/settings.steps_per_mm[Z_AXIS]; block->millimeters = sqrt(square(delta_x_mm) + square(delta_y_mm) + square(delta_z_mm)); uint32_t microseconds; if (!invert_feed_rate) { microseconds = lround((block->millimeters/feed_rate)*1000000); } else { microseconds = lround(ONE_MINUTE_OF_MICROSECONDS/feed_rate); } // Calculate speed in mm/minute for each axis double multiplier = 60.0*1000000.0/microseconds; block->speed_x = delta_x_mm * multiplier; block->speed_y = delta_y_mm * multiplier; block->speed_z = delta_z_mm * multiplier; block->nominal_speed = block->millimeters * multiplier; block->nominal_rate = ceil(block->step_event_count * multiplier); block->entry_factor = 0.0; // Compute the acceleration rate for the trapezoid generator. Depending on the slope of the line // average travel per step event changes. For a line along one axis the travel per step event // is equal to the travel/step in the particular axis. For a 45 degree line the steppers of both // axes might step for every step event. Travel per step event is then sqrt(travel_x^2+travel_y^2). // To generate trapezoids with contant acceleration between blocks the rate_delta must be computed // specifically for each line to compensate for this phenomenon: double travel_per_step = block->millimeters/block->step_event_count; block->rate_delta = ceil( ((settings.acceleration*60.0)/(ACCELERATION_TICKS_PER_SECOND))/ // acceleration mm/sec/sec per acceleration_tick travel_per_step); // convert to: acceleration steps/min/acceleration_tick if (acceleration_manager_enabled) { // compute a preliminary conservative acceleration trapezoid double safe_speed_factor = factor_for_safe_speed(block); calculate_trapezoid_for_block(block, safe_speed_factor, safe_speed_factor); } else { block->initial_rate = block->nominal_rate; block->final_rate = block->nominal_rate; block->accelerate_until = 0; block->decelerate_after = block->step_event_count; block->rate_delta = 0; } // Compute direction bits for this block block->direction_bits = 0; if (target[X_AXIS] < position[X_AXIS]) { block->direction_bits |= (1<<X_DIRECTION_BIT); } if (target[Y_AXIS] < position[Y_AXIS]) { block->direction_bits |= (1<<Y_DIRECTION_BIT); } if (target[Z_AXIS] < position[Z_AXIS]) { block->direction_bits |= (1<<Z_DIRECTION_BIT); } // Move buffer head block_buffer_head = next_buffer_head; // Update position memcpy(position, target, sizeof(target)); // position[] = target[] if (acceleration_manager_enabled) { planner_recalculate(); } st_wake_up(); }
int main(void) { uint8_t numSensors = 0, i; // unsigned long nextflash = 0; // Configure all pins as inputs with pullups initially DDRA = 0x00; PORTA = 0xff; DDRB = 0x00; PORTB = 0xff; // Serial output line DDRB |= _BV(PINB0); PORTB |= _BV(PINB0); // LED // DDRA |= _BV(PINA0); // Radio power is PA1 PORTA &= ~_BV(PINA1); DDRA |= _BV(PINA1); // Onewire power is PA2 PORTA &= ~_BV(PINA2); DDRA |= _BV(PINA2); myPutStr("Hello world\r\n"); // Various power-saving things // Disable BOD while sleeping. I hope. MCUCR |= (_BV(BODS) | _BV(BODSE)); MCUCR &= ~_BV(BODSE); MCUCR |= (_BV(BODS)); // Disable the ADC ADCSRA &= ~_BV(ADEN); // Disable the Analog Comparator ACSR |= _BV(ACD); // Disable clocking of timer1 and ADC PRR |= (_BV(PRTIM1)|_BV(PRADC)); timerInit(); wdtInit(); initInterrupts(); // Power up the Onewire bus PORTA |= _BV(PINA2); while(numSensors == 0) { myPutStr("Scanning for sensors\r\n"); numSensors = search_sensors(); myPutStr("Found "); myPutUint8(numSensors); myPutStr(" sensors\r\n"); for (i=0;i<numSensors;i++) { uint8_t j; myPutStr("Sensor "); myPutUint8(i); myPutStr(" address "); for (j=0;j<OW_ROMCODE_SIZE;j++) { myPutUint8(gSensorIDs[i][j]); } if (gSensorIDs[i][0] == DS18S20_FAMILY_CODE ) { myPutStr(" DS18S20/DS1820"); } else if ( gSensorIDs[i][0] == DS1822_FAMILY_CODE ) { myPutStr(" DS1822"); } else { myPutStr(" DS18B20"); } if ( DS18X20_get_power_status( &gSensorIDs[i][0] ) == DS18X20_POWER_PARASITE ) { myPutStr(" parasite\r\n"); } else { myPutStr(" external\r\n"); } // Enable 12 bit mode (won't do anything on DS18S20) DS18X20_write_scratchpad(&gSensorIDs[i][0], 0, 0, DS18B20_12_BIT); DS18X20_scratchpad_to_eeprom(DS18X20_get_power_status( &gSensorIDs[i][0] ),&gSensorIDs[i][0]); } } while(1) { unsigned long wakepoint; myRadioBuf_t radiobuf; //char debugbuf[10]; // if ((signed long)now - (signed long)nextflash >= 0) { // debugLedToggle(0); // nextflash = now + 1000; // } // Power up the Onewire bus PORTA |= _BV(PINA2); // Let is stabilize for a few ms wakepoint = getMillis() + 15; numSensors = search_sensors(); while (! ((signed long)getMillis() - (signed long)wakepoint >= 0)) { set_sleep_mode(SLEEP_MODE_IDLE); sleep_mode(); } if ( DS18X20_start_meas( DS18X20_POWER_PARASITE, NULL ) == DS18X20_OK) { wakepoint = getMillis() + DS18B20_TCONV_12BIT; while (! ((signed long)getMillis() - (signed long)wakepoint >= 0)) { set_sleep_mode(SLEEP_MODE_IDLE); sleep_mode(); } // Power the radio up PORTA |= _BV(PINA1); // Wakepoint set to now +100ms to allow radio to wake wakepoint = getMillis() + 100; for ( i = 0; i < numSensors; i++ ) { radiobuf.tenthousandths = -9999999L; if (DS18X20_read_maxres( &gSensorIDs[i][0], &(radiobuf.tenthousandths) ) != DS18X20_OK) { radiobuf.tenthousandths = -9999999L; } //myPutStr("Sensor "); uint8_t j; for (j=0;j<OW_ROMCODE_SIZE;j++) { radiobuf.sensid[j] = gSensorIDs[i][j]; //myPutUint8(gSensorIDs[i][j]); } //myPutStr(" = "); //sprintf(debugbuf, "%d.%d\r\n", (int)(radiobuf.tenthousandths/10000), (int)(radiobuf.tenthousandths % 10000)); //myPutStr(debugbuf); if (0 == i) { // First time around, radio not initialized while (! ((signed long)getMillis() - (signed long)wakepoint >= 0)) { set_sleep_mode(SLEEP_MODE_IDLE); sleep_mode(); } radioInit(); // No auto ack radioSetAutoAck(0); radioOpenWritingPipe(pipe); } radiobuf.tstamp = getMillis(); //myPutStr("about to radioWrite, i="); //myPutUint8(i); //myPutStr("..."); radioWrite(&radiobuf,sizeof(radiobuf)); //myPutStr("Done\r\n"); } // Power the radio down PORTA &= ~_BV(PINA1); // Plus the CE and CSN pins PORTA &= ~_BV(PINA7); PORTB &= ~_BV(PINB2); // And the onewire bus PORTA &= ~_BV(PINA2); } else { myPutStr("Error measuring sensors\n"); } //tmp = getMillis(); //radioWrite(&tmp , sizeof(unsigned long) ); // Sleep hard until WDT fires set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_mode(); } }
int main() { cli(); wdt_disable(); // To make sure nothing weird happens init_tlc5940(); init_spi(); init_ps(); init_blank_timer(); init_effect_timer(); init_playlist(); initUSART(); sei(); hcsr04_start_continuous_meas(); adc_start(); serial_elo_init(); // Select correct startup mode pick_startup_mode(); while(1) { if(serial_available()) { uint8_t cmd = serial_read(); #if defined AVR_ZCL serial_zcl_process(cmd); #elif defined AVR_ELO serial_elo_process(cmd); #elif defined SIMU // Do nothing #else #error Unsupported serial communication type #endif } switch (mode) { case MODE_SLEEP: // Fall through to MODE_IDLE case MODE_IDLE: // No operation sleep_mode(); break; case MODE_PLAYLIST: ticks = centisecs(); if (ticks > effect_length) { next_effect(); init_current_effect(); } // no need to break! // fall to MODE_EFFECT on purpose case MODE_EFFECT: // If a buffer is not yet flipped if (flags.may_flip) break; // Update clock and sensor values ticks = centisecs(); sensors.distance1 = hcsr04_get_distance_in_cm(); sensors.distance2 = hcsr04_get_distance_in_cm(); //TODO: use separate sensor sensors.ambient_light = adc_get(0) >> 2; sensors.sound_pressure_level = adc_get(1) >> 2; // Do the actual drawing draw_t draw = (draw_t)pgm_get(effect->draw,word); if (draw != NULL) { draw(); allow_flipping(true); } // Slow down drawing if FPS is going to be too high uint16_t target_ticks = ticks + pgm_get(effect->minimum_ticks,byte); while (centisecs() < target_ticks ) { sleep_mode(); } break; } } return 0; }
void systemSleep() { set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Sleep mode is set here sleep_enable(); sleep_mode(); // System actually sleeps here sleep_disable(); // System continues execution here when watchdog timed out }
void micro_sleep(uint8_t howlong) { uint8_t saved_sreg = SREG, saved_howlong = howlong; #if AVR_CONF_USE32KCRYSTAL /* Save TIMER2 configuration if clock.c is using it */ uint8_t savedTCNT2=TCNT2, savedTCCR2A=TCCR2A, savedTCCR2B = TCCR2B, savedOCR2A = OCR2A; #endif // if (howlong==0) { // set_sleep_mode(SLEEP_MODE_PWR_DOWN); // UART can't wake from powerdown // } else { set_sleep_mode(SLEEP_MODE_PWR_SAVE); // Sleep for howlong seconds if (howlong==0) howlong=3; // 3*32/(32768/1024) = 3 second sleep cycle if not specified cli(); // Disable interrupts for the present ASSR |= (1 << AS2); // Set TIMER2 asyncronous from external crystal TCCR2A =(1<<WGM21); // CTC mode TCCR2B =((1<<CS22)|(1<<CS21)|(1<<CS20));// Prescale by 1024 = 32 ticks/sec // while(ASSR & (1 << TCR2BUB)); // Wait for TCNT2 write to finish. OCR2A = howlong*32; // Set TIMER2 output compare register // while(ASSR & (1 << OCR2AUB)); // Wait for OCR2 write to finish. SREG = saved_sreg; // Restore interrupt state. // UCSR(USART,B)&= ~(1<<RXCIE(USART)) // Disable the RX Complete interrupt; // UCSR0B|=(1<<RXCIE0); // Enable UART0 RX complete interrupt // UCSR1B|=(1<<RXCIE1); // Enable UART1 RX complete interrupt // TCNT2 = 0; // Reset TIMER2 timer counter value. // while(ASSR & (1 << TCN2UB)); // Wait for TCNT2 write to finish before entering sleep. // TIMSK2 |= (1 << OCIE2A); // Enable TIMER2 output compare interrupt. // } TCNT2 = 0; // Reset timer watchdog_stop(); // Silence annoying distractions while(ASSR & (1 << TCN2UB)); // Wait for TCNT2 write to (which assures TCCR2x and OCR2A are finished!) TIMSK2 |= (1 << OCIE2A); // Enable TIMER2 output compare interrupt SMCR |= (1 << SE); // Enable sleep mode. while (1) { // TCNT2 = 0; // Cleared automatically in CTC mode // while(ASSR & (1 << TCN2UB)); // Wait for TCNT2 write to finish before entering sleep. serial_char_received=0; // Set when chars received by UART sleep_mode(); // Sleep /* Adjust clock.c for the time spent sleeping */ extern void clock_adjust_seconds(uint8_t howmany); clock_adjust_seconds(howlong); // if (TIMSK2&(1<<OCIE2A)) break; // Exit sleep if not awakened by TIMER2 PRINTF("."); if (saved_howlong) break; // Exit sleep if nonzero time specified // PRINTF("%d",serial_char_received); if (serial_char_received) break; } SMCR &= ~(1 << SE); //Disable sleep mode after wakeup #if AVR_CONF_USE32KCRYSTAL /* Restore clock.c configuration */ // OCRSetup(); cli(); TCCR2A = savedTCCR2A; TCCR2B = savedTCCR2B; OCR2A = savedOCR2A; TCNT2 = savedTCNT2; sei(); #else TIMSK2 &= ~(1 << OCIE2A); //Disable TIMER2 interrupt #endif watchdog_start(); }
int main(void) { unsigned char i; char * _ptr; const char * _ptr1; //Initialize display buffer with StartUp strings strcpy_P(&str_array[vga_symbols_per_row*18],&str1[0]); strcpy_P(&str_array[vga_symbols_per_row*19],&str2[0]); strcpy_P(&str_array[vga_symbols_per_row*0],&str3[0]); strcpy_P(&str_array[vga_symbols_per_row*5],&str4[0]); strcpy_P(&str_array[vga_symbols_per_row*10],&str5[0]); avr_init(); for(;;) { //Wait compare interrupt signal from Timer1 sleep_mode(); //Check visible field if(video_enable_flg) { //OK, visible //Main render routine //Set pointer for render line (display bufffer) _ptr = &str_array[raw_render * vga_symbols_per_row]; //Set pointer for render line (character generator) _ptr1 = &symbol[0][y_line_render >> 1]; //Cycle for render line i = vga_symbols_per_row; while(i--) { SPDR = PRG_RDB(_ptr1 + (* _ptr++)*symbol_height/2); video_on; //That's a great pity can't shift data faster (8Mhz at FOSC=16Mhz)!! NOP; NOP; } //Delay for draw last symbol NOP; NOP; NOP; NOP; NOP; NOP; video_off; } else { //Not visible //Can do something else.. //*****Users handlers example static unsigned int framecount, time; //Simplest task switcher (linecount<45 not visible) switch ( linecount ) { //Task for make ADC0 convertion case 0: //Enable conversion only at the begin of video line count //to avoid flickering at the top display ADCSRA |= 1<<ADSC;//start the single conversion while(bit_is_set(ADCSRA, ADSC)); break; //Task for refresh ADC0 convertion result case 3: _display_adc(196*ADCH); break; //Task for show and count time value case 9: //Count frame for time count framecount++; //Time count if (framecount==60) { framecount = 0; //Running timer only when PinC.1 = "0"; if (bit_is_clear(PINC,1)) { //Increment every second _display_time(++time); } else { time = 0; } } break; //Default task Check and show state of PINC.1 default: if (bit_is_set(PINC,1)) str_array[7] = '1'; else str_array[7] = '0'; } //*****Users handlers example } }//for(;;)