Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 3

Logic Power

The MCU runs on 3.3V which is derived from 5V DC. VDDA is the same as VDD.

System Clock
54 MHZ using the internal 16 MHz RC oscillator (HSI) and PLL as SYSCLK. The ADC clock is set to half of SYSCLK (27
MHz) to give a conversion time of 0.519 microseconds at the fastest (14 cycles).

Interrupts
The system uses only xx interrupts, one every 138.9 (or 46.3 for 21.6 kHz inverter frequency) microsecond for driving
inverter/ charger PWM period and the other for keeping time to manage tasks and delays between events.

1. DMA1CH1 (ADC data) conversion complete event


2. SysTick interrupt every millisecond
3. DCH interrupt (PC15)
4. CLMT interrupt (PA6)
5. RP interrupt (PB5 - chint)

PWM Generation and Timers

TIM1       PWM on CH1, CH1N, CH2 & CH2N; CH3N SLOPE compensation; CH4CC for start ADC trigger
TIM3       CH1 CLMT; CH2 RP (reverse phase current limit)
TIM14     CH1 clear comparator during charging phase
TIM16     CH1 current limit (even multiple of inverter frequency & greater than 100 KHz)
TIM17     CH1 Buzzer

A dual frequency system will be implemented (7.2 kHz and 21.6 kHz) for reducing audio noise for home consumers. We
generate 144 points sinewave. TIM1 will be used for generation of PWM (and its complementary output with dead band).
TIM1 is set to run at SYS_CLK/3 (pre-scaler of two, 18 MHz) for 7.2 kHz or at SYS_CLK (54 MHz, pre-scaler of zero) and
centre-aligned up/down mode (PWM Mode 1) is used. TIM1->ARR is set to 1249 to get desired PWM on CH1 & CH2 and
its inverse on CH1N & CH2N. Using the sin table of 144 values, TIM1-> CRRx is calculated in the ISR. As 21.6 kHz will
require 3 times 144 values, the CRR for 21.6 kHz mode will be changed for every 3 PWM periods of 46.3 microseconds
each.

TIM1CH4 (it has the capability to trigger ADC directly) is used to start the ADC every cycle roughly at 2.5 microseconds
before the middle of the PWM pulse or just after the pulse if the pulse width is narrower than 5 microseconds.

CCR4=1114, if CRR < 1100 otherwise 2500-CRR

As the ADC can at most scan 8 channels (in more flexible mode that we will use) in one go, we will have 4 values each of
generated voltage and load current in the middle of PWM pulse triggered by CCR4 (or after the pulse if pulse is narrower
than 5 microseconds). In the corresponding interrupt service routine, we load up to 8 more scan channels on the ADC and
start ADC by software (set ADSTART bit) after copying the samples to other variables and disabling interrupt flag for
DMA1CH1. In about 5 microsecond, the remaining channels will get scanned. The interrupt flag will be enabled
immediately in 7.2 kHz mode and after two more interrupts in 21.6 kHz mode.

Dead time insertion between OCx & OCxN is managed using PWM feature of TIM1. We need approx. 1.5 microsecond
dead band between complementary outputs and it is achieved by loading appropriate multiplier (81 or 27) to 18.5 or 55.6
nanosecond clock periods (corresponds to 54 MHz or 18 MHz clock to TIM1).

The output voltage of phases is controlled by varying CRR (of TIM1CH1 in half cycle and TIM1CH2) in a sinusoidal
fashion. During the time one channel output sinusoidal PWM, the other channel will be off and CHxN on for whole
duration. A sine table of 144 values (multiplied by 1250 and reduced to 16 bit integer) is used as CRR value for open loop
operation. A modulation factor between 0 and 1000 (1000 corresponds to 1) is calculated by PI control and is multiplied with
the table value (and divided by 1000) for closed loop control of voltage. A value of 1250 is added to this to level shift the
voltage generated.

We need two digital to analog signals that will be implemented using PWM outputs:

TIM1CH3N (running at 7.2 or 21.6 kHz) for slope compensation. The voltage output will be 3.3*CCR3/1250.
TIM16CH1 (running at 216 kHz, up counter) for current limit. The voltage output will be 3.3*CCR1/250.

Two routines will be provided to set a value for the DAC outputs: setSlope (uint16_t val) and setCI (uint8_t val). Parameter
val should be between 0..1249 for setSlope and 0..250 for setCI. The output will be (3.3*val/1023) V.

TIM17CH1 is used for buzzer to generate musical notes using PWM. The frequency is calculated based on the note being
played.
SysTick is used for time management (specifically task manager). An interrupt is generated every millisecond. The interrupt
service routine increments a global variable milliFromStart to keep the time in milliseconds. It is used by task manager to
schedule tasks in the while (1) loop. At a lot of places it is also used to calculate the time difference between two events.

****NEED TO ADD INPUT/CAPTURE TIMER CHANNELS****

When true over-current is sensed, a disable PWM signal is generated and for the remaining cycle no current flows using
BRK signal. PWM is programmed in such a way that the next cycle starts afresh with PWM enabled (using specific STM32
feature). This results in limiting the current. But if this condition persists for some cycles (count specified in EEPROM)
continuously, system is shut down indicating overload error. After waiting for some time (specified in EEPROM), the
system is restarted assuming the overload condition may have changed.

Sensing and ADC


System has 7 analog signals to read. Two of these are multiplexed to be used as digital output pins too. When digi is high,
the data read from these pins should be considered as valid else should be thrown away.

The most important signals are generated voltage (vOut) and load current (iOut). These are used for control as well as other
actions. These are to be sampled precisely at the middle of the PWM pulse. To improve the signal, we will read these values
4 times each. The first value of the signals is likely to have switching noise so we discard and then we take median of the
next three values to reduce random noise.

The remaining 5 signals will be read only once in a cycle.

ADC clock has been set to half the SYSCLK (27 MHz) to keep the calculations simpler though the maximum ADC clock
allowed is higher. This gives a scan & conversion time of 0.52 microseconds at the fastest (1.5+12.5 cycles). Some signals
may require slower sampling time and time will appropriately be higher than 0.52 second.

Sensing logic uses two scans (8+5) continuous mode and converted values are automatically stored in memory using DMA.
We will be taking 144 samples per cycle of AC waveform generated (20 ms). This implies that we get one set of samples
every 138.9 micro sec (approx.) from DMA in memory.

These variables are scanned in the following sequence-

First scan: vOut, vOut, iOut, iOut, iOut, iOut, vIn, vIn
Second scan: vDC, vDC, rMain, temp, temp2

The second scan is started in ISR for DMACH1 interrupt. And we will only consider temp and temp2 in case digi is low for
at least one cycle.

Raw data of scanned channels is available in an array int16_t samples[8] when interrupt service routine is invoked. The data
is moved to internal instantaneous value variables after some processing. As the ADC may have 1.5 bits of error, last two
bits are made zero. vOut and iOut have 4 values each. Median of the last 3 values is taken for further use. All voltages are
kept multiplied by 16 and currents multiplied by 128 after subtracting offset error of the channel so that required precision
can be maintained. Finally this value is divided by the gain error of the channel. A 220 v reading will be stored as 3520
while 1.1 ampere current will be stored as 141.

Most ADC inputs will have an attenuator/ amplifier (with an optional level shifter) to bring the input to the desired 0-3.3 V
range (As VREF is set to 3.3 V).

***Abhinav Sharma: add a range table for different signals ***

The interrupt service routine calculates partial sums for v*i, v*v, i*i etc.

Pseudo-code of ISR
//subPulse keeps the pulse number: 0..2 for 21.6 kHz/ it is always zero for 7.2 kHz
//j (0..143) keeps track of sine value to be used
//pulse 0 do nothing; pulse 1 collect data; pulse 2 load CRR
//j = 143 end of 20 millisecond cycle

jshadow = j // save j
if 7.2 kHz {
j += 1
}
else {
subPulse += 1
if subPulse > 2 {
subPulse = 0
j += 1
}
}
if j > 143 j = 0
if subPulse == 1 return
If 21.6 kHz and (subPulse == 0) and (j != 0) {
loadCRR(jshadow)
return
}
Load channel numbers for non-vout and non-iout channels in ADC
Disable interrupt for DMA-ADC after loading DMA address for samples2[8]
Start ADC to scan the remaining channels

Process vout and iout (mask, median, offset, gain, calculate partial sums of v*v,
i*i, i*v etc)
***data must have been scanned by now at least 5 microseconds after ADSTART***

Clear data ready flag DMA-ADC so that interrupt does not occur when it is enabled
Load channel numbers for vout and iout back
Loading DMA address for samples1[8]
Enable interrupt for DMA-ADC

Process other scanned channels (mask, offset, gain, calculate partial sums of temp,
temp2, vDc etc) based on digi

ff (j == 0 and subPulse != 2) {
calculate averages and RMS values
call piloop to update ‘a’
}
loadCRR(jshadow)

You might also like