I modified a PWM library, link to download below:
Example sketch supports phase shift between Timer 1 and Timer 3.
/*
Test sketch for arduino PWM library - modified version.
CLI - command line interface:
d - debug, shift phase on regular time base interval, demo mode.
f - set frequency, "f100" - 100 Hz.
l - set duty cycle, "l2000".
p - set phase, "p90".
Direct Registers Manipulation:
1. "a80" - set address
2. "w10111" - write data, leading 0 could be ommited.
3. "r" - read current registers.
NOTE: Use direct registers programming VERY Carefully !!!
created 16 June. 2017
Anatoly Kuzmenko
anatolyk69@gmail.com
This example code is in the public domain.
Works for Timer 1 & 3 so far:
Pin 11 12 timer1
Pin 2 3 5 timer3
Timer-1 is primery clock generator, Timer-3 secondary, phase shifted clock.
*/
#include <PWM.h>
String in_String = "";
boolean end_input = false;
uint8_t adres_reg = 0;
uint8_t debug_osm = 0;
uint8_t prime_pin = 11;
uint8_t secon_pin = 2;
uint16_t level_pwm = 32767; // 1 -/- 65535
uint16_t phase_pwm = 90; // degree 1 -/- 360
uint32_t freqn_pwm = 35; // frequency in Hz
unsigned long previousMillis = 0;
const long interval = 500;
void setup()
{
Serial.begin(115200);
in_String.reserve(200);
InitTimersSafe();
}
void loop()
{
int32_t tempr = 0;
char * pEnd;
if(debug_osm) {
uint32_t currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
phaseShift();
}
}
serialEvent();
if( end_input) {
char cmd = in_String[0];
in_String[0] = '+';
if( cmd == 'd' ) {
debug_osm = 1 - debug_osm;
if(debug_osm) Serial.print(F("\nDebug aktiv."));
else Serial.print(F("\nDebug de-aktiv."));
}
if( cmd == 'f' ) {
tempr = strtol( in_String.c_str(), &pEnd, 10);
Serial.print(F("\n\tFreq: "));
Serial.print(tempr, DEC);
freqn_pwm = tempr;
bool success1 = SetPinFrequencySafe(prime_pin, freqn_pwm);
bool success2 = SetPinFrequencySafe(secon_pin, freqn_pwm);
GTCCR |= ((1<<TSM)|(1<<PSRASY)|(1<<PSRSYNC));
GTCCR &= ~(1<<TSM);
if(success1 && success2) {
pwmWriteHR(prime_pin, level_pwm);
pwmWriteHR(secon_pin, level_pwm);
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
}
}
if( cmd == 'l' ) {
tempr = strtol( in_String.c_str(), &pEnd, 10);
Serial.print(F("\n\tLevel: "));
Serial.print(tempr, DEC);
level_pwm = tempr;
pwmWriteHR(prime_pin, level_pwm);
pwmWriteHR(secon_pin, level_pwm);
}
if( cmd == 'p' ) {
tempr = strtol( in_String.c_str(), &pEnd, 10);
Serial.print(F("\n\tPhase: "));
Serial.print(tempr, DEC);
phase_pwm = tempr;
//GTCCR |= ((1<<TSM)|(1<<PSRASY)|(1<<PSRSYNC));
GTCCR |= (1<<TSM);
tempr = ICR3 * (phase_pwm /360.0) -1;
if(tempr < 0) tempr = 0;
TCNT1 = 0;
TCNT3 = tempr;
GTCCR &= ~(1<<TSM);
}
if( cmd == 'a' ) {
adres_reg = strtol( in_String.c_str(), &pEnd, 16);
Serial.print(F("\n\tReg: "));
Serial.print(adres_reg, HEX);
Serial.print(F("\tvalue: "));
tempr = (*(uint8_t*)adres_reg);
Serial.print(tempr, BIN);
}
if( cmd == 'r' ) {
Serial.print(F("\n\tReg: "));
Serial.print(adres_reg, HEX);
Serial.print(F("\tvalue: "));
tempr = (*(uint8_t*)adres_reg);
Serial.print(tempr, BIN);
}
if( cmd == 'w' ) {
Serial.print(F("\n\tReg: "));
Serial.print(adres_reg, HEX);
Serial.print(F("\tvalue: "));
tempr = (*(uint8_t*)adres_reg);
Serial.print(tempr, BIN);
tempr = strtol( in_String.c_str(), &pEnd, 2);
(*(uint8_t*)adres_reg) = tempr;
Serial.print(F("\tnew value: "));
tempr = (*(uint8_t*)adres_reg);
Serial.print( tempr, BIN);
}
in_String = "";
end_input= false;
}
}
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
in_String += inChar;
if (inChar == '\n') {
end_input= true;
}
}
}
void phaseShift() {
static uint16_t phase_loc = 0;
uint16_t tempr = 0;
//GTCCR |= ((1<<TSM)|(1<<PSRASY)|(1<<PSRSYNC));
GTCCR |= (1<<TSM);
// GTCCR |= _BV (TSM);
tempr = ICR3 * (phase_loc /360.0) -1;
if(tempr < 0) tempr = 0;
TCNT1 = 0;
TCNT3 = tempr;
GTCCR &= ~(1<<TSM);
// GTCCR &= ~(_BV (TSM));
phase_loc += 30;
if(phase_loc > 360) phase_loc = 0;
}
Have fun.
PWM.zip (15.3 KB)