cancel
Showing results for 
Search instead for 
Did you mean: 

stm32 nucleo driving buzzer with notes

Baaa.1
Associate

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 ?

4 REPLIES 4

> 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
Associate

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

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

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