/** **************************************************************************************** * @brief Read ADC conversion result * @param[in] S ADC read configuration, contains work mode, trigger source, start/end channel * @param[in] buf ADC result buffer * @param[in] samples Sample number * @param[in] callback callback after all the samples conversion finish * @description * This function is used to read ADC specified channel conversion result. * @note * When use scaning mode, only can select first 6 channel (AIN0,AIN1,AIN2,AIN3,AIN01,AIN23) ***************************************************************************************** */ void adc_read(const adc_read_configuration *S, int16_t *buf, uint32_t samples, void (*callback)(void)) { uint32_t reg; uint32_t mask; adc_env.mode = S->mode; adc_env.trig_src = S->trig_src; adc_env.start_ch = S->start_ch; adc_env.end_ch = S->end_ch; adc_env.bufptr = buf; adc_env.samples = samples; adc_env.callback = callback; // Busrt scan mode, need read all of the channel after once trigger if (S->mode == SINGLE_SCAN_MOD) { scan_ch_num = S->end_ch - S->start_ch + 1; } else { scan_ch_num = 1; } #if (CONFIG_ADC_ENABLE_INTERRUPT==FALSE) && (ADC_DMA_EN==TRUE) dma_init(); // samples*2 <= 0x7FF dma_rx(DMA_TRANS_HALF_WORD, DMA_ADC, (uint32_t)buf, samples*2, callback); #endif mask = ADC_MASK_SCAN_CH_START | ADC_MASK_SCAN_CH_END | ADC_MASK_SCAN_INTV | ADC_MASK_SCAN_EN | ADC_MASK_SINGLE_EN | ADC_MASK_START_SEL | ADC_MASK_SFT_START | ADC_MASK_POW_UP_DLY | ADC_MASK_POW_DN_CTRL | ADC_MASK_ADC_EN; reg = (S->start_ch << ADC_POS_SCAN_CH_START) // set adc channel, or set scan start channel | (S->end_ch << ADC_POS_SCAN_CH_END) // set scan end channel | (0x03 << ADC_POS_SCAN_INTV) // should not be set to 0 at single mode | (S->trig_src << ADC_POS_START_SEL) // select ADC trigger source | (0x3F << ADC_POS_POW_UP_DLY) // power up delay | ADC_MASK_POW_DN_CTRL // enable power down control by hardware, only work in single mode | ADC_MASK_ADC_EN; // enable ADC if ((S->mode == SINGLE_SCAN_MOD) || (S->mode == SINGLE_MOD)) { // default is continue reg |= ADC_MASK_SINGLE_EN; // single mode enable } if ((S->mode == SINGLE_SCAN_MOD) || (S->mode == CONTINUE_SCAN_MOD)) { // default is not scan reg |= ADC_MASK_SCAN_EN; // scan mode enable } adc_adc_SetADC0WithMask(QN_ADC, mask, reg); if (adc_env.trig_src == ADC_TRIG_SOFT) { // SFT_START 0->1 trigger ADC conversion adc_adc_SetADC0WithMask(QN_ADC, ADC_MASK_SFT_START, MASK_ENABLE); } #if CONFIG_ADC_ENABLE_INTERRUPT==TRUE dev_prevent_sleep(PM_MASK_ADC_ACTIVE_BIT); #elif (CONFIG_ADC_ENABLE_INTERRUPT==FALSE) && (ADC_DMA_EN==FALSE) // polling while(samples > 0) { for (int i = 0; ((i < scan_ch_num)&&(samples)); i++) { while(!(adc_adc_GetSR(QN_ADC) & ADC_MASK_DAT_RDY_IF)); *buf++ = adc_adc_GetDATA(QN_ADC); samples--; } // Single mode enable, software trigger if ( (samples) && (adc_env.trig_src == ADC_TRIG_SOFT) && ((S->mode == SINGLE_SCAN_MOD)||(S->mode == SINGLE_MOD))) { // SFT_START 0->1 trigger ADC conversion adc_adc_SetADC0WithMask(QN_ADC, ADC_MASK_SFT_START, MASK_DISABLE); adc_adc_SetADC0WithMask(QN_ADC, ADC_MASK_SFT_START, MASK_ENABLE); } } // disable ADC adc_enable(MASK_DISABLE); adc_clean_fifo(); #if ADC_CALLBACK_EN==TRUE if (callback != NULL) { callback(); } #endif #endif }
/*! * \brief Get the current potentiometer value. * * \param pxLog a Log structure. * * \return true upon success, false if error. */ bool b_potentiometer_get_value( xLogDef *pxLog ) { int i_current_val; /* enable channel for sensor */ adc_enable( adc, ADC_POTENTIOMETER_CHANNEL ); /* start conversion */ adc_start( adc ); /* get value for sensor */ i_current_val = adc_get_value( adc, ADC_POTENTIOMETER_CHANNEL ) * 100 / ADC_MAX_VALUE; /* Disable channel for sensor */ adc_disable( adc, ADC_POTENTIOMETER_CHANNEL ); // Alloc memory for the log string. pxLog->pcStringLog = pvPortMalloc( 16*sizeof( char ) ); if( NULL == pxLog->pcStringLog ) { return( false ); } pxLog->pfFreeStringLog = vPortFree; // Because pvPortMalloc() was used to // alloc the log string. // Build the log string. if( i_current_val <= ul_pot_min ) { sprintf( pxLog->pcStringLog, "%3d%% | min", i_current_val ); // if alarms have to be checked and no alarm for min was pending if (( b_pot_alarm == pdTRUE ) && ( b_pot_alarm_min == pdFALSE )) { // alarm has been taken into account, // don't reenter this test before leaving min area b_pot_alarm_min = pdTRUE; // allow alarm if max is reached b_pot_alarm_max = pdFALSE; // post alarm to SMTP task v_SMTP_Post("Min Potentiometer Alarm", NULL); } } else if( i_current_val >= ul_pot_max ) { sprintf( pxLog->pcStringLog, "%3d%% | max", i_current_val ); // if alarms have to be checked and no alarm for max was pending if (( b_pot_alarm == pdTRUE ) && ( b_pot_alarm_max == pdFALSE )) { // alarm has been taken into account, // don't reenter this test before leaving max area b_pot_alarm_max = pdTRUE; // allow alarm if min is reached b_pot_alarm_min = pdFALSE; // post alarm to SMTP task v_SMTP_Post("Max Potentiometer Alarm", NULL); } } else { sprintf( pxLog->pcStringLog, "%3d%%", i_current_val ); // if alarms have to be checked if ( b_pot_alarm == pdTRUE ) { // no alarm is pending b_pot_alarm_max = pdFALSE; b_pot_alarm_min = pdFALSE; } } return( true ); }
/** * \brief Example entry point. * * \return Unused (ANSI-C compatibility). */ int main(void) { uint8_t c_choice; int16_t s_adc_value; int16_t s_dac_value; int16_t s_threshold = 0; float f_dac_data; uint32_t ul_dac_data; /* Initialize the SAM system. */ sysclk_init(); board_init(); configure_console(); /* Output example information. */ puts(STRING_HEADER); /* Initialize threshold. */ gs_us_low_threshold = 1023; gs_us_high_threshold = 4095; struct adc_config adc_cfg = { /* System clock division factor is 16 */ .prescal = ADC_PRESCAL_DIV16, /* The APB clock is used */ .clksel = ADC_CLKSEL_APBCLK, /* Max speed is 150K */ .speed = ADC_SPEED_150K, /* ADC Reference voltage is internal 1.0V */ .refsel = ADC_REFSEL_0, /* Enables the Startup time */ .start_up = CONFIG_ADC_STARTUP }; struct adc_seq_config adc_seq_cfg = { /* Select Vref for shift cycle */ .zoomrange = ADC_ZOOMRANGE_0, /* Pad Ground */ .muxneg = ADC_MUXNEG_1, /* DAC Internal */ .muxpos = ADC_MUXPOS_3, /* Enables the internal voltage sources */ .internal = ADC_INTERNAL_3, /* Disables the ADC gain error reduction */ .gcomp = ADC_GCOMP_DIS, /* Disables the HWLA mode */ .hwla = ADC_HWLA_DIS, /* 12-bits resolution */ .res = ADC_RES_12_BIT, /* Enables the single-ended mode */ .bipolar = ADC_BIPOLAR_SINGLEENDED }; struct adc_ch_config adc_ch_cfg = { .seq_cfg = &adc_seq_cfg, /* Internal Timer Max Counter */ .internal_timer_max_count = 60, /* Window monitor mode is off */ .window_mode = ADC_WM_MODE_3, /* The equivalent voltage value is 1023 * VOLT_REF / 4095 = 250mv. */ .low_threshold = gs_us_low_threshold, /* The equivalent voltage value is 4095 * VOLT_REF / 4095 = 1000mv. */ .high_threshold = gs_us_high_threshold, }; start_dac(); if(adc_init(&g_adc_inst, ADCIFE, &adc_cfg) != STATUS_OK) { puts("-F- ADC Init Fail!\n\r"); while(1); } if(adc_enable(&g_adc_inst) != STATUS_OK) { puts("-F- ADC Enable Fail!\n\r"); while(1); } adc_ch_set_config(&g_adc_inst, &adc_ch_cfg); adc_configure_trigger(&g_adc_inst, ADC_TRIG_CON); adc_configure_gain(&g_adc_inst, ADC_GAIN_1X); adc_set_callback(&g_adc_inst, ADC_WINDOW_MONITOR, adcife_wm_handler, ADCIFE_IRQn, 1); /* Display main menu. */ display_menu(); while (1) { scanf("%c", (char *)&c_choice); printf("%c\r\n", c_choice); switch (c_choice) { case '0': adc_disable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR); printf("DAC output is set to(mv) from 0mv to %dmv: ", (int32_t)VOLT_REF); s_dac_value = get_voltage(); puts("\r"); f_dac_data = (float)s_dac_value * DACC_MAX_DATA / VDDANA; ul_dac_data = f_to_int(f_dac_data); if (s_dac_value >= 0) { dacc_write_conversion_data(DACC, ul_dac_data); } delay_ms(100); adc_clear_status(&g_adc_inst, ADCIFE_SCR_WM); adc_enable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR); break; case '1': adc_disable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR); printf("Low threshold is set to(mv) from 0mv to %dmv: ", (int32_t)VOLT_REF); s_threshold = get_voltage(); puts("\r"); if (s_threshold >= 0) { s_adc_value = s_threshold * MAX_DIGITAL / VOLT_REF; adc_configure_wm_threshold(&g_adc_inst, s_adc_value, gs_us_high_threshold); /* Renew low threshold. */ gs_us_low_threshold = s_adc_value; float f_low_threshold = (float)gs_us_low_threshold * VOLT_REF / MAX_DIGITAL; uint32_t ul_low_threshold = f_to_int(f_low_threshold); printf("Setting low threshold to %u mv (reg value to 0x%x ~%d%%)\n\r", ul_low_threshold, gs_us_low_threshold, gs_us_low_threshold * 100 / MAX_DIGITAL); } adc_clear_status(&g_adc_inst, ADCIFE_SCR_WM); adc_enable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR); break; case '2': adc_disable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR); printf("High threshold is set to(mv)from 0mv to %dmv:", (int32_t)VOLT_REF); s_threshold = get_voltage(); puts("\r"); if (s_threshold >= 0) { s_adc_value = s_threshold * MAX_DIGITAL / VOLT_REF; adc_configure_wm_threshold(&g_adc_inst, gs_us_low_threshold, s_adc_value); /* Renew high threshold. */ gs_us_high_threshold = s_adc_value; float f_high_threshold = (float)gs_us_high_threshold * VOLT_REF / MAX_DIGITAL; uint32_t ul_high_threshold = f_to_int(f_high_threshold); printf("Setting high threshold to %u mv (reg value to 0x%x ~%d%%)\n\r", ul_high_threshold, gs_us_high_threshold, gs_us_high_threshold * 100 / MAX_DIGITAL); } adc_clear_status(&g_adc_inst, ADCIFE_SCR_WM); adc_enable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR); break; case '3': adc_disable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR); puts("-a. Above low threshold.\n\r" "-b. Below high threshold.\n\r" "-c. In the comparison window.\n\r" "-d. Out of the comparison window.\n\r" "-q. Quit the setting.\r"); c_choice = get_wm_mode(); adc_configure_wm_mode(&g_adc_inst, c_choice); printf("Comparison mode is %c.\n\r", 'a' + c_choice - 1); adc_clear_status(&g_adc_inst, ADCIFE_SCR_WM); adc_enable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR); break; case 'm': display_menu(); break; case 'i': display_info(); adc_clear_status(&g_adc_inst, ADCIFE_SCR_WM); adc_enable_interrupt(&g_adc_inst, ADC_WINDOW_MONITOR); break; } puts("Press \'m\' or \'M\' to display the main menu again!\r"); } }
/** **************************************************************************************** * @brief ADC interrupt handler **************************************************************************************** */ void ADC_IRQHandler(void) { uint32_t status, data; status = adc_adc_GetSR(QN_ADC); if (status & ADC_MASK_DAT_RDY_IF) { while (adc_adc_GetSR(QN_ADC) & ADC_MASK_DAT_RDY_IF) { /* clear interrupt flag by read data */ data = adc_adc_GetDATA(QN_ADC); if (adc_env.samples > 0) { *adc_env.bufptr++ = data; adc_env.samples--; if (adc_env.samples == 0) { adc_enable(MASK_DISABLE); // disable ADC adc_clean_fifo(); NVIC_ClearPendingIRQ(ADC_IRQn); #if ADC_CALLBACK_EN==TRUE if (adc_env.callback != NULL) { adc_env.callback(); } #endif } else { // single mode enable, software trigger if ((adc_env.trig_src == ADC_TRIG_SOFT) && ((adc_env.mode == SINGLE_SCAN_MOD)||(adc_env.mode == SINGLE_MOD))) { scan_ch_num--; if (scan_ch_num == 0) { // SFT_START 0->1 trigger ADC conversion adc_adc_SetADC0WithMask(QN_ADC, ADC_MASK_SFT_START, MASK_DISABLE); adc_adc_SetADC0WithMask(QN_ADC, ADC_MASK_SFT_START, MASK_ENABLE); // restore scan_ch_num if (adc_env.mode == SINGLE_SCAN_MOD) { scan_ch_num = adc_env.end_ch - adc_env.start_ch + 1; } else { scan_ch_num = 1; } } } } } } } if (status & ADC_MASK_FIFO_OF_IF) { adc_clean_fifo(); /* clear interrupt flag */ adc_adc_ClrSR(QN_ADC, ADC_MASK_FIFO_OF_IF); } if (status & ADC_MASK_WCMP_IF) { /* clear interrupt flag */ adc_adc_ClrSR(QN_ADC, ADC_MASK_WCMP_IF); #if ADC_WCMP_CALLBACK_EN==TRUE if (adc_env.wcmp_callback != NULL) { adc_env.wcmp_callback(); } #endif } }
void alphasense_adc_getValue( void ) { //ALPHASENSE_STATS * const ps = &g_internal; struct adc_config adc_conf; struct adc_channel_config adcch_conf; uint8_t inputgain = 1;//, elements = 20; //char szBUF[64]; // DISABLE jtag - it locks the upper 4 pins of PORT B CCP = CCP_IOREG_gc; // Secret handshake MCU.MCUCR = 0b00000001; PORTB.PIN0CTRL = PORT_OPC_TOTEM_gc; // Auxiliary Electrode PORTB.PIN2CTRL = PORT_OPC_TOTEM_gc; // Working Electrode PORTB.PIN6CTRL = PORT_OPC_TOTEM_gc; // GND x offset adc_read_configuration(&ALPHASENSE_ADC, &adc_conf); adcch_read_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf); adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12, ADC_REF_VCC); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_set_clock_rate(&adc_conf, 200000UL); adc_write_configuration(&ALPHASENSE_ADC, &adc_conf); adcch_set_input(&adcch_conf, ADCCH_POS_PIN6, ADCCH_NEG_NONE, inputgain); adcch_write_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf); adc_enable(&ALPHASENSE_ADC); adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); const int16_t off = adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_disable(&ALPHASENSE_ADC); //sprintf_P(szBUF,PSTR("Offset: %u\t"),off); //debug_string(NORMAL,szBUF,false); //adcch_set_input(&adcch_conf, ADCCH_POS_BANDGAP, ADCCH_NEG_NONE, inputgain); //adcch_write_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf); //adc_enable(&ALPHASENSE_ADC); //adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //const uint16_t gain = adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //adc_disable(&ALPHASENSE_ADC); ////sprintf_P(szBUF,PSTR("gain: %u\t"),gain); ////debug_string(NORMAL,szBUF,false); adcch_set_input(&adcch_conf, ADCCH_POS_PIN0, ADCCH_NEG_NONE, inputgain); adcch_write_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf); adc_enable(&ALPHASENSE_ADC); adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); const int16_t adc_w = adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH)-off; adc_disable(&ALPHASENSE_ADC); //sprintf_P(szBUF,PSTR("ADC_WORK: %u\t"),adc_w); //debug_string(NORMAL,szBUF,false); adcch_set_input(&adcch_conf, ADCCH_POS_PIN2, ADCCH_NEG_NONE, inputgain); adcch_write_configuration(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH, &adcch_conf); adc_enable(&ALPHASENSE_ADC); adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); const int16_t adc_a = adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH)-off; adc_disable(&ALPHASENSE_ADC); //sprintf_P(szBUF,PSTR("ADC_AUX: %u\r\n"),adc_a); //debug_string(NORMAL,szBUF,false); //adc_enable(&ALPHASENSE_ADC); // //for (int i=0;i<elements;i++) //{ //adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //adc_start_conversion(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //adc_wait_for_interrupt_flag(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); //result[i]=adc_get_result(&ALPHASENSE_ADC, ALPHASENSE_ADC_CH); // //} //adc_disable(&ALPHASENSE_ADC); PORTB.PIN0CTRL = PORT_OPC_PULLUP_gc; PORTB.PIN2CTRL = PORT_OPC_PULLUP_gc; PORTB.PIN6CTRL = PORT_OPC_PULLUP_gc; g_recordingData_Alphasense = true; g_partialSumWork+=(int32_t)adc_w; g_partialSumAux+=(int32_t)adc_a; g_partialCount_Alphasense++; g_recordingData_Alphasense = false; //sprintf_P(szBUF,PSTR("Sample: %u\tPartialSumWork: %lu\tPartialSumAux: %lu\r\n"),g_partialCount, g_partialSumWork,g_partialSumAux); //debug_string(NORMAL,szBUF,false); //ps->working = adc_w; //ps->aux = adc_a; }
/** * \brief This function initialize the ADCB,gets ADCB-CH0 offset and configure * ADCB-CH0 for oversampling * - ADCB-CH0 is configured in 12bit, signed differential mode without gain * - To read ADC offset, ADCB-Pin3(PB3) used as both +ve and -ve input * - After reading ADC offset,to start oversampling,ADCB +ve and -ve input * are configured */ void init_adc(void) { /* Initialize configuration structures */ adc_read_configuration(&ADCB, &adc_conf); adcch_read_configuration(&ADCB, ADC_CH0, &adc_ch_conf); /* Configure the ADCB module: * - Signed, 12-bit resolution * - External reference on AREFB pin. * - 250 KSPS ADC clock rate * - Manual conversion triggering * - Callback function */ adc_set_conversion_parameters(&adc_conf, ADC_SIGN_ON, ADC_RES_12, ADC_REF_AREFB); adc_set_clock_rate(&adc_conf, 250000UL); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_write_configuration(&ADCB, &adc_conf); adc_set_callback(&ADCB, &adc_handler); /* Configure ADC B channel 0 for offset calculation * - Differential mode without gain * - Selected Pin3 (PB3) as +ve and -ve input for offset calculation */ adcch_set_input(&adc_ch_conf, ADCCH_POS_PIN3, ADCCH_NEG_PIN3, 1); adcch_write_configuration(&ADCB, ADC_CH0, &adc_ch_conf); /* Enable ADCB */ adc_enable(&ADCB); /* Get ADC offset in to ADC_Offset variable and disable ADC */ adc_offset_one_sample = adc_offset_get_signed(); /* Find ADC_Offset for for total number of samples */ adc_offset = adc_offset_one_sample * ADC_OVER_SAMPLED_NUMBER; /* Disable ADC to configure for oversampling */ adc_disable(&ADCB); /* Configure the ADCB module for oversampling: * - Signed, 12-bit resolution * - External reference on AREFB pin. * - 250 KSPS ADC clock rate * - Free running mode on Channel0 ( First Channel) */ adc_set_conversion_trigger(&adc_conf, ADC_TRIG_FREERUN_SWEEP, 1, 0); adc_write_configuration(&ADCB, &adc_conf); /* Configure ADC B channel 0 for oversampling input * - Differential mode without gain * - Selected Pin1 (PB1) as +ve and Pin2 (PB2) as-ve input * - Conversion complete interrupt */ adcch_set_input(&adc_ch_conf, ADC_OVER_SAMP_POSTIVE_PIN, ADC_OVER_SAMP_NEGATIVE_PIN, 1); adcch_set_interrupt_mode(&adc_ch_conf, ADCCH_MODE_COMPLETE); adcch_enable_interrupt(&adc_ch_conf); adcch_write_configuration(&ADCB, ADC_CH0, &adc_ch_conf); /* Enable ADCB */ adc_enable(&ADCB); }
void vControl ( void *pvParameters ) { portTickType xLastWakeTime; signed char valx, valy; unsigned char ls, rs, lb, rb; can_frame_t out_frame; can_frame_t in_frame; out_frame.id = 1; out_frame.dlc = 6; xLastWakeTime = xTaskGetTickCount (); /* Button init */ buttons_init (); /* FSM init */ fsm_init (); /* CAN init */ can_init (); /* ADC init */ adc_init ( ctrlNUM_ADC_VALUES ); /* Touch init */ touch_init ( 30, 30, 30, 30 ); while (1) { vTaskDelayUntil ( &xLastWakeTime, ctrlTASK_FREQUENCY ); if ( adc_conversion_complete () == pdTRUE ) { adc_disable (); adc_get_value ( &valx, 0 ); adc_get_value ( &valy, 0 ); touch_measure ( &ls, &rs, &lb, &rb ); out_frame.data[0] = valx; out_frame.data[1] = valy; out_frame.data[2] = ls; out_frame.data[3] = rs; out_frame.data[4] = lb; out_frame.data[5] = rb; if (fsm_get_state() == ST_PLAY) { can_transmit (&out_frame); } can_receive (&in_frame, 0); if (in_frame.data[0] == GAME_SENSOR_TRIGGERED) { // TODO: set triggered state fsm_event_t *event = pvPortMalloc (sizeof (fsm_event_t)); event->type = EV_STOP; event->ptr = NULL; fsm_event_put (event, portMAX_DELAY); in_frame.data[0] = 0; } else if (in_frame.data[0] == GAME_SENSOR_CLEARED) { // TODO: set cleared state in_frame.data[0] = 0; } adc_enable (); adc_conversion_start (); } fsm_update (); } }
void ui_wakeup(void) { backlight_start_pwm(); adc_enable(&LIGHT_SENSOR_ADC_MODULE); led_power_on(); }
int main(void) { system_init(); clock_init(); led_init(); led_set(0x01); //show life UART_Init(BAUD); UART_Write("\nInit"); //Show UART life motor_init(); adc_init(); //Enable Analog pins adc_enable(CHANNEL_SENSOR_LEFT); adc_enable(CHANNEL_SENSOR_RIGHT); adc_enable(CHANNEL_SENSOR_FRONT); //Sensor value variables uint16_t sensor_left_value = 0; uint16_t sensor_right_value = 0; uint16_t sensor_front_value = 0; //Analog inputSignal conditioning arrays circBuf_t left_buffer; circBuf_t right_buffer; circBuf_t front_buffer; //Initialise sensor averaging buffers initCircBuf(&left_buffer, ROLLING_AVERAGE_LENGTH); initCircBuf(&right_buffer, ROLLING_AVERAGE_LENGTH); initCircBuf(&front_buffer, ROLLING_AVERAGE_LENGTH); //UART output buffer char buffer[UART_BUFF_SIZE] = {0}; //=====Application specific variables===== //TODO: initialise circbuff circBuf_t sweep_times; initCircBuf(&sweep_times, SWEEP_TIME_MEMORY_LENGTH); short sweep_del_t_last = 0; short sweep_end_t_last = 0; //time when front sensor begins to see grey. uint32_t grey_time_start = 0; bool sweep_ended = FALSE; //set high if the front sensor crosses the line bool front_crossed_black = FALSE; //set high if front finds finish line bool front_crossed_grey = FALSE; bool sensor_update_serviced = TRUE; action current_action = IDLE; int16_t forward_speed = DEFAULT_FORWARD_SPEED; int16_t turn_speed = DEFAULT_SPEED; //Scheduler variables uint32_t t = 0; //Loop control time variables uint32_t maze_logic_t_last = 0; uint32_t sample_t_last = 0; uint32_t UART_t_last = 0; clock_set_ms(0); sei(); // Enable all interrupts UART_Write("ialized\n"); //wait for start command DDRD &= ~BIT(7); PORTD |= BIT(7); //motor_set(128, 128); while((PIND & BIT(7))) { continue; } while(1) { t = clock_get_ms(); //check if a sensor update has occured if ((sensor_update_serviced == FALSE) && (t%MAZE_LOGIC_PERIOD == 0) && (t != maze_logic_t_last)) { sensor_update_serviced = TRUE; // finishing condition is a grey read for a set period if(is_grey(sensor_front_value) && front_crossed_grey == FALSE) { front_crossed_grey = TRUE; grey_time_start = t; //TODO: adjust so that finishing condition is a 1/2 whole sweeps on grey line } else if (is_grey(sensor_front_value) && front_crossed_grey == TRUE) { // if ((grey_time_start + GREY_TIME) <= t ) { // Finish line found. Stop robot. maze_completed(); // wait for button push front_crossed_grey = FALSE; } } else { front_crossed_grey = FALSE; } //see if the front sensor crosses the line in case we run into a gap if(is_black(sensor_front_value)&&front_crossed_black == FALSE) { front_crossed_black = TRUE; //check for false finish line if(front_crossed_grey) front_crossed_grey = FALSE; //false alarm } // when both rear sensors go black, this indicates an intersection (turns included). // try turning left if(is_black(sensor_left_value) && is_black(sensor_right_value)) { sweep_ended = TRUE; motor_set(0, 255); PORTB |= BIT(3); PORTB |= BIT(4); } //when both sensors are completely white this indicates a dead end or a tape-gap else if (is_white(sensor_left_value) && is_white(sensor_right_value)) { sweep_ended = TRUE; PORTB &= ~BIT(3); PORTB &= ~BIT(4); //current_action = ON_WHITE; //Check if the front sensor is on black, or has been during the last sweep. if(is_black(sensor_front_value) | front_crossed_black) motor_set(255, 255); else if (is_white(sensor_front_value)) motor_set(-255, 255); } //sweep to the side that reads the darkest value else if (sensor_left_value + SENSOR_TOLLERANCE < sensor_right_value) { PORTB &= ~BIT(3); PORTB |= BIT(4); if (current_action == SWEEP_LEFT) sweep_ended = TRUE; current_action = SWEEP_RIGHT; motor_set(forward_speed + turn_speed, forward_speed); } else if(sensor_right_value + SENSOR_TOLLERANCE< sensor_left_value) { PORTB |= BIT(3); PORTB &= ~BIT(4); if (current_action == SWEEP_RIGHT) sweep_ended = TRUE; current_action = SWEEP_LEFT; motor_set(forward_speed, forward_speed+ turn_speed); } //If a new sweep started this cycle, find how long it took if (sweep_ended) { //reset front black crossing detection variable sweep_ended = FALSE; if (front_crossed_black) front_crossed_black = FALSE; //Calculate sweep time sweep_del_t_last = t - sweep_end_t_last; sweep_end_t_last = t; writeCircBuf(&sweep_times, sweep_del_t_last); //adjust turn_speed for battery level. if (sweep_del_t_last > IDEAL_SWEEP_TIME) { turn_speed += 5; } if (sweep_del_t_last < IDEAL_SWEEP_TIME) { turn_speed -= 5; } turn_speed = regulate_within(turn_speed, MIN_TURN_SPEED, MAX_TURN_SPEED); } } //Sensor value update if((t%SAMPLE_PERIOD == 0) & (t!=sample_t_last)) { sample_t_last = t; //read in analog values sensor_update(CHANNEL_SENSOR_LEFT, &left_buffer, &sensor_left_value ); sensor_update(CHANNEL_SENSOR_RIGHT, &right_buffer, &sensor_right_value ); sensor_update(CHANNEL_SENSOR_FRONT, &front_buffer, &sensor_front_value ); sensor_update_serviced = FALSE; } //display debug information if((t%UART_PERIOD == 0) & (t != UART_t_last) & UART_ENABLED) { UART_t_last = t; sprintf(buffer, "sweep_time: %u \n", sweep_del_t_last); UART_Write(buffer); sprintf(buffer, "L: %u F: %u R: %u", sensor_left_value, sensor_front_value, sensor_right_value); UART_Write(buffer); UART_Write("\n"); } } }
int main(void) { uint8_t state = 0; serial_baud_9600(); serial_mode_8e1(); serial_transmitter_enable(); sleep_mode_idle(); pin13_mode_output(); pin13_low(); /* setup timer2 to trigger interrupt a * once every millisecond * 128 * (124 + 1) / 16MHz = 1ms */ timer2_mode_ctc(); timer2_clock_d128(); timer2_compare_a_set(124); timer2_interrupt_a_enable(); ow_timer_init(); adc_reference_internal_5v(); adc_pin_select(5); adc_clock_d128(); adc_trigger_freerunning(); adc_trigger_enable(); adc_interrupt_enable(); adc_enable(); sei(); start_temp_measure(); while (1) { uint16_t value; cli(); if (!new_value && !ev_timer) { sleep_enable(); sei(); sleep_cpu(); sleep_disable(); continue; } sei(); if (new_value) { value = adc_data(); new_value = 0; if (state && value < BOUND_LOW) { uint16_t now = time; char *p, *q; timer2_clock_reset(); time = 0; pin13_low(); p = sprint_uint16_b10(buf, now); *p++ = ' '; q= last_temp_buf; while (*q) *p++ = *q++; *p++ = '\n'; *p = '\0'; serial_puts(buf); state = 0; continue; } if (value > BOUND_HIGH) { pin13_high(); state = 1; } } if (ev_timer) handle_timer(); } }
int main(void) { struct adc_config adc_conf; struct adc_channel_config adcch_conf; board_init(); sysclk_init(); sleepmgr_init(); irq_initialize_vectors(); cpu_irq_enable(); // Initialize configuration structures. adc_read_configuration(&ADCA, &adc_conf); adcch_read_configuration(&ADCA, ADC_CH0, &adcch_conf); /* Configure the ADC module: * - unsigned, 12-bit results * - bandgap (1 V) voltage reference * - 200 kHz maximum clock rate * - manual conversion triggering */ adc_set_conversion_parameters(&adc_conf, ADC_SIGN_OFF, ADC_RES_12, ADC_REF_BANDGAP); adc_set_clock_rate(&adc_conf, 200000UL); adc_set_conversion_trigger(&adc_conf, ADC_TRIG_MANUAL, 1, 0); adc_write_configuration(&ADCA, &adc_conf); /* Configure ADC channel 0: * - single-ended measurement from configured input pin * - interrupt flag set on completed conversion */ adcch_set_input(&adcch_conf, INPUT_PIN, ADCCH_NEG_NONE, 1); adcch_set_interrupt_mode(&adcch_conf, ADCCH_MODE_COMPLETE); adcch_disable_interrupt(&adcch_conf); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); // Enable the ADC and do one dummy conversion. adc_enable(&ADCA); adc_start_conversion(&ADCA, ADC_CH0); adc_wait_for_interrupt_flag(&ADCA, ADC_CH0); // Light up LED 1, wait for button press. ioport_set_pin_low(LED1_PIN); wait_for_button(); // Perform oversampling of offset. cal_data.offset = get_mean_sample_value(); // Light up LED 2, wait for button press. ioport_set_pin_low(LED2_PIN); wait_for_button(); // Perform oversampling of 0.9 V for gain calibration. cal_data.gain = get_mean_sample_value() - cal_data.offset; // Turn off LEDs. ioport_set_pin_high(LED1_PIN); ioport_set_pin_high(LED2_PIN); // Enable interrupts on ADC channel, then trigger first conversion. adcch_enable_interrupt(&adcch_conf); adcch_write_configuration(&ADCA, ADC_CH0, &adcch_conf); adc_start_conversion(&ADCA, ADC_CH0); do { // Sleep until ADC interrupt triggers. sleepmgr_enter_sleep(); } while (1); }