Tone library with no delay

Post here first, or if you can't find a relevant section!
Post Reply
sigi
Posts: 57
Joined: Mon Sep 28, 2020 3:17 pm

Tone library with no delay

Post by sigi »

Hi
I made this sketch to sound a melody on a pin using a timer and an array of frequencies and periods...

Code: Select all

HardwareTimer Timer(4);
uint8_t Pin = PB9;
bool Enabled;

long lastStart;
long Freq;
long lastFreq;
long lastConfig;
int lastCounter;
long Dura;
int counter;

uint32_t DutyCyc;
uint32_t PeriodCyc;
uint16_t Prescaler;
uint16_t Overflow;

int pista1[20][2] = {
{850 , 300 }, 
{0   , 50  },
{450 , 100}, 
};

int pista2[20][2] = {
{500 , 500 }, 
{0   , 50  },
{500 , 500}, 
{0   , 50 }, 
{0 , 50}, 
{0   ,50 }, 
{0 , 50},
};
  int len = 20;
  
  
  
void setup() { 
pinMode(Pin, PWM);
pwmWrite(Pin,0);
//delay(2000);
}

void loop() {
SoundArray(pista1);

if (millis()>=10000 & millis()<=10010) {Enabled=true;}
if (millis()>=20000 & millis()<=20010) {Enabled=true;}
}


void SoundArray(int (&image)[20][2]){
if (Enabled) {
long Freq = image[counter][0];
long Dura = image[counter][1];
		if (Freq != lastFreq) {
				if (Freq>0) {
								if (Freq != lastConfig) {
									ConfigTimer(Freq); 
									lastConfig=Freq; 
		             } 
		             Play();
					} else {Mute();}
				lastFreq=Freq;
				lastStart=millis();
		}
	
		if (millis()>= (lastStart+Dura)) {
			counter++;
			if (counter==len) {Mute(); Enabled=false;  counter=0;}
		}
}
	
}





void ConfigTimer (long Freq) {
Timer.pause();	
PeriodCyc = (1000000/Freq) * (F_CPU/1000000.0);
#define MAX_RELOAD ((1 << 16) - 1)
Prescaler = (PeriodCyc / MAX_RELOAD) + 1.0;
Timer.setPrescaleFactor(Prescaler);
Overflow = (PeriodCyc + (Prescaler / 2.0)) / Prescaler;
Timer.setOverflow(Overflow);
DutyCyc = Overflow/2;
Timer.refresh();
Timer.resume();

}


void Play() {
pwmWrite(Pin,DutyCyc);

}

void Mute() {
pwmWrite(Pin,0);	

}

as a sketch it works... so I decided to make a library...

h file...

Code: Select all

#ifndef BuzzerT_h
#define BuzzerT_h

#include "Arduino.h"

class BuzzerT{
private:

public:
	
int pista1[20][2] = {
{850 , 300 }, 
{0   , 50  },
{450 , 100 }, 
};

int pista2[20][2] = {
{200 , 1500 }, 
{0   , 50  },
{700 , 500 }, 
{0   , 50  }, 
{134  , 50  }, 
{0   , 50  }, 
{150   , 50  },
};


uint8_t Enabled;
HardwareTimer *TIMER;
int *image[20][2] ={};

uint8_t Pin;

unsigned long lastStart;
int Freq;
int Dura;

int  lastFreq;
int  lastConfig;
uint8_t counter;
uint8_t lastCounter;


uint32_t DutyCyc;
uint32_t PeriodCyc;
uint16_t Prescaler;
uint16_t Overflow;


BuzzerT(uint8_t Pin, int (&image)[20][2], uint8_t Enabled);
void SoundArray();
void ConfigTimer(int  Freq);
void Mute();
void Play();


};

#endif


cpp file:

Code: Select all

#include "Arduino.h"
#include "BuzzerT.h"

BuzzerT::BuzzerT(uint8_t Pin, int (&image)[20][2], uint8_t Enabled) {	
this->Pin = Pin;
this->Enabled = Enabled;
this->image[20][2] = &image[20][2];//<<-------- not working!
pinMode(Pin, PWM);
TIMER = new HardwareTimer(4);
Mute();
}


void BuzzerT::SoundArray(){
//Serial.print("Enabled "); Serial.println(String(Enabled));

if (Enabled) {
Freq = (int)image[counter][0];	
Serial.print("Freq ");Serial.println(String(Freq));

Dura = (int)image[counter][1];
Serial.print("Dura ");Serial.println(String(Dura));

			if (Freq != lastFreq) {
				if (Freq>0) {
								if (Freq != lastConfig) {
									ConfigTimer(Freq); 
									lastConfig=Freq; 
		             } 
		             Play();
					} else {Mute();}
				lastFreq=Freq;
				lastStart=millis();
		}
	
		if (millis()>= (lastStart+Dura)) {
			counter++;Serial.println(String(counter));
			if (counter==20) {Mute(); Enabled=false;  counter=0;}
		}
}
	
}


void BuzzerT::ConfigTimer(int Freq){
TIMER->pause();	
PeriodCyc = (1000000/Freq) * (F_CPU/1000000.0);// ciclos por us del STM32
#define MAX_RELOAD ((1 << 16) - 1)//timer 16 bits resolution
Prescaler = (PeriodCyc / MAX_RELOAD) + 1.0;
TIMER->setPrescaleFactor(Prescaler);
Overflow = (PeriodCyc + (Prescaler / 2.0)) / Prescaler;
TIMER->setOverflow(Overflow);
DutyCyc = Overflow/2;
TIMER->refresh();
TIMER->resume();
}

void BuzzerT::Mute(){pwmWrite(Pin,0      );}
void BuzzerT::Play(){pwmWrite(Pin,DutyCyc);}



the problem is that the pointer to the array inside the library I want to use for each sound is not getting the data correctly, so I think the problem is in this line:

Code: Select all

BuzzerT::BuzzerT(uint8_t Pin, int (&image)[20][2], uint8_t Enabled) {	
this->Pin = Pin;
this->Enabled = Enabled;
this->image[20][2] = &image[20][2];//<<-------- not working!
pinMode(Pin, PWM);
TIMER = new HardwareTimer(4);
Mute();
}
link to a complete code with example...
https://mega.nz/file/4Oxn2aoB#Nf-Vfqid2 ... GJ0BO4F1Yc

Help please!
dannyf
Posts: 446
Joined: Sat Jul 04, 2020 7:46 pm

Re: Tone library with no delay

Post by dannyf »

my 2 cents:
1. nothing can be of no delay.
2. arrays need to be referenced.
3. may want to code the numbers (20 or 2) as macros or part of a struct so the users can reconfigure the library easily for his/her applications.
4. may want to remove the uart print out of the library.
sigi
Posts: 57
Joined: Mon Sep 28, 2020 3:17 pm

Re: Tone library with no delay

Post by sigi »

well I already solve my problem... Attachment with the library if anybody want to try it:
https://github.com/sigifre/Buzzer-Stm32-No-delay
Post Reply

Return to “General discussion”