How do I make this AVR digital thermometer sound a buzzer? Please help.

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

I designed a dual thermometer with ATMega16 and LM35 for measuring the temperature of two different components. Now one component is temperature critical. I need the thermometer to sound a buzzer when the temperature reaches a threshold (say 28C).

 

The buzzer should beep like this:

 

On (5 sec), Off (15 sec) and so on.

 

My code is this:

 

(Many thanks to Mr. David Prentice, who helped me understand the basics of ADC and write the code.)

 

#include <avr/io.h>             // special function registers
#include <stdio.h>              // sprintf()
#define F_CPU 4000000           // you are running on 4MHz RC
#include <util/delay.h>         // _delay_xx()
#include "lcd.h"                // Fleury LCD library

int readADC(char channel)


{
	ADMUX = (3 << REFS0)|(1<<ADLAR)|(channel << MUX0);    // VREF=2.56V, 8-bit, channel #0-7 is on PA0-PA7 pins
	_delay_us(10);              // allow multiplexer to settle
	ADCSRA |= (1<<ADSC);        // Start Conversion
	while (ADCSRA & (1<<ADSC)); // wait for completion
	return ADCH;                // 8-bit result because we use ADLAR
}

int main(void)
{
	char display[32], channel = 0, degree = 0xDF;       // special character for degree symbol
	int tempC, i;
	ADCSRA = (1<<ADEN)|(7 << ADPS0);        // Enable, div128

	lcd_init(LCD_DISP_ON);
	
		
	while (1) {
		
                lcd_clrscr();
		lcd_gotoxy(4,0);
		lcd_puts("The Bagho's");
		_delay_ms(1100);
		lcd_gotoxy(0,1);
		lcd_puts("Dual Thermometer");
		_delay_ms(5000);
		lcd_clrscr();
		
		for (i=1; i<60; i++)
		{
		
		tempC = readADC(channel);       // 10mV per C.  full-scale is 2.56V i.e. 256C
		sprintf(display, "Channel %d %3d%cC ", channel, tempC, degree);
		lcd_gotoxy(0,channel);               // 1st column, N'th line
		lcd_puts(display);      // string is all printed in one go
		_delay_ms(500);
		channel++;
		if (channel >= 2)
		channel = 0;
		
		}
	
	}
}

I tried a lot to get info on the internet, but it hasn't been of any help.

Last Edited: Mon. Jun 1, 2015 - 11:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So follow David's advice to you: get out a pencil & paper and start thinking about what is involved in generating this alarm, and detecting the threshold ...

 

https://www.avrfreaks.net/comment...

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

(note that I've just given you 1 clue on how the problem can be subdivided)

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

Okay! I will! smiley

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

I cannot tell from that code which of the channels 0 or 1 is the critical one but I guess you are going to want something like:

if ((channel == CRITICAL_CHANNEL) && (tempC > SOME_THRESHOLD) && (buzzing_not_already_started)) {
  // start the buzzing process
}

On the whole you can design your software like this. Write down in "broad brushstrokes" what you want to achieve. Worry about the details like "SOME_THRESHOLD" and how you are going to handle "buzzer_not_already_started" later.

 

It may be better to do this design on paper rather than in you C editor. When you have the overall plan you can implement the specifics of the detail in C.

 

EDIT: just learning the fundamentals of the English language ;-)

Last Edited: Mon. Jun 1, 2015 - 11:52 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you clawson!

 

So can I add this following line between the delay 500 ms and channel++ line?

 

if ((channel == 1) && (tempC > 28) && (PORTD= 0x00))

{

 

PORTD= 0xFF;  //Turns ON buzzer

_delay_ms(5000); //5 second delay on

PORTD= 0x00;

_delay_ms(15000)

}

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

Too specific - broad brushstrokes first - as I say think, then design what it is you want to achieve first. Worry about the specifics of implementation when you have worked out the design.

 

Personally I don't know why you'd wait 500ms before reporting the alarm condition so I don't know why you wouldn't place such a check just immediately after taking the reading that matters - but details like this will come out when you THINK and DESIGN this thing. It seems to be a tragic deficiency in the modern education of potential engineers that they are taught the specifics of the syntax of C and how a device such as an ADC or timer or LCD works but no one seems to be teaching engineers to spend some time up front reading, thinking, designing, specifying before they rush into an implementation. It is utterly vital. The final solutions will be all the poorer for the lack of it.

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

Bagho,

 

You should also become aware of the limits of the delay functions.

 

http://www.nongnu.org/avr-libc/u...

 

... and in particular, this quotation...

When the user request delay which exceed the maximum possible one, _delay_ms() provides a decreased resolution functionality. In this mode _delay_ms() will work with a resolution of 1/10 ms, providing delays up to 6.5535 seconds (independent from CPU frequency). The user will not be informed about decreased resolution.

 

But I agree with the others; pencil and paper first.

 

Cheers,

 

Ross

 

Ross McKenzie ValuSoft Melbourne Australia

Last Edited: Mon. Jun 1, 2015 - 12:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yup you are right. In my case, maybe it's because I have no engineering background. Electronics is purely my passion. I need to think more on this problem I guess.

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

Indeed! Thanks a lot for the suggestion.

 

I wish there were a way to implement delay in seconds.  smiley

 

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

The computer works step by step. Read an input. Is it hi or lo? Set a variable true or false to save the result. Turn an output on or off depending on the state of a variable. If you can express the program as a sequence of steps needed to get the result you want, and can write the steps or describe it to someone, you are about at the point to start the implementation. Transitioning from the design phase.

 

Imagecraft compiler user

Last Edited: Mon. Jun 1, 2015 - 03:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bagho wrote:
I wish there were a way to implement delay in seconds.  smiley

 

Of course there is - think about it!

 

 

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

Electronics is purely my passion.

I'd have thought that gave all the more reason to try and learn to do it properly?

 

It isn't just about knowing the syntax of "int main(int argc, char * argv[])", "unsigned char number;", for(), while() and so on.

 

Engineering is about a process - the coding is just one step in that process.

 

I wish there were a way to implement delay in seconds.

As for delays. A lesson you will learn fairly early on in embedded engineering is that almost no one ever purposefully sits in a pointless delay in the real world. If nothing else you actually probably want to sleep() while you are delaying but usually that's going to mean an interrupt. Talking of interrupts almost all embedded apps employ some kind of housekeeping timer interrupt that maybe "ticks" once every 1/10/20/50ms or similar. (In Windows and Linux it used to be 10ms. These days it is 1ms or sometimes less). You can use this single source of "ticking" for all sorts of things. Say you want to delay for 30ms you might take a look at the current timer count then do something when that timer count is now+30ms. Such a universal timer is so common that almost all modern ARM processors even have a timer called SYSTICK for the very purpose. So if I were you I'd take a first look at timer interrupts and using one of the AVR timers to count up some global "system tick" that you cal use for various time measurement purposes. A second is then just now+1000 of a 1ms rate timer (or now+100 on 10ms).

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

I still have a doubt. What if I need a 1 second delay and my system tick is not 1ms or 10ms? Is it possible? Please guide me.

 

Imagecraft compiler user

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

Bob,

 

Only you would be perverse enough to run a systick at some speed that wasn't an obvious factor of "human time" like 35ms or whatever. I guess you count 28 ticks then wait the additional 20ms in some other way to make it up to 1000ms ?

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

you are do not used command "delay", because the procesor is closed. He is  not doing. He is sleeping. You must use interrupts. Set the timer (example T0 )  that he generate interrupt every example 10 ms . Later uC counts interrupts , and after example to count 100 interrupts you have 1s. Then you increment variable  , they increment variable ( she reply behind for time measurement ). uC all time worked . In  this time you are doing reading from sensor , to compare actualy read-out and set temperature , or to generate sound in the pin . if  you don't know , how that doing - you write.

 

i'm sorry , i'm learning english.i'm beginner. please to set right my sentence.

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

example code for interrupts for topic above 

<

/*
 * main.c

 */

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

volatile uint8_t ms2=0;
volatile uint8_t flaga1s=0;
volatile uint8_t sekundy=0;

int main (void)
{
TCCR1B|=(1<<WGM12);        //mode CTC
TCCR1A|=(1<<CS11)|(1<<CS10);  //divide  64 for 8MHZ;this is 125kHz or 8us
OCR1A=249;        //interrupts after 250 imp. clock, this is  2ms

 sei ();

if (flaga1s=1)
    {

    }
}

//-------------------------------------interrupts-------------------------------------------------------------

ISR ( TIMER1_COMPA_vect)
{
ms2++;
if (ms2>500)
    {
    flaga1s=1;
    sekundy++;
    }
}

>

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

Thank you! Your responses are extremely useful. I am reading up now on interrupts and system ticks. This is a great forum! 

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

Perverse? Have any avrfreaks ever had someone at work tell them they were perverse? Time for a forced vacation?

 

Imagecraft compiler user

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

I tell my own colleagues all the time that they are perverse (they are an extremely weird bunch!(*)) I can only assume it means something crushingly worse to the Americans who have never really grasped the English language.

 

(* pretty much like the folks here in fact - myself included).