imranahmed
Advanced Member level 3
- Joined
- Dec 4, 2011
- Messages
- 822
- Helped
- 3
- Reputation
- 6
- Reaction score
- 3
- Trophy points
- 1,298
- Location
- Karachi,Pakistan
- Activity points
- 6,533
void InitTimer2(){ //CTC timer2
OCR2 = 155;
TCCR2 |= 0x0E;
TIMSK |= 0x80;
TCNT2 = 0;
}
ISR(TIMER2_COMP_vect){
TCNT2 = 0;
if((PINC & (1<<PC3)) == 0)
{
swcount2++;
if(swcount2==100){
q++;
swcount2=0;
}}
switch(q){
case 0:
av=read_adc(3); // yellow amps
dv1 = dv1 + (av - dv1) * fc ;
mcount2++;
if(mcount2==100)
{
mcount2=0;
dispv1=dv1;
}
break;
case 1:
ampset = read_eeprom_word(&my_eeprom_word);
dispv1 = ampset;
if((PINC & (1<<PC4)) == 0){
mcount2++;
if(mcount2==50)
{
mcount2=0;
ampset++;
write_eeprom_word(&my_eeprom_word,ampset);//store value in eeprom
dispv1=ampset;
}
}
if((PINC & (1<<PC5)) == 0){
mcount2++;
if(mcount2==50)
{
mcount2=0;
ampset--;
write_eeprom_word(&my_eeprom_word,ampset); // store value in eeprom
dispv1=ampset;
}
}
break;
default:
q=0;
break;
}
while(1)
{
cli();
tmp1=dispv1;
tmp=dispv;
sei();
Print1(tmp1); // Print1 for digit 1-3
Print(tmp); // Print for digit 4-6
if(tmp1>ampset)
{
PORTD |= 1<<PD7;
}
}
My first impression of the code, it's a very bad idea to do all these things in a timer interrupt.
unsigned char mcount=0,p=0,swcount=0,flag=0;
unsigned int av=0,RBV=0;
float fc=0.005,dispv=0,dispv1=0,dv=0,dv1=0,dv2=0,tmp1=0,tmp=0;
void InitTimer0(){ //Overflow timer0
TCCR0|=(1<<CS01)|(1<<CS00); // PRESCALAR = 64
TIMSK|=(1<<TOIE0);
TCNT0 = 0;
OCR0 = 20;
}
void InitTimer1(){
TCCR1B |= 0x09;
OCR1AH = 0x9C;
OCR1AL = 0x3F;
TIMSK |= 0x10;
}
void InitADC()
{
ADMUX |=(1<<REFS0); // For Aref=AVcc;
ADCSRA|=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS0);// Prescalar = 32
ADCSRA|=(1<<ADSC);
}
uint16_t read_adc(uint8_t ch)
{
//Select ADC Channel ch must be 0-7
ADMUX = (ADMUX & 0xF8) | ch;
ADCSRA|=(1<<ADSC);
while(!(ADCSRA & (1<<ADIF)));
ADCSRA|=(1<<ADIF);
return(ADCW);
}
ISR(TIMER1_COMPA_vect)
{
if((PIND & (1<<PD6)) == 0)
{
swcount++;
if(swcount==100)
{
p++;
swcount=0;
}
}
mcount++;
}
ISR(TIMER0_OVF_vect)
{
TCNT0=0;
// This interrupt service routine (ISR)
// Updates the displays
static uint8_t i=0;
if(i==5)
{
//If on last display then come
//back to first.
i=0;
}
else
{
//Goto Next display
i++;
}
//Activate a display according to i
PORTD&=(0b11000000);
PORTD|=(1<<i);
SevenSegment(digits[i]);
}
void state_display(){
switch(p){
case 0:
PORTC &= ~(1<<PC0);
PORTC &= ~(1<<PC2);
PORTC |= 1<<PC1;
av=read_adc(1); // yellow volts
dv = dv + ( av - dv) * fc ;
av=read_adc(3); // yellow amps
dv1 = dv1 + (av - dv1) * fc ;
if(mcount==100)
{
mcount=0;
dispv=dv;
dispv1=dv1;
flag=1;
}
break;
case 1:
PORTC &= ~(1<<PC1);
PORTC |= 1<<PC2;
av=read_adc(2); // blue volts
dv = dv + ( av - dv) * fc ;
av=read_adc(3); // yellow amps
dv1 = dv1 + (av - dv1) * fc ;
if(mcount==100)
{
mcount=0;
dispv=dv;
dispv1=dv1;
flag=1;
}
break;
case 2:
PORTC &= ~(1<<PC2);
PORTC |= 1<<PC0;
av=read_adc(0); // red volts
dv = dv + ( av - dv) * fc ;
av=read_adc(3); // yellow amps
dv1 = dv1 + (av - dv1) * fc ;
if(mcount==100)
{
mcount=0;
dispv=dv;
dispv1=dv1;
flag=1;
}
break;
case 3:
PORTC |= 1<<PC0;
PORTC |= 1<<PC2;
av=read_adc(0); // red_blue volts
dv = dv + ( av - dv) * fc ;
av=read_adc(2); // blue_red volts
dv2 = dv2 + ( av - dv2) * fc ;
RBV=((dv+dv2)*0.866);
av=read_adc(3); // yellow amps
dv1 = dv1 + (av - dv1) * fc ;
if(mcount==100)
{
mcount=0;
dispv=RBV;
dispv1=dv1;
flag=1;
}
break;
case 4:
PORTC &= ~(1<<PC0);
PORTC |= 1<<PC1;
PORTC |= 1<<PC2;
av=read_adc(2); // blue_yellow volts
dv = dv + ( av - dv) * fc ;
av=read_adc(1); // yellow_blue volts
dv2 = dv2 + ( av - dv2) * fc ;
RBV=((dv+dv2)*0.866);
av=read_adc(3); // yellow amps
dv1 = dv1 + (av - dv1) * fc ;
if(mcount==100)
{
mcount=0;
dispv=RBV;
dispv1=dv1;
flag=1;
}
break;
case 5:
PORTC &= ~(1<<PC2);
PORTC |= 1<<PC0;
PORTC |= 1<<PC1;
av=read_adc(0); // red_yellow volts
dv = dv + ( av - dv) * fc ;
av=read_adc(1); // yellow_red volts
dv2 = dv2 + ( av - dv2) * fc ;
RBV=((dv+dv2)*0.866);
av=read_adc(3); // yellow amps
dv1 = dv1 + (av - dv1) * fc ;
if(mcount==100)
{
mcount=0;
dispv=RBV;
dispv1=dv1;
flag=1;
}
break;
default:
p=0;
break;
}}
void atomic_display(){
cli();
tmp1=dispv1;
tmp=dispv;
sei();
Print1(tmp1); // Print1 for digit 1-3
Print(tmp); // Print for digit 4-6
}
void initialize(){
DDRD|= 0b00111111;
PORTD|= 0b01111111;
//Port B AS OUTPUT
SEVEN_SEGMENT_DDR=0XFF;
//Turn off all segments
SEVEN_SEGMENT_PORT=0X00;
// _delay_ms(1000);
InitTimer0();
InitTimer1();
InitADC();
DDRA = 0b00000000;
DDRC |= 0x07;
PORTC = 0x00;
//Enable Global Interrupts
sei();
//Infinite loop
}
int main()
{
initialize();
while(1)
{
state_display();
if(flag==1)
atomic_display();
}
}
I agree with KlausST. Your code can't work for AC measurement.
The problem you are presently addressing is about Ampmeter user interface: Range selection, scaling, display.
My first impression of the code, it's a very bad idea to do all these things in a timer interrupt.
The only place where flag is set should be in measurement isr.
Flag must be cleared when handled in main loop
Some days ago we managed all the adc_read in measurement isr. Why, why do you do this in main loop now?
Thats' good, you didn't mention a rectifier before. Let us assume that you are correctly converting the CT output current to DC voltage at ADC input.Why my code cannot work with AC measurement?
I also use ZXCT1041 IC is full-wave precision rectifier for signal conditioning for input of ADC.
please try to inform us what you do:
... rectifier ... how can we know?
... is there an anaolg filter connected between rectifier and ADC input?
... isr setup: what frequency, what is the isr for?
... portc0 to portc2: what is it for?
... what display do you have?
... where is print and print1 defined? do they calculate digits(i)?
ISR() // 5 ms
{
if(button_press==PC3)
{
mcount++;
}
main()
{
if(mcount==50)
{
digits++;
}
}
ISR() // 5 ms
{
if(button_press==PC3)
{
mcount++;
mcount1++;
}
main()
{
if(mcount==50)
{
mcount=0;
digits++;
if(mcount==200)
{
mcount2=0;
if(mcount==10)
{
mcount=0;
digits++;
}
}
}
}
ISR(TIMER1_COMPA_vect)
{
mcount++;
mcount1++;
if((PIND & (1<<PD6)) == 0)
{
swcount++;
if(swcount==100)
{
p++;
swcount=0;
}
}
if((PINC & (1<<PC3)) == 0)
{
swcount1++;
if(swcount1==100)
{
q++;
swcount1=0;
}
}
[COLOR="#0000FF"]if((PINC & (1<<PC4)) == 0)
{
mcount2++;
}[/COLOR]
if((PINC & (1<<PC5)) == 0)
{
mcount3++;
}
[COLOR="#0000FF"]case 1:[/COLOR]
dispv1=dv1c;
flag=1;
if(mcount2==50)
{
mcount2=0;
if(dv1b<100)
dv1b=dv1b+0.1;
else if(dv1b>=100)
dv1b=dv1b+1;
write_eeprom_float(&my_eeprom_float,dv1b);
}
if(mcount3==50)
{
mcount3=0;
if(dv1b<100)
dv1b=dv1b-0.1;
else if(dv1b>=100)
dv1b=dv1b-1;
write_eeprom_float(&my_eeprom_float,dv1b);
}
if(dv1b<100 && y==4)
{
PORTB &= ~(1<<PB7);
dv1c = dv1b * 10;
}
if(dv1b>=100 && y==4)
{
PORTB |= (1<<PB7);
dv1c = dv1b;
}
if(dv1b<0)
{
dv1b=999;
dispv1=dv1b;
write_eeprom_float(&my_eeprom_float,dv1b);
flag=1;
}
if(dv1b>999)
{
dv1b=0;
dispv1=dv1b;
write_eeprom_float(&my_eeprom_float,dv1b);
flag=1;
}
[COLOR="#0000FF"] break;[/COLOR]
}
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#define SEVEN_SEGMENT_PORT PORTB
#define SEVEN_SEGMENT_DDR DDRB
#define read_eeprom_float(address) eeprom_read_float ((const float*)address)
#define write_eeprom_float(address,value) eeprom_write_float ((float*)address,(float)value)
//declare an eeprom variable
unsigned int EEMEM my_eeprom_float;
volatile uint8_t digits[2];
volatile uint8_t digits1[2];
static uint8_t y=0;
unsigned char mcount=0,mcount1=0,mcount2=0,mcount3=0,mcount4=0,m=0,z=0,e=0,f=0,p=0,q=0,swcount=0,swcount1=0,flag=0;
unsigned int av=0,RBV=0,tmpset=0;
float fc=0.003,dispv=0,dispv1=0,dv=0,dv1=0,dv1a=0,dv1b=0,dv1c=0,dv2=0,tmp1=0,tmp=0;
void SevenSegment(uint8_t n)
{
// n must be less than 9
//~0x3f,~0x06,~0x5b,~0x4f,~0x66,
//~0x6d,~0x7d,~0x07,~0x7f,~0x67;
switch (n)
{
case 0:
//.gfedcba
SEVEN_SEGMENT_PORT=0b11000000;
break;
case 1:
//.gfedcba
SEVEN_SEGMENT_PORT=0b11111001;
break;
case 2:
//.gfedcba
SEVEN_SEGMENT_PORT=0b10100100;
break;
case 3:
//.gfedcba
SEVEN_SEGMENT_PORT=0b10110000;
break;
case 4:
//.gfedcba
SEVEN_SEGMENT_PORT=0b10011001;
break;
case 5:
//.gfedcba
SEVEN_SEGMENT_PORT=0b10010010;
break;
case 6:
//.gfedcba
SEVEN_SEGMENT_PORT=0b10000010;
break;
case 7:
//.gfedcba
SEVEN_SEGMENT_PORT=0b11111000;
break;
case 8:
//.gfedcba
SEVEN_SEGMENT_PORT=0b10000000;
break;
case 9:
//.gfedcba
SEVEN_SEGMENT_PORT=0b10010000;
break;
}
}
void Print1(uint16_t num1)
{
/*
This function breaks apart a given integer into separate digits
and writes them to the display array i.e. digits[]
*/
uint8_t i=5;
uint8_t j;
if(num1>999)
return ;
while(num1)
{
digits1[i]=num1%10;
i++;
num1=num1/10;
}
for(j=i;j<8;j++)
digits1[j]=0;
}
void InitTimer0(){ //Overflow timer0
TCCR0|=(1<<CS01)|(1<<CS00); // PRESCALAR = 64
TIMSK|=(1<<TOIE0);
TCNT0 = 0;
OCR0 = 20;
}
void InitTimer1(){
TCCR1B |= 0x09;
OCR1AH = 0x9C;
OCR1AL = 0x3F;
TIMSK |= 0x10;
}
void InitADC()
{
ADMUX |=(1<<REFS0); // For Aref=AVcc;
ADCSRA|=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS0);// Prescalar = 32
ADCSRA|=(1<<ADSC);
}
uint16_t read_adc(uint8_t ch)
{
//Select ADC Channel ch must be 0-7
ADMUX = (ADMUX & 0xF8) | ch;
ADCSRA|=(1<<ADSC);
while(!(ADCSRA & (1<<ADIF)));
ADCSRA|=(1<<ADIF);
return(ADCW);
}
ISR(TIMER1_COMPA_vect)
{
mcount++;
mcount1++;
if((PIND & (1<<PD6)) == 0)
{
swcount++;
if(swcount==100)
{
p++;
swcount=0;
}
}
if((PINC & (1<<PC3)) == 0)
{
swcount1++;
if(swcount1==100)
{
q++;
swcount1=0;
}
}
if((PINC & (1<<PC4)) == 0)
{
mcount2++;
}
if((PINC & (1<<PC5)) == 0)
{
mcount3++;
}
}
ISR(TIMER0_OVF_vect)
{
TCNT0=0;
// This interrupt service routine (ISR)
// Updates the displays
if(y==5)
{
//If on last display then come
//back to first.
y=0;
}
else
{
//Goto Next display
y++;
}
//Activate a display according to i
PORTD&=(0b11000000);
PORTD|=(1<<y);
SevenSegment(digits[y]);
}
void state_display_amps(){
switch(q){
case 0:
e=0;
f=0;
av=read_adc(3);// yellow amps
dv1 = dv1 + (av - dv1) * fc ;
if(dv1<100 && y==4)
{
PORTB &= ~(1<<PB7);
dv1a=dv1*10;
}
if(dv1>=100 && y==4)
{
PORTB |= (1<<PB7);
dv1a=dv1;
}
if(mcount1==100)
{
mcount1=0;
dispv1=dv1a;
flag=1;
}
break;
case 1:
e=1;
dispv1=dv1c;
flag=1;
if(mcount2==50)
{
mcount2=0;
if(dv1b<100)
dv1b=dv1b+0.1;
else if(dv1b>=100)
dv1b=dv1b+1;
write_eeprom_float(&my_eeprom_float,dv1b);
}
if(mcount3==50)
{
mcount3=0;
if(dv1b<100)
dv1b=dv1b-0.1;
else if(dv1b>=100)
dv1b=dv1b-1;
write_eeprom_float(&my_eeprom_float,dv1b);
}
if(dv1b<100 && y==4)
{
PORTB &= ~(1<<PB7);
dv1c = dv1b * 10;
}
if(dv1b>=100 && y==4)
{
PORTB |= (1<<PB7);
dv1c = dv1b;
}
if(dv1b<0)
{
dv1b=999;
dispv1=dv1b;
write_eeprom_float(&my_eeprom_float,dv1b);
flag=1;
}
if(dv1b>999)
{
dv1b=0;
dispv1=dv1b;
write_eeprom_float(&my_eeprom_float,dv1b);
flag=1;
}
break;
default:
q=0;
break;
}
}
void atomic_display(){
cli();
tmp1=dispv1;
sei();
Print1(tmp1); // Print1 for digit 1-3
}
void initialize(){
dv1b = read_eeprom_float(&my_eeprom_float); // restore from eeprom
DDRD |= 0b10111111;
PORTD |= 0b01111111;
DDRA = 0b00000000;
DDRC |= 0b00000111; //76543210
PORTC |= 0b00111000;
//Port B AS OUTPUT
SEVEN_SEGMENT_DDR=0XFF;
//Turn off all segments
SEVEN_SEGMENT_PORT=0X00;
// _delay_ms(1000);
InitTimer0();
InitTimer1();
InitADC();
//Enable Global Interrupts
sei();
//Infinite loop
}
int main()
{
initialize();
while(1)
{
state_display_amps();
if(flag==1)
{
atomic_display();
flag=0;
}
}
}
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?