Embedded Systems and Power Electronics

Total Pageviews

About Me

My photo
I am currently a PhD student at UC Berkeley, following a 6-year journey working at Apple after my undergrad years at Cornell University. I am a 2025 Paul & Daisy Soros fellow. I grew up in Dhaka, Bangladesh where my interest in electronics was cultivated, resulting in the creation of this blog.

BTemplates.com

Powered by Blogger.

Nov 10, 2023

SmartSinePy, and an example of GUI development with PySide6


Source code at: https://github.com/SyedTahmidMahbub/SmartSinePy

Quite a very long time ago, I had posted a Windows tool called Smart Sine to generate a sine table. See: https://tahmidmc.blogspot.com/2012/10/smart-sine-software-to-generate-sine.html

This was very useful for pre-generating the sine-table instead of in the main program itself, often useful to save space (and not have to perform trig operations) especially on 8-bit microcontrollers.

I was recently looking into developing quick GUIs for some test bench automation and was primarily looking for something where I could position and size GUI elements visually (a WYSIWYG editor, basically) and decided to dig into QT Designer and PySide6. I don't mind defining properties and event handlers programmatically (in fact I do prefer it) but what I really don't want to do is have to add every GUI element in code and define its location and size - this is where the QT Designer's visual editing really comes in helpful! Reminds me a lot of the Visual Studio GUI editor back in Visual Basic development days.

This provided a good opportunity to redo Smart Sine and have an example project for developing the GUI application. A few aspects explored on the GUI side of things:

  • Creating the layout in QT Designer
  • Getting inputs from a table
  • Working with GUI widget signals (events such as button pressed or slider value changed)
  • Updating text in labels and a text browser (textbox)
  • Generating a plot with matplotlib and embedded it on the GUI
This is a great reference for embedding matplotlib: https://david.roesel.cz/notes/posts/matplotlib-figure-embedded-in-qt/
Particularly about temporarily adding a text box within the widget to specify the layout.

For this particular project, I read in the .ui file (that QT Designer generates) straight in the main code without an intermediate conversion.

Here is a snapshot from QT Designer:

Here are a couple snapshots of the application running:
There are a fair few Python dependencies that you will have to install. A one-line command for installing them is:
python3 -m pip install pyside6 numpy pyperclip matplotlib

If there's interest in packaging this up into an executable, let me know!

The code is commented and should be self-explanatory. But if there are specific questions or anything that is unclear, let me know and I can clear it up!

Nov 3, 2023

Modified Sine Wave Inverter: Harmonic Elimination


In inverter designs, we see the concept of a modified (or quasi) sine wave inverter - "better" than a square wave but still very easy to implement by adding a deadtime. By adjusting the duty cycle of the square wave, the output RMS value can be adjusted - and this is often used in inverters for feedback regulation.

One concept that is tied to how a modified sine wave output is better than a square wave has to do with harmonic elimination.

To start off with, let's remind ourselves that a square wave is composed of an infinite number of sine waves at odd multiples of the wave's frequency. Here is a great reference for this: Fourier Series--Square Wave -- from Wolfram MathWorld

Now, if we consider the modified sine wave, what happens to the harmonic contents?


We can solve for the nth harmonic (where n=1, 3, 5, 7, ...) which gives a Fourier coefficient of:

Why is this interesting? Can we fix the duty cycle so that we eliminate certain harmonics? Yes! We can make the cos term go to zero by picking nδ = π/2 = 90°. We could then pick δ = 30° and eliminate the 3rd harmonic! Or we could pick δ = 18° and eliminate the 5th harmonic. If we had to pick just one, it would then make sense to eliminate the 3rd harmonic which has a higher Fourier coefficient than the 5th! This will contribute to a better THD (total harmonic distortion).

We can of course time shift this waveform and retain the same benefits - this would then correspond to a standard (edge-aligned) PWM. If we are using a full-bridge to generate this waveform, this would correspond to a duty cycle (for each pair of diagonal switches) of (180°-30°-30°)/360° = 33.33%. The off time would, of course, reduce the output RMS voltage compared to a square wave, so you would have to keep that in mind!

What about multiple harmonic eliminations? We can come up with a scheme where we add multiple notches and eliminate multiple harmonics. And, in fact, this is what SPWM achieves by forming these notches in a "sinusoidally optimal" fashion and eliminating several lower order harmonics. I have several articles where I have discussed SPWM (such as Generation and Implementation of Sine Wave Table) albeit not in the context of harmonic elimination.

Can we do this in one-stage inverters like with an iron core? No. Unfortunately, in these one-stage inverters, the output voltage regulation is obtained by altering the duty cycle and so you can't have a fixed δ and optimize for a particular harmonic elimination.

Can we do this with two-stage inverters such as ones where the input voltage is first stepped up with a ferrite transformer at high frequencies followed by an H-bridge to generate the output? Yes - if we use feedback to control the output of the first stage, we can use this constant δ on the output of the second stage.

Aug 13, 2023

2023 Updates: PhD; Pi Pico


It's 2023 and I'm back to keep the blog going! Lots have changed in my life in the past 6 years since I last posted on the blog.

PhD

After a six-year stint working as a hardware engineer at Apple, I am excited to now be pursuing my PhD in Electrical Engineering, focused on Power Electronics, at UC Berkeley. I start working with Professor Robert Pilawa-Podgurski this week! I anticipate more posts centered around power electronics in the future.

Why did I want to go back to school in a PhD program? There are 3 key aspects to this:

  1. Technical depth. With the recent rapid advances enabled by wide bandgap semiconductors, the recent explosion in adoption of EVs and an expansion in the number of research labs in academia, now is an exciting time for power electronics.
  2. Positive contributions to climate crisis solutions. Growing up in Bangladesh, I witnessed firsthand the devastating impact of natural disasters that continue to be exacerbated by the climate crisis. Direct impacts of this are witnessed every year half-way across the world in California where I now live. I envision pursuing research opportunities to significantly reduce emissions in the transportation and energy sectors: the largest contributors to the climate crisis and fields that can be directly improved through power electronics.
  3. Education. This blog has been an early testament to my interest in sharing engineering information and knowledge. I would like to continue to do so, but also engage in a more formal manner through educational institutions, particularly with typically underserved institutions.

Pi Pico

In the short term, I am exploring the Raspberry Pi Pico (based on the RP2040 MCU) using MicroPython. Having the resources to support running MicroPython, in a super-cheap part, is an exciting opportunity for me to explore. The idea here is to use Python (very simple software bringup time) to do the software heavy lifting and leveraging on-board hardware for timing-sensitive/hardware applications.

Here is a great relevant podcast episode: The Amp Hour #529 – Embedded Hardware with the Raspberry Pi Team

Why Micropython? Listen to 11:30-12:30 in the linked podcast episode where the below qutoes are taken from.

Computing is just so cheap compared to what it has been historically. That then enables things that are maybe not super efficient, not super tight timing like Micropython but who cares at that point? A lot of people will come in and say things like 'in this benchmark, I found that MicroPython is 100x slower than C' but if your C code is 100x faster than you need, then it doesn't matter. You just write the code you need and you focus on the parts that add value to your project and then you move on to your next project.

Jun 15, 2017

A digital communication project using OFDM and 32-QAM


This past semester (my last one during my undergrad years!), I was enrolled in ECE4670 -- Intro to Digital Communication with Professor Aaron Wagner. The final project required constructing the encoder and decoder (in Matlab) to send data over an existing channel (Cornell’s commcloud server). The project was done in groups of 2 and I had worked with my friend Balazs Szegletes. It was a fun learning experience, and I wanted to share the details of the project here!

The communication channel is effectively a DAC that outputs the results of the encoder, X, a low-pass filter, and then an ADC that samples this and sends data, Y, to the decoder. The means for sending data to the channel involves writing the data to a wav file, which is then passed as an input parameter to a program called ccplay that is provided for the class. The program handles the DAC and ADC and saves the sampled output as another wav file. The goal is to be able to push data through the channel as quick as possible with few number of bit errors. The figure of merit is computed as:
FOM = (min(R, 300000)*(1-N/50000)10)/max(1,400*Po)
Where R is the data rate defined as (100,000/(L/44100)) where L is the length of the output of the encoder
N is the number of bit errors
Po is the average transmitted power

The channel properties can be modeled by the Toeplitz matrix H, such that:
Y = HX + Z, where Z is iid (independent, identically distributed) Gaussian noise. The commcloud server has two such channels, audio0 and audio1.

This builds on a previous lab, where orthogonal frequency division multiplexing (OFDM) is used with on/off keying to send data over the channel. This scheme achieved a data rate of about 14,000 bits per second with zero errors, resulting in a figure of merit of about 14,000. The high performance design utilizes orthogonal frequency division multiplexing (OFDM) and quadrature amplitude modulation (QAM) to achieve a figure of merit much higher than the previous lab.

The overall OFDM system block diagram is shown below (taken from Professor Wagner’s course’s Scribe notes):

The big gain in performance stems from the use of QAM, which allows encoding multiple bits per sample, in the complex plane. A modulation order (M) of 5 was selected for the design, ie 32-QAM. This was experimentally determined to be the optimal modulation order, which gives the highest data rate (R) before bit errors (N) start outweighing the benefits from a higher data rate.

The encoder encodes the incoming bit-stream into frequency components and then processes it as described below before sending out its time-domain signal over the channel.

The encoder accepts the input vector (of length 100,000) and encodes the vector using 32-QAM into 100,000/5 complex samples in a vector x. The encoder then separates x into 8 equal sized data blocks D1...D8 of length L1. The size of L1 is determined by modulation order M: L1=(100,000/(8*5)). Two training blocks, T1 and T2, each a vector consisting all 1’s and of length L1,  are inserted to create the following vector, x, of length 10L1.


Using a seed of 1, and Matlab’s rand function, a vector, p1, of pseudorandom phase angles (between 0 and 2 pi) is generated. These are used to create a vector p2 of phasors, where:
p2(i) = gamma*exp(1jp1(i)) for all i = indices of elements of p1,p2. The constant gamma sets the average power level.

The elements of this vector are then multiplied element-wise with the elements in vector x. This is to prevent the constructive addition of several frequency components in the time domain which would cause the time-domain signal to clip or saturate. 

Each block is then prepended by NZpre zero’s. NZpost zero’s are appended to each block. Let this vector be called X. X is then padded with 0 for DC and concatenated with X*. This ensures that the time domain signal is real-valued. The inverse DFT of this is taken to get the real-valued time domain signal. Each block is prepended with a cyclic prefix (length Kc) to make the (Toeplitz) channel transformation effectively look circulant. The encoder then outputs this vector.

The training blocks are inserted into the data vector so that it may be used at the decoder end for training of channel properties. Each element of a training block (in the frequency domain) has magnitude 1 and a phase theta_t. When this element goes through the channel, it is attenuated and incurs a phase shift and is presented to the decoder with magnitude gamma_c(attenuation of the channel) and phase (theat_t+theta_c) where theta_c is the phase added by the channel. Each frequency component has an associated attenuation and phase addition. Since the training block is the same length as any individual data block, there exists known training information about attenuation and phase for each frequency of interest in the system/encoding at the decoder end. The decoder is then able to use this block’s received data to cancel channel effects for the other blocks. However, it must be noted that the the attenuation and phase addition of the channel are not static and vary with time. Thus it is important not to let the training data be stale. This is the reason two training blocks are used, and also why they are inserted in the order they are, with respect to the data blocks.

It was observed that placing only one training block at the beginning of the data vector allows determining channel phase reasonably well for only a couple data blocks adjacent to it. Additionally, it was noted that decreasing the number of blocks also made the prediction worse. By placing the two training blocks as they are in the vector allows using a block to cancel channel effects for two adjacent data blocks. The phase variation from the training data to the two data blocks is small enough to allow sufficiently high figure of merit. The phase variation from D1 to D4 is illustrated below:
While the shift is somewhat significant, it is still possible to correctly decode the information. As can be imagined, too far from this and the bit error rate gets terrible.

At the decoder end, synchronization is performed to determine the start of the signal. This is done by thresholding the average power level over five samples. To recover the samples encoded in the frequency domain, the decoder reverses what the encoder did, firstly ignoring the cyclic prefix, performing a DFT, dropping the flipped conjugate second half of the vector and then dropping the zero-padding. Since gamma_c*exp(1j*theta_c) is known from the training block for each of the frequency levels, the samples in D1 to D4 are divided by gamma_c*exp(1j*theta_c) from T1 to cancel the channel effects. Similarly, D5 to D8 use the channel information from T2. Finally, the pseudo-random phases added at the encoder side are removed by dividing by each of the known phases element-wise. These phases are known since the random number generator had a fixed seed of 1. The individual data blocks are then demodulated (QAM) and concatenated to each other to form the 100,000 long bit vector. For modulating and demodulating using QAM, Matlab’s inbuilt functions qammod and qamdemod are used.

The following constants were determined to give the highest figure of merit:
NZpre = 110
NZpost = 1050
gamma =7.8 (chosen to meet the power constraint of 1/400)
Kc = 170

Experimentally, the figure of merit scores are about 44,000, and 56,000 for channels audio0 and audio1 respectively. The constants NZpre, NZpost, gamma, modulation order M, number of data blocks, number of training blocks, and placement of training block were all experimented with and the results presented here represent the best combination for the highest figure of merit. With only one training block, the phase drift was high enough to negate the benefits of higher data rate obtained from 32-QAM. However, adding a third training block was seen as a waste since it would minimally reduce the number of bit errors but would hurt the data rate appreciably. Using convolutional coding was considered but it was determined as not worth the effort given the performance obtained and the added complexity.

I expect to write another post soon to discuss some technical background behind OFDM, training and synchronization. Let me know what you think and if there's something else from the project you'd like me to cover in more detail!

Dec 16, 2016

PIC32 JTAG Loader / ICSP programmer


This past semester, I worked on an independent study/project where I explored the programming of the PIC32. I've provided the details in the following PDF document. The key takeaway I believe is:

"This document presents sufficient background information on the project, and implementation specific details. The most important contribution this makes is adding the experiences and a full implementation of the project. For even more detail and a thorough understanding, it is recommended that this report be read along with the reference documents mentioned in Section 4.1."

I plan on improving this, as well as exploring the option of programming other PICs this summer. A cursory look made me think that the PIC32 programming standard was more complicated than the PIC16's. I'll find out!

All the project code and settings can be found here. This includes the PIC32 project, as well as the MATLAB code for the programmer software
https://drive.google.com/open?id=0B4SoPFPRNziHeUhXQlZSRWxyeW8
Please let me know if you have any comments or feedback!

Feb 6, 2016

Creating my own TV Tuner IR remote with a PIC16F684



While I was home this winter, I saw that the remote for our TV tuner was damaged physically, causing the buttons to not function responsively. Some of them just didn't work. I saw this as an opportunity for a fun couple days' project to build a new remote controller for the tuner.

The TV tuner was manufactured by a brand name RealView and, as expected, I couldn't find much detail about it. Thus, I had to reverse engineer the remote. From my previous experience in working with IR remotes, I had a hunch that the IR was most likely modulated at ~38kHz or ~56kHz. For those of you who don't know how this works, I highly recommend going through this website: http://www.sbprojects.com/knowledge/ir/

Thus, I connected a 38kHz IR receiver I had at home (TSOP1738) to an oscilloscope in order to figure out what IR protocol is used by the remote. Upon pressing the 4 key on the remote, I saw the following waveform:

Fig. 1: Oscilloscope waveform capture of the received IR signal

Note that I inverted the signal on the oscilloscope since the IR receiver output is active-low.

I then compared the waveform to some of the common IR protocols, paying particular attention to the initial first high and low states. After going through SIRC, RC5, RC6 among others, I noticed that this matched the NEC protocol: http://www.sbprojects.com/knowledge/ir/nec.php

Fig. 2: Standard NEC IR protocol pulse train

Fig. 3: NEC IR protocol logic high and logic low signals

Using the waveform shown above, I found that ~address was not being sent, meaning that the extended NEC protocol was being used:

Fig. 4: Extended NEC IR protocol pulse train

From the waveform, I found that the address was 0xBD02. I then proceeded to make a simple decoder with a PIC16F877A since I had a development board with an IR sensor mounted on it. Using this, I found all the required commands for the different keys of the remote. I decided to exclude some of the keys that were never used (eg play, pause, stop, fast forward, rewind).
You can find this part of the project here:
https://drive.google.com/file/d/0B4SoPFPRNziHZjk2N3pNLVE5V1E/view?usp=sharing

This left me with the following keys and commands:


KeyCommand
09
10
21
32
43
54
65
76
87
98
UP18
DOWN19
RIGHT16
LEFT17
PREVIOUS CHANNEL13
-/--10
POWER20
MENU21
MUTE12

I then proceeded to write an IR transmitter using the PIC16F684 (using the MPLAB X IDE and XC8 compiler), following the timing information from the extended NEC protocol. In order to connect all the keys, I connected them in matrix keypad form.

In order to power the remote off 2xAA batteries, it is necessary to use sleep mode - otherwise the battery will be drained extremely quickly. So, in order to detect when a button is pressed, an interrupt is used. After the IR command is sent, the microcontroller goes to sleep. The interrupt wakes up the microcontroller when a button is pressed. Debouncing is achieved using simple software delays. When a button is held down, the NEC command repeat sequence is not sent. Instead, the remote relies on releasing the button and pressing it again.

To minimize leakage current through the input capacitor, I decided not to use an electrolytic capacitor. A red LED illuminates to confirm that a button has been pressed.

 Fig. 5: Schematic of IR remote design

Everything was put together, a PCB was designed and when tested with the TV tuner, everything worked as expected! I measured the sleep current with a portable DMM and it was read as 1.6μA! I'm not sure how accurate the DMM is at such low currents, so I wouldn't entirely trust this number - however, it does seem to be within spec for the PIC16F684.

Due to a lack of time, I had to put the remote together with electric tape! Here you can see pictures of the final design:

Fig. 6: Final IR remote, top

 Fig. 7: Final IR remote, bottom

I am back at college now, but I have been told that the same set of batteries are still working on the remote, and it is working perfectly fine!

You can find the MPLABX project, source code, schematic and pcb files all here:
https://drive.google.com/file/d/0B4SoPFPRNziHV2I1U1Bldm1OYUE/view?usp=sharing

Let me know what you think! If you have any questions, let me know in the comments section!