0
\$\begingroup\$

I have created 2 different PWMs using timer 1 and 2 on ATmega8, that is used to control a linear motor. I'm using a hall effect sensor to detect changes in voltage as the linear motor moves left and right. This change in voltage I feed into a ADC pin in the ATmega8 in order to convert it to digital. Then I basically use the USART functions of the ATmega8 to display the voltage the hall effect sensor basically detects.

I'm running the ADC in free running mode with interrupts to continuously detect a hall effect value.

The problem im having at the moment is that as soon as the interrupt is called to read the adc value i have a function in the interrupt that involves transmitting the adc value to the screen.......

Currently what happens is that as soon as I do that the PWM stops working, its as if the program is stuck in the interrupt in an infinite loop.

However, if I remove the serial transmission function, the PWM starts working again which confuses me?

//TRANSMISSION FUNCTION

 void USARTWriteChar(uint8_t data) {            //Wait untill the transmitter is ready

    while(!(UCSRA & (1<<UDRE)))
      {
    //Do nothing
      }

     UDR=data;
  }

//Main function containing PWM

  while (1)
   {
    OCR1A = Push1;                                  // Output compare register A Time 1  
    OCR1B = 0;
    _delay_ms(400);                                 // set on time A    



    OCR1A = 0;                                      
    OCR1B = 0; 
    _delay_ms(400);                                    // set dead time B

}

 //Interrupt function   

  ISR(ADC_vect) {
   read = ADCH;
   USARTWriteChar(read);    
 }

I am running the ATmega8 at 8Mhz clock frequency with BAUD of 9600.

However when I take off USARTWriteChar(read); (still keeping rad = ADCH ) from the ISR the PWM works meaning the ADC interrupt is not causing problems but USART is for some reasons.

\$\endgroup\$
3
  • \$\begingroup\$ Tell us about the timing of all of this stuff. How long is your instruction cycle, sampling period, etc. And while you're editing that information in, clean up the code please. Odds are you can eliminate the problem by doing a few simple restructuring items, and setting the PWM properly in it's own ISR. What you're doing in the main loop doesn't make much sense. But tall of this requires knowing something about the timing requirements. \$\endgroup\$
    – Matt Young
    Commented Sep 27, 2013 at 3:55
  • \$\begingroup\$ @MattYoung our sampling period is 60khz , we are running atmega8 at 8mhz. We need the base frequcy of the pwm around 4-hz thats why I am using delay function with timer the smallest frequency we can achieve is 15hz. \$\endgroup\$
    – subz
    Commented Sep 27, 2013 at 4:28
  • \$\begingroup\$ What is so special about 4Hz? That is obscenely slow. It seems kind of pointless to sample the pot that fast if you're updating the pwm that slowly. You say the PWM works? I can't see how. That isn't how it was designed to work. It would probably be easier to generate a timer interrupt at 400 Hz, count the interrupts, and toggle the bit manually. \$\endgroup\$
    – Matt Young
    Commented Sep 27, 2013 at 4:46

1 Answer 1

3
\$\begingroup\$

Never ever write or read from a UART from within an interrupt handler. I assume the following happens:

  • Interrupt occurs because a new value is available
  • You start writing to the UART
  • A new interrupt occurs
  • The write to the UART is done, the interrupt has already been triggered and again you are in the interrupt routine.
  • Therefore your main loop will starve to death

What you should do:

  • If your Atmega has a hardware PWM, use that one to generate the PWM signal
  • In your interrupt routine, only set a flag that new data is available (store that in some variable) and write that data only in the main routine out to your UART
\$\endgroup\$
2
  • \$\begingroup\$ i would like to do it inside the main loop but i am having problem because i am using the delay function, i want to see the digital output in realtime from the adc which is connected to a sensor but with the delay function present it wont give me realtime reading thats why i was trying to use interrupts. Is there any possible of way doing this ? Thanks for the help :) \$\endgroup\$
    – subz
    Commented Sep 27, 2013 at 10:27
  • \$\begingroup\$ You might want to define realtime. Writing about 10 chars out your UART will take approximately 10ms (@9600Baud). So the maximum frequency you can output to your UART is about 100Hz. How fast do you sample your signal? Configure the PWM so it runs in hardware and doesn't require you to do anything in the main. \$\endgroup\$
    – Tom L.
    Commented Sep 27, 2013 at 11:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.