2020-06-04 09:24 AM
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 ?
2020-06-04 09:40 AM
> 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
2020-06-07 02:57 AM
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);
}
2020-06-07 07:23 AM
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;
};
2020-06-07 07:25 AM
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