ATmega4808 TCA PWM signals in split mode

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

Hi,

Currently I'm making a driver to run a buzzer, directly from the pin of the ATmega4808.

 

I'm having a problem setting up the output of the pwm signal of the timer TCA in the buzzer pin, I can not make the signal appear in the buzzer pin, my code right now is the following:

 

#define F_CPU 20000000UL

#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <util/delay.h>

/******************************************************************************
 * Functions                                                                  *
 ******************************************************************************/
 void setup()
{
		// By default the 20MHz clock is selected

		CPU_CCP = CCP_IOREG_gc;
		// Disable Prescaler
		CLKCTRL_MCLKCTRLB = ~CLKCTRL_PEN_bm;

		while(CLKCTRL_MCLKSTATUS & CLKCTRL_SOSC_bm);

		PORTA.DIRSET = PIN4_bm; // BUzzer

		// TCA0 Init
		PORTMUX.TCAROUTEA = PORTMUX_TCA0_PORTA_gc; 			// Set waveform output on PORT A

		TCA0.SPLIT.CTRLD  = TCA_SPLIT_SPLITM_bm;    		// Enable split mode

		TCA0.SPLIT.CTRLB  = TCA_SPLIT_HCMP1EN_bm;			// Enable compare channel PIN(1 + 3) = PA4

		TCA0.SPLIT.HPER  = 0X4D;
		TCA0.SPLIT.HCMP0 = 0X26;

		TCA0.SPLIT.CTRLA = TCA_SPLIT_CLKSEL_DIV64_gc       // Set clock source (sys_clk/64)
						 | TCA_SPLIT_ENABLE_bm;             // Start timer 

}

int main()
{
	setup();

	while(1)
	{

	}
}

 

I allready checked the pinout and all the connections of my layout and did not found nothing wrong, below is part of the connections:

 

The buzzer that I am using is the following, https://pt.mouser.com/ProductDetail/TDK/PS1240P02BT?qs=sGAEpiMZZMsK322k1rNFfYfXmCWsjkB8iQfg2vl062k%3D

 

And I am sure that my hardware its currect because I managed to put the buzzer working in 2 ways;

 

1º - I set up the pwm signal to be in the pin PA3, the LED_RED pin, by changing the following bits (PORTA.DIRSET = PIN3_bm; and TCA0.SPLIT.CTRLB = TCA_SPLIT_HCMP0EN_bm;), there I could see the signal with the osciloscope and by accident
I shorted the output of this pin (LED_RED) with the output of the buzzer pin (BUZZER) that made buzzer work.

 

2º - I disable the TCA pwm and in the while(1) in the main fuction I made the pin of the buzzer toggle its state with a delay of 250 microseconds and the buzzer worked.

 

So in short, I can put the PWM in the LED_RED pin, but if I try to put it on the buzzer it does not work, the signal just not appear at all.

 

I would apprecieate your help.

 

Regards,
Garcia.

 

This topic has a solution.
Last Edited: Mon. Sep 9, 2019 - 03:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Gonçalo Garcia wrote:

		CPU_CCP = CCP_IOREG_gc;
		// Disable Prescaler
		CLKCTRL_MCLKCTRLB = ~CLKCTRL_PEN_bm;

Just to note that this kind of thing is far better done using the _PROTECTED_WRITE() macro in xmega.h ! (in plain C you can't guarantee the timing).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Well, I havent went deep inside your code. BUT..

 

Buzzer has two pins, you have two ways to run it either by putting one pin to GND and other to GPIO or by connecting both pins to GPIO's depending on how strong the sound you like to have...in each case you need a resistor in series.

 

First one: The main idea is that you are turning ON/OFF the pin either by PWM or by a loop....

second one: you are turning ON one pin and swithching and vice versa...ofcurse by PWM or a loop.

 

If you have done one of those two methods...theoritically your Buzzer should work.]

 

Regards,

Moe

 

 

EDIT: second one, one pin ON the other while other is off (e.g. 100us or 1ms) and then the opposite for the other pin.

Last Edited: Mon. Sep 9, 2019 - 02:50 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I found the issue!

The problem was that I was not setting the value of the comparator for the right pin.

I was setting everything for the PA4 pin, but the value of the comparator for this pin, that sets the duty cycle I was doing it wrong.

 

In short this register 

		TCA0.SPLIT.HCMP0 = 0X26;

should be change to 

 

		TCA0.SPLIT.HCMP1 = 0X26;

because it works as the same as the 

TCA0.SPLIT.CTRLB  = TCA_SPLIT_HCMP1EN_bm;

where the HCMPn, is PA(n + 3),

so if you want to set the PA3 as PWM you have to put it like this:

        TCA0.SPLIT.CTRLB = TCA_SPLIT_HCMP0EN_bm;	// Enable compare channel    of PIN(0 + 3) = PA3
	TCA0.SPLIT.HCMP0 = 0X26;              	        // Set compare channel value of PIN(0 + 3) = PA3 

and for the PA4 is similar

        TCA0.SPLIT.CTRLB = TCA_SPLIT_HCMP1EN_bm;	// Enable compare channel    of PIN(1 + 3) = PA4
        TCA0.SPLIT.HCMP1 = 0X26;              	        // Set compare channel value of PIN(1 + 3) = PA4

 

Thanks for the help any way.