Skip to main content
Baaa.1
Associate
June 4, 2020
Question

stm32 nucleo driving buzzer with notes

  • June 4, 2020
  • 4 replies
  • 4388 views

I want to drive simple buzzer with HAL library.I did this with mbed library and I played simple pirates of the caribbean melody.

My mbed code like this :

#include "mbed.h"
 
#define NOTE_C4 262 //Defining note frequency
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_D5 587
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_G5 784
#define NOTE_A5 880
#define NOTE_B5 988
 
PwmOut buzzer(PA_1);
PwmOut redpin(PA_8);
PwmOut greenpin(PA_9);
PwmOut bluepin(PA_10);
 
DigitalOut myled(LED1);
 
float notes[] = { //Note of the song, 0 is a rest/pulse
 NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0, 
 NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0, 
 NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,
 NOTE_A4, NOTE_G4, NOTE_A4, 0,
 
 NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0, 
 NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0, 
 NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,
 NOTE_A4, NOTE_G4, NOTE_A4, 0,
 
 NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0, 
 NOTE_A4, NOTE_C5, NOTE_D5, NOTE_D5, 0, 
 NOTE_D5, NOTE_E5, NOTE_F5, NOTE_F5, 0,
 NOTE_E5, NOTE_D5, NOTE_E5, NOTE_A4, 0,
 
 NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0, 
 NOTE_D5, NOTE_E5, NOTE_A4, 0, 
 NOTE_A4, NOTE_C5, NOTE_B4, NOTE_B4, 0,
 NOTE_C5, NOTE_A4, NOTE_B4, 0,
 
 NOTE_A4, NOTE_A4, 
 //Repeat of first part
 NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0, 
 NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,
 NOTE_A4, NOTE_G4, NOTE_A4, 0,
 
 NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0, 
 NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0, 
 NOTE_C5, NOTE_D5, NOTE_B4, NOTE_B4, 0,
 NOTE_A4, NOTE_G4, NOTE_A4, 0,
 
 NOTE_E4, NOTE_G4, NOTE_A4, NOTE_A4, 0, 
 NOTE_A4, NOTE_C5, NOTE_D5, NOTE_D5, 0, 
 NOTE_D5, NOTE_E5, NOTE_F5, NOTE_F5, 0,
 NOTE_E5, NOTE_D5, NOTE_E5, NOTE_A4, 0,
 
 NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C5, 0, 
 NOTE_D5, NOTE_E5, NOTE_A4, 0, 
 NOTE_A4, NOTE_C5, NOTE_B4, NOTE_B4, 0,
 NOTE_C5, NOTE_A4, NOTE_B4, 0,
 //End of Repeat
 
 NOTE_E5, 0, 0, NOTE_F5, 0, 0,
 NOTE_E5, NOTE_E5, 0, NOTE_G5, 0, NOTE_E5, NOTE_D5, 0, 0,
 NOTE_D5, 0, 0, NOTE_C5, 0, 0,
 NOTE_B4, NOTE_C5, 0, NOTE_B4, 0, NOTE_A4,
 
 NOTE_E5, 0, 0, NOTE_F5, 0, 0,
 NOTE_E5, NOTE_E5, 0, NOTE_G5, 0, NOTE_E5, NOTE_D5, 0, 0,
 NOTE_D5, 0, 0, NOTE_C5, 0, 0,
 NOTE_B4, NOTE_C5, 0, NOTE_B4, 0, NOTE_A4
};
int duration[] = { //duration of each note (in ms) Quarter Note is set to 250 ms
 125, 125, 250, 125, 125, 
 125, 125, 250, 125, 125,
 125, 125, 250, 125, 125,
 125, 125, 375, 125, 
 
 125, 125, 250, 125, 125, 
 125, 125, 250, 125, 125,
 125, 125, 250, 125, 125,
 125, 125, 375, 125, 
 
 125, 125, 250, 125, 125, 
 125, 125, 250, 125, 125,
 125, 125, 250, 125, 125,
 125, 125, 125, 250, 125,
 
 125, 125, 250, 125, 125, 
 250, 125, 250, 125, 
 125, 125, 250, 125, 125,
 125, 125, 375, 375,
 
 250, 125,
 //Rpeat of First Part
 125, 125, 250, 125, 125,
 125, 125, 250, 125, 125,
 125, 125, 375, 125, 
 
 125, 125, 250, 125, 125, 
 125, 125, 250, 125, 125,
 125, 125, 250, 125, 125,
 125, 125, 375, 125, 
 
 125, 125, 250, 125, 125, 
 125, 125, 250, 125, 125,
 125, 125, 250, 125, 125,
 125, 125, 125, 250, 125,
 
 125, 125, 250, 125, 125, 
 250, 125, 250, 125, 
 125, 125, 250, 125, 125,
 125, 125, 375, 375,
 //End of Repeat
 
 250, 125, 375, 250, 125, 375,
 125, 125, 125, 125, 125, 125, 125, 125, 375,
 250, 125, 375, 250, 125, 375,
 125, 125, 125, 125, 125, 500,
 
 250, 125, 375, 250, 125, 375,
 125, 125, 125, 125, 125, 125, 125, 125, 375,
 250, 125, 375, 250, 125, 375,
 125, 125, 125, 125, 125, 500
};
void led_write(float red,float green, float blue){
 redpin = red;
 greenpin = green;
 bluepin = blue;
 }
 
 
int main() {
 const int songspeed = 1.5;
 float result;
 float bzz = 0.5;
 
 
 while(1) {
 
 
 for(int i=0;i<203;i++){
 
 int w = duration[i] * songspeed;
 if(notes[i] == 0){
 result = 1;
 bzz = 0;
 }
 else {
 result = 1 / notes[i]; 
 bzz = 0.4; 
 }
 
 if(NOTE_E4 == notes[i])
 led_write(1.0,0.0,1.0); 
 else
 led_write(0.0,0.0,0.0);
 buzzer.period(result);
 buzzer.write(bzz); 
 
 wait_ms(w);
 
 }
 
 
 }
}

I want to play same music with HAL but I'm very noob on hal.I tried the pwm output and I set the notes into htim.Instance->CCR but I could not change the duty cycle.

My clock frequency is 90mhz prescaler 90-1 and counter 1000-1 for note frequency.

My code like this :

int main(void)
{
 /* USER CODE BEGIN 1 */
 
 /* USER CODE END 1 */
 
 /* MCU Configuration--------------------------------------------------------*/
 
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();
 
 /* USER CODE BEGIN Init */
 
 /* USER CODE END Init */
 
 /* Configure the system clock */
 SystemClock_Config();
 
 /* USER CODE BEGIN SysInit */
 
 /* USER CODE END SysInit */
 
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_TIM1_Init();
 MX_TIM2_Init();
 /* USER CODE BEGIN 2 */
 HAL_TIM_Base_Start(&htim1);
 HAL_TIM_Base_Start(&htim2);
 
 
 HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
 HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
 HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
 
 HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
 
	 int r=255;
	 int g=0;
	 int b=0;
	 int t=10;
 
// notes and duraction is the same ( I removed for length)
	 const int songspeed = 1.5;
	 float result;
 
 
 /* USER CODE END 2 */
 
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 /* USER CODE END WHILE */
 
 /* USER CODE BEGIN 3 */
	 for(int i=0;i<203;i++){
 int w = duration[i] * songspeed;
 if(notes[i] == 0){
 result = 0;
 
 }
 else {
 result = notes[i];
 
 }
  set_sound(result);
 
 HAL_Delay(w);
	 }
  set_rgb(200, 0.0, 200);
 
 }
 
 /* USER CODE END 3 */
}

How can I do this ?

This topic has been closed for replies.

4 replies

waclawek.jan
Super User
June 4, 2020

> I set the notes into htim.Instance->CCR but I could not change the duty cycle.

You change duty cycle by setting CCR, but that's not what you want.

Frequency = 1 / period, so to change frequency, you want to change the period, not the duty cycle. You can achieve that by writing to TIMx_ARR.

You want to have the ARR preload set, TIMx_CR1.ARPE=1; I don't know how this is achieved in Cube/HAL, I don't use it.

Read the timer chapter in Reference Manual.

JW

Baaa.1
Baaa.1Author
Associate
June 7, 2020

Thanks for help @Community member​ 

I find a solution . My solution :

int setfreq(int freq) // 1 to 3000 Hz
{
int period = 60000 / freq; // compute period as function of 60KHz ticks
TIM2->ARR = period - 1;
TIM2->CCR2 = period / 2; // Channel 2 50/50
TIM2->CNT = 0;
return 0;
}
static void MX_TIM2_Init(void)
{
 
 /* USER CODE BEGIN TIM2_Init 0 */
 
 /* USER CODE END TIM2_Init 0 */
 
 TIM_ClockConfigTypeDef sClockSourceConfig = {0};
 TIM_MasterConfigTypeDef sMasterConfig = {0};
 TIM_OC_InitTypeDef sConfigOC = {0};
 
 /* USER CODE BEGIN TIM2_Init 1 */
 htim2.Instance = TIM2;
 htim2.Init.Prescaler = 1500-1;
 /* USER CODE END TIM2_Init 1 */
 
 htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
 htim2.Init.Period = 1000-1;
 htim2.Init.ClockDivision = 0;
 htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
 if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
 {
 Error_Handler();
 }
 sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
 if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
 {
 Error_Handler();
 }
 if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
 {
 Error_Handler();
 }
 sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
 if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
 {
 Error_Handler();
 }
 sConfigOC.OCMode = TIM_OCMODE_PWM1;
 sConfigOC.Pulse = (htim2.Init.Period + 1)/2;
 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
 sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
 if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN TIM2_Init 2 */
 
 /* USER CODE END TIM2_Init 2 */
 HAL_TIM_MspPostInit(&htim2);
 
}

S.Ma
Principal
June 7, 2020

Done the buzzer on piezzo using LPTIMer because it's light and simple.

const uint32_t MidiNotes_us[] = {
 1000000000/27500, // A0 27.5Hz [midi note 21]
 1000000000/29135, // 29.1Hz
 1000000000/30868, // B0 30.8Hz
 1000000000/32703, // C1 32.7Hz
 1000000000/34648, // 
 1000000000/36708, // 
 1000000000/38891, // 
 1000000000/41203, // 
 1000000000/43654, // 
 1000000000/46249, // 
 1000000000/48999, // 
 1000000000/51913, // 
 1000000000/55000, // 
 1000000000/58270, // 
 1000000000/61735, // 
 1000000000/65406, // 
 1000000000/69296, // 
 1000000000/73416, // 
 1000000000/77782, // 
 1000000000/82407, // 
 1000000000/87307, // 
 1000000000/92499, // 
 1000000000/97999, // 
 1000000000/103830, // 
 1000000000/110000, // 
 1000000000/116540, // 
 1000000000/123470, // 
 1000000000/130810, // 
 1000000000/138590, // 
 1000000000/146830, // 
 1000000000/155560, // 
 1000000000/164810, // 
 1000000000/174610, // 
 1000000000/185000, // 
 1000000000/196000, // 
 1000000000/207650, // 
 1000000000/220000, // 
 1000000000/233080, // 
 1000000000/261630, // ** 60
 1000000000/277180, // 
 1000000000/293670, // 
 1000000000/311130, // 
 1000000000/329630, // 
 1000000000/349230, // 
 1000000000/369990, // 
 1000000000/392000, // 
 1000000000/415300, // 
 1000000000/440000, // ** 69
 1000000000/466160, // 
 1000000000/493880, // 
 1000000000/523250, // 
 1000000000/554370, // 
 1000000000/587330, // 
 1000000000/622250, // 
 1000000000/659260, // 
 1000000000/698460, // 
 1000000000/739990, // 
 1000000000/783990, // 
 1000000000/836100, // 
 1000000000/880000, // 
 1000000000/932330, // 
 1000000000/987770, // 
 1000000000/1046500, // 
 1000000000/1108700, // 
 1000000000/1174700, // 
 1000000000/1244500, // 
 1000000000/1318500, // 
 1000000000/1396900, // 
 1000000000/1480000, // 
 1000000000/1568000, // 
 1000000000/1661200, // 
 1000000000/1760000, // 
 1000000000/1864700, // 
 1000000000/1975500, // 
 1000000000/2093000, // 
 1000000000/2217500, // 
 1000000000/2349300, // 
 1000000000/2489000, // 
 1000000000/2637000, // 
 1000000000/2793000, // 
 1000000000/2960000, // 
 1000000000/3136000, // 
 1000000000/3322400, // 
 1000000000/3520000, // 
 1000000000/3729300, // 
 1000000000/3951100, // 
 1000000000/4186000, // 108
};
 
 
// d dd d dddd dd
const uint32_t StarTrekMelody[] = { 
 
 MAKEWORD(Re2,6),
 MAKEWORD(Sol2,3),
 MAKEWORD(Do3,6),
 MAKEWORD(Si2,3),
 MAKEWORD(Sol2,2),
 MAKEWORD(Mi2,2),
 MAKEWORD(La2,2),
 MAKEWORD(Re3,2),
 MAKEWORD(Re3,1),
 MAKEWORD(Fa3h,6),
 0,
};
int32_t BuzzerInit(buzzer_t* pbuzzer) {
 
 IO_PinConfigure(pbuzzer->pPiezoPin);
 pbuzzer->Countdown_50ms = 0;
 pbuzzer->Level = 1;
 pbuzzer->MelodyCounter = -1; // don't play any melody
 pbuzzer->pMelody = 0; // no melody defined
 
 BuzzerStop(pbuzzer); //+
 LPTIM1_Init();
 
 return 0;
}
 
int32_t BuzzerPlayMelody(buzzer_t* pbuzzer, uint32_t* pMelody) {
 
 pbuzzer->pMelody = pMelody;
 pbuzzer->MelodyCounter = 0; // get started. -1 = no melody
 pbuzzer->Countdown_50ms = 0;
 pbuzzer->Level = 1;
 return 0;
}
 
//-------- lower level, play a single note, either defined by MIDI, Hz or us 
 
int32_t BuzzerIsNotePlaying(buzzer_t* pbuzzer) {
 
 if(pbuzzer->MelodyCounter==-1)
 return 0;
 return 1;
}
int32_t BuzzerPlay_MIDI(buzzer_t* pbuzzer, int32_t MIDI_Note, int32_t Duration_100ms) {
 
 if(MIDI_Note<21)
 TrapError(); // unsupported
 if(MIDI_Note>108)
 TrapError(); // unsupported
 
 pbuzzer->Period_Hz = 1000000/MidiNotes_us[MIDI_Note]; // back to frequencies
 
 return BuzzerPlay_us( pbuzzer, MidiNotes_us[MIDI_Note], Duration_100ms);
}
 
int32_t BuzzerPlay_Hz(buzzer_t* pbuzzer, int32_t Hz, int32_t Duration_100ms) {
 
 int32_t us;
 
 if(Hz<30)
 return -1;
 //TrapError();
 if(Hz>30000)
 return -1;
 //TrapError();
 
 pbuzzer->Period_Hz = Hz;
 us = 1000000/(uint32_t)Hz;
 
 return BuzzerPlay_us(pbuzzer, us, Duration_100ms);
}
 
int32_t BuzzerPlay_us(buzzer_t* pbuzzer, int32_t us, int32_t Duration_100ms) { 
 
 if(Duration_100ms==0){
 pbuzzer->Countdown_50ms = 1; // will stop next 50ms
 return 0; // stop playing?
 };
 
 if(pbuzzer->Level==0)
 pbuzzer->Level = 1;
 
 pbuzzer->Period_us = us;
 if(pbuzzer->pPiezoPin->Init.Alternate != 0) { // PWM mode is possible
 BuzzerStop(pbuzzer);
 LPTIM1_SetPWM_us(pbuzzer->Period_us/2);
 }else{
 LPTIM1_SetTick_us(pbuzzer->Period_us/2); 
 }
 
 pbuzzer->Countdown_50ms = Duration_100ms*2;
 return 0;
}
 
 
int32_t BuzzerStop(buzzer_t* pbuzzer) {
 LPTIM1_SetTick_us(0);
 return 0;
}
 
 
int32_t Buzzer_50ms(buzzer_t* pbuzzer) {
 
 uint16_t Note;
// this is used as countdown for playing buzzer note timeout (note play duration implementation) 
 
 if(pbuzzer->Countdown_50ms==0) {
 // are we playing a melody?
 if((pbuzzer->pMelody==0)||(pbuzzer->MelodyCounter<0)) // no melody or nothing to play, do nothing
 return 0; // no melody to play
 
 // melody playing //BuzzerPlay_Hz(2000, 10);
 Note = pbuzzer->pMelody[pbuzzer->MelodyCounter];
 if(Note==0) { // EOL 
 pbuzzer->MelodyCounter=-1;
 return 0;
 }
 
 BuzzerPlay_MIDI(pbuzzer, (Note>>8)&0xFF, Note & 0xFF);
 pbuzzer->MelodyCounter++;
 return 0; // not yet
 }
 
 pbuzzer->Countdown_50ms--; // 50 msec elapsed
 
 if(pbuzzer->Countdown_50ms==0) { // time's up?
 BuzzerStop(pbuzzer);//LPTIM1_SetTick_us(0); // stop buzzer
 }else
 return 0;
 
//============= 8>< -------------------------------- 
return 0; // disable the demo
}
 
 
int32_t BuzzerTick(buzzer_t* pbuzzer) { // this is called when AW add-on board is present
 
 pbuzzer->Toggle++;
 if(pbuzzer->Toggle & 0x01) {
 IO_PinSetLow(pbuzzer->pPiezoPin); 
 }else{
 IO_PinSetHigh(pbuzzer->pPiezoPin);
 }
 return 0;
}; 

S.Ma
Principal
June 7, 2020

Originally got one piezzo on a non Timer pin and had to do SW waves by GPIO... really not great result.

Then used LPTIM on the GPIO to be able to run a melody as background task.

Key info: Here is STL32L4R5 @ 48 MHz