November 29, 2012
by Osarus
|
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
|
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
|
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
|
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
|
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)
- 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.
- 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
|
Also, respect the limits pcbolt advised of. Those are Chip/Pin max's. |
November 30, 2012
by pcbolt
|
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
|
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
|
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
|
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
|
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
|
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
|
What voltage are you switching with transistors? I would hope not mains voltage... |
December 24, 2012
by Osarus
|
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
|
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
|
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
|
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. |