I'm writing using Google translate, sorry for my bad English.
I have an old product. The Atmega48-20au model was used to drive the IGBTs in the switching power supply section. Unfortunately spare parts and software are no longer available and I need to get this product working.
The circuit works with half bridge topology. The biggest problem here is that it operates at 125khz per IGBT. atmega48-88-328 has the same pin layout. I can program it with the minicore library via the Arduino ide. I'm not very good at Arduino, but even though I tried for a few days, I couldn't get an output above 31khz from Arduino pins 9 and 10. I'm trying to code with Arduino Uno and Rigol oscilloscope. SMPS will operate at 31khz level, but the power and efficiency loss will be too high.
I found GyverPWM library for high pwm output. The person who prepared the library is Russian and all the resources are in Russian, which I did not understand because I do not have much experience.
With this code I get a useful signal at 31khz. This is an original code. I do not use the A0 analogread command. There is no voltage measurement in my circuit. It works with a fixed duty cycle of 48%.
But I need to get at least 100khz. The design power of SMPS is around 700w.
I would be grateful if you could help me.
I am adding an example schema
int Output_PWM = 0;
int DT = 10; // Set Dead Time
int Voutput = 0;
int inductor = 0;
int SetPoint = 500; // 500 = 15V @ Voltage output
void setup()
{
pinMode(10, OUTPUT); // PWM Signal Lo Side
pinMode(9, OUTPUT); // PWM Signal High Side
pinMode(13, OUTPUT); // LED Signal OK System RUN
Serial.begin(9600);
TCCR1A = 0b11100001; //Set Record Phase Correct PWM
TCCR1B = 0b00000001; //set Fsw = 31.372 kHz
delay(1000);
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
}
void loop()
{
Output_PWM = analogRead(A0);
Iinductor = analogRead(A1); // Read ADC A1 for inductor
Output_PWM = 255-(Output_PWM/8);
if (Output_PWM<5){Output_PWM=10;}
if (Output_PWM>250){Output_PWM=255;}
OCR1A = Output_PWM; //PIN D11
OCR1B = (Output_PWM-DT); //PIN D3
delay(50);
}
2 days ago I found out that I can get 62 khz PWM on Arduino. But what really worries me is that I see 125khz PWM when I measure with the oscilloscope from the working device.
When I used gyverpwm, I couldn't figure out how to change the phase of one of the PWMs.
While the 1st pwm is high, the 2nd pwm should be low
While the 1st pwm is low, the 2nd pwm should be high
there should never be two high and two low
The library actually is very simple.
Its documentation has not been translated into English, but this documentation is not needed there.
See examples.
Here is an example of setting 150 KHZ PWM frequency on pins 9 and 10. I have translated some comments into English:
#include <GyverPWM.h>
void setup() {
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
// only pins D3, D5, D9 & D10 available on ATmega328
// run PWM on D9 with freq 150'000 Hz, FAST_PWM mode
PWM_frequency(9, 150000, FAST_PWM);
// run PWM on D10 with freq 150'000 Hz, FAST_PWM mode
PWM_frequency(10, 150000, FAST_PWM);
// pins 9 & 10 can use the same PWM frequencies only!
}
void loop() {
// PWM duty should be always set in range 0-255 regardless to actual PWM resolution
PWM_set(9, 25); // duty 10%
PWM_set(10, 255 -25); // duty 90%
}
I looked at all the topics related to PWM yesterday and I missed this topic. I will review the codes and try it tomorrow.
Actually, what I want is two synchronous square waves. For example, two signals will operate with 48% duty cycle and there will be 2% dead time between them.
If a PWM is 90%, the IGBT connected here will have great difficulty and will fail.
But even if you correct the delay value, with this code you will never get more than a couple of kilohertz frequency because the digitalWrite() function is too slow for it.
Use hardware timers as we discussed above - this is the only way for you.
With the code below, 42% duty cycle operates at 125 kHz.
I am thinking of stopping it with the following code in case of any error.
void stopPWM() {
TCCR1A = 0; //Reset Timer1 control registers
TCCR1B = 0; //Reset Timer1 control registers
All I want to do now is to create a soft start for pmw.
For example, I want the duty cycle to start with 20% at the first run and reach 42% duty cycle in 500ms and remain constant.
void setup() {
pinMode(9, OUTPUT); //output A
pinMode(10, OUTPUT); //output B
TCCR1A = 0; //clear timer registers
TCCR1B = 0;
TCNT1 = 0;
TCCR1B |= _BV(CS10); //no prescaler
ICR1 = 64;//PWM mode counts up and back down for 80 counts
OCR1A = 37; //Pin 9 match
//output A set rising/clear falling
TCCR1A |= _BV(COM1A1) | _BV(COM1A0); //output A set rising/clear falling
OCR1B = 27; //Pin 10 match
TCCR1A |= _BV(COM1B1); //output B clear rising/set falling
}
void loop() {
TCCR1B |= _BV(WGM13); //PWM mode with ICR1 Mode 10
TCCR1A |= _BV(WGM11); //WGM13:WGM10 set 1010
}