Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
madsci1016
PostPosted: Nov 16, 2010 - 03:35 AM
Newbie


Joined: Nov 16, 2010
Posts: 11


I'm trying to use an ATtiny85 to charleplex some LEDs, and using a hardware timer to generate PWM for a 'fade up / fade down' effect. Code attached.

Randomly, there's an initial "blip" pulse of random length before the correct pulse train starts when enabling PWM. The blip measures from 0 to 2.040 ms in length. This is causing a quick strobe (flash) before the LED is 'fading' up.

What's causing this blip?
 
 View user's profile Send private message  
Reply with quote Back to top
mikesorrenti
PostPosted: Nov 16, 2010 - 04:39 AM
Rookie


Joined: Nov 16, 2010
Posts: 25
Location: Space Coast, FL

First thing that jumps out at me is

Code:
#define F_CPU 8000000UL  // 1 MHz


Are you running at 8MHz or 1MHz? I'm not sure if this would cause your problem but would at minimum screw up your delay() calls. Maybe something isn't timing like you think.

_________________
Hope I can help,
Mike
My Robotics/AVR Blog
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
madsci1016
PostPosted: Nov 16, 2010 - 04:41 AM
Newbie


Joined: Nov 16, 2010
Posts: 11


Sorry, I'm running at 8Mhz, I just forgot to change the comment from the cut&paste.
 
 View user's profile Send private message  
Reply with quote Back to top
mikesorrenti
PostPosted: Nov 16, 2010 - 04:48 AM
Rookie


Joined: Nov 16, 2010
Posts: 25
Location: Space Coast, FL

In fadeInOut, why do you call setDuty twice?

Maybe not related, but shouldn't have things there without a reason.

_________________
Hope I can help,
Mike
My Robotics/AVR Blog
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
madsci1016
PostPosted: Nov 16, 2010 - 04:59 AM
Newbie


Joined: Nov 16, 2010
Posts: 11


Err, I originally tried this in an Arduino enviroment using both pwm channels and was observing the same problem. I (roughly) brought they code out of Arduino to eliminate it as the cause. But I was sloppy and missed removing the second call to what would be the second pin.

Just tried removing it now, still same problem.
 
 View user's profile Send private message  
Reply with quote Back to top
mikesorrenti
PostPosted: Nov 16, 2010 - 05:06 AM
Rookie


Joined: Nov 16, 2010
Posts: 25
Location: Space Coast, FL

madsci1016 wrote:
Err, I originally tried this in an Arduino enviroment using both pwm channels and was observing the same problem. I (roughly) brought they code out of Arduino to eliminate it as the cause. But I was sloppy and missed removing the second call to what would be the second pin.

Just tried removing it now, still same problem.

Yeah I thought it looked odd.

If I was debugging it in front of me I'd have to bring the code a little simpler and then start pulling pieces off until it went away, then poke around that spot a bit.

Unfortunately I can't really see the reason by just skimming your code.

Best of luck. I'm sure someone will chime in soon.

_________________
Hope I can help,
Mike
My Robotics/AVR Blog
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Koshchi
PostPosted: Nov 16, 2010 - 06:24 AM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15127
Location: Vancouver, BC

Why are you not including <avr/io.h>?

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Nov 16, 2010 - 10:23 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71904
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

Why are you not including <avr/io.h>?

Presumably because:
Code:
C:\WinAVR-20100110\avr\include\avr>grep "#include <avr/io.h>" interrupt.h
#include <avr/io.h>

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
madsci1016
PostPosted: Nov 18, 2010 - 04:38 AM
Newbie


Joined: Nov 16, 2010
Posts: 11


12 downloads and no other thoughts?

Sorry it's messy. When I get back from traveling for work I'll clean it up and simplify it. I was hoping it was something easy like "you forgot poking register ABC"

The best way to summarize what I see is that it's like when I enable the PWM, the IO pin goes HIGH (or LOW) until the timer overflows, then starts correctly running PWM. The manual mentioned something like this in the section on resetting the pre-scaler, and I followed the suggestion (I think) to correct for this, but no change.

I had a temp fix, where I enabled the PWM when the DDR register was set for input, delayed 10ms, then enabled the IO as output. This 'skips' the PWM blip, but i'd really like to figure out why it's doing it in the first place.
 
 View user's profile Send private message  
Reply with quote Back to top
madsci1016
PostPosted: Nov 19, 2010 - 01:51 PM
Newbie


Joined: Nov 16, 2010
Posts: 11


Well, according to this guy:

http://www.societyofrobots.com/robotfor ... 0#msg94580

It seems this is just a thing with ATtiny PWM.

I think I'm just going to do software PWM, since I won't be doing anything else.

Thanks guys for taking the time to look.
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Nov 19, 2010 - 02:39 PM
10k+ Postman


Joined: Feb 12, 2005
Posts: 20702
Location: Wormshill, England

Looking at your code, you do not start any PWM until you call setDuty() after the first delay(1000).

When you disable COM0A1 bit, the o/p pin reverts to GPIO.

You could achieve your effects in a simpler manner.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
theusch
PostPosted: Nov 19, 2010 - 04:33 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 29284
Location: Wisconsin USA

I'm not intimately familiar with LED PWMs, or PWM on that particular model.

Without digging into the code and experimenting, the symptom descriptions would appar to me as if the "start" isn't from a set of known conditions. For example, at "start" the compare flag might already be set and there is one cycle of PWM where the output is in an undesirable state.

So, I'd examine the "start" sequence. I guess since there are problems, I'd stop the timer, clear the TCNT, clear all pertinent IF flags, set the OCR register(s), set the TOP register(s) if pertinent, configure the node as an output, set the output to the desired initial state, connect the pin to the timer with COM bits, set the mode WGM bits, then start the timer with CS bits.

Regardless of AVR model, I cannot think of why there might be an blip, much less of significant duration (up to several milliseconds), using the above sequence.

In practice, I combine most of the steps above. When the timer is stopped, I disconnect the output and set it to the desired "idle" state. When ready to 'start", I go through roughly the sequence above.

Lee
 
 View user's profile Send private message  
Reply with quote Back to top
madsci1016
PostPosted: Nov 20, 2010 - 02:31 PM
Newbie


Joined: Nov 16, 2010
Posts: 11


@david.prentice, I am charlie-plexing LEDs, so I need the pin to go into High-Z mode in-between PWM cycles. Care to fill me in on the simpler method?

@Lee, I'll give it a try, just seems like a lot of resetting stuff every time I want to start PWM again during the same program.
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: Nov 20, 2010 - 08:33 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 29284
Location: Wisconsin USA

Quote:

@Lee, I'll give it a try, just seems like a lot of resetting stuff every time I want to start PWM again during the same program.

Like, three lines of code, to address a situation that seems to be vexing you?

Yes, indeed, if you start PWM in an arbitrary state, especially (as it appears to be here) in a state where a bogus compare match can fire immediately--you can get a "blip". Note that the AVR is just doing what you tell it to.
 
 View user's profile Send private message  
Reply with quote Back to top
madsci1016
PostPosted: Nov 20, 2010 - 09:48 PM
Newbie


Joined: Nov 16, 2010
Posts: 11


theusch wrote:

Like, three lines of code, to address a situation that seems to be vexing you?


Three?

Quote:
I'd stop the timer, clear the TCNT, clear all pertinent IF flags, set the OCR register(s), set the TOP register(s) if pertinent, configure the node as an output, set the output to the desired initial state, connect the pin to the timer with COM bits, set the mode WGM bits, then start the timer with CS bits.


You can do all that in three instructions?

Best I could do was :

Code:
TCNT0 = 0;
TIFR = 0b00011010;
OCR0A = val;
sbi(DDRB, 0);
sbi(PORTB, 0);
TCCR0A = 0b10000011;
TCCR0B = 0b00000011;


and when I'm done with PWM:

Code:
cbi(DDRB, 0);
cbi(PORTB, 0);
TCCR0B = 0b00000000;
TCCR0A = 0b00000000;
OCR0A = 0;


And still, i'm getting blips. Any other thoughts?
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Nov 21, 2010 - 12:21 PM
10k+ Postman


Joined: Feb 12, 2005
Posts: 20702
Location: Wormshill, England

If you are connecting 4 LEDs to 3 AVR pins, you clearly want to have them lit simultaneously.

I ran this on a mega168 @ 16MHz.
I did not see any glitches. However, you will need to limit the minimum level to 1. The Charlieplexing interrupt occurs every 1024us. The ISR() takes 4us in CodeVision. Obviously you will need an IRQ latency of less than 1000us to ensure that OCR0A gets updated fast enough.

You should be able to recompile for a Tiny25 @ 8MHz. Your minimum latency will be 2000us. I can see no particular reason for using PWM modes. You need to multiplex at 1ms to 10ms period anyway to avoid flicker. You would only be doing one complete PWM period anyway before you change the duty cycle. (and then OCR0A does not change immediately)

Code:

// Charlieplex an array of LEDs,  all with independent brightness.
// Turn all LEDs off by OC0A.dir = 0

#include "/src/scripts/portab_kbv.h"

#define REDPWM 6                // OCR0A o/p pin
#define ONETWO 4                // charlieplex 1,2
#define THREEFOUR 7             // charlieplex 3,4
#define PWMPORT PORTD
#define PWMDDR  DDRD

uint8_t level[4] = { 1, 1, 1, 1 }; // levels must be > 0

ISR(TIM0_OVF)                   // 1.024ms @ 16MHz
{
    static uint8_t n = 3;       // start as #3
    if (++n > 3)
        n = 0;
    OCR0A = level[n];                             //ONE,TWO,THR,FOU
    PWMPORT ^= (1<<ONETWO)|(1<<THREEFOUR);        // 11, 00, 11, 00
    if ((n & 1) == 0)
        PWMDDR ^= (1<<ONETWO)|(1<<THREEFOUR);     // 10, 10, 01, 01
}

void main()
{
    uint8_t i, j;
    TCCR0A = (1<<COM0A0);             // toggle OC0A on compare
    TCCR0B = (1<<CS01)|(1<<CS00);     // div64
    TIMSK0 = (1<<TOIE0);              // GPIO mode, interrupt on OVF
    PWMPORT &= ~((1<<REDPWM)|(1<<ONETWO)|(1<<THREEFOUR));     // RST default anyway.
    PWMDDR = (1<<REDPWM)|(0<<ONETWO)|(1<<THREEFOUR);  // start as #3
    SEI();

    for (;;) {
        for (i = 0; i < 4; i++) {
            for (j = 1; j < 255; j++) {
                level[i] = j;
                DELAY_MS(10);
            }
        }
        for (i = 4; i-- > 0; ) {
            for (j = 255; j > 1; j--) {
                level[i] = j;
                DELAY_MS(10);
            }
        }
    }
}

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
madsci1016
PostPosted: Nov 21, 2010 - 04:28 PM
Newbie


Joined: Nov 16, 2010
Posts: 11


Quote:
If you are connecting 4 LEDs to 3 AVR pins, you clearly want to have them lit simultaneously.


Actually, the end result will be 8 LEDs on 4 pins, with only two lit simultaneously at different PWM levels. I haven't finish scaling up to that level till I figured this out. The reason I went with Charlie-plexing was to avoid using any external components like decoders or shift registers.

But thanks for the code David, I'm going to try to dissect it to see what you did.
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Nov 21, 2010 - 05:13 PM
10k+ Postman


Joined: Feb 12, 2005
Posts: 20702
Location: Wormshill, England

You just double up your level[] array.
You could use the OCR0B pin for the other 4 LEDs.

I take your point that you only want to view two LEDs at any one time. However 8 simultaneous LEDs with different intensities is pretty simple.

You only have two pins left on a Tiny25 (one if you keep RST). What else will your Tiny do?

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
madsci1016
PostPosted: Nov 21, 2010 - 07:47 PM
Newbie


Joined: Nov 16, 2010
Posts: 11


Quote:
You could use the OCR0B pin for the other 4 LEDs.


That's what I planed on.

Quote:
You only have two pins left on a Tiny25 (one if you keep RST). What else will your Tiny do?


Nothing, So I could have easily done this in software, but I wanted to solve the hardware issue for my own sake of learning & understanding.

Another project I am working on is using a ATtiny85 to measure voltage, current and phase angle (to calculate pf, real, reactive power, etc) off my Apartment's mains. So I wanted to gain more experience with ATtiny timers through this.
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Nov 21, 2010 - 08:11 PM
10k+ Postman


Joined: Feb 12, 2005
Posts: 20702
Location: Wormshill, England

I would reckon that it is easiest to develop your programs on a mega328 or mega324. Or perhaps use a tiny2313 when playing with the USI.

The Tiny25 has some special facilities with PLL and dead time, but most things, most of the time are similar with all AVRs.

Simply re-compile for the reduced-pin target, and check that everything works ok.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits