ADC problem with v-usb HID mouse
Posted: Mon Feb 28, 2011 12:58 pm
Hello, forum
I am using V-USB HID mouse example on ATMEGA8 and it works fine.
I want to use ADC for mouse movement.
The general idea is that the mouse speed (.dx and .dy) depends on the speed of voltage change on ADC pin (ADC0, pin 23 in my case). The problem is that the mouse pointer (on PC screen) sometimes makes weird jumps ranging from few cm to over a half of the screen width (all on the x-axis as they should be).
Here is the code i am using. It is just for x-axis. The added code:
//*****************************************************************************
//
// ADC module initialization
//
//*****************************************************************************
void adc_init(void)
{
//select reference voltage
//AVCC with external capacitor at AREF pin
ADMUX|=(0<<REFS1)|(1<<REFS0);
//set prescaller and enable ADC
ADCSRA|=(1<<ADEN)|(1<<ADIE);//enable ADC with dummy conversion
}
//*****************************************************************************
//
// ADC single conversion routine
//
//*****************************************************************************
void adc_start_conversion(char channel)
{
//set ADC channel
ADMUX=(ADMUX&0xF0)|channel;
//Start conversion with Interrupt after conversion
//enable global interrupts
sei();
ADCSRA |= (1<<ADSC)|(1<<ADIE);
}
int adc_value;
int adc_value_prev;
int diff;
void value()
{
adc_value_prev=adc_value;
adc_value=ADCL;
adc_value+=(ADCH<<8);
diff=adc_value-adc_value_prev;
reportBuffer.dx=diff;
}
ISR (ADC_vect)
{
sei();
value();
}
And here is the main loop with changes:
for(;;){ /* main event loop */
DBG1(0x02, 0, 0); /* debug output: main loop iterates */
wdt_reset();
usbPoll();
if(usbInterruptIsReady()){
/* called after every poll of the interrupt endpoint */
adc_start_conversion(0);
DBG1(0x03, 0, 0); /* debug output: interrupt report prepared */
usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
}
My inital guess was that the interrupt from ADC does not work well together with USB generated interrupts. I tried to use ADC without interrupt (ADCSRA |= (1<<ADSC)|(0<<ADIE);) , but with no significant improvement.
Any idea where is the problem?
Could it be that the USB interrupts the ADConversion, to that the "current" value of ADC is "0"?
I am using V-USB HID mouse example on ATMEGA8 and it works fine.
I want to use ADC for mouse movement.
The general idea is that the mouse speed (.dx and .dy) depends on the speed of voltage change on ADC pin (ADC0, pin 23 in my case). The problem is that the mouse pointer (on PC screen) sometimes makes weird jumps ranging from few cm to over a half of the screen width (all on the x-axis as they should be).
Here is the code i am using. It is just for x-axis. The added code:
//*****************************************************************************
//
// ADC module initialization
//
//*****************************************************************************
void adc_init(void)
{
//select reference voltage
//AVCC with external capacitor at AREF pin
ADMUX|=(0<<REFS1)|(1<<REFS0);
//set prescaller and enable ADC
ADCSRA|=(1<<ADEN)|(1<<ADIE);//enable ADC with dummy conversion
}
//*****************************************************************************
//
// ADC single conversion routine
//
//*****************************************************************************
void adc_start_conversion(char channel)
{
//set ADC channel
ADMUX=(ADMUX&0xF0)|channel;
//Start conversion with Interrupt after conversion
//enable global interrupts
sei();
ADCSRA |= (1<<ADSC)|(1<<ADIE);
}
int adc_value;
int adc_value_prev;
int diff;
void value()
{
adc_value_prev=adc_value;
adc_value=ADCL;
adc_value+=(ADCH<<8);
diff=adc_value-adc_value_prev;
reportBuffer.dx=diff;
}
ISR (ADC_vect)
{
sei();
value();
}
And here is the main loop with changes:
for(;;){ /* main event loop */
DBG1(0x02, 0, 0); /* debug output: main loop iterates */
wdt_reset();
usbPoll();
if(usbInterruptIsReady()){
/* called after every poll of the interrupt endpoint */
adc_start_conversion(0);
DBG1(0x03, 0, 0); /* debug output: interrupt report prepared */
usbSetInterrupt((void *)&reportBuffer, sizeof(reportBuffer));
}
My inital guess was that the interrupt from ADC does not work well together with USB generated interrupts. I tried to use ADC without interrupt (ADCSRA |= (1<<ADSC)|(0<<ADIE);) , but with no significant improvement.
Any idea where is the problem?
Could it be that the USB interrupts the ADConversion, to that the "current" value of ADC is "0"?