Solved: Water flow meter

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

Hi,

I am trying to convert the following code <http://diyhacking.com/projects/F... from Arduino IDE to AVR studio.The program is used for measuring the amount of water flowing through a pipe using water flow meter (FS400A).I worked on converting the Arduino code to AVR and I get an output as 0 in cool term when I run the code and pour water through the pipe.So could anyone kindly point out the mistake in my logic.

The flow meter is connected to INT0 (4th PIN) of ATMEGA 168.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>

#define F_CPU 8000000UL
#define BAUD 9600
#define MYUBBR F_CPU/16/BAUD-1

float calibrationFactor = 4.5;
float flowRate=0;
volatile unsigned int pulseCount=0;
unsigned long oldTime=0;
unsigned int flowMilliLitres=0;
unsigned long totalMilliLitres=0;

void uart_init(unsigned int ubrr){

	// Setting the baud rate to ubrr
	UCSR0A = 0<<U2X0;
	UBRR0H = (unsigned char)(ubrr >> 8);
	UBRR0L = (unsigned char)ubrr;
	//Setting the frame format to 8 data bit, no parity bit, 1 stop bit
	UCSR0C = 3<<UCSZ00;
	UCSR0B = (1<<TXEN0)|(1<<RXEN0);
}

void USART_Transmit( unsigned int data ){

	while (!(UCSR0A & (1<<UDRE0)));
	UDR0 = data;
}

void timer_1(){

        TCCR1A = (0 << WGM11)| (0 << WGM10 );
	TCCR1B = (0 << WGM12)| (0 << WGM13 );// normal mode
	TCCR1B |= (1 << CS12) | (1 << CS10);// set prescaler to 1024 and start the timer
	TCNT1=0;
}

int main(void){

	// Setting system clock to 8MHz
	CLKPR = (1 << CLKPCE);
	CLKPR = 0;

	uart_init(MYUBBR);
	timer_1();
	DDRD &= ~(1 << DDD2);     // Clear the PD2 pin
	PORTD |= (1 << PORTD2);   // turn On the Pull-up

	EICRA |= (1 << ISC00);    // set INT0 to trigger on ANY logic change
        EIMSK |= (1 << INT0);     // Turns on INT0
	sei();					  //enable interrupt

       while(1){

		if(TCNT1>=0x1E83)
				{
					cli();	//disable interrupt

					flowRate = ((1000 / (TCNT1 - oldTime)) * pulseCount) / calibrationFactor;
					oldTime = TCNT1;
    				        flowMilliLitres = (flowRate / 60) * 1000;
    				        totalMilliLitres += flowMilliLitres;

					USART_Transmit(flowRate);  // Print the integer part of the variable

    				        USART_Transmit(flowMilliLitres);

        				USART_Transmit(totalMilliLitres);

        				pulseCount = 0;// Reset the pulse counter so we can start incrementing again

					TCNT1=0;
    	         			sei();

				}
			}
}

	ISR (INT0_vect){pulseCount++;}

 

This topic has a solution.
Last Edited: Wed. Sep 6, 2017 - 09:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Why not simply IMPORT the project into Studio? No conversion necessary.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

This is an example of how Arduino makes the complex, simple. Serial.print(value) invokes a formatter that converts the value to a string. In the above code we see tge OP trying to print an integer value by just sending it out the usart.
So USART_Transmit() just sends one character. You need to read up on avr-gcc stdio then use printf() to do the print conversion/formatting. If this is too hard, then just bask in the ease of Arduino.

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

Can you kindly explain how to import into studio.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have got my AVR code working .Thanks for the responses.

 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>


#define F_CPU 8000000UL
#define BAUD 9600
#define MYUBBR F_CPU/16/BAUD-1


float calibrationFactor = 4.5;
float flowRate=0;
volatile unsigned int pulseCount=0;
unsigned long oldTime=0;
unsigned int flowMilliLitres=0;
unsigned long totalMilliLitres=0;
volatile unsigned long int millisec=0;
volatile unsigned long int sec=0;


void uart_init(unsigned int ubrr){
	
	// Setting the baud rate to ubrr
	UCSR0A = 0<<U2X0;
	UBRR0H = (unsigned char)(ubrr >> 8);
	UBRR0L = (unsigned char)ubrr;
	//Setting the frame format to 8 data bit, no parity bit, 1 stop bit
	UCSR0C = 3<<UCSZ00;
	UCSR0B = (1<<TXEN0)|(1<<RXEN0);
}


void USART_Transmit( unsigned int data ){
	
	while (!(UCSR0A & (1<<UDRE0)));
	UDR0 = data;
}


void timer_0(){

	TCCR0A = (1 << WGM01);// CTC 
	TIMSK0 |= (1 << OCIE0A);//Set interrupt on compare match
    TCCR0B |= (1 << CS02) | (1 << CS00);// set prescaler to 1024 and start the timer
	OCR0A = 0x07;
}


int main(void){
	
	// Setting system clock to 8MHz
	CLKPR = (1 << CLKPCE);
	CLKPR = 0;

	uart_init(MYUBBR);
	DDRD &= ~(1 << DDD2);     // Clear the PD2 pin
	PORTD |= (1 << PORTD2);   // turn On the Pull-up
	   
    
	EICRA |= (0 << ISC00)|(1 << ISC01);    // set INT0 to trigger on ANY logic change
    EIMSK |= (1 << INT0);     // Turns on INT0
	
	timer_0();
	sei();// enable interrupts		
	while (1)   {
					if((millisec-oldTime)>=1000)
					{	
						sec++;
						if(sec==1)
						{
							cli();
										
							flowRate = ((1000.0 / (millisec - oldTime)) * pulseCount) / calibrationFactor;
							oldTime = millisec;
							flowMilliLitres = (flowRate / 60) * 1000;
    						totalMilliLitres += flowMilliLitres;
										
							
							USART_Transmit(flowRate)
						
							USART_Transmit(flowMilliLitres);
						
							
							int b =(totalMilliLitres & 0b11111111) ;
							int c=(totalMilliLitres >> 8);
							
							USART_Transmit(c);
						
							USART_Transmit(b);
										

							millisec=0;
							sec=0;
							pulseCount = 0;
										
							sei();
						}
					}							
				}
}


ISR (TIMER0_COMPA_vect){millisec++;}


ISR (INT0_vect){pulseCount++;}


	 	

 

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

You're not accessing millisec and pulseCount atomically. This will result in random errors.