How to build a different time operation of the SoundPlay function ?

General discussion on mikroC PRO for AVR.
Post Reply
Author
Message
public2010
Posts: 94
Joined: 05 May 2009 18:31
Location: Somewhere in Europe

How to build a different time operation of the SoundPlay function ?

#1 Post by public2010 » 24 Jan 2022 14:29

After some time of using mikroC for AVR, I began to discover the beauty of this compiler. Thanks mikroe!

Today I had to use the function:

Code: Select all

Sound_Play (2000, 3000);
which means, in the previous example, that it generates on a 2kHz MCU pin for 3 seconds. Ok?

Now, let me tell you my issue.
I am going to create a software where the duration of 3 seconds is not known or rather is variable. That is, this variable duration will have to be determined if I have a certain value on another pin of the MCU. It is possible that at some point I need the 2kHz to work for 2 seconds, sometimes less, in other situations more. But how do I make this software? Some tips, please!
For example, on PB0 pins the frequency is generated and at an ADC input I capture the value of 5Vdc. When this value appears on the ADC pins, then the SoundPlay function stops generating the frequency on the PB0 pin. But how do I do that?

Best Regards,
pub.

Levi
Posts: 55
Joined: 01 Mar 2008 20:27

Re: How to build a different time operation of the SoundPlay function ?

#2 Post by Levi » 24 Jan 2022 16:39

Hi,

Use something like:

Code: Select all

unsigned int sound_duration=1000;//default 
.
.

Sound_Play (2000, sound_duration);//change variabile  sound_duration acording to your needs 
Regards,
Levi

public2010
Posts: 94
Joined: 05 May 2009 18:31
Location: Somewhere in Europe

Re: How to build a different time operation of the SoundPlay function ?

#3 Post by public2010 » 24 Jan 2022 21:04

Thanks for the reply @Levi. Your example is good, but it might not help me much. Why? Please read the following:

Today I have better analyzed how to structure the future software and the problem is as follows: I will have to set the "signal duration", say, to 10 seconds. It is a cover for the most unfortunate case. Now, it may happen that I have to be random, that at one point this duration is 5 seconds, another time 7 seconds. I think it will never exceed 10 seconds.
So far, everything is understandable, I hope, but the question arises: if initially everything is set for 10 seconds, how do I stop the signal at 5 seconds or 7 seconds, if the function is turned on for 10 seconds by default or initially ???

Levi
Posts: 55
Joined: 01 Mar 2008 20:27

Re: How to build a different time operation of the SoundPlay function ?

#4 Post by Levi » 25 Jan 2022 10:38

Hi,
In this case you have to build your own sound function, because I think the built in mikroe sound library will block your code as long as the sound duration time is set and your main loop will not be responsive.
The easiest way to do it is by setting a timer interrupt routine and inside this function then toggle an output port/pin- equal to your 2Khz sound frequency period then ... enable and disable this output port by a counter set or preset to your duration requirements somewhere in your program
Regards,
Levi

public2010
Posts: 94
Joined: 05 May 2009 18:31
Location: Somewhere in Europe

Re: How to build a different time operation of the SoundPlay function ?

#5 Post by public2010 » 25 Jan 2022 19:00

@Levi, I was afraid of this answer --- to use a ... Timer. So, let's get back to using a Timer.

I searched the office drawer for an Atmega16 and I want to generate on the port C pins, let's say two frequencies used in the old analog communications, namely: 1644 Hz and 2544 Hz. I opened a very good Mikroelectronika tool, namely: "Timer Calculator" and here, I would like your opinion or other users, I chose as "Intrrrerupt time" the value: 0.4us ??? Is that enough? What do you think ?

Here's how the code looks like:

Code: Select all

unsigned int cnt=0;
unsigned long adc;

//Timer0 Prescaler = 0; Preload = 2; Actual Interrupt Time = 375 ns

void InitTimer0(){
  SREG_I_bit = 1;       // enable intrrerupts
  OCR0 = 2;  		
  TCCR0 = 0x28;
  TCCR0 |= 0x01;
  OCIE0_bit = 1;
}

void Timer0Overflow_ISR() org IVT_ADDR_TIMER0_COMP {
if(++cnt==46)     	// "cnt" can adjust the value of the PORTC output frequency
                          	//  cnt=46 for 1646Hz
                          	//  if I choose a cnt = 29 it results in 2600Hz and at a cnt = 30 it results in 2519Hz. Ups!
            { cnt = 0;
                 if(PORTC) PORTC = 0x00;
                 else PORTC = 0xFF;
             }
}

void main() {

DDRC = 0xFF;   // Setup PORT C output

ADC_Init();   	//  ADC init

do
{
 adc = 0;
 adc = ADC_Read(0);
    if(adc<900)
               {
                    InitTimer0();
                }
} while(1);
}
In the code above the timer starts and the PORTC activates with a frequency of approximately 1646Hz, not 1644Hz, more precisely, it also depends on the accuracy of the measuring device, in my case 1646Hz.

The problem is that I can't get 2544Hz fixed ??? Should I use another timer ??? Or could I use just one timer?

However, how can I stop the generation of these frequencies on port C ??

Levi
Posts: 55
Joined: 01 Mar 2008 20:27

Re: How to build a different time operation of the SoundPlay function ?

#6 Post by Levi » 26 Jan 2022 16:05

Hi,
Regarding 2544Hz frequency , you should calculate the period with formula T=1/F so for 2544Hz you will have T=393.081us in this case the port
pin should be '1' for T/2 and '0' for T/2.
For a better accuracy of the T it is better to use Timer 1 or other timer ,play with the mikroe TimerCalculator :)
Regarding how to stop the frequency , the answer is in the void InitTimer0() function.
Regards,
Levi

public2010
Posts: 94
Joined: 05 May 2009 18:31
Location: Somewhere in Europe

Re: How to build a different time operation of the SoundPlay function ?

#7 Post by public2010 » 26 Jan 2022 20:59

Thanks @Levi for the reply.

I'm worried about how to stop the timer when I switch the value to "TCCR0 = 0x28;" ---> "TCCR0 = 0x00;".
To be more precise, I tried to divide the timer like this (_ON and _OFF). On the PA0 input (ADC0) I connected a switch and a resistor but when the PA0 input is 0V (short press button) the timer stops hard, I have to press several times, plus sometimes it stops even in 0V or 5V, I mean the PC0 output.

Below is the timer0 code:

Code: Select all

//Timer0 Prescaler = 0; Preload = 2; Actual Interrupt Time = 375 ns

void InitTimer0_ON(){
  SREG_I_bit = 1;       // enable intrrerupts
  OCR0 = 2;
  TCCR0 = 0x28;
  TCCR0 |= 0x01;
  OCIE0_bit = 1;
}

void InitTimer0_OFF(){
  SREG_I_bit = 1;       // enable intrrerupts
  OCR0 = 2;
  TCCR0 = 0x00;
  TCCR0 |= 0x01;
  OCIE0_bit = 1;
}

void Timer0_ONOverflow_ISR() org IVT_ADDR_TIMER0_COMP {

adc = 0;
adc = ADC_Read(0);

if(++cnt==46)   "cnt" can adjust the value of the PORTC output frequency
            { cnt = 0;
                 if(PORTC0_bit) PORTC0_bit = 0;
                 else PORTC0_bit = 1;
             }
if(adc<500) { InitTimer0_OFF(); PORTC0_bit = 0; }  // stop timer 0
}
I need a solution to be able to turn off the timer much more accurately and safely, so that the PC0 output switches firmly and always to 0V. Please, can you help me with some advice?
Also, I noticed that the frequency on the PC0 output changed if I entered the ADC0 reading instructions in the timer, otherwise I can't stop it !!! Or maybe someone knows a solution, please!

Levi
Posts: 55
Joined: 01 Mar 2008 20:27

Re: How to build a different time operation of the SoundPlay function ?

#8 Post by Levi » 27 Jan 2022 09:39

Hi,
It is not a good practice to do a lot of work in interrupt routine , especially stop the interrupt inside interrupt.
Use the main loop and make settings there.If interrupt is not affecting your main loop, you can let it run...
and enable disable the toggle port inside interrupt routine(or outside). Regarding adc inside interrupt can create a lot of problems to your
program , (not recommended for this type of microcontroller) just think about side efects in the conversion time needed for adc module in combination with timer interrupt...


Regrads,
Levi

public2010
Posts: 94
Joined: 05 May 2009 18:31
Location: Somewhere in Europe

Re: How to build a different time operation of the SoundPlay function ?

#9 Post by public2010 » 27 Jan 2022 18:03

Can you give me a more accurate software example, please!

Levi
Posts: 55
Joined: 01 Mar 2008 20:27

Re: How to build a different time operation of the SoundPlay function ?

#10 Post by Levi » 28 Jan 2022 10:10

Hi,
Is there possible to set a pwm output in your project?
If yes , this could be used as 2Khz frequency and start stop it from your main code without affecting processor time.
Regards,
Levi

public2010
Posts: 94
Joined: 05 May 2009 18:31
Location: Somewhere in Europe

Re: How to build a different time operation of the SoundPlay function ?

#11 Post by public2010 » 28 Jan 2022 14:06

Levi wrote:
28 Jan 2022 10:10
Is there possible to set a pwm output in your project?
Unfortunately no.
I would like to generate on the output, for example pin PC0, the two frequencies of 1644Hz and 2544Hz, that's all.
I was thinking of dividing the timer into ON and OFF but once the timer is initialized, only the timer instructions are run. If I add additional instructions in the timer, they change the value of the output frequency, which is not a desired thing.

LATER EDIT: Does anyone have the code or the whole internal structure of the Sound Play function, because that's where I think the answers to my problem are !!!

Levi
Posts: 55
Joined: 01 Mar 2008 20:27

Re: How to build a different time operation of the SoundPlay function ?

#12 Post by Levi » 28 Jan 2022 16:55

Hi,

Library from mikro are proprietary for now,I am afraid you will not get the source code .
I made something similar to sound library some time ago but for pic microcontroler(not interrupt based no timer) , if it is for any help...

Code: Select all


//-----------------------------------------------------------
void delayUsound(uint32_t micros) {

    for(i=0;i<micros;i++)__delay_us(1);
}

//-----------------------------------------
void Sound(uint32_t frequency,uint32_t duration)
{

	uint32_t duration=(1000000/frequency);
 
	for(i=0;i<duration;i++){
	 PORTAbits.RA2=~ PORTAbits.RA2;// toggle sound port pin
	delayUsound(frequency);

	}
	 // sound pin off
     PORTAbits.RA2=0;//port sound to zero
}

Regards,
Levi

public2010
Posts: 94
Joined: 05 May 2009 18:31
Location: Somewhere in Europe

Re: How to build a different time operation of the SoundPlay function ?

#13 Post by public2010 » 28 Jan 2022 18:19

Thanks @Levi,
I rewrote your code below to make it compatible with mikroC for AVR but the PC0 output remains blocked at 5V !!! I think that because the constant "micros" has no value !!! Or is it possible that I did something wrong? Please, can you check?

Code: Select all

unsigned long i, adc, micros, frequency, duration;

void delay_sound() {
    for(i=0;i<micros;i++) { Delay_us(1); }
}

void Sound()
{
	duration=(1000000/frequency);

	for(i=0;i<duration;i++){
	 PORTC0_bit = ~PORTC0_bit;// toggle sound port pin
	delay_sound();
	}
	 // sound pin off
    PORTC0_bit = 0;  //port sound to zero
}

void main() {

DDRC = 0xFF;   // Setup PORT C output
ADC_Init();      //  ADC init

do {
      adc = 0; 
      adc = ADC_Read(0);
            if(adc<900)
                {  frequency = 1644; Sound(); }
    } while(1);
}

Levi
Posts: 55
Joined: 01 Mar 2008 20:27

Re: How to build a different time operation of the SoundPlay function ?

#14 Post by Levi » 31 Jan 2022 11:22

Hi,

Code: Select all

 
 void delay_sound()       should be   void delay_sound(unsigned int  micros )

 
Regards,
Levi

public2010
Posts: 94
Joined: 05 May 2009 18:31
Location: Somewhere in Europe

Re: How to build a different time operation of the SoundPlay function ?

#15 Post by public2010 » 01 Feb 2022 11:30

Code: Select all

void delay_sound()

should be

Code: Select all

void delay_sound(unsigned int  micros )
Thanks for the reply but in my case, if I apply your recommendation, mikroC for AVR returns the following error:

Code: Select all

40 314 Not enough parameters
After this test I added a line how to calculate "micros" namely:

Code: Select all

micros= 1 / (2 * frequency);
and the following line:

Code: Select all

duration=1000000/frequency;
I don't think it makes sense in software anymore!!!

So, I moved everything from Atmega16 to Attiny85 and the code looks like this now:

Code: Select all

unsigned long i, adc, frequency, duration =10000;

void delay_sound(unsigned int micros) {
    for(i=0;i<micros;i++) { Delay_us(1); }
}

void Sound()
{
	micros= 1 / (2 * frequency);

	for(i=0;i<duration;i++){
	 PORTB0_bit = ~PORTB0_bit;// toggle sound port pin
	delay_sound();
	}
	 // sound pin off
    PORTB0_bit = 0;  //port sound to zero
}

void main() {

DDRB = 0xFF;   // Setup PORT B output
ADC_Init();      //  ADC init

do {
      adc = 0;
      adc = ADC_Read(0);
            if(adc<900)
                {  frequency = 1644; Sound(); }
    } while(1);
}
where I set the "duration" parameter to 10 seconds by default.

The initial problem remains, unfortunately, because if I try to scan the ADC2 (PB4) pin from Attiny85 to reset the PB0 output, then the PB0 output frequency changes !!! So, anyway I do, I get to the problem with the timers again ???

Post Reply

Return to “mikroC PRO for AVR General”