NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Bad for chip? Using all outputs to fade xmas lights with software pwm, timers and interrupts

November 29, 2012
by Osarus
Osarus's Avatar

Hey,

I'm using timers and interrupter to fade leds with software pwm I'm looking to do this on all 26pins setup as outputs

Is this bad in any way? (wear stuff out?... explode?) Will i need some sort of filter between the chip and transistor gate to smooth out the pulses into a voltage? Ill be changing it to power transistor gates to run Christmas fairy lights... 3000 so far =D

Currently using 1 led just to test, 128 steps of brightness longest black pause is about 1/60th of a sec so no flicker.

It's very messy but for anyone interested. It's more a proof of concept untill i know its safe =D

#define F_CPU 14745600
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/delay.h>
#include <stdio.h>

#define _ms(n) (17*n)
#define BTUP() (bit_is_clear(PINC,4))
#define BTDOWN() (bit_is_clear(PINC,5))

unsigned char port_write=0b00000000;
unsigned int bitje=0;
int const bitsize=128; //number of brightness steps

unsigned int one_pwm[bitsize];
unsigned int p1=1; // Set value of point to rightmost zero in array

void wait(unsigned int a) //basic wait
{
    volatile unsigned int b,c;
    for(b=0;b!= a; b++)
        for(c=0;c!= 50;c++);
            return;
}

void init_pwm () // Initialize pwm arrays
{
    unsigned int tel=0;
    for (tel=1;tel<bitsize;tel++)
    {
        one_pwm[tel]=0;
    }
    one_pwm[0]=1; // Set value of rightmost bit in array
    p1=1; // Set value of point to rightmost zero in array
    return;
}

 void ioinit (void)
{
   DDRC  = 0b11001111; //1 = output, 0 = input
   PORTC = 0b00110000; //Enable pin 5, 4 and x3 internal pullup
   DDRB  = 0b11111111; //1= output, 0 = input
   PORTB = 0b00000010; //Set PB pins 0, x1 and x2 to high
}

ISR(SIG_OUTPUT_COMPARE1A) 
{
 if (one_pwm[bitje]==1)
    { port_write |= (1<<1);}
 else
    {port_write &= ~(1<<1);}

 bitje++;
 if (bitje>=bitsize) {bitje=0;}
 PORTB=port_write;
 return;
}

int main(void)
{
    TIMSK1 = _BV(OCIE1A); //Enable Interrupt Timer/Counter 1,Output Compare A
    TCCR1B = _BV(CS10) | _BV(CS11) | _BV(WGM12); //Clock/8, 0.000008 secs/tick, Mode=CTC
    OCR1A =8; // SIG_COMPARE1A triggered every 0.000008*16 Seconds

    init_pwm();
    sei();
    ioinit();
    unsigned int maxdelay=10;
    unsigned int updown=0;
    unsigned int delayy=5;

    while (1){
    if (!BTUP()){
        if (updown==0){
            if (p1<bitsize){
                     one_pwm[p1]=1;
                     p1++;
            }else{
            updown = 1;
            }
        }else{
            if (p1>0){
                p1--;
                one_pwm[p1]=0;
            }else{
                updown = 0;
                delayy = delayy + 10;
            }
        }
    }
        _delay_ms(delayy);
    }
}
November 29, 2012
by Rick_S
Rick_S's Avatar

How do you propose to have 26 outputs on an ATMEGA328P?? Even if you we're to reset the fuses so that the reset pin was an output and went with the internal oscillator so the crystal pins could be used, you would have at most 23 available. Not to mention, I'd be surprised to see that many outputs doing any kind of PWM all at once. Timing would be a nightmare.

Rick

November 29, 2012
by Osarus
Osarus's Avatar

Sorry your right, using 22 pins... not sure where i pulled 26 from.

Iv yet to play around with more then 2 so ill see how i go with timing, i can lower it right down to 8 brightness levels if i need more cycles. I was going to set the interrupter function to inc or dec each pin up or down 1 notch each cycle. first bit of each pwm variable i have for enable/disable second for up/down direction, rest for brightness level. With some global isdone variables for each pin and some simple wait's in the main until isdone type statements in main i think it should be ok for what im going!

I'm just wondering if its bad to switch all the pins around so fast so much?

November 29, 2012
by pcbolt
pcbolt's Avatar

Osarus -

I think you should be OK. The LED display built by the Nerdkit guys uses quite a bit of switching and control of many lights with quite a few of the available pins in use. If you are using power FET's, they should be doing most of the heavy lifting. You should really look into using shift registers for expanding the project from here. That would up your pin count by a 4 to 1 ratio (maybe even 8 to 1 depending on your configuration). In your testing phase, keep an eye on your power usage when using more than a couple of LED's since you may run into the 200 mAmp limit for the chip (individual pins max out at 40 mAmp). Take a peek at the NK tutorial for the LED display if you get a chance...there's tons of info there that might help with your project.

November 30, 2012
by Rick_S
Rick_S's Avatar

You won't hurt the chip by switching it's pins on and off unless you apply more load to them than the microcontroller is capable of supplying. So as long as the base current required for your transistors isn't more (if they were all on at once) than the max load the chip can supply (Observe these notes from the datasheet)

  1. Although each I/O port can sink more than the test conditions (20 mA at VCC = 5V, 10 mA at VCC = 3V) under steady state conditions (non-transient), the following must be observed: ATmega48PA/88PA/168PA/328P: 1] The sum of all IOL, for ports C0 - C5, ADC7, ADC6 should not exceed 100 mA. 2] The sum of all IOL, for ports B0 - B5, D5 - D7, XTAL1, XTAL2 should not exceed 100 mA. 3] The sum of all IOL, for ports D0 - D4, RESET should not exceed 100 mA. If IOL exceeds the test condition, VOL may exceed the related specification. Pins are not guaranteed to sink current greater than the listed test condition.
  2. Although each I/O port can source more than the test conditions (20 mA at VCC = 5V, 10 mA at VCC = 3V) under steady state conditions (non-transient), the following must be observed: ATmega48PA/88PA/168PA/328P: 1] The sum of all IOH, for ports C0 - C5, D0- D4, ADC7, RESET should not exceed 150 mA. 2] The sum of all IOH, for ports B0 - B5, D5 - D7, ADC6, XTAL1, XTAL2 should not exceed 150 mA. If IIOH exceeds the test condition, VOH may exceed the related specification. Pins are not guaranteed to source current greater than the listed test condition.

These notes are copied from the datasheet's Electrical Characteristics section.

Rick

November 30, 2012
by Rick_S
Rick_S's Avatar

Also, respect the limits pcbolt advised of. Those are Chip/Pin max's.

November 30, 2012
by pcbolt
pcbolt's Avatar

Rick -

Should it be about time to break out the "If you have any doubts about what the ATmega's can do" video?

November 30, 2012
by Rick_S
Rick_S's Avatar

LOL, I still watch that from time to time, and each time I do, I still come away amazed at it. It always goes to remind me what can be done given the proper programming skills.

November 30, 2012
by Ralphxyz
Ralphxyz's Avatar

Of course it helps if you are another Linus!!

There is another demo on one of the LCD threads here in the Nerdkits forum, it is amazing what one can do.

Ralph

December 02, 2012
by Osarus
Osarus's Avatar

I could not find info on register endurance or lifetime, i also could not find any info on one failing, see if this lasts running all Christmas im guessing it will be fine=D

Thanks for the tips on power usage, and thanks for the video link that is crazy! I had looked at registers but would rather make the array like setup used in the scrolly LED tutorial ^_^

Working perfectly so far with 17 channels controlling 4000 lights all starting and stopping at random times at different speeds :) now to stick it on trees....

For anyone interested i put lots of comments in code

The cycles are hard to get your head around though say u have 4 "shades" these are 4 possible brightness's 4 bits

1000 1/4 brightness 1100 1/2 1110 3/4 1111 full brightness

it takes 4 loops of the interrupt to make up one of these brightness's or one "cycle" you can then set the number of full cycles before it inc/dec brightness, giving you control of the speed it changes

define F_CPU 14745600

include <avr/io.h>

include <avr/interrupt.h>

include <avr/wdt.h>

include <avr/delay.h>

include <stdio.h>

//random macros i use to be lazy while testing ^_^

define _ms(n) (17*n)

define BTUP() (bit_is_clear(PINC,4))

define BTDOWN() (bit_is_clear(PINC,5))

define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))

define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))

define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))

define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))

define WRITEBIT(RADDRESS,RBIT,WADDRESS,WBIT) (CHECKBIT(RADDRESS,RBIT) ? SETBIT(WADDRESS,WBIT) : CLEARBIT(WADDRESS,WBIT))

//set pins on these which are written to ports volatile unsigned char portb_write=0b00000000; volatile unsigned char portc_write=0b00000000; volatile unsigned char portd_write=0b00000000;

unsigned int const shades=64; //resolution for brightness. ie for 64 it gives you brigtness levels from 1/64'th to 63/64'ths. volatile unsigned int tick_count = 0; //interuupt has to loop though the number set in "shades" times to make one cycle. this keeps track of where you are. volatile unsigned int active_count = 0; //when nothing is set to fade this makes the interrupt code smaller. volatile unsigned int active_pwm_values[23]; //current ticks to stay on volatile unsigned int active_pwm_updown[23]; //1= brighter fade up 0v to vss, 0= dimmer fade down vss to 0v volatile unsigned int active_pwm_cycles[23]; //number of full cycles each pin has been through volatile unsigned int active_pwm_cycles_per_tick[23]; //cycles at each brightness, rate of change/speed volatile unsigned int b; //for loops volatile unsigned int trig = 0; //me testing interrupts, can an interrupt get called a second time if its already running?

//function to setup fades, pin numbers 1-17. 1-5=PORTB pins 1-5. 6-11=PORTC pins 0-5. 12-17=PORTD pins 2-7 //at current settings speed of 1-5 is reasonable, cant be anything u like though.... //brighter, 1= get brighter, 0=get dimmer //start, start value to fade up or down from ie "shades/2" would start from half brightness void setfade(unsigned int pin, unsigned int speed, unsigned int brighter, unsigned int start) { active_pwm_values[pin] = start; active_pwm_cycles_per_tick[pin] = speed; active_pwm_updown[pin] = brighter; active_count++; }

//The interuupt process! ISR(SIG_OUTPUT_COMPARE1A) { //Turn pins off when they are at there percentage through a cycle of shades //turn them all back on at end of cycle, and increase/decrease brightness as appropriate. Check if they need to be removed.

if (active_count != 0){ //save afew cycles if nothings happening
    //port B
    if (active_pwm_values[1] == tick_count){ //active_pwm_values needs to be checked either way, more efficent to disable pins by setting active_pwm_values to shades+1 outside normal range.
    portb_write &= ~(1<<1);
    }
    if (active_pwm_values[2] == tick_count){
    portb_write &= ~(1<<2);
    }
    if (active_pwm_values[3] == tick_count){
    portb_write &= ~(1<<3);
    }
    if (active_pwm_values[4] == tick_count){
    portb_write &= ~(1<<4);
    }
    if (active_pwm_values[5] == tick_count){
    portb_write &= ~(1<<5);
    }

    //Port C
    if (active_pwm_values[6] == tick_count){
    portc_write &= ~(1<<0);
    }
    if (active_pwm_values[7] == tick_count){
    portc_write &= ~(1<<1);
    }
    if (active_pwm_values[8] == tick_count){
    portc_write &= ~(1<<2);
    }
    if (active_pwm_values[9] == tick_count){
    portc_write &= ~(1<<3);
    }
    if (active_pwm_values[10] == tick_count){
    portc_write &= ~(1<<4);
    }
    if (active_pwm_values[11] == tick_count){
    portc_write &= ~(1<<5);
    }

    //Port D pins 2-7
    if (active_pwm_values[12] == tick_count){
    portd_write &= ~(1<<2);
    }
    if (active_pwm_values[13] == tick_count){
    portd_write &= ~(1<<3);
    }
    if (active_pwm_values[14] == tick_count){
    portd_write &= ~(1<<4);
    }
    if (active_pwm_values[15] == tick_count){
    portd_write &= ~(1<<5);
    }
    if (active_pwm_values[16] == tick_count){
    portd_write &= ~(1<<6);
    }
    if (active_pwm_values[17] == tick_count){
    portd_write &= ~(1<<7);
    }

    if (tick_count == shades) { //if at end up cycle
        tick_count=0;
        for(b=1;b!= 18; b++){                                           // for every pin
            if (active_pwm_values[b] <= shades){                        // with a brightness between 0 and shades
                if ((b > 5) && (b < 12)){                               //turn fading pins back on to start a new cycle
                    portc_write |= (1<<(b-6)); //port c pins 0-5
                }else if (b > 11){
                    portd_write |= (1<<(b-10)); //port d pins 0-5
                }else{
                    portb_write |= (1<<b); //port b  pin 1-5
                }
               active_pwm_cycles[b]++;                                  //increase pins cycle count
                if (active_pwm_cycles[b] > active_pwm_cycles_per_tick[b]){ //check if need to increase/decrease brightness taking speed into account
                    active_pwm_cycles[b] = 0;
                     if(active_pwm_updown[b] == 0){
                        active_pwm_values[b]--;                         //decrease brightness
                        if (active_pwm_values[b] == 0){                //if dimmer pin ends life turn pin back off and kill it
                            active_pwm_values[b] = shades+1; 
                            active_count--;
                            if ((b > 5) && (b < 12)){
                                portc_write &= ~(1<<(b-6)); //port c pins 0-5
                            }else if (b > 11){
                                portd_write &= ~(1<<(b-10)); //port d pins 0-5
                            }else{
                                portb_write &= ~(1<<b); //port b  pin 1-5
                            }
                        }
                     }else{ 
                        active_pwm_values[b]++;                     //increase brightness, this also pushes it to shades+1 which disables it
                        if (active_pwm_values[b] > shades){         //if brighter pin ends life its already on just kill it
                            active_count--;
                        }
                     }
                }
            }
        }
    }
    PORTB=portb_write;      //white values to ports
    PORTC=portc_write;
    PORTD=portd_write;
    tick_count++;           //count a tick for cycle!
}

return;

}

//setup pins void ioinit (void) { DDRB = 0b00111110; //1= output, 0 = input. 1-5 enable PORTB = 0b00000000; //Set PB pins to low DDRC = 0b11111111; //1 = output, 0 = input. 0-5 enable PORTC = 0b00000000; //Set PC pins to low DDRD = 0b11111100; //1= output, 0 = input. 2-7 enable PORTD = 0b00000000; //Set PD pins to low

}

int main(void) {

TIMSK1 = _BV(OCIE1A); //Enable Interrupt Timer/Counter 1,Output Compare A
TCCR1B = _BV(CS10) | _BV(CS11) | _BV(WGM12); //Mode=CTC, 8mhz/64 = 125,000hz or 0.000008 seconds per tick
OCR1A =8; // triggered interrupt every 0.000008*8 Seconds faster is smoother even with lower shade counts
ioinit(); //setup pins function
sei(); //turn interuupts on

//disable all pins by settings to shades+1 outside normal range. for(b=1;b!= 18; b++){ active_pwm_values[b] = shades + 1; if ((random() % 3) > 1){ //set dimmer/brighter to a random value, was just using to test stuff active_pwm_updown[b] = 0; }else{ active_pwm_updown[b] = 1;
} }

while (1){ //run forever

for (b=1;b!=18; b++){
    setfade(b,1,1,1);
}
while(active_pwm_values[1] != shades+1){ //used as triggers to wait untill fade finishes
}

unsigned int c;
unsigned int cc;
unsigned int ccc;

    while(1){
    //random motion function on all pins
        for (b=1;b!=18; b++){
            if (active_pwm_values[b] == (shades+1)){    
                c =(rand() % 15) + 1;
                if ((b > 5) && (b < 12)){
                    if (active_pwm_updown[(b-6)] == 1){
                        ccc = 0;
                        cc = shades-1;
                    }else{
                        ccc = 1;
                        cc = 1;
                    }
                }else if (b > 11){

                    if (active_pwm_updown[(b-10)] == 1){
                        ccc = 0;
                        cc = shades-1;
                    }else{
                        ccc = 1;
                        cc = 1;
                    }
                }else{
                    if (active_pwm_updown[(b)] == 1){
                        ccc = 0;
                        cc = shades-1;
                    }else{
                        ccc = 1;
                        cc = 1;
                    }

                }
                setfade(b,(c+1),ccc,cc);
            }
        }
        _delay_ms(1000);
    }
}

}

December 02, 2012
by Osarus
Osarus's Avatar

DAME U LACK OF EDIT BUTTON

#define F_CPU 14745600
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/delay.h>
#include <stdio.h>

//random macros i use to be lazy while testing ^_^
#define _ms(n) (17*n)
#define BTUP() (bit_is_clear(PINC,4))
#define BTDOWN() (bit_is_clear(PINC,5))
#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))
#define WRITEBIT(RADDRESS,RBIT,WADDRESS,WBIT) (CHECKBIT(RADDRESS,RBIT) ? SETBIT(WADDRESS,WBIT) : CLEARBIT(WADDRESS,WBIT))

//set pins on these which are written to ports
volatile unsigned char portb_write=0b00000000;
volatile unsigned char portc_write=0b00000000;
volatile unsigned char portd_write=0b00000000;

unsigned int const shades=64;  //resolution for brightness. ie for 64 it gives you brigtness levels from 1/64'th to 63/64'ths.
volatile unsigned int tick_count = 0; //interuupt has to loop though the number set in "shades" times to make one cycle. this keeps track of where you are.
volatile unsigned int active_count = 0; //when nothing is set to fade this makes the interrupt code smaller.
volatile unsigned int active_pwm_values[23];  //current ticks to stay on
volatile unsigned int active_pwm_updown[23];  //1= brighter fade up 0v to vss, 0= dimmer fade down vss to 0v
volatile unsigned int active_pwm_cycles[23];  //number of full cycles each pin has been through
volatile unsigned int active_pwm_cycles_per_tick[23]; //cycles at each brightness, rate of change/speed
volatile unsigned int b; //for loops
volatile unsigned int trig = 0; //me testing interrupts, can an interrupt get called a second time if its already running?

//function to setup fades, pin numbers 1-17. 1-5=PORTB pins 1-5. 6-11=PORTC pins 0-5. 12-17=PORTD pins 2-7
//at current settings speed of 1-5 is reasonable, cant be anything u like though....
//brighter, 1= get brighter, 0=get dimmer
//start, start value to fade up or down from ie "shades/2" would start from half brightness
void setfade(unsigned int pin, unsigned int speed, unsigned int brighter, unsigned int start) 
{
        active_pwm_values[pin] = start;
        active_pwm_cycles_per_tick[pin] = speed;
        active_pwm_updown[pin] = brighter;
        active_count++;
}

//The interuupt process!
ISR(SIG_OUTPUT_COMPARE1A)
{
//Turn  pins off when they are at there percentage through a cycle of shades
//turn them all back on at end of cycle, and increase/decrease brightness as appropriate. Check if they need to be removed.

    if (active_count != 0){ //save afew cycles if nothings happening
        //port B
        if (active_pwm_values[1] == tick_count){ //active_pwm_values needs to be checked either way, more efficent to disable pins by setting active_pwm_values to shades+1 outside normal range.
        portb_write &= ~(1<<1);
        }
        if (active_pwm_values[2] == tick_count){
        portb_write &= ~(1<<2);
        }
        if (active_pwm_values[3] == tick_count){
        portb_write &= ~(1<<3);
        }
        if (active_pwm_values[4] == tick_count){
        portb_write &= ~(1<<4);
        }
        if (active_pwm_values[5] == tick_count){
        portb_write &= ~(1<<5);
        }

        //Port C
        if (active_pwm_values[6] == tick_count){
        portc_write &= ~(1<<0);
        }
        if (active_pwm_values[7] == tick_count){
        portc_write &= ~(1<<1);
        }
        if (active_pwm_values[8] == tick_count){
        portc_write &= ~(1<<2);
        }
        if (active_pwm_values[9] == tick_count){
        portc_write &= ~(1<<3);
        }
        if (active_pwm_values[10] == tick_count){
        portc_write &= ~(1<<4);
        }
        if (active_pwm_values[11] == tick_count){
        portc_write &= ~(1<<5);
        }

        //Port D pins 2-7
        if (active_pwm_values[12] == tick_count){
        portd_write &= ~(1<<2);
        }
        if (active_pwm_values[13] == tick_count){
        portd_write &= ~(1<<3);
        }
        if (active_pwm_values[14] == tick_count){
        portd_write &= ~(1<<4);
        }
        if (active_pwm_values[15] == tick_count){
        portd_write &= ~(1<<5);
        }
        if (active_pwm_values[16] == tick_count){
        portd_write &= ~(1<<6);
        }
        if (active_pwm_values[17] == tick_count){
        portd_write &= ~(1<<7);
        }

        if (tick_count == shades) { //if at end up cycle
            tick_count=0;
            for(b=1;b!= 18; b++){                                           // for every pin
                if (active_pwm_values[b] <= shades){                        // with a brightness between 0 and shades
                    if ((b > 5) && (b < 12)){                               //turn fading pins back on to start a new cycle
                        portc_write |= (1<<(b-6)); //port c pins 0-5
                    }else if (b > 11){
                        portd_write |= (1<<(b-10)); //port d pins 0-5
                    }else{
                        portb_write |= (1<<b); //port b  pin 1-5
                    }
                   active_pwm_cycles[b]++;                                  //increase pins cycle count
                    if (active_pwm_cycles[b] > active_pwm_cycles_per_tick[b]){ //check if need to increase/decrease brightness taking speed into account
                        active_pwm_cycles[b] = 0;
                         if(active_pwm_updown[b] == 0){
                            active_pwm_values[b]--;                         //decrease brightness
                            if (active_pwm_values[b] == 0){                //if dimmer pin ends life turn pin back off and kill it
                                active_pwm_values[b] = shades+1; 
                                active_count--;
                                if ((b > 5) && (b < 12)){
                                    portc_write &= ~(1<<(b-6)); //port c pins 0-5
                                }else if (b > 11){
                                    portd_write &= ~(1<<(b-10)); //port d pins 0-5
                                }else{
                                    portb_write &= ~(1<<b); //port b  pin 1-5
                                }
                            }
                         }else{ 
                            active_pwm_values[b]++;                     //increase brightness, this also pushes it to shades+1 which disables it
                            if (active_pwm_values[b] > shades){         //if brighter pin ends life its already on just kill it
                                active_count--;
                            }
                         }
                    }
                }
            }
        }
        PORTB=portb_write;      //white values to ports
        PORTC=portc_write;
        PORTD=portd_write;
        tick_count++;           //count a tick for cycle!
    }

    return;
}

//setup pins
 void ioinit (void)
{
   DDRB  = 0b00111110; //1= output, 0 = input. 1-5 enable
   PORTB = 0b00000000; //Set PB pins to low
   DDRC  = 0b11111111; //1 = output, 0 = input. 0-5 enable
   PORTC = 0b00000000; //Set PC pins to low
   DDRD  = 0b11111100; //1= output, 0 = input. 2-7 enable
   PORTD = 0b00000000; //Set PD pins to low

}

int main(void)
{

    TIMSK1 = _BV(OCIE1A); //Enable Interrupt Timer/Counter 1,Output Compare A
    TCCR1B = _BV(CS10) | _BV(CS11) | _BV(WGM12); //Mode=CTC, 8mhz/64 = 125,000hz or 0.000008 seconds per tick
    OCR1A =8; // triggered interrupt every 0.000008*8 Seconds faster is smoother even with lower shade counts
    ioinit(); //setup pins function
    sei(); //turn interuupts on

//disable all pins by settings to shades+1 outside normal range.
    for(b=1;b!= 18; b++){ 
            active_pwm_values[b] = shades + 1;
            if ((random() % 3) > 1){ //set dimmer/brighter to a random value, was just using to test stuff
            active_pwm_updown[b] = 0;
            }else{
            active_pwm_updown[b] = 1;           
            }
    }

while (1){ //run forever

    for (b=1;b!=18; b++){
        setfade(b,1,1,1);
    }
    while(active_pwm_values[1] != shades+1){ //used as triggers to wait untill fade finishes
    }

    unsigned int c;
    unsigned int cc;
    unsigned int ccc;

        while(1){
        //random motion function on all pins
            for (b=1;b!=18; b++){
                if (active_pwm_values[b] == (shades+1)){    
                    c =(rand() % 15) + 1;
                    if ((b > 5) && (b < 12)){
                        if (active_pwm_updown[(b-6)] == 1){
                            ccc = 0;
                            cc = shades-1;
                        }else{
                            ccc = 1;
                            cc = 1;
                        }
                    }else if (b > 11){

                        if (active_pwm_updown[(b-10)] == 1){
                            ccc = 0;
                            cc = shades-1;
                        }else{
                            ccc = 1;
                            cc = 1;
                        }
                    }else{
                        if (active_pwm_updown[(b)] == 1){
                            ccc = 0;
                            cc = shades-1;
                        }else{
                            ccc = 1;
                            cc = 1;
                        }

                    }
                    setfade(b,(c+1),ccc,cc);
                }
            }
            _delay_ms(1000);
        }
    }
}
December 02, 2012
by Ralphxyz
Ralphxyz's Avatar

DAME U LACK OF EDIT BUTTON

AMEN, to that.

There have been (FREE/easily supported) forum/billboard software for at least thirty years that allowed edits.

Ralph

December 23, 2012
by alex555
alex555's Avatar

What voltage are you switching with transistors? I would hope not mains voltage...

December 24, 2012
by Osarus
Osarus's Avatar

About 33v max, 0.1A. I'm using the existing transistors from the original controllers, added a lead to each gate and one to ground and poked them out a hole used for a button to keep things safer.

I'm using 2 shift registers and most of portd to control 21 channels, it's worked out quite well ^_^

Although i almost gave up with an infuriating bug when the size of my code was too apparently too large... I assumed it wouldn't upload if it was too big, but it says it uploads fine and then fails on verification? I didn't think i would have used it all up either... about 350 lines of code, its 1 interrupt function, and basically everything else is just calling 2 other functions over and over. Sound about right? or have i messed up how it optimizes code or linking something wierdly to make it huge?

Also is it possible to monitor over usb for resets or problems? Or am i limited to printf_P() over UART stream and MVLAB simulator for debugging?

December 24, 2012
by Noter
Noter's Avatar

Basically the verification error means the code/data put on the atmega does not match the contents of the .hex file that was uploaded. Best practice is to figure it out and fix before proceeding.

December 24, 2012
by Ralphxyz
Ralphxyz's Avatar

Or am i limited to printf_P() over UART stream and MVLAB simulator for debugging

You can use Atmel AVR Studio 6 for debugging!! And as I have said in another thread with the Atmel Dragon programmer you can do on chip debugging.

Neither of which I have yet to learn how to do/use. So I'd really love someone to figure it out and offer to help get me going.

From my limited past programming experiences I'd really gotten dependent on having a debugger but have been limited to flashing leds and doing essentially print screens messages to the LCD.

Ralph

December 24, 2012
by JimFrederickson
JimFrederickson's Avatar

USB is just for communications an possibly power.

If you hook up the USB directly to your Microcontroller then any "debugging information" you get will need to come from your Microcontroller.

If you want to track "Resets/Power Ups" one thing you can do, is that each time your Microcontroller boots is to write some sequence into the the EEPROM in the Microcontroller.

Then you can print out that sequence to the USB/Serial Port.

That way, you can track resets. You can also write certain values from variables, or anything else for that matter, there too. (Keep in mind that like the Flash Memory for Programming the EEPROM does have a limited life/endurance affected by writing to it. Writing to the EEPROM is by "byte", not by "page", so I am pretty sure life is limited by "bytes" as well. If you are going to be writing alot to the EEPROM you can create series of blocks, and put a sequence number at the head of each block and always write to the block with the lowest sequence number to spread out the writes and increase it's useful life for a given application.)

Now there are cheap devices that will plug into your USB and then your Microcontroller that are designed to provide debugging information to you. They can be quite helpful, but often there are some trade-offs. (Since these devices are communicating with your Microcontroller they take away some pins that would normally be available to you, and sometimes impose restriction on what you can do both hardware/software wise as well.)

There also are more expensive devices for debugging as well that can provide full emulation of the Microcontroller.

For me, I have found that since there is enough programming space on the AVR, 168/328, for quite a bit of code just adding code for debugging purposes is quite helpful. So far that has enabled me to debug anything I have created. (I generally mark that code with comments before and after, to create a block, so that I can remove it easily later on...)

One thing to watch out for, which I have run into alot, is that the RAM for Data Storage is shared between your Program's Data and the C Stack.

Your Program's Data storage grows upwards, and the C Stack grows downwards.

If they "collide" then there will, most likely, be problems with your program at some point.

Post a Reply

Please log in to post a reply.

Did you know that you can build a circuit to convert the "dit" and "dah" of Morse code back into letters automatically? Learn more...