I wrote this code in my exam, but it have some problems(and because of this i get failed).
While debugging through my board(i've got an atmel atmega328p Xplained mini), i don't know why, but while entering in the main switch and between switch (currentstatus) and case checkled: all my status variables are reset to zero. If i debug it via simulator it seems to work fine.
If i upload the code to the board it works bad, like if it doesn't recognise some interrupts.
Plus i want to ask you another thing. I use for my exam a daughter board that prevents to access to the right pin of PWM output and plus i have to drive specific outupt(the leds of my daughter board, for example in this code i've to drive PORTC5 and PORTC4), so i've to implement the PWM by hand. I've tried to implement the solution that you can see in the code(i'm using a timer of 1ms). Is there a more simple and smart solution?
Can you help me?
#include <avr/io.h>
#include <avr/interrupt.h>
typedef enum{checkled, heatingup, exposure, stop} machine;
machine currentstate=checkled;
typedef enum{twenty, fourty, sixty, eighty} brightness;
brightness light=twenty;
typedef enum{twoseconds, fourseconds, eightseconds, sixteenseconds} exposuretime;
exposuretime time=twoseconds;
volatile uint16_t tick=0;
volatile uint16_t oldtick=0;
volatile uint8_t flagchanged=0;
ISR(PCINT2_vect)
{
if((PIND&(1<<PIND2))==0)
{
if(currentstate==checkled)
currentstate=heatingup;
}
if((PIND&(1<<PIND3))==0)
{
if(currentstate==exposure || currentstate==heatingup)
{
currentstate=stop;
PORTC&=~(1<<PORTC4);
tick=0;
}
}
if((PIND&(1<<PIND4))==0)
{
if(currentstate==checkled)
{
flagchanged=1;
if(time==sixteenseconds)//rise time
;
else if(time==eightseconds)
time=sixteenseconds;
else if(time==fourseconds)
time=eightseconds;
else if(time==twoseconds)
time=fourseconds;
}
}
if((PIND&(1<<PIND5))==0)
{
if(currentstate==checkled)
{
flagchanged=1;
if(time==sixteenseconds)//decrease time
time=eightseconds;
else if(time==eightseconds)
time=fourseconds;
else if(time==fourseconds)
time=twoseconds;
else if(time==twoseconds)
;
}
}
if((PIND&(1<<PIND6))==0)
{
if(currentstate==checkled)
{
flagchanged=1;
if(light==eighty)//rise brightness
;
else if(light==sixty)
light=eighty;
else if(light==fourty)
light=sixty;
else if(light==twenty)
light=fourty;
}
}
if((PIND&(1<<PIND7))==0)
{
if(currentstate==checkled)
{
flagchanged=1;
if(light==eighty)//decrease brightness
light=sixty;
else if(light==sixty)
light=fourty;
else if(light==fourty)
light=twenty;
else if(light==twenty)
;
}
}
}
ISR(TIMER1_COMPA_vect)
{
tick++;
}
int main(void)
{
//DDRs
DDRD&=~((1<<PIND2)|(1<<PIND3)|(1<<PIND4)|(1<<PIND5)|(1<<PIND6)|(1<<PIND7));//input
PORTD|=(1<<PORTD2)|(1<<PORTD3)|(1<<PORTD4)|(1<<PORTD5)|(1<<PORTD6)|(1<<PORTD7);//pull-up resistors
DDRC|=(1<<PORTC0)|(1<<PORTC1)|(1<<PORTC2)|(1<<PORTC3)|(1<<PORTC4)|(1<<PORTC5);//output
//PCINTERRUPT
PCICR|=(1<<PCIE2);
PCMSK2|=(1<<PCINT18)|(1<<PCINT19)|(1<<PCINT20)|(1<<PCINT21)|(1<<PCINT22)|(1<<PCINT23);
//TIMER
TCCR0A|=(1<<WGM01);
TIMSK0|=(1<<OCIE0A);
OCR0A=15;//((clockfrequency/prescaler)*time)-1 - 1millisecond
TCCR0B|=(1<<CS02)|(1<<CS00);
sei();
volatile uint8_t counter=0;
volatile uint16_t check=0;
while(1)
{
switch (currentstate)//FORM HERE
{
case checkled://TO HERE every variable is reset to ZERO
if(flagchanged!=0)
{
if(light==twenty)//led intesita
{
PORTC&=~(1<<PORTC0);
PORTC&=~(1<<PORTC1);
}
else if(light==fourty)
{
PORTC|=(1<<PORTC0);
PORTC&=~(1<<PORTC1);
}
else if(light==sixty)
{
PORTC&=~(1<<PORTC0);
PORTC|=(1<<PORTC1);
}
else if(light==eighty)
{
PORTC|=(1<<PORTC0);
PORTC|=(1<<PORTC1);
}
if(time==twoseconds)//led time
{
PORTC&=~(1<<PORTC2);
PORTC&=~(1<<PORTC3);
}
else if(time==fourseconds)
{
PORTC|=(1<<PORTC2);
PORTC&=~(1<<PORTC3);
}
else if(time==eightseconds)
{
PORTC&=~(1<<PORTC2);
PORTC|=(1<<PORTC3);
}
else if(time==sixteenseconds)
{
PORTC|=(1<<PORTC2);
PORTC|=(1<<PORTC3);
}
flagchanged=0;
}
break;
case heatingup:
if(tick<=3000)
{
if(tick!=oldtick)
{
oldtick=tick;
if((tick%500)==0)//duty cycle al 50%
PORTC^=(1<<PORTC5);
if((tick%5)==0)//5% duty cycle
{
if(counter<=94)//per il 95% del periodo sta spento
{
PORTC&=~(1<<PORTC4);
}
else if(counter>=95 && counter<=101)//per il 5% del periodo sta acceso
{
if(counter==101)
{
PORTC&=~(1<<PORTC4);
counter=0;
}
else
PORTC|=(1<<PORTC4);
}
counter++;
}
}
}
else
{
currentstate=exposure;
counter=0;
tick=0;
PORTC|=(1<<PORTC5);
//checking time of how much the lamp needs to be light up
switch (time)
{
case twoseconds:
check=2000;
break;
case fourseconds:
check=4000;
break;
case eightseconds:
check=8000;
break;
case sixteenseconds:
check=16000;
break;
}
}
break;
case exposure:
if(tick<=check)
{
switch (light)//Checking duty cycle
{
case twenty://20% duty cycle
if(tick!=oldtick)
{
if((tick%20)==0)
{
if(counter<=4)//80% off
{
PORTC&=~(1<<PORTC4);
}
else if(counter>=5 && counter<=6)//20% on
{
if(counter==6)
{
PORTC&=~(1<<PORTC4);
counter=0;
}
else
PORTC|=(1<<PORTC4);
}
counter++;
}
}
break;
case fourty://40% duty cycle
if(tick!=oldtick)
{
if((tick%20)==0)
{
if(counter<=3)//60% off
{
PORTC&=~(1<<PORTC4);
}
else if(counter>=4 && counter<=6)//40% on
{
if(counter==6)
{
PORTC&=~(1<<PORTC4);
counter=0;
}
else
PORTC|=(1<<PORTC4);
}
counter++;
}
}
break;
case sixty://60% duty cycle
if(tick!=oldtick)
{
if((tick%20)==0)
{
if(counter<=2)//40% off
{
PORTC&=~(1<<PORTC4);
}
else if(counter>=3 && counter<=6)//60% on
{
if(counter==6)
{
PORTC&=~(1<<PORTC4);
counter=0;
}
else
PORTC|=(1<<PORTC4);
}
counter++;
}
}
break;
case eighty://80% duty cycle
if(tick!=oldtick)
{
if((tick%20)==0)
{
if(counter<=1)//20% off
{
PORTC&=~(1<<PORTC4);
}
else if(counter>=2 && counter<=6)//80% on
{
if(counter==6)
{
PORTC&=~(1<<PORTC4);
counter=0;
}
else
PORTC|=(1<<PORTC4);
}
counter++;
}
}
break;
}
}
else
{
PORTC&=~(1<<PORTC4);
PORTC&=~(1<<PORTC5);
currentstate=checkled;
flagchanged=1;
}
break;
case stop://Emergency stop
if(tick<=2000)
{
if(tick!=oldtick)
{
oldtick=tick;
if((tick%250)==0)
PORTC|=(1<<PORTC5);
}
}
else
{
PORTC&=~(1<<PORTC5);
flagchanged=1;
currentstate=checkled;
}
break;
}
}
}