Duration Meter

Go To Last Post
16 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello all

we have a periodic signal and want to meter it's Duration and Frequency by atmega8 Ic

by following codes :

ISR (INT1_vect){
static unsigned char flag_start=0,state=1;

		if(state==1){
			TCNT1_old=TCNT1;
			overflow=0;
			state=0;
		}else if(state==0){
			diff_time=TCNT1-TCNT1_old+(overflow*1000);
			state=1;

		}

}

 


ISR(TIMER1_OVF_vect){

    overflow++;
    TCNT1=-1000;

}

 

the diff_time is Duration.

Why this code is wrong and doesn't work?

 

 

Last Edited: Sat. Nov 20, 2021 - 07:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please, do not put extra spaces in the code, it is NOT necessary.

 

Which is the frequency, or period of the signal?

Or, Min/Max values.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

grohote wrote:
do not put extra spaces in the code, it is NOT necessary

on the contrary, some whitespace in that code would make it a whole lot easier to read!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

While the other two argue over spacing.....

 

Please post your ENTIRE code.  That little bit really does not tell the whole tale.

 

 

In a nutshell though....if all you are doing is reading a pulse...hopefully one that has been properly cleaned up prior to firing the INT1 ISR..Once the pulsed rising edge hits, in the ISR you START the timer.

 

Then return to the main loop and sit in a while() loop until the falling edge is sensed and then in the IR turn the TIMER off and record the TCNTx register.

 

Return to main loop and then take the TCNTx register and multiply it by the single clock cycle of the timer and theres your pulse width.

 

Clear teh counter and reset everything and wait for another pulse.

 

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
some whitespace in that code would make it a whole lot easier to read

 

Exactly! Spaces are missing around "=", "+"... OP, if you mind, please.

 

I have nothing against a normal indenting, but why to have 16 spaces instead of 8?

And, why so many empty lines, do we really need 4 empty lines?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

make sure tcount_old and overflow maintain their values between calls

 

note 

}else if(state==0){

could likely just be else (since it was not 1), assuming it is never anything but 0 or 1 

 

if(state==1)

why not (optionally) reset your tnct during the first edge?  (set tcnt=0  to begin the measure)   This is the simplest way to start, get more complicated later.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sun. Nov 21, 2021 - 03:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

grohote wrote:
Exactly! Spaces are missing around "=", "+"... OP, if you mind, please.

 

Really?  You are completely unable to read the text?

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I Do TCNT1=0 but the duration=time between two rising edge is not fix!

the edited code is it here:

overflow variable is the number of the Timer Interrupt occurs.

ISR (INT1_vect){	
static unsigned char flag_start=0,state=1;
		if(state==1){
			TCNT1=0;
			overflow=0;
			state=0;
		}else if(state==0){
			diff_time=TCNT1+(overflow*1000);
			state=1;	
			flag_frequency_manager=0;
		}
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just on the spacing issue, I agree that generally accepted and commonly used spacing techniques make code more readable, however, it takes time and experience to learn coding standards, and someone new to the development of software will write what is termed 'untidy' code for a while until they learn them over time. When I started coding some 40 years ago I also didn't space and indent my code the way it was generally expected, but I learned as I progressed in life and my career. In fact, even when using accepted coding layout practices, that won't shield you from some developers who feel their type of formatting is better than the standard you have adopted and will still argue the point. Yet another point is developers also develop their own quirks when developing that other developers find much like squeezing the toothpaste tube in the middle and bitch and moan about. This irritates me because it is like a 'My way is better than yours' school-yard argument.

 

I don't think that criticizing someone new to coding for the format and readability of their initial attempts does anything to help them with their issues in their code, however I agree that they should be progressing over time as they learn, and the readability should increase as they do. In this instance it was a relatively relaxed criticism of their coding standards, however I have seen some posts ( and not just here) where people are downright nasty to others because of their style of coding. I believe that, if you find someone's code hard to read, rather just don't read it than start pulling strips off them for it.

 

My 2c. Flame away.

 

Wayne

East London
South Africa

 

  • No, I am not an Electronics Engineer, just a 54 year old hobbyist/enthusiast
  • Yes, I am using Proteus to learn more about circuit design and electronics
  • No, I do not own a licensed copy of Proteus, I am evaluating it legitimately
  • No, I do not believe in software or intellectual property piracy or theft
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:
Please post your ENTIRE code.
yes

Have you declared overflow as volatile?

As Jim asked in post #4, is the signal generating the interrupt "properly cleaned up?"

As grohote asked in post #2, what is the frequency and duty cycle of the signal?

 

Answering these will help us help you.

David

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

frequency is between 10Khz to 50Khz

Duty Cycle is from zero to 100%

the code is following:

#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>

#include "lcd.h"
#include<avr/interrupt.h>

#define sbi(x, y) x |= _BV(y)                  // set bit
#define cbi(x, y) x &= ~(_BV(y))               // clear bit
#define tbi(x, y) x ^= _BV(y)                  // toggle bit
#define is_high(x, y) ((x & _BV(y)) == _BV(y)) //(for input) checks if the input is high (Logic 1)  //پ?ن نوشته شود نه پورت


volatile uint16_t overflow;
float diff_time,duty;
float frequency=0;
volatile uint16_t sum_,k;


volatile uint16_t TCNT1_old;
volatile uint8_t flag_frequency_manager=0;
volatile uint8_t flag_duty_enable;
volatile uint16_t duty_variable;
ISR (INT1_vect){	
static unsigned char flag_start=0,state=1;

	if(flag_frequency_manager){

		if(is_high(PIND,3)){
			if(state==1){
				TCNT1=0;
				overflow=0;
				state=0;
				flag_duty_enable=1;
			}else if(state==0){
				TCNT1_old=TCNT1;
				
				diff_time=(1000000/TCNT1)+overflow*1000;
				frequency=diff_time/1000;

				state=1;	
				flag_frequency_manager=0;
			}

		}
		
	}
	
	if(flag_duty_enable && is_high(PIND,3)==0){flag_duty_enable=0;duty_variable=TCNT1;}
	
}

volatile unsigned char flag_lcd=0,flag_mean_current;
volatile unsigned int cnt0,cnt1,cnt3,cnt4;
ISR(TIMER1_OVF_vect){
	
	overflow++;
}


ISR(TIMER2_OVF_vect){
	
	TCNT2=-126;
	if(++cnt0>4000){cnt0=0;flag_lcd=1;/*duty=duty_variable/TCNT1_old;*/}
	if(++cnt1>30){cnt1=0;flag_frequency_manager=1;}
	if(++cnt3>100){cnt3=0;ADCSRA|=0x40;}

	
}


volatile float current_;
volatile double ADCW_double;
uint16_t data_t;
ISR(ADC_vect){

	ADCW_double=ADCW;
	ADCW_double=((970-ADCW_double)*17.834);
	if(ADCW_double<10) ADCW_double=0;
	current_=ADCW_double;
	flag_mean_current=1;
}
	
	
char line1[25],line2[25] ,line3[25], line4[25];
uint16_t mean_array[101];


int main(void){

	{
		// Declare your local variables here

		// Input/Output Ports initialization
		// Port B initialization
		// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
		DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
		// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
		PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

		// Port C initialization
		// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
		DDRC=(0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
		// State: Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
		PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

		// Port D initialization
		// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
		DDRD=(1<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
		// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
		PORTD=(1<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (1<<PORTD3) | (1<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

		// Timer/Counter 0 initialization
		// Clock source: System Clock
		// Clock value: Timer 0 Stopped
		TCCR0=(0<<CS02) | (0<<CS01) | (0<<CS00);
		TCNT0=0x00;

		// Timer/Counter 1 initialization
		// Clock source: System Clock
		// Clock value: 1000/000 kHz
		// Mode: Normal top=0xFFFF
		// OC1A output: Disconnected
		// OC1B output: Disconnected
		// Noise Canceler: Off
		// Input Capture on Falling Edge
		// Timer Period: 65/536 ms
		// Timer1 Overflow Interrupt: On
		// Input Capture Interrupt: Off
		// Compare A Match Interrupt: Off
		// Compare B Match Interrupt: Off
		TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
		TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10);
		TCNT1H=0x00;
		TCNT1L=0x00;
		ICR1H=0x00;
		ICR1L=0x00;
		OCR1AH=0x00;
		OCR1AL=0x00;
		OCR1BH=0x00;
		OCR1BL=0x00;

		// Timer/Counter 2 initialization
		// Clock source: System Clock
		// Clock value: 1000/000 kHz
		// Mode: Normal top=0xFF
		// OC2 output: Disconnected
		// Timer Period: 0/256 ms
		ASSR=0<<AS2;
		TCCR2=(0<<COM21) | (0<<COM20) | (0<<CS22) | (1<<CS21) | (0<<CS20);
		TCNT2=0x00;
		OCR2=0x00;

		// Timer(s)/Counter(s) Interrupt(s) initialization
		TIMSK=(0<<OCIE2) | (1<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (1<<TOIE1) | (0<<TOIE0);


		// External Interrupt(s) initialization
		// INT0: Off
		// INT1: On
		// INT1 Mode: Any change
		GICR|=(1<<INT1) | (0<<INT0);
		MCUCR=(0<<ISC11) | (1<<ISC10) | (0<<ISC01) | (0<<ISC00);
		GIFR=(1<<INTF1) | (0<<INTF0);

		

		// USART initialization
		// USART disabled
		UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (0<<RXEN) | (0<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);

		// Analog Comparator initialization
		// Analog Comparator: Off
		// The Analog Comparator's positive input is
		// connected to the AIN0 pin
		// The Analog Comparator's negative input is
		// connected to the AIN1 pin
		ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);

		// ADC initialization
		// ADC Clock frequency: 1000/000 kHz
		// ADC Voltage Reference: AREF pin
		ADMUX=(1<<REFS1) | (1<<REFS0) | (0<<ADLAR);
		ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADFR) | (0<<ADIF) | (1<<ADIE) | (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
		SFIOR=(0<<ACME);
		
		
		// SPI initialization
		// SPI disabled
		SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);

		// TWI initialization
		// TWI disabled
		TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);

		// Alphanumeric LCD initialization
		// Connections are specified in the
		// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
		// RS - PORTB Bit 0
		// RD - PORTB Bit 1
		// EN - PORTB Bit 2
		// D4 - PORTB Bit 3
		// D5 - PORTB Bit 4
		// D6 - PORTB Bit 5
		// D7 - PORTB Bit 6
		// Characters/line: 20
		LCD_Init(4,20);

		// Global enable interrupts
	
	}
	
	sei();
	LCD_SetUp(PD_0,PD_1,PD_2,P_NC,P_NC,P_NC,P_NC,PB_0,PB_1,PB_2,PD_5);
	LCD_Init(4,20);
	LCD_DisplayString("Explore Embedded\n");
	LCD_DisplayString("LCD 4-bit Mode\n");
	LCD_DisplayString("20 x 4 \n");
	LCD_DisplayString(":)  :O");
			
	while(1){
		
		if(flag_mean_current){
			
			flag_mean_current=0;
			
			mean_array[100]=current_;
			for(k=0;k<100;k++) mean_array[k]=mean_array[k+1];
			for(k=0;k<100;k++) sum_+=mean_array[k];
			sum_=sum_/100;
			
		}
		
		if(flag_lcd){
			flag_lcd=0;
		
			sprintf(line1,"Voltage : 25.18 Volt");
			
			sprintf(line2,"Frequency: %3.0f   KH  ",frequency);
			sprintf(line3,"Duty :     %3.0f    %% ",duty_variable*diff_time/10000);
			
			sprintf(line4,"Current:   %3d mA",sum_);
								
			LCD_SetCursor(0,0);
			LCD_DisplayString(line1);
			
			LCD_SetCursor(1,0);
			LCD_DisplayString(line2);
			
			LCD_SetCursor(2,0);
			LCD_DisplayString(line3);
			
			LCD_SetCursor(3,0);
			LCD_DisplayString(line4);
			
			
		}
	}
	
	return 0;
	
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have 3 counters, one is too many.

Basically, one counter will measure a time base of 0.5 or 1s, (or 0.512 or 1.024s or anything) and in that time you can count pulses.

This is the first step- make it all easier. Try to measure frequency, with 16b counter and T1.

Then pulse width- it is another measure, well different.

 

Do start with ADC, if this works you are sure that LCD works as well.

Do print results each Timebase period, it means that this counter works.

Use T1 (PD5) for counting external pulses.

 

Try it, wish you success.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hasanzadeh99 wrote:
frequency is between 10Khz to 50Khz

Note that the correct spelling is 10kHz to 50kHz

 

So what results does your code give you?

 

What investigation / testing / debugging have you done to find what's going on?

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

your code has enough fluff, that it is hard to analyze

		// SPI initialization
		// SPI disabled
		SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);

The first 2 lines add nothing, except to make it harder to see other lines that actually do something (every line you waste gobbles up the space for another that you actually need to look at).   

Why burn up a dozen lines over and over to say initialization?  Say it once, if even that .O therwise it is impossible to review you program without without unnecessary scrolling all around.  Would you rather spend time scrolling or actually be able to see the issues?

 

The bottom block is a good example....EASY to read & see exactly what is going on

		if(flag_lcd){
			flag_lcd=0;

			sprintf(line1,"Voltage : 25.18 Volt");

			sprintf(line2,"Frequency: %3.0f   KH  ",frequency);
			sprintf(line3,"Duty :     %3.0f    %% ",duty_variable*diff_time/10000);

			sprintf(line4,"Current:   %3d mA",sum_);

			LCD_SetCursor(0,0);
			LCD_DisplayString(line1);

			LCD_SetCursor(1,0);
			LCD_DisplayString(line2);

			LCD_SetCursor(2,0);
			LCD_DisplayString(line3);

			LCD_SetCursor(3,0);
			LCD_DisplayString(line4);

compared to 

 

if(flag_lcd){
			flag_lcd=0;

	                // print the voltage for the user
			sprintf(line1,"Voltage : 25.18 Volt");

			// print the frequency for the user
			sprintf(line2,"Frequency: %3.0f   KH  ",frequency);

			// also print the duty for the user
			sprintf(line3,"Duty :     %3.0f    %% ",duty_variable*diff_time/10000);

			// print the summed current level for the user
			sprintf(line4,"Current:   %3d mA",sum_);

			// move the cursor elsewhere
			// each line requires a new cursor position
			// display a string on the LCD
			// this forms the first line of message
			LCD_SetCursor(0,0);
			LCD_DisplayString(line1);

			// move the cursor elsewhere
			// each line requires a new cursor position
			// display a string on the LCD
			// this forms the next line of message
			LCD_SetCursor(1,0);
			LCD_DisplayString(line2);

			// move the cursor elsewhere
			// each line requires a new cursor position
			// display a string on the LCD
			// this forms the next line of message
			LCD_SetCursor(2,0);
			LCD_DisplayString(line2);

			// move the cursor elsewhere
			// each line requires a new cursor position
			// display a string on the LCD
			// this forms the next line of message
			LCD_SetCursor(3,0);
			LCD_DisplayString(line4);

So now it may be harder to notice any errors that creep in (at least one has been buried here)

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Tue. Nov 23, 2021 - 07:45 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You didn't tell us the CPU, so I assume that it is a Mega328P.

The auto-generated code in the initialization section doesn't match Mega328P register descriptions, and the comments don't match the code. Never trust auto-generated code.

 

The ADC is running way too fast.  You won't get 10-bit accuracy at ADC clock speeds above @30,000 samples-per-second, so you should be using the /128 ADC pre-scaler.

The ADC has no start_conversion signal.  There is a IRQ routine that runs when the conversion is finished, but there is nothing to start the ADC.

 

I had to rewrite the code in order to get some idea about what's going on:  Ain't you guys ever heard of -comments-?

/* SomeElectricCurrentMonitor.ino    from AVRfreaks 11/23/2021   */

#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include "lcd.h"
#include<avr/interrupt.h>

#define sbi(x, y) x |= _BV(y)                  // set bit
#define cbi(x, y) x &= ~(_BV(y))               // clear bit
#define tbi(x, y) x ^= _BV(y)                  // toggle bit
#define is_high(x, y) ((x & _BV(y)) == _BV(y)) //(for input) checks if the input is high (Logic 1)  //??? ????? ??? ?? ????

volatile unsigned int cnt0, cnt1, cnt3;	// updated by Timer2                       
volatile float    current_in_MilliAmps, sum_;                                         
                                                                             
char	 line1[25],line2[25] ,line3[25], line4[25];        
float    mean_array[101];                                  
volatile uint16_t T1_OverflowCount;
float    diff_time, frequency = 0;
volatile uint16_t k_loopCount, duty_variable;
volatile boolean  is_FrequencyManagerUpdated_Needed = false;
volatile boolean  isDutyCycleOutputEnabled;  
volatile boolean  isItTimeForA_LCDdisplay_Update = false;
boolean 	  is_ADCUpdate_Available = false;

ISR (INT1_vect) {	// push switch on PIND3  ::: interrupt of RISING and FALLING edges
    static unsigned char state = 1; 

    if ( is_FrequencyManagerUpdated_Needed == true ) {   // [22def, 49, 64]              
	if (digitalRead(3) == HIGH) { // assuming that this means button is presseed
	    if (state == 1) {
	    	TCNT1 = 0;
	    	T1_OverflowCount = 0;
	    	state = 0;
	    	isDutyCycleOutputEnabled = true;
	    } else if (state == 0)  {	// assuming that this means button has been released              
			        diff_time = (1000000/TCNT1) + T1_OverflowCount * 1000;
			        frequency = diff_time/1000;
			        state = 1;	
			        is_FrequencyManagerUpdated_Needed = false;
	    }}}       
            
    if ( (isDutyCycleOutputEnabled == true) && (digitalRead(3) == LOW) )   { isDutyCycleOutputEnabled = false; duty_variable=TCNT1; }	
}

ISR(TIMER1_OVF_vect)  {	T1_OverflowCount++;  }

ISR(TIMER2_OVF_vect) {	
    TCNT2 = -126;	// 0x7f loaded into TCN2    @8000 overflows per second
    if( ++cnt0 > 4000) { cnt0 = 0; isItTimeForA_LCDdisplay_Update    = true;  } // one/half second
    if( ++cnt1 > 30  ) { cnt1 = 0; is_FrequencyManagerUpdated_Needed = true; }
    if( ++cnt3 > 100)  { cnt3 = 0; ADCSRA |= 0x40; }
}


ISR(ADC_vect) {   // ADC start_conversion is never triggered
    volatile float   latestADCW_float;
    latestADCW_float = (float) ADCW;   // analogRead(A0); would return this
    latestADCW_float = ( (970 - latestADCW_float ) * 17.834);
    if ( latestADCW_float < 10 ) latestADCW_float = 0;
    current_in_MilliAmps = latestADCW_float;
    is_ADCUpdate_Available = true;
}


void setup() {   
     DDRB  = (0<<DDB7)   | (0<<DDB6)   | (0<<DDB5)   | (0<<DDB4)   | (0<<DDB3)   | (0<<DDB2)   | (0<<DDB1)   | (0<<DDB0);
     PORTB = (0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
     
     DDRC =                (0<<DDC6)   | (0<<DDC5)   | (0<<DDC4)   | (0<<DDC3)   | (0<<DDC2)   | (0<<DDC1)   | (0<<DDC0);
     PORTC=                (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);
      
     DDRD  = (1<<DDD7)   | (0<<DDD6)   | (0<<DDD5)   | (0<<DDD4)   | (0<<DDD3)   | (0<<DDD2)   | (0<<DDD1)   | (0<<DDD0);
     PORTD = (1<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (1<<PORTD3) | (1<<PORTD2) | (0<<PORTD1) | (0<<PORTD0); 
         
     TCCR0B = (0<<CS02) | (0<<CS01) | (0<<CS00);
     TCNT0 = 0x00;
    
     TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
     TCCR1B = (0<<ICNC1)  | (0<<ICES1)  | (0<<WGM13)  | (0<<WGM12)  | (0<<CS12)  | (1<<CS11)   | (0<<CS10);
     TCNT1H = 0x00;
     TCNT1L = 0x00;
     ICR1H  = 0x00;
     ICR1L  = 0x00;
     OCR1AH = 0x00;
     OCR1AL = 0x00;
     OCR1BH = 0x00;
     OCR1BL = 0x00;
     
     // Timer/Counter 2 initialization
     // Clock source: System Clock
     // Clock pre-scaled value: {clock/8}  ~~ 1.00 MHz
     // Mode: Normal top=0xFF
     // OC2 output: Disconnected
     // Timer Period: 256 microSeconds
     ASSR   = 0 << AS2;
     TCCR2A = (0<<COM2A1) | (0<<COM2A0) | (0<<COM2B1) | (0<<COM2B0) | (0<<WGM21) | (0<<WGM20);
     TCCR2B = (0<<CS22) | (0<<CS21) | (0<<CS20);
     TCNT2  = 0x00;
     OCR2A  = 0x00;
     OCR2B  = 0x00;
     TIMSK2 = (0<<OCIE2B) |(0<<OCIE2A) | (1<<TOIE2); 
     
     // External Interrupt(s) initialization
     // INT0: Off
     // INT1: On
     // INT1 Mode: Any change
     EIMSK |=  (1<<INT1)  | (0<<INT0);
     EICRA  =  (0<<ISC11) | (1<<ISC10) | (0<<ISC01) | (0<<ISC00);
     EIFR   =  (1<<INTF1) | (0<<INTF0);
     UCSR0B  =  (0<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (0<<RXEN0) | (0<<TXEN0) | (0<<UCSZ02) | (0<<RXB80) | (0<<TXB80);

     ACSR   =  (1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
     
     // ADC initialization
     // ADC Clock frequency: 1000/000 kHz   [System clock/8]
     // ADC Voltage Reference: Internal 1.1V with ext cap on AREF
     // ADC result is right adjusted  ADCH: xxxxxx98  ADCL: 76543210
     // mux channel 0   Arduino_A0 (PC0)
     ADMUX  = (1<<REFS1) | (1<<REFS0) | (0<<ADLAR); 
     ADCSRA = (1<<ADEN)  | (0<<ADSC)  | (0<<ADATE)  | (0<<ADIF) | (1<<ADIE) | (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
     ADCSRB = (0<<ACME); 
     
     // Alphanumeric LCD initialization
     // Connections are specified in the
     // Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
     // RS - PORTB Bit 0
     // RD - PORTB Bit 1
     // EN - PORTB Bit 2
     // D4 - PORTB Bit 3
     // D5 - PORTB Bit 4
     // D6 - PORTB Bit 5
     // D7 - PORTB Bit 6
     // Characters/line: 20
     LCD_Init(4,20);
     
     // Global enable interrupts
     sei();
     LCD_SetUp(PD_0,PD_1,PD_2,P_NC,P_NC,P_NC,P_NC,PB_0,PB_1,PB_2,PD_5);
     LCD_Init(4,20);
     LCD_DisplayString("Explore Embedded\n");
     LCD_DisplayString("LCD 4-bit Mode\n");
     LCD_DisplayString("20 x 4 \n");
     LCD_DisplayString(":)  :O"); 
}
			
void loop() {	
     if( is_ADCUpdate_Available == true )  {	
         
     	   is_ADCUpdate_Available = false;    // [85 in IRQ] 
     	   mean_array[100] = current_in_MilliAmps;
     	   for( k_loopCount=0; k_loopCount<100; k_loopCount++) 
     	      mean_array[k_loopCount] = mean_array[k_loopCount + 1];
     	   for( k_loopCount=0; k_loopCount<100; k_loopCount++) 
     	      sum_ += mean_array[k_loopCount];
     	   sum_ = sum_/100;	
     }
     
     if( isItTimeForA_LCDdisplay_Update == true ) {
         isItTimeForA_LCDdisplay_Update = false;   
     	   sprintf(line1,"Voltage : 25.18 Volt");  	
     	   sprintf(line2,"Frequency: %3.0f   KH  ", frequency);
     	   sprintf(line3,"Duty :     %3.0f    %% ", duty_variable * diff_time/10000);	
     	   sprintf(line4,"Current:   %3f mA", sum_);     	 					
         LCD_SetCursor(0,0); LCD_DisplayString(line1);     	
       	 LCD_SetCursor(1,0); LCD_DisplayString(line2);    	
         LCD_SetCursor(2,0); LCD_DisplayString(line3);
         LCD_SetCursor(3,0); LCD_DisplayString(line4); 	
     }		
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hasanzadeh99 wrote:
we have a periodic signal and want to meter its Duration and Frequency by atmega8 Ic

So what does the ADC have to do with that?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...