int8 verificaObstaculo(void) { int result_tmp = 0; int8 result_final = 0; int result_media = 0; int8 i = 0; const int8 n_samples = 5; result_tmp = 0; for (i = n_samples; i > 0; i--) { ADC_START_CONVERSION(); adcWaitConversionFinish(); result_tmp += ADC; //lê os 10 bits do ADC _delay_us(25); //tempo de cada amostragem utilizando a frequencia do ADC em 1MHz } result_media = (result_tmp / n_samples); //faço uma média para evitar falsos positivos //printf("ADC result:\t%d\n", result_media); //debug if (result_media > 500) { result_final = 1; } if (result_media <= 500) { result_final = 0; } result_media = 0; return result_final; }
/************************************************************************* Function: ADC_init Purpose: set up the ADC to be used in IR sensor **************************************************************************/ void ADC_init(void) { SENSOR_IR_DDR &= ~_BV(SENSOR_IR_BIT); //ADC in 10bits : used in IR sensor routine : without shift left or right ADC_REFERENCE_AREF(); //ADC reference in 5V ADC_CLOCK_PRESCALER_128(); /* the original ADC frequency of this project was 125KHz (Prescaler = 128), thus, I changed it to sample faster, in 1MHz (Prescaler16) * I have some loss in precision, working in 10 bits with a frequency bigger than 200KHz, but in this case this do not matters * */ ADC_ENABLE(); ADC_SELECT_CHANNEL_2(); ADC_DIGITAL_INPUT_2_DISABLE(); ADC_START_CONVERSION(); //I discard the first sample, which takes 25 clock cycles ADC_WAIT_CONVERSION_FINISH(); }
void init_adc(void) { adcs = NULL; next_adc_to_consider = NULL; sample_buffer_head = 0; sample_buffer_count = 2; uint8_t i; for (i = 0; i < SAMPLE_BUFFER_SIZE; ++i) { sample_buffer[i] = NULL; } ADC_SET_VREF(AREF); ADC_SET_ADJUST(RIGHT); ADC_SET_AUTO_TRIGGER_SRC(ADC_TRIGGER_FREERUNNING); ADC_AUTO_TRIGGER_ENABLE(); ADC_SET_PRESCALER_DIV(64); ADC_SET_CHANNEL(ADC_CHANNEL_GND); ADC_CC_INTERRUPT_ENABLE(); ADC_ENABLE(); ADC_START_CONVERSION(); process_start(&adc_process); }
int main(void) { /* Set A7 as an output. (Needed for PWM.) */ DDRA |= _BV(DD7); PORTA = 0; /* Let input power stabilize... */ _delay_ms(500); /* * Configure Timer0 as a fast PWM. It will * - turn on the output pin at the start of each cycle * - turn it off when the value hits DUTY_CYCLE_REG * - wrap to 0 when it hits OCR0A */ TCCR0A = _BV(COM0B1) | _BV(WGM01) | _BV(WGM00); OCR0A = PWM_RESOLUTION; /* Start with 40% duty cycle and ramp up to avoid inrush. */ DUTY_CYCLE_REG = (uint8_t)(PWM_RESOLUTION * 0.40); /* Set Timer0 clock source to be main oscillator. This enables the timer. */ TCCR0B = _BV(CS00) | _BV(WGM02); /* * Turn on the ADC, * - use internal voltage ref. * - configure ADC0 as our source * - left-adjust the result, 8-bits is enough for us * - disable digital input buffer on pin * - enable the ADC. */ ADMUX = /* REF = */ _BV(REFS1) | /* INPUT = */ 0; ADCSRA |= /* PRESCALER = 16 = 2^ */ 4; ADCSRB |= /* LEFT-ADJUST */ _BV(ADLAR); DDRA &= ~_BV(DD0); DIDR0 |= _BV(ADC0D); ADC_ENABLE(); _delay_ms(1); /* * Now enter our main loop. Monitor the output voltage and manipulate * the duty cycle to control it. */ while (1) { /* Wait for the Timer0 to overflow... */ loop_until_bit_is_set(TIFR0, TOV0); /* End of our OFF period, should be peak voltage... */ TIFR0 |= _BV(TOV0); /* Clear the flag. */ /* Check the output voltage. */ ADC_START_CONVERSION(); loop_until_bit_is_clear(ADCSRA, ADSC); uint8_t adc_result = ADCH; if (adc_result < DESIRED_ADC_RESULT && DUTY_CYCLE_REG < MAX_PWM_LEVEL) { DUTY_CYCLE_REG++; } else if (adc_result > DESIRED_ADC_RESULT && DUTY_CYCLE_REG > MIN_PWM_LEVEL) { DUTY_CYCLE_REG--; } } }