Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

RPM measurement of 8-Motors Continuously

Status
Not open for further replies.

kmdineshece

Member level 1
Joined
Dec 17, 2013
Messages
36
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
384
Hi everyone!...
8-magenetic sensor , 2-LM324 (8-operation-amplifiers), 8:1 Multiplexer (74HC4051), ATmega88PA


I want to measure RPM of 8-Motors continuously, I have written a code, but the controller sometimes reads previous sensor output and update into succeed sensor(next, eg: resultant of sensor one is update into second)
Conditions:if RPM less than 9800 update as Zero,
if RPM above 22000 update as old,

pls help me!...

DSC_0006.JPGi1.png
Code:
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include<avr/pgmspace.h>
#include<math.h>
#include<stdlib.h>
#include <util/delay.h>
#include<string.h>
#include<stdio.h>
volatile uint16_t count=0,flag=0,flag1=0,sensor=0,m=1,z=1,breake,data=0; //Main revolution counter
volatile uint16_t newpulse=0; //Revolution per second
volatile uint16_t old=0; //Revolution per second
volatile unsigned int result,rps,rpm,rpmold,rpm_old[25],led[25],rps0,rps1,rps2,rps3,rpm_rsm[25]; //Revolution per second
volatile uint16_t capture=0,captureold; //Revolution per second
volatile uint16_t period1; //Main revolution counter
volatile uint16_t period2,period3;
#define F_CPU 20000000UL

uint32_t T;
//unsigned int count=0;
float RPM_float;
char RPM_arr[6];
float RPMa_float;
char RPMa_arr[6];

#define USART_BAUDRATE 19200
#define UBRR_VALUE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
void USART0Init(void)
{
	// Set baud rate
	UBRR0H = (uint8_t)(UBRR_VALUE>>8);
	UBRR0L = (uint8_t)UBRR_VALUE;
	// Set frame format to 8 data bits, no parity, 1 stop bit
	UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);
	//enable transmission and reception
	UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
}
void USART0SendByte(unsigned char u8Data)
{
	//wait while previous byte is completed
	while(!(UCSR0A&(1<<UDRE0))){};
	// Transmit data
	UDR0 = u8Data;
}
uint8_t USART0ReceiveByte()
{
	// Wait for byte to be received
	while(!(UCSR0A&(1<<RXC0))){};
	// Return received data
	return UDR0;
}

void USART_puts(char *s)
{
	while(*s)
	{
		USART0SendByte(*s);
		s++;
	}
}

void Wait()
{
	uint8_t i;
	for(i=0;i<2;i++)
	{
		_delay_loop_2(0);
	}
}
pulse()
{
	OCR0B   = 30;                 //24
	DDRD    |= (1<<PORTD5);         //OC0B output
	TCCR0A = (1<<COM0B0)|(1<<WGM01); //toggle, CTC
	TCCR0B = (1<<CS01);             //div1
	//OCR0A  = F_CPU/8/2/40000 - 1;   //set CTC freq
	OCR0A=30;
}
address (unsigned int i)
{
	if(i==1)
	{
		PORTB &= ~(1 << PINB2); //MUX-1
		PORTB |= (1 << PINB3)|(1 << PINB4);
		PORTD &= ~(1 << PIND2);		//000 Address
		PORTD &= ~(1 << PIND3);	
		PORTD &= ~(1 << PIND4);	
		
	}
	else if(i==2)
	{
		PORTB &= ~(1 << PINB2); //MUX-1
		PORTD &= ~(1 << PIND4);		//001 Address
		PORTD &= ~(1 << PIND3);	
		PORTD |= (1 << PIND2);
		
	}
	else if(i==3)
	{
		PORTB &= ~(1 << PINB2); //MUX-1
		PORTD &= ~(1 << PIND2);		//010 Address
		PORTD &= ~(1 << PIND4);	
		PORTD |= (1 << PIND3);
	}
	else if(i==4)
	{
		PORTB &= ~(1 << PINB2); //MUX-1
		PORTD &= ~(1 << PIND4);		                //011 Address
		PORTD |= (1 << PIND2)|(1 << PIND3);
	}
	else if(i==5)
	{
		PORTB &= ~(1 << PINB2); //MUX-1
		PORTD &= ~(1 << PIND3);		//100 Address
		PORTD &= ~(1 << PIND2);
		PORTD |= (1 << PIND4);
	}
	else if(i==6)
	{
		PORTB &= ~(1 << PINB2); //MUX-1
		PORTD &= ~(1 << PIND3);	                	//101 Address
		PORTD |= (1 << PIND4)|(1 << PIND2);
	}
	else if(i==7)
	{
		PORTB &= ~(1 << PINB2); //MUX-1
		PORTD &= ~(1 << PIND2);	                	//110 Address
		PORTD |= (1 << PIND3)|(1 << PIND4);
	}
	else if(i==8)
	{
		PORTB &= ~(1 << PINB2); //MUX-1
		PORTD |= (1 << PIND3)|(1 << PIND4)|(1 << PIND2);  //111 Address
	}
	}
store_data(int x, unsigned int y)
{
	if(x==1)
	{
		rpm_old[1]=rpm;
	}
	else if(x==2)
	{
		rpm_old[2]=rpm;
	}
	else if(x==3)
	{
		rpm_old[3]=rpm;
	}
	else if(x==4)
	{
		rpm_old[4]=rpm;
	}
	else if(x==5)
	{
		rpm_old[5]=rpm;
	}
	else if(x==6)
	{
		rpm_old[6]=rpm;
	}
	else if(x==7)
	{
		rpm_old[7]=rpm;
	}
else if(x==8)
{
	rpm_old[8]=rpm;
}
}
void main()
{
		PORTB|=(1<<PINB0);     //pullup enabled
	DDRB&=~(1<<PINB0);     //ICR1 as input
	DDRB|=(1<<PINB2)|(1<<PINB3)|(1<<PINB4);
	DDRD|=(1<<PIND2)|(1<<PIND3)|(1<<PIND4)|(1<<PIND5)|(1<<PIND6)|(1<<PIND7);
	
	TCCR1A =0;      // normal mode
	TCCR0A=0;
	
	TCCR1B |= (1<<ICES1)|(1<<CS12);     
	TIMSK1 |= (1<<ICIE1)|(1<<TOIE1);     // (00100001) Input capture and overflow interupts enabled
  
	TCNT1 =0;       // start from 0
	
	sei();
	
	uint8_t u8TempData;
	
	PORTB &= ~(1 << PINB2); //MUX-1
	PORTB |= (1 << PINB3)|(1 << PINB4);
	PORTD &= ~(1 << PIND4);		//000 Address
	PORTD &= ~(1 << PIND2);	
	PORTD &= ~(1 << PIND3);	
	
	USART0Init();
	
	while(1)
	{


		if(flag1==1)
		{
			TIMSK1 &=~(1<<ICES1);
			TIMSK1 &=~(1<<TOIE1);
			if(m==1)
			{
			address(2);	
						
			if((9800<=rpm)&&(rpm<=22000))
			{
			    store_data(m,rpm);	
				sprintf(RPMa_arr,"RPM1:%5u\n\r",rpm);
				USART_puts(RPMa_arr);
				//sprintf(RPMa_arr,"RPMC1:%5u\n\r",data);
				//USART_puts(RPMa_arr);
				
			}
			else if(rpm<9800)
			{
				breake=0;
				sprintf(RPMa_arr,"RPM1:%5u\n\r",breake);
				USART_puts(RPMa_arr);
				
				
			}
			else if(rpm>22000)
			{
				sprintf(RPMa_arr,"RPM1:%5u\n\r",rpm_old[m]);
				USART_puts(RPMa_arr);
				//sprintf(RPMa_arr,"RPMC1:%5u\n\r",data);
				//USART_puts(RPMa_arr);
				
			}
			
			
			m!=1;
			rpm=0;
			flag1=0;
			}
			
			else if(m==2)
			{
				address(3);
				if((9800<=rpm)&&(rpm<=22000))
				{
					
					store_data(m,rpm);	
					sprintf(RPMa_arr,"RPM2:%5u\n\r",rpm);
					//sprintf(RPM_arr,"%5d",RPM1);
					USART_puts(RPMa_arr);
				//	sprintf(RPMa_arr,"RPMC2:%5u\n\r",data);
					//USART_puts(RPMa_arr);
				}
				else if(rpm<9800)
				{ 
					breake=0;
					sprintf(RPMa_arr,"RPM2:%5u\n\r",breake);
					USART_puts(RPMa_arr);
					
					}
				else if(rpm>22000)
				{
					sprintf(RPMa_arr,"RPM2:%5u\n\r",rpm_old[m]);
					USART_puts(RPMa_arr);
				//	sprintf(RPMa_arr,"RPMC1:%5u\n\r",data);
				//	USART_puts(RPMa_arr);
					
				}
				
				//PORTB &= ~(1 << PINB2); //MUX-1
				//PORTD &= ~((1 << PIND2)|(1 << PIND3));		//010 Address
				//PORTD |= (1 << PIND4);
				
				m!=2;
				rpm=0;
				data=0;
				flag1=0;
			}
			else if(m==3)
			{
				address(4);
				if((9800<=rpm)&&(rpm<=22000))
				{
					
					store_data(m,rpm);	
					sprintf(RPMa_arr,"RPM3:%5u\n\r",rpm);
					//sprintf(RPM_arr,"%5d",RPM1);
					USART_puts(RPMa_arr);
					//sprintf(RPMa_arr,"RPMC3:%5u\n\r",data);
					//USART_puts(RPMa_arr);
				}
				else if(rpm<9800)
				{
					breake=0;
					sprintf(RPMa_arr,"RPM3:%5u\n\r",breake);
					USART_puts(RPMa_arr);
					
				}
				else if(rpm>22000)
				{
					sprintf(RPMa_arr,"RPM3:%5u\n\r",rpm_old[m]);
					USART_puts(RPMa_arr);
					//sprintf(RPMa_arr,"RPMC3:%5u\n\r",data);
					//USART_puts(RPMa_arr);
					
				}
				
				rpm=0;
				data=0;
				//PORTB &= ~(1 << PINB2); //MUX-1
				//PORTD &= ~((1 << PIND4)|(1 << PIND3));		//011 Address
				//PORTD |= (1 << PIND2);
				//sensor=3;
				
				m!=3;
				flag1=0;
			}
			else if(m==4)
			{
				address(5);
				if((9800<=rpm)&&(rpm<=22000))
				{
					
					store_data(m,rpm);	
					sprintf(RPMa_arr,"RPM4:%5u\n\r",rpm);
					//sprintf(RPM_arr,"%5d",RPM1);
					USART_puts(RPMa_arr);
					//sprintf(RPMa_arr,"RPMC4:%5u\n\r",data);
					//USART_puts(RPMa_arr);
				}
				else if(rpm<9800)
				{
					breake=0;
					sprintf(RPMa_arr,"RPM4:%5u\n\r",breake);
					USART_puts(RPMa_arr);
					
				}
				else if(rpm>22000)
				{
					sprintf(RPMa_arr,"RPM4:%5u\n\r",rpm_old[m]);
					USART_puts(RPMa_arr);
					//sprintf(RPMa_arr,"RPMC4:%5u\n\r",data);
					//USART_puts(RPMa_arr);
					
				}
				
				rpm=0;
				data=0;
			//	PORTB &= ~(1 << PINB2); //MUX-1
				//PORTD &= ~((1 << PIND4)|(1 << PIND2));		//100 Address
				//PORTD |= (1 << PIND3);
				//sensor=4;
				m!=4;
				flag1=0;
			}
			else if(m==5)
			{
				address(6);
				if((9800<=rpm)&&(rpm<=22000))
				{
					
					store_data(m,rpm);	
					sprintf(RPMa_arr,"RPM5:%5u\n\r",rpm);
					//sprintf(RPM_arr,"%5d",RPM1);
					USART_puts(RPMa_arr);
					
				}
				else if(rpm<9800)
				{
					breake=0;
					sprintf(RPMa_arr,"RPM5:%5u\n\r",breake);
					USART_puts(RPMa_arr);
					
				}
				else if(rpm>22000)
				{
					sprintf(RPMa_arr,"RPM5:%5u\n\r",rpm_old[m]);
					USART_puts(RPMa_arr);
					//sprintf(RPMa_arr,"RPMC5:%5u\n\r",data);
					//USART_puts(RPMa_arr);
					
				}
				
				rpm=0;
				data=0;
				//PORTB &= ~(1 << PINB2); //MUX-1
				//PORTD &= ~(1 << PIND4);	                	//101 Address
				//PORTD |= (1 << PIND3)|(1 << PIND2);
				//sensor=5;
				m!=5;
				flag1=0;
			}
			else if(m==6)
			{
				address(7);
				if((9800<=rpm)&&(rpm<=22000))
				{
					store_data(m,rpm);	
					
					sprintf(RPMa_arr,"RPM6:%5u\n\r",rpm);
					//sprintf(RPM_arr,"%5d",RPM1);
					USART_puts(RPMa_arr);
					
				}
				else if(rpm<9800)
				{
					breake=0;
					sprintf(RPMa_arr,"RPM6:%5u\n\r",breake);
					USART_puts(RPMa_arr);
					
				}
				else if(rpm>22000)
				{
					sprintf(RPMa_arr,"RPM6:%5u\n\r",rpm_old[m]);
					USART_puts(RPMa_arr);
					
					
				}
				
				rpm=0;
				data=0;
				//PORTB &= ~(1 << PINB2); //MUX-1
				//PORTD &= ~(1 << PIND2);	                	//110 Address
				//PORTD |= (1 << PIND3)|(1 << PIND4);
				//sensor=6;
				m!=6;
				flag1=0;
			}
			else if(m==7)
			{
				address(8);
				if((9800<=rpm)&&(rpm<=22000))
				{
					
					store_data(m,rpm);	
					sprintf(RPMa_arr,"RPM7:%5u\n\r",rpm);
					//sprintf(RPM_arr,"%5d",RPM1);
					USART_puts(RPMa_arr);
					
				}
				else if(rpm<9800)
				{
					breake=0;
					sprintf(RPMa_arr,"RPM7:%5u\n\r",breake);
					USART_puts(RPMa_arr);
					
				}
				else if(rpm>22000)
				{
					sprintf(RPMa_arr,"RPM7:%5u\n\r",rpm_old[m]);
					USART_puts(RPMa_arr);
					
					
				}
				
				rpm=0;
				data=0;
				//PORTB &= ~(1 << PINB2); //MUX-1
				//PORTD |= (1 << PIND3)|(1 << PIND4)|(1 << PIND2);  //111 Address
				//sensor=7;
				m!=7;
				flag1=0;
			}
			else if(m==8)
			{
				address(1);
				if((9800<=rpm)&&(rpm<=22000))
				{
					
					store_data(m,rpm);	
					sprintf(RPMa_arr,"RPM8:%5u\n\r",rpm);
					//sprintf(RPM_arr,"%5d",RPM1);
					USART_puts(RPMa_arr);
					
				}
				else if(rpm<9800)
				{
					breake=0;
					sprintf(RPMa_arr,"RPM8:%5u\n\r",breake);
					USART_puts(RPMa_arr);
					
				}
				else if(rpm>22000)
				{
					sprintf(RPMa_arr,"RPM8:%5u\n\r",rpm_old[m]);
					USART_puts(RPMa_arr);
					
					
				}
				
				rpm=0;
				data=0;
				//PORTB &= ~(1 << PINB3); //MUX-2
				//PORTB |= (1 << PINB2)|(1 << PINB4);
				//PORTD &= ~((1 << PIND4)|(1 << PIND3)|(1 << PIND2));		//000 

Address
				//sensor=8;
				
				m=0;
				flag1=0;
			}
			/*
			else if(sensor==8)
			{
				
				if((9500<=rpm)&&(rpm<=25000))
				{
					
					
					sprintf(RPMa_arr,"RPM9:%5u\n\r",rpm);
					//sprintf(RPM_arr,"%5d",RPM1);
					USART_puts(RPMa_arr);
				}
				else if(rpm<9500)
				{
					sprintf(RPMa_arr,"RPM9:%5u\n\r",rpm);
					USART_puts(RPMa_arr);
				}
				else if(rpm>25000)
				{
					sprintf(RPMa_arr,"RPM9:%5u\n\r",rpm);
					USART_puts(RPMa_arr);
					
				}
				rpm=0;
				PORTB &= ~(1 << PINB3); //MUX-2
				PORTD &= ~((1 << PIND4)|(1 << PIND3));		           //001 Address
				PORTD |= (1 << PIND2);
				
				sensor=9;
				flag1=0;
			}
			
				TCCR1B |= (1<<ICES1)|(1<<CS12);  
		
	}
}

ISR(TIMER1_CAPT_vect)
{
	//CPU Jumps here automatically when INT0 pin detect a falling edge
	
	period2=ICR1;
	result=period2-period1;
	period1=period2;
	rps=(1000000/(result*128/10)*60);
	}

ISR(TIMER1_OVF_vect)
{
	
	//CPU Jumps here every 1 sec exactly!
	TIMSK1 &= ~(1<<ICIE1); 
	
	rpm=rps;
	capture=result;
	m=m+1;
	result=0;
	period1=0;
	period2=0;
	rps=0;
	
	flag1=1;
	//TCNT1=0;
	
}
 

Hello!

You should be aware that it's very difficult to help you.
1. There is nothing to explain how it work or how it should work.
2. You gives us more than 500 lines of code.
3. Some parts of your code are badly written. Example (see below)
4. Your main code is clearly too long.
On top of that, when reading your main function, it does 8 times the same thing. The only
difference (apparently) is that when m is equal to some_val, then you write RPMx%5u
and the x is some_val. Why not making a function of this repetitive process. You would
7 x 35 lines of code. It would then be clear, understandable, maintainable.
5. Using variable names like "data" or "flag1" is a mistake. If you read your code in 3 month
or even 3 weeks, you will not understand it anymore. If the flag means for example sensor
is busy, why not calling it "sensor_busy_flag"?

Some strange code:
store_data(int x, unsigned int y) {
if(x==1) {
rpm_old[1]=rpm;
}
else if(x==2) {
rpm_old[2]=rpm;
}
else if(x==3) {
rpm_old[3]=rpm;
}
else if(x==4) {
rpm_old[4]=rpm;
}
else if(x==5) {
rpm_old[5]=rpm;
}
else if(x==6) {
rpm_old[6]=rpm;
}
else if(x==7) {
rpm_old[7]=rpm;
}
else if(x==8) {
rpm_old[8]=rpm;
}
}

Why don't you write rpm_old[x] = rpm? This would work in all the cases.
and beside this you have a y variable which is not used. Your store_data
function is absolutely useless. Simply write rpm_old[x] = rpm;

The same can be said about the address function. There is a lot of room for improvement.

For your info: instead of many else if, you should use a switch statement.

Dora.
 
Thank u for ur reply!....
Actually the program working with some unwanted exceptions, switching problem(MUX selection line)
how to read data from multiple sensors using Interrupt Capture Pin (ICP), the controller gives repeated unwanted value, when the motor is OFF also,
today i minimized this code as per ur guidelines, eventhough error output,
the problem is capturing ISR, how write this part effectively
Code:
ISR(TIMER1_CAPT_vect)
{
	//CPU Jumps here automatically when INT0 pin detect a falling edge
	
	period2=ICR1;
	result=period2-period1;
	period1=period2;
	rps=(1000000/(result*128/10)*60);
	}

- - - Updated - - -

just reading RPM of two sensors, this could also facing some switching problem,
pls guide me!.....
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include<avr/pgmspace.h>
#include<math.h>
#include<stdlib.h>
#include <util/delay.h>
#include<string.h>
#include<stdio.h>
volatile uint16_t count=0,flag=0,flag1=0,sensor=0,m=0,z=1,breake,data=0; //Main revolution counter
volatile uint16_t newpulse=0; //Revolution per second
volatile uint16_t old=0; //Revolution per second
volatile unsigned int result,rps,rpm,rpmold,rpm_old[25],led[25],rps0,rps1,rps2,rps3,rpm_rsm[25]; //Revolution per second
volatile uint16_t capture=0,captureold; //Revolution per second
volatile uint16_t period1; //Main revolution counter
volatile uint16_t period2,period3;
#define F_CPU 20000000UL

uint32_t T;
//unsigned int count=0;
float RPM_float;
char RPM_arr[6];
float RPMa_float;
char RPMa_arr[6];

#define USART_BAUDRATE 19200
#define UBRR_VALUE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
void USART0Init(void)
{
	// Set baud rate
	UBRR0H = (uint8_t)(UBRR_VALUE>>8);
	UBRR0L = (uint8_t)UBRR_VALUE;
	// Set frame format to 8 data bits, no parity, 1 stop bit
	UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);
	//enable transmission and reception
	UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
}
void USART0SendByte(unsigned char u8Data)
{
	//wait while previous byte is completed
	while(!(UCSR0A&(1<<UDRE0))){};
	// Transmit data
	UDR0 = u8Data;
}
uint8_t USART0ReceiveByte()
{
	// Wait for byte to be received
	while(!(UCSR0A&(1<<RXC0))){};
	// Return received data
	return UDR0;
}

void USART_puts(char *s)
{
	while(*s)
	{
		USART0SendByte(*s);
		s++;
	}
}

void Wait()
{
	uint8_t i;
	for(i=0;i<2;i++)
	{
		_delay_loop_2(0);
	}
}

address (unsigned int i)
{
	if(i==1)
	{
		PORTB &= ~(1 << PINB2); //MUX-1
		PORTB |= (1 << PINB3)|(1 << PINB4);
		PORTD &= ~(1 << PIND2);		//000 Address
		PORTD &= ~(1 << PIND3);	
		PORTD &= ~(1 << PIND4);	
		
	}
	else if(i==2)
	{
		PORTB &= ~(1 << PINB2); //MUX-1
		PORTD &= ~(1 << PIND4);		//001 Address
		PORTD &= ~(1 << PIND3);	
		PORTD |= (1 << PIND2);
		
	}

	}
store_data(int x, unsigned int y)
{
	if(x==1)
	{
		rpm_old[1]=rpm;
	}
	else if(x==2)
	{
		rpm_old[2]=rpm;
	}

}
void main()
{
		PORTB|=(1<<PINB0);     //pullup enabled
	DDRB&=~(1<<PINB0);     //ICR1 as input
	DDRB|=(1<<PINB2)|(1<<PINB3)|(1<<PINB4);
	DDRD|=(1<<PIND2)|(1<<PIND3)|(1<<PIND4)|(1<<PIND5)|(1<<PIND6)|(1<<PIND7);
	
	TCCR1A =0;      // normal mode
	TCCR0A=0;
	
	TCCR1B |= (1<<ICES1)|(1<<CS12);     
	TIMSK1 |= (1<<ICIE1)|(1<<TOIE1);     // (00100001) Input capture and overflow interupts enabled
  
	TCNT1 =0;       // start from 0
	
	sei();
	
	uint8_t u8TempData;
	
	PORTB &= ~(1 << PINB2); //MUX-1
	PORTB |= (1 << PINB3)|(1 << PINB4);
	PORTD &= ~(1 << PIND4);		//000 Address
	PORTD &= ~(1 << PIND2);	
	PORTD &= ~(1 << PIND3);	
	
	USART0Init();
	
	while(1)
	{


		if(flag1==1)
		{
			TIMSK1 &=~(1<<ICES1);
			TIMSK1 &=~(1<<TOIE1);
			if(m==1)
			{
			address(2);	
						
			if((9800<=rpm)&&(rpm<=22000))
			{
			    store_data(m,rpm);	
				sprintf(RPMa_arr,"RPM1:%5u\n\r",rpm);
				USART_puts(RPMa_arr);
				
			}
			else if(rpm<9800)
			{
				breake=0;
				sprintf(RPMa_arr,"RPM1:%5u\n\r",breake);
				USART_puts(RPMa_arr);
				
				
			}
			else if(rpm>22000)
			{
				sprintf(RPMa_arr,"RPM1:%5u\n\r",rpm_old[m]);
				USART_puts(RPMa_arr);
				
			}
			
			
			m!=1;
			rpm=0;
			flag1=0;
			}
			
			else if(m==2)
			{
				address(3);
				if((9800<=rpm)&&(rpm<=22000))
				{
					
					store_data(m,rpm);	
					sprintf(RPMa_arr,"RPM2:%5u\n\r",rpm);

					USART_puts(RPMa_arr);
				}
				else if(rpm<9800)
				{ 
					breake=0;
					sprintf(RPMa_arr,"RPM2:%5u\n\r",breake);
					USART_puts(RPMa_arr);
					
					}
				else if(rpm>22000)
				{
					sprintf(RPMa_arr,"RPM2:%5u\n\r",rpm_old[m]);
					USART_puts(RPMa_arr);
					
				}
				
				
				m=0;
				rpm=0;
				data=0;
				flag1=0;
			}
		TCCR1B |= (1<<ICES1)|(1<<CS12);  
		
	}
}

ISR(TIMER1_CAPT_vect)
{
	//CPU Jumps here automatically when ICP pin detect a edge
	
	period2=ICR1;
	result=period2-period1;
	period1=period2;
	rps=(1000000/(result*128/10)*60);
	}

ISR(TIMER1_OVF_vect)
{
	

	TIMSK1 &= ~(1<<ICIE1); 
	
	rpm=rps;
	capture=result;
	m=m+1;
	result=0;
	period1=0;
	period2=0;
	rps=0;
	
	flag1=1;
	
	
}
 

What happens if two or more motors are running at the same RPM ? Which one will you read ?
 

no no!....i want to read all the motors, and i would update the RPM of the motor and the motor, whether it is running or not!....

actually the problem ,
example: 2 motors,
Motor 1 running , the controller update its corresponding RPM(RPM1) exactly, the same time motor 2 is OFF, but the controller update motor 1 RPM often at the place of RPM2, how it happens? that is a error,
 

Explain how you are trying to read the pulses from 8 sensors. have you successfully made a project which reads RPM of one motor ? I mainly use PIC and I have not done RPM measurement using AVR. What I did in PIC is use Timer1 as an external counter and read the pulses and convert it to RPM.

You are using Multiplexer to detect interrupt but what happens if you are reading 4th channel and the output of opamp 1 goes high due to pulse detect. How do you read that ? It will be missed.
 
Last edited:

Hi,

how fast is max pulse frequency?
Is it one per revolution?
What max RPM dou you need?

If it is 22000 RPM with one pulse per RPM (50% duty cycle) this makes 370 Hz.
It can be safely detected by an interrrupt reading all the 8 digital signals with 1kHz. But RPM resolution is only 60RPM with one uptate every second.

The capture method has far better resolution, but it works safely only with one sensor.


Klaus
 

I am writing a code for you based on your circuit. It will take one or two days. For a project like yours I would use PSoC like this.

https://www.fabtolab.com/freeSoC-mini-development-kit

You can create 8 x 16bit counters and assign any pin for the 8 inputs and there will be 8 interrupts. Just have 8 unsigned long variables which increment on timer overflows. Then use the overflow value and time in the timer register and do the required maths to get the frequency. Convert this to RPM.
 

@KlausST

Is this calculation correct ?

Max RPM is 22,000

pulses per sec = 22,000 / 60 = 366.66 = approx 370

f = 370 Hz

T = 1/370 = 2.7 ms

All the 8 inputs of the mux may go high at the same time.

assuming this case

T/2 = 1.35 ms

assuming 50% duty pulses

So, if all the mux inputs are high at the same time then he has 1.35 ms time to read all the 8 inputs.

1.35 ms / 8 = 169 us

so, he has to read channels at 169 us.

If this is correct, what happens if frequency of pulses is say 370 / 2 = 183 ?

Will the interrupt trigger more than once for the same pulse as it is read at 169 us ?
 

Here I am attaching Atmel Studio version code. I was not able to test it because last week I installed Windows 10 Enterprise and today I tried to install Atmel Studio 6.2 SP1 but it is not installing and giving error. I will try to compile the Atmel Studio code on my old PC tomorrow and update here.

First before writing the AVR code, I tried if the project works with a PIC and it did work. I wrote the code using mikroC PRO PIC. Then I implemented the code in mikroC PRO AVR and it worked but with one problem that is UART prints the pulseCount and RPM for all the eight channels but it prints some garbage also. Maybe it is a mikroC PRO AVR UART library problem. The PIC version works well. I tested both using Proteus. I am attaching Atmel Studio Code which you can try in your Atmel Studio and also I am posting mikroC PRO PIC and AVR versions of the project and Proteus files. Try to compile the Atmel Studio version code in Atmel Studio and see if it works.

I have created a timer1 interrupt of 200ms and every 200ms pulses of one channel is counted. Then the 8 results are multiplied by 5 to get pulse counts for 1 sec and this is then multiplied by 60 to get the RPM.

broken link removed
 

Attachments

  • Tachometer 8 Channel ATMega88P 8MHz.txt
    2.8 KB · Views: 100
  • Tachometer 8 Channel PIC18F26K22 8MHz mikroC PRO PIC.rar
    102.1 KB · Views: 81
  • Tachometer 8 Channel Sim SS.png
    Tachometer 8 Channel Sim SS.png
    56 KB · Views: 186
  • Tachometer 8 Channel ATMega88P 8MHz mikroC PRO AVR.rar
    107.5 KB · Views: 122
  • Tachometer 8 Channels ATMega88P 8MHz.png
    Tachometer 8 Channels ATMega88P 8MHz.png
    31.4 KB · Views: 169
Last edited by a moderator:
Hi,

@pic.programmer
Yes you are right. If you sample every 169 us a new channel then it should work.
(Not with the capture feature)

Good job.

Klaus
 

@KlausST

I wrote a code using two timers and one external interrupt. One timer was used to create 1 sec delay and the other timer was used to switch the MUX channels at 169 us but it didn't give correct values. I will post that code tomorrow. I had written that code for PIC. Then I wrote a slightly different code where one timer was used and one external interrupt was used. It just counts pulses of each channel for 200 ms and calculates the RPM. As the frequency is between 163 Hz and 370 Hz one can just read pulses for say 50 ms for each channel and then multiply the value by 20 to get pulses for 1 sec (for each channel) and then multiply it by 60 to get RPM.

Here I am attaching Atmel Studio 6.1 files. I tested it in Proteus but it didn't work. It gives 5 warnings while compiling related to ltoa() functions. maybe someone more experienced with Atmel Studio might be able to help the OP.
 

Attachments

  • Tachometer 8 Channels Atmel Studio 6.1.rar
    43.3 KB · Views: 81
Hi,

I recommend to use 8 flags with the last state of the 8 channels.
Within the 169us interrupt i'd first read the input state, then switch the mux. So the signal has plenty of time to settle.
You have to compare the just read state with the sate of the same state, but before. Then just react on every change of state...if the state before is not the state now. This gives two edges per revolution. But the signal must be clean, free of contact bouncing.
Now eight counters, one for each channel has to be incremented on every state change.

Klaus
 
Here is the Atmel Studio code. It compiles fine in Atmel Studio 6.2. I tried compiling it and testing it in proteus but it is not working. I can see in Proteus the MUX channels are switching but I don't see any output. maybe INT0 interrupt is not happening. The same code works if implemented in mikroC PRO AVR. So, I can't tell what is the exact problem. Earlier it was giving 4 warnings and I have modified that code so that now there are no warnings.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#define F_CPU 8000000UL
 
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <string.h>
 
char str1[30], str2[17], str3[17];
unsigned long pulseCount[8] = {0, 0, 0, 0, 0, 0, 0, 0}, muxSelectValue = 0, i = 0;
unsigned int baudrate = 0, baudPrescale = 0;
unsigned char process = 0;
 
void UART1_Init(unsigned int baudrate);
void UART1_Write(char text);
void UART1_Write_Text(char *text);
 
//Timer1 Prescaler = 64; Preload = 24999; Actual Interrupt Time = 200 ms
//Place/Copy this part in declaration section
void InitTimer1() {
    TCCR1A = 0x80;
    TCCR1B = 0x0B;
    OCR1AH = 0x61;
    OCR1AL = 0xA7;
    TIMSK1 = (1<<OCIE1A);
}
 
ISR(TIMER1_COMPA_vect) {
    //Enter your code here
    PORTB = (PORTB & 0b11100011) | (++muxSelectValue << 2);
    if((muxSelectValue >> 2) == 8) {
         cli();
         muxSelectValue = 0;
         process = 1;
    }
}
 
ISR(INT0_vect) {
    pulseCount[muxSelectValue]++;
    EIFR = (0<<INTF0);
}
 
void UART1_Init(unsigned int baudrate) {
   baudPrescale = (((F_CPU / (baudrate * 16UL))) - 1);
   UBRR0L = baudPrescale;
   UBRR0H = (baudPrescale >> 8);
   UCSR0B = ((1<<TXEN0)|(1<<RXEN0) | (0<<RXCIE0));
}
 
 
void UART1_Write(char text) {
   while((UCSR0A &(1<<UDRE0)) == 0);
   UDR0 = text;
}
 
void UART1_Write_Text(char *text) {
   while(*text)
     UART1_Write(*text++);
}
 
int main(void) {
 
    DDRB = 0xFF;
    DDRC = 0xFF;
    DDRD = 0b11111010;
 
    PINB = 0x00;
    PINC = 0x00;
    PIND = 0x00;
 
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
 
    _delay_ms(200);
 
    UART1_Init(19200);
    _delay_ms(200);
    UART1_Write_Text("Tachometer values\r\n\r\n");
 
    EICRA = 0x03;
    EIMSK = (1<<INT0);
 
    InitTimer1();
 
    muxSelectValue = 0;
 
    PORTB = (PORTB & 0b11100011);
 
    sei();
 
    while(1) {
 
            if(process) {
                  for(i = 0; i < 8; i++) {
                        
                        ultoa(pulseCount[i] * 5, str1, 10);
                        ultoa(i, str2, 10);
                        ultoa(pulseCount[i] * 5 * 60, str3, 10);
                        
                        pulseCount[i] = 0;
                        strcat(str3, " RPM");
 
                        strcat(str1, " Channel ");
                        strcat(str1, str2);
                        strcat(str1, ", ");
                        strcat(str1, str3);
                        strcat(str1, "\r\n");
                        UART1_Write_Text(str1);
                  }
 
                  UART1_Write_Text("\r\n\r\n");
 
                  muxSelectValue = 0;
                  PORTB = (PORTB & 0b11100011);
                  process = 0;
 
                  _delay_ms(2000);
 
                  InitTimer1();
 
                  EIMSK = (1<<INT0);
                  sei();
            }
    }
}




Edit:

I used an LED and debugged the execution of Atmel Studio code and it indeed gets inside the
Code:
if(process) {...}
code but the for() loop is not ececuting. I put LEDs in ISRs and checked it. The ISRs are executing fine. So, you have to find out whether the problem is with the usage of
Code:
ultoa()
function.
 
Last edited:
But I'm using Capture Pin ,,,do you have experienced Capture Pin (ICP) logic,
 

In PIC the CCPx pin can be used for capture function and it can be used for RPM measurement but only for one channel. Does ICP (capture) pin of AVR does the same thing ? If yes, then it can only be used to capture pulses of one channel. You canmake 8 channel using such a feature (capture) of AVR.
 
yes!...ICP also same!...but i have some doubts. how to select mux address, whether interrupt should be disabled during address selection?
 

Interrupts can be disabled if needed. I think with capture only one channel reading is possible. Why not just use the code I posted. It reads each input for 200 ms and then multiplies the result by 5 and then by 60 to get the RPM. If you want faster reading then you can just read each channel for 50 ms and then multiply the results by 20 and then by 60 to get the RPM. This way it needs 50 ms x 8 = 400 ms for reading all the channels. Then another 500 ms to process the data and display it. So, in 900 ms you will get data once.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top