Last active
September 29, 2023 13:00
-
-
Save ollewelin/4afcf202a6ff267aa70e5b289724abc2 to your computer and use it in GitHub Desktop.
3-phase PWM with deadtime 31.25kHz Arduino UNO. 6 transistors PWM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//This is a code made to run 3-phase PWM drive stage with 6-transistors, in other words 3 half bridge transistors with an Arduino UNO | |
//This setup is made with User settings of DEAD TIME. So here the the dead time can be adjusted by user. const int dead_time = 10;//10 = 0.625 us | |
//The PWM work here with fix frequancy of 31.25kHz (Other settings may not work proper when use all 3 TIMERS, if you want more flexibilty use Arduino MEGA 2560 or some other plattform) | |
//Olle Welin [email protected] | |
// TL Transistor Low side of half bridge pair | |
// TH Transistor High side of half bridge pair | |
// PWM assignement at Arduino UNO is by following: | |
//~6 TL, PH0, TMR0, pwm_ph0 data value | |
//~5 TH, PH0, TMR0, pwm_ph0 data value | |
//~9 TL, PH1, TMR1, pwm_ph1 data value | |
//~10 TH, PH1, TMR1, pwm_ph1 data value | |
//~11 TL, PH2, TMR2, pwm_ph2 data value | |
//~3 TH, PH2, TMR2, pwm_ph2 data value | |
void setup() | |
{ | |
pinMode(3, INPUT); //PWM is set to input before PWM initialized to prevent start up short circuit | |
pinMode(5, INPUT); //PWM is set to input before PWM initialized to prevent start up short circuit | |
pinMode(6, INPUT); //PWM is set to input before PWM initialized to prevent start up short circuit | |
pinMode(9, INPUT); //PWM is set to input before PWM initialized to prevent start up short circuit | |
pinMode(10, INPUT); //PWM is set to input before PWM initialized to prevent start up short circuit | |
pinMode(11, INPUT); //PWM is set to input before PWM initialized to prevent start up short circuit | |
// start serial port at 9600 bps: | |
Serial.begin(9600); | |
while (!Serial) { | |
; // wait for serial port to connect. Needed for Leonardo only | |
} | |
} | |
const int dead_time = 10;//10 = 0.625 us | |
const int half_dead_time = dead_time / 2;// | |
int pwm_ph0=0; | |
int pwm_ph1=0; | |
int pwm_ph2=0; | |
void update_pwm(void) | |
{ | |
//Limit the pwm_phx so it take the dead time into account so it not will swap over when reach end limit of workable PWM range | |
if(pwm_ph0 > (255 - half_dead_time)) | |
{ | |
pwm_ph0 = (255 - half_dead_time); | |
} | |
if(pwm_ph1 > (255 - half_dead_time)) | |
{ | |
pwm_ph1 = (255 - half_dead_time); | |
} | |
if(pwm_ph2 > (255 - half_dead_time)) | |
{ | |
pwm_ph2 = (255 - half_dead_time); | |
} | |
if(pwm_ph0 < half_dead_time) | |
{ | |
pwm_ph0 = half_dead_time; | |
} | |
if(pwm_ph1 < half_dead_time) | |
{ | |
pwm_ph1 = half_dead_time; | |
} | |
if(pwm_ph2 < half_dead_time) | |
{ | |
pwm_ph2 = half_dead_time; | |
} | |
//All The PWM will run from 0xFF to 0x00 and up again to TOP 0xFF | |
//The OCRnx will automatic update when TCNTn is on TOP 0xFF by hardware | |
//Therefor it is sutible to change both OCRnx pair on a place where TCNT not update to ensure that the hardware automatic update NOT occur exact when only one of the two OCRnx have changed by this code | |
while(TCNT0 > 0x7F) | |
{ | |
} | |
//Now it's safe to update OCR0x pair (connect to same transistor pair) | |
OCR0A = (pwm_ph0 + half_dead_time);//~6 TL PH0 TMR0 | |
OCR0B = (pwm_ph0 - half_dead_time);//~5 TH PH0 TMR0 | |
while(TCNT1 > 0x7F) | |
{ | |
} | |
//Now it's safe to update OCR1x pair (connect to same transistor pair) | |
OCR1A = (pwm_ph1 + half_dead_time);//~9 TL PH1 TMR1 | |
OCR1B = (pwm_ph1 - half_dead_time);//~10 TH PH1 TMR1 | |
while(TCNT2 > 0x7F) | |
{ | |
} | |
//Now it's safe to update OCR2x pair (connect to same transistor pair) | |
OCR2A = (pwm_ph2 + half_dead_time);//~3 TH PH2 TMR2 | |
OCR2B = (pwm_ph2 - half_dead_time);//~11 TL PH2 TMR2 | |
} | |
void sync_pwm_timers(void) | |
{ | |
GTCCR = (GTCCR & 0xFF) | 0x81;// Set bit Bit 7 – TSM: Timer/Counter Synchronization Mode | |
//Writing the TSM bit to one activates the Timer/Counter Synchronization mode. In this mode, the value that is written | |
//to the PSRASY and PSRSYNC bits is kept, hence keeping the corresponding prescaler reset signals asserted. | |
//This ensures that the corresponding Timer/Counters are halted and can be configured to the same value without | |
//the risk of one of them advancing during configuration. When the TSM bit is written to zero, the PSRASY and | |
//PSRSYNC bits are cleared by hardware, and the Timer/Counters start counting simultaneously. | |
TCNT0 = 00;//Syncronize PWM timers | |
TCNT1 = 0x0000;//Syncronize PWM timers | |
TCNT2 = 0x00;//Syncronize PWM timers | |
GTCCR = (GTCCR & 0x7E);// Rest bit Bit 7 – TSM: Timer/Counter Synchronization Mode | |
} | |
void loop() | |
{ | |
TCCR1A = 0xE1;//PWM, Phase Correct 8-bit TOP at 0xFF | |
TCCR0A = 0xE1;//PWM, Phase Correct 8-bit TOP at 0xFF | |
TCCR2A = 0xE1;//PWM, Phase Correct 8-bit TOP at 0xFF | |
TCCR2B = 0x01;//clkI/O/1 (No prescaling) 31.25kHz PWM frequency | |
TCCR1B = 0x01;//clkI/O/1 (No prescaling) 31.25kHz PWM frequency | |
TCCR0B = 0x01;//clkI/O/1 (No prescaling) 31.25kHz PWM frequency | |
sync_pwm_timers(); | |
pwm_ph0=128;//128 = center. User PWM Range is value between (0 + half_dead_time) to (255 - half_dead_time) | |
pwm_ph1=128; | |
pwm_ph2=128; | |
update_pwm(); | |
pinMode(3, OUTPUT); //PWM output | |
pinMode(5, OUTPUT); //PWM output | |
pinMode(6, OUTPUT); //PWM output | |
pinMode(9, OUTPUT); //PWM output | |
pinMode(10, OUTPUT); //PWM output | |
pinMode(11, OUTPUT); //PWM output | |
Serial.println("This is a code made to run 3-phase PWM drive stage with 6-transistor"); | |
Serial.println("This setup is made with User settings of DEAD TIME. So here the the dead time can be adjusted by user. const int dead_time = 10;//10 = 0.625 us"); | |
while(1) | |
{ | |
pwm_ph0=128;// Center | |
pwm_ph1=128; | |
pwm_ph2=128; | |
update_pwm(); | |
delay(100000);//delay timer scale is screwd up by the new PWM TMR settings | |
pwm_ph0=10;// Test some other values | |
pwm_ph1=249;//Above value or below value 6 the update_pwm() function will automatic limit so the PWM not wrap over because of the dead_time | |
pwm_ph2=30;// | |
update_pwm(); | |
delay(100000); | |
} | |
} |
Hello, thank you for sharing this work. how can i set frequency for pwm in this code. frequency can be 300hz or 400hz.
I don't understand the first operation : (GTCCR & 0xFF)
at this line :
GTCCR = (GTCCR & 0xFF) | 0x81;
Since GTCCR
is a 8 bits registers, GTCCR & 0xFF
is the same as GTCCR
, am I wrong?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Wao, Iove this contribution. The code was expressly used