I have a a single slope PWM signal suitable for driving a servo.
I can get output on WO2 (PB2) but the frequency is a bit off.
The data sheet defines the frequency as:
Fpwm = Fclk_per/(Scalar * (PER +1))
With a tuned (I had to tune the device using MegaTinyTuner [MegaTinyTuner](megaTinyCore/megaavr/extras/Ref_Tuning.md at master · SpenceKonde/megaTinyCore · GitHub to get serial debug to work at the correct baud - I was using my scope’s 1KHz reference output for the timing source) 20MHz device, a per-scaler of 8 and 50Hz as my PWM frequency.
Rearrange this and you get:
((20000000 / (50 * 8)) -1 = 49999
However using my scope this generated a frequency of 49Hz
I had to use a PER value of 48900 to get a measured frequency of 50Hz
Are you able to explain what I got wrong?
Please see the code snippet that sets the PWM signal going…
void PWM_0_TCA0_init(){
takeOverTCA0(); // millis() is using TCB0
PORTMUX_CTRLC |= PORTMUX_TCA02_DEFAULT_gc; // Use default pin (the alt pin is physically unavailable)
// from the data sheet the single slope PWM signal frequency is defined as below:
// Fpwm = Fclk_per/(Scalar 8 (PER +1))
// PER = (Fclk_per/(Fpwm * Scalar)) - 1
// ((20000000 / (50 * 8)) -1 = 49999
// TCA0_SINGLE_PER = 49999; // sets 49Hz signal
TCA0_SINGLE_PER = 48900; // sets 50Hz signal
TCA0_SINGLE_CTRLA = TCA_SINGLE_CLKSEL_DIV8_gc; //Select division factor (1,2,4,8,16,64,256,1024) but not enabled
TCA0_SINGLE_CTRLA |= TCA_SINGLE_ENABLE_bm; // Enable when servo is started
TCA0_SINGLE_INTCTRL = TCA_SINGLE_OVF_bm; // Overflow Interrupt Enable: enabled - I want to count PWM pulses
TCA0_SINGLE_CTRLB = TCA_SINGLE_WGMODE_SINGLESLOPE_gc; // select waveform generation mode - fast PWM for servo control on WO2
TCA0_SINGLE_CTRLB |= TCA_SINGLE_CMP2EN_bm; // enable output on WO2 when servo is started
TCA0_SINGLE_CMP2BUF = TCA0_CMP_Lock; // signal to drive the servo into lock position
}
And for good measure, my platformio.ini
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:ATtiny1604]
platform = atmelmegaavr
board = ATtiny1604
framework = arduino
build_unflags = -DMILLIS_USE_TIMERA0 ; stop megaTinyCore using TCA0
build_flags = -DMILLIS_USE_TIMERB0 ; have it use TIMERB0
board_build.f_cpu = 20000000L
; upload_speed = 115200
upload_speed = 230400 ; seems to work for me
upload_port = /dev/ttyUSB0
monitor_port = /dev/ttyUSB1
monitor_speed = 115200
monitor_filters = send_on_enter ; to mimic Arduino serial monitor
monitor_echo = true ; so I may see commands typed in
upload_flags =
--tool
uart
--device
ATtiny1604
--uart
$UPLOAD_PORT
--clk
$UPLOAD_SPEED
upload_command = pymcuprog write --erase $UPLOAD_FLAGS --filename $SOURCE