What is digital signal processing? Well, digital signal processing is a technique used to extract or modify data in a meaningful way within the digital realm. What exactly does that mean?
Let’s look at analog signal processing first. If you have a signal with low and high frequency components, and you’re only interested in the low frequency, then you can use an RC filter to get rid of the high frequency information. If that’s not enough, then you can use higher order filters, which typically require opamps. Analog signal processing is relatively straight forward: the circuit cleans up the signal so that whatever ultimately interprets the data doesn’t have to worry about filters.
But there are situations where analog signal processing isn’t viable:
You buy a sensor and it only has a digital interface. For example, a temperature sensor could output the measured temperature as 16 bit data sent over a SPI bus.
The PCB has already been designed, fabricated and assembled, and it’s too late to re-spin the board. Turns out the system had more noise than expected, so the filter that’s present on the board isn’t enough to get the job done.
There’s not enough room on the PCB to add a filter. A simple RC filter is tiny, but what if you want to have a 5th order filter? That would require multiple opamps as well as a bunch of resistors and capacitors. Also, what if opamps require ±12V, and you only have 5 volts available?
There are situations where the filter characteristic has to change on the fly. For example, a user may tell the system through a GUI what the cut-off frequency of a filter should be. How would you implement this in an analog filter?
The list above shows situations where digital signal processing would be useful. You can’t put an RC filter on a digital signal and expect it to clean up the data; you need something more complicated.
Digital signal processing, much like analog signal processing, is mostly about filters. The simplest possible filter you can have for a system is a moving average. If the filter length if 5, then the output of the filter is the average of the 5 most recent data readings. The longer the filter length, the greater the reduction in noise since averaging causes noise to cancel out. A drawback to a longer filter is slower response, though, since the newest data points tend to get swamped out by the older data points.
Another way to use averages in a filter is to take multiple samples and treat that as a single sample point. For example, take ten readings from a sensor, average the ten values, then just use the average in the algorithm. The key difference between this scheme and the previous moving average scheme is that you’ve changed your effective sampling rate; if you read data from the sensor 100 times a second, the software will only see it has 10 readings per second since it takes 10 samples to generate 1 piece of usable data. Meanwhile, for a moving average filter, 100 samples will yield 100 pieces of usable data. Signal processing involving multiple rates like this is called multirate signal processing.
Averaging is great for reducing noise and shaping signals in the time domain, but what if you’re trying to get rid of frequency components? How would you use digital signal processing to create a single pole low pass filter? Well, again, let’s see how an analog filter works.
An analog filter has an input, the filter, and the output. The output, y(t), can be calculated by convolving the filter’s impulse response, h(t), with the input signal, x(t). A filter’s impulse response is the filter’s output when the input is an infinitely short, infinitely large spike. Let’s take a look at a simple RC filter’s impulse response:
Derivative of RC filter’s step response
I used LTSpice to simulate an RC filter, and got the filter’s step response. Then, I took the derivative of this step response to calculate the function’s impulse response. I did this because, even in simulation, an impulse response is hard to create. As you can see, the filter’s impulse response is a decaying exponential; how quickly the waveform decays depends on the cutoff frequency, which is 20 kHz in this case.
So now we have the impulse response of an analog filter. How is this used in digital signal processing? Well, as it turns out, a digital filter can be very similar to an analog filter. In an analog filter, you have y(t) = x(t) * h(t). If you sample the input signal and digitize it, you’ll get x[n], which is a discrete signal. If you sample the impulse response of your filter, then you’ll get h[n]. Amazingly, filtering a digital signal is as simple as convolving x[n] and h[n]! So in the digital realm, you have y[n] = x[n] * h[n]. Make sure you’re sampling the impulse response at the same rate as the input signal.
Low pass filter impulse response
Low pass filter kernel
h[n] is called the filter kernel. Just like how an analog filter’s impulse response defines the filter, the filter kernel defines the digital filter. Note that the impulse response and the filter kernel have been normalized; the area under the curve of the impulse response and the sum of data points in the filter kernel are 1. This property is desirable if you want a DC gain of 1.
In our example, we have a system that samples the input at 3 MHz and the filter’s cutoff frequency is 20 kHz. To test the filter, let’s have the inputs be sinusoids that are equal to, one decade below and one decade above the cutoff frequency.
Input signals at 2 KHz, 20 kHz and 200 kHz
In the figure above, note the change in x-axis scale; all three signals are sampled at the same rate, but because the bottom graph is far more zoomed in than the others, it looks more discrete.
The filter kernel we’re using is for a single order low pass filter. Therefore, we would expect the 2 kHz signal to be unaffected by the filter, the 20 kHz to be -3dB of the original signal (around 71%), and the 200 kHz signal to be -20 dB (about 10%). And the results are…
Filtered signals
The amplitude of all three signals were 1 before the filter. Now, the amplitudes are 1, 0.708 and 0.1 for 2 kHz, 20 kHz and 200 kHz, respectively. We’ve implemented a purely digital filter! Without using an RC filter, we’ve successfully attenuated a high frequency signal without significantly affecting the lower frequencies. The filter also produces the phase shift that you’d expect from an analog low pass filter; note that the 20 KHz signal is out of phase with the 2 kHz signal (200 kHz is also out of phase, but its small amplitude makes it less noticeable).
Digital signal processing is a very powerful tool. The example above uses a filter kernel based off of an RC filter, but you can use more powerful filter kernels. For example, you can sample the impulse response of a 6th order Chebyshev filter and get the same performance as an analog filter. In addition, you can use filter kernels that don’t have any basis in analog filters, allowing you to create filters that work for your specific application.
Digital signal processing isn’t all roses, though. It has several drawbacks:
Since you don’t have a circuit that performs filtering, the microcontroller or microprocessor will have to do that. This means the code becomes more complex, you lose processor cycles, and the microprocessor consumes more power.
If you skimp out on analog filters, then you’ll usually find you have to sample at a much higher rate. This is because of the Nyquist theorem: the sampling rate of your system must be at least twice the highest frequency component in the signal. An analog filter can reduce the frequency range of the signal of interest, allowing you to sample at a lower rate. By increasing your sampling rate, you force more work onto the microprocessor, increasing overhead, power consumption, etc.
Converting an analog signal to a digital one will always result in the loss of data. Not only are you sampling, which results in data lost in terms of time, but you’re also quantizing the data, typically by an ADC. The infinite number of values the analog waveform can take has been reduced to 65535 by a 16 bit ADC. Granted, you have to sample the data even if you have an analog filter, but by using digital signal processing, you lose data earlier in the signal chain which might be detrimental to the system.
The main drawback to the filter I’ve shown here is the computationally intense nature of convolution. If the kernel is a thousand samples long, then convolution requires at least 1000 multiplications and 999 additions to produce a single output sample, which will then needed to be repeated each time you want a new output sample. A shortcut around this is taking the FFT of x[n] and h[n], multiplying the results together, and then performing the IFFT to get y[n], but that’s also computationally intense.
Another shortcoming of DSP is its inability to truly replicate analog filters. If I wanted the filter kernel to completely replicate the RC filter’s impulse response, then the filter kernel would be infinitely long since the impulse response of an RC filter never reaches zero. You typically want to capture 5 to 10 time constants of the filter, or make the kernel long enough that round-off errors create more problems than a truncated kernel, but the point is the digital filter isn’t a 100% accurate representation of the analog filter.
The example filter we’ve discussed here is an FIR (Finite Impulse Response) filter, so called because the filter kernel produces an impulse response that is finite length. The other filter type used in DSP is the IIR (Infinite Impulse Response) filter, which are filters that have infinitely long impulse responses by using recursion. That is, the output of an IIR filter depend not only on the current and past values of the input signal, but also on the past values of the output. By feeding the past output values back into the filter, you can have impulse responses that never reach zero, just like analog filters. IIR filters are significantly less computationally intense than FIR filters, but they also do not replicate analog filter characteristics as well as FIR filters.
I built the prototype I showed last time on a PCB and then placed the PCB inside of an enclosure. Then, I met up with my friend, and we built the UV chamber together.
Finished UV Chamber, front view. Notice the UV LED Controller on top of the bucket. Thanks to my friend for adding much needed personality to my project 🙂
Finished UV Cure chamber, top view. Note the LCD screen and 4 buttons. Speaker is inside the enclosure.
First, we needed a housing for the UV chamber. I was thinking we could buy something plastic, and cover the inside with aluminum foil then place the UV LEDs on top of that. However, in the interest of simplicity, we just went with a metal 12 quartz bucket. The bucket was more than large enough for our purposes, and its metallic finish meant that UV light could bounce around for a bit, increasing the amount of UV the object placed inside would absorb. The bucket, since it was metal, was sturdy enough for us to mount the UV LED controller onto.
LED strips on the bottom face as well as side wall.
The bucket has two surfaces: the side wall and the bottom face. In order to shine UV LED on the print from all directions, I decided to place a couple of LED strips on the bottom face connected in series. For the side wall, in order to minimize soldering, I decided to have a single long strip in a spiral configuration. The spiral would connect to the LED strips on the bottom face on one end, and the UV LED Controller on the other end.
I tried to space the spiral so that there was 1.5 inches between LED strips on different levels. For my setup, I got about 5 full loops. There’s a couple of things I’d like to note about the assembly process:
Soldering the LED strips to the bottom face was a real pain. I peeled the adhesive off the strips and placed them at the bottom of the bucket, then I had to solder while the strips were in their final position. I tinned the pads on the LED strips and the wires, then put a blob of solder on the tip of my iron, then I had to hold the wire in position with one hand and solder with the other. It’s really hard to solder when the things you’re trying to solder are (a) in a cramped space, (b) you can’t get a good look and (c) they’re far away. There’s also no ventilation in the bucket, so I got dizzy really quick from breathing in the fumes. In hindsight, the LED strips on the bottom probably weren’t necessary since the bucket was so tall; the spiral by itself should enough.
The metal bucket is conductive, so be sure it doesn’t cause a short circuit! The LED strips are fine near the middle, but at their ends they have exposed pads that carry current. I placed a piece of electrical tape under the ends of each strip to prevent a short.
The UV LED strips I used were waterproof, so they had some sort of coating; I think it’s silicone. They make soldering impossible. In order to tin the pads, you have to (a) hack away at the silicone using your fingernails or a knife, (b) scrape away the residual silicone left on the pads using the tip of your knife, and (c) rub isopropyl alcohol (99%) on the pads to clean them. It’s a pain, so that’s why I opted to have a single long LED strip for the spiral to minimize soldering. I still think it’s a good idea to use waterproof LED strips, but if it’s too much of a hassle, you can use non-waterproof LED strips; just be careful when putting anything wet into the chamber.
The blue braid connects one end of the spiral to the UV LED controller. The braid exits on the left and runs up the side of the bucket to the controller.
Before I put in the LED strips, I drilled some holes to mount the UV LED controller and hacked away at the left edge of the bucket to make room for the wires going to the controller. I de-burred the holes and, since I didn’t have a file, covered the hacked away portions of the bucket with electrical tape to prevent burrs from digging into the wires. After that, all I had to do was mount the controller and hook it up to the LED strip.
UV LEDs on at full brightness.
Here you can see me testing the full assembly. Looks cool! I especially like how the two strips of glue light up. This was only for test purposes; you shouldn’t look into the bucket when it’s on since UV can damage your eyes.
After fully assembling the UV Cure Chamber, we took it for a test spin. We printed a couple of small objects from the resin 3D printer, cleaned them using isopropyl alcohol, and then exposed them to 100% brightness for 2 hours. I unfortunately don’t know anything about resin printers, so I couldn’t tell that the prints changed; however, my friend was very pleased with the results. They assured me that the prints cured properly, so I’ll take their word for it. Sorry for the anticlimactic finish.
I was very surprised by how hot the bucket got; I knew the LED strips would produce heat, but I didn’t expect the bucket to be noticeably warm to the touch. I couldn’t find information about the LED strips temperature rating, so I’ll have to keep my ears open for when my friend reports a failure. I may need to install a small fan to the bucket to reduce the heating. On the other hand, my friend told me that the heat helps the resin cure faster since curing is a chemical process, so you could consider the LED strip warming the bucket a “feature.” In fact, many professional UV curing chambers have heaters built in and they heat up the chamber to a set temperature before blasting the prints with UV. Regardless, this is something to keep in mind. Also, I used electrical tape to hold the LED strips and wiring down in a couple of places. I used electrical tape since that’s what I had on hand at the time; duct tape may be more appropriate.
One last thing; you should put some sort of rack in the chamber. The rack will help expose the bottom of the print to UV so it will cure there too. You can also flip the print periodically to make sure all sides get exposed to UV. Lastly, you can put a piece of aluminum foil on the surface beneath the print to reflect light onto the bottom of the print. You can do any combination of these three things to enhance the amount of UV your print gets.
Last time, we looked at reading and writing registers in an AVR microcontroller. This time, lets look at KL46Z256, which is an ARM Cortex-M0+ microcontroller.
Previously, we saw that Atmel provided us with a header file that allows us to read and write individual registers, like DDRD, PORTD and PIND. This works fine, but isn’t it a bit odd that these registers are completely separate from each other? In other words, wouldn’t it be convenient if these registers were grouped together? NXP does this in their header files, and we’ll be looking at that in this blog post.
Similar to AVRs, we see we have a data direction register (PDDR), input register (PDIR) and output register (PDOR). Conveniently, we also have set, clear and toggle output registers. If you look in the header file for this microcontroller, you’ll see the following:
Various definitions, shown using Platform I/O
As you can see, we have a GPIO_Type structure that contains fields PDOR, PSOR, PCOR, PTOR, PDIR and PDDR, which are 32 bit, volatile data. According to the datasheet, GPIOA has a base address of 0x400FF000, which is indicated by the definition of GPIOA_BASE. The definition GPIOA is the base address, GPIOA_BASE, cast as a pointer to a GPIO_Type.
What does this mean? Well, since GPIOA is a pointer to a structure, we can access the fields of GPIOA using the arrow operator. Therefore, we can write to registers of interest using the following code:
Set Port A pin 1 as output, then set Port A pin 1 output high
Here, thanks to GPIOA, the code clearly shows that PDDR and PDOR are both part of the GPIO peripheral. This is in contrast to the AVR header file: if you didn’t know off the top of your head what PDDR and PORTD were, then it’s not obvious they are registers for the same peripheral.
Again, we can see that there are many registers. The corresponding structure in the header file is shown below:
Structure for ADC in header file
Like the GPIO module, we have an ADC_Type structure. Interestingly, this structure contains arrays within its fields. This provides further grouping, as (for example) ADC0_SC1A and ADC0_SC1B are now grouped together within an array.
Just like GPIO, we have ADC0, which is the ADC module’s base address cast as a pointer to the ADC_Type structure. In order to write to the registers, you use the same approach, now only slightly more complicated due to the array in one of the fields:
Writing all 0’s to ADC0_SC1A and ADC0_CFG1
Note that it is possible to address registers like you did in AVR if you prefer; some may find it inconvenient to use the arrow operator. The header file provides macros for this specific case:
Register accessing macros for ADC Note GPIO and other peripherals also have macros like this
The definitions on the left simply plug ADC0 (which is a pointer to the ADC0 base address) into macros (defined on the right) which perform the arrow operator. If the register definition is part of an array within the structure, the macro will also perform indexing as well. Additionally, since the names of the definitions on the left all have the same prefix, the programmer will know right away that all of these definitions are for the same peripheral.
Besides grouping registers into structures and arrays, the NXP header file also provides macros for reading and writing bits within registers:
We can see that this particular register has 5 distinct fields: ADLPC, ADIV, ADLSMP, MODE and ADICLK. One way to go about setting up this register would be to memorize the position and bit width of each of these fields ; for example, you could memorize ADIV is bits 5 and 6. A more elegant solution is provided by the header file using macros:
The macros for bit manipulation for each register are in groups of four:
Mask: masks are used to clear or set specific bits. For example, ADC_CFG1_ADIV_MASK is 0x6, which means only bits 5 and 6 are high.
Shift: this number is used to indicate how many times the bits should be shifted. For ADIV, you’re interested in bits 5 and 6, so you’d have a shift of 5 (from bit 0).
Width: this number indicates how many bits are within a section. ADIV is composed of two bits.
Macro: this macro uses an input as well as the corresponding shift and bit mask to create the data you want.
Let’s do an example:
Based on the datasheet, let’s say you want a divide ratio of 4. That means you want ADIV to contain 0b10. If you don’t use the macros provided in the header file, then the process is painful and clumsy. Worse, you’re hard-coding numbers into your code:
Working with one bit at a time is inconvenient. Another way to do this is to take 0b10 and shift it into the right position. A good practice is to use masks so that you don’t accidentally read or write where you don’t mean to; in this case, you only want to manipulate bits 5 and 6. The macro ADC_CFG1_ADIV(x) will do all of this for you:
Remember that ADC_CFG1_ADIV(x) doesn’t write to the register for you! All it does is shift and mask the input argument. Now, in order to actually write to the register, you use the assign operator:
The beauty of this macro is that you can write to multiple fields at once using the OR operator. Say you want MODE to be 0b11 while ADIV is 0b10:
As you can see, the combination of register macros and bit manipulation macros provide convenient and abstract tools to configure peripherals. Even without knowing the address of ADC0_CFG1, or knowing ADIV and MODE’s position within ADC0_CFG1, you’re done!
First, let’s talk about how the ATMEGA328 drives a GPIO pin. The figure above shows the hardware that the microcontroller uses: the key components are listed below:
Pxn: this connects to the physical pin on the microcontroller and is accessible to circuits that connect to the microcontroller. This is what you drive or read from.
DDxn: this is the Data Direction register. It enables the buffer that drives Pxn when the pin is configured as an output, and disables the buffer when the pin is configured as an input.
PORTxn: this register holds the value that the buffer will drive if it is enabled.
PINxn: this register holds the value that Pxn is driven to.
Here, x denotes port, while n denotes pin number; for example, port C pin 3 would have PC3, DDC3, etc. Say you want to configure Port D pin 0 as an output, driving a high; then, you would have to make DDD0 output a 1 and PORTD0 output a 1. Then, PIND0 will be driven high by the buffer. If you wanted Port D pin 0 to be an input, then you would make DDD0 store a 0 and see what value gets stored into PIND0.
Simple enough assuming you can read from/write to those registers, but how do you actually go about doing that? The ATMEGA328 uses a very popular scheme called memory mapped I/O. Memory mapped I/O treats the registers used by peripherals (ADCs, GPIO, UART, etc.) as being part of the memory. Just like how you can read and write to addresses in SRAM, if you write to a register’s address, then the microcontroller will understand that the data is being read from/ written to a peripheral register and sends the data to the correct register. For the ATMEGA328, if we want to configure I/O registers, we’ll need to write to registers located in addresses 0x0020 to 0x005F.
Great; now we know that we have to read and write registers to control peripherals, and we know we can address them using memory mapped I/O. But if we want to write to DDD0 and PORTD0, as well as read from PIND0, what addresses do we use? This is where the vendor comes in (Microchip / Atmel, in this case); they need to tell you want registers are located at what addresses. Looking through the datasheet, there are two locations where you can find this information: the register description for I/O ports, and the register summary register summary for the whole chip, both shown below:
Snippet from I/O Port register description, from ATMEGA328 datasheet
Snippet from Register Summary, from ATMEGA328 datasheet
Note that the address is given in two forms; one as the absolute address in parentheses and as an offset from the base address (which is 0x20 in this case). So, to set DDD0 and PORTD0, as well as read from PIND0, you’ll need to read/write bit 0 from registers DDRD, PORTD and PIND respectively, which have addresses 0x0A (0x2A), 0x0B (0x2B) and 0x09 (0x29), respectively.
Let’s do a quick recap: by looking at the GPIO driver circuit, we saw we can control and get information about the GPIO by reading and writing registers. Thanks to memory mapped I/O, we have a system for reading and writing to specific registers in the chip. And from the datasheet, we know what addresses we need to read and write. But here’s a question; in the example code given at the beginning of this post, we wrote to DDRD and PORTD. How does the compiler know what DDRD and PORTD are? Does it even know they’re 8 bit registers? If so, does it know what their addresses are?
The answer is yes, since the compiler doesn’t throw an error and the microcontroller behaves as expected. But how does it know? Well, the Arduino IDE hides this from you for the sake of user-friendliness, but if you examine your Arduino code through something like Platform I/O or Atmel Studio 7, then with enough snooping around you’ll find the following:
Various definitions, shown using Platform I/O
The picture above shows the definitions used to read and write registers. PIND, DDRD and PORTD are registers and have the address offsets of 0x09, 0x0A and 0x0B, respectively. The offset is put into the _SFR_IO8 macro, which calculates the absolute address using __SFR_OFFSET (which is 0x20, as expected). Then, the absolute address is cast as a pointer to a volatile 8 bit value using the _MMIO_BYTE macro, which is then dereferenced, allowing us to read and write the selected register. The definitions for PIND0, DDD0 and PORTD0 show what position in the register the relevant bits are, which means you can use these definitions instead of memorizing the bit position or looking it up in the datasheet. Thanks to these definitions, you can write much more human readable code; an example of setting the DDD0 bit is shown below, with and without macros. Note that the header files that these definitions come from, like the datasheet, are provided by the chip manufacturer or software you use for programming the microcontroller; you’re not expected to write these yourself.
Manual register and bit addressing (above) vs. using macros and definitions (below). Both lines do the same thing.
For those interested, using the keyword volatile is extremely important. Volatile means the CPU must read or write from memory (or memory mapped I/O registers). If volatile is not used, then the CPU may have a local copy of DDRD in its cache, and when you change its value, the cached value changes, but not the actual data direction register. When volatile is used, the CPU doesn’t keep a local copy, ensuring that what you’re reading is directly from the memory mapped register, or you’re writing to the memory mapped register.
A friend told me that they got a 3D resin printer, and they do not want to spend the money to buy a UV cure chamber. Resin printers produce solid objects, but the resin hasn’t cured, which means the prints are structurally weak. To bring them to full strength, you have to clean them and then put them into a UV cure chamber, where the UV light causes the resin to cure. My friend told me that there are YouTube videos (1, 2) that show how to make your own cure chamber, so I thought I’d help my friend out.
Unlike my other projects, where I start the project with a vision of what I want, this one was for a friend. Since my friend wasn’t very familiar with electronics, they could not give me the specifics of what they wanted in the design for the UV cure chamber. Therefore, I thought it would be best to go straight to prototyping and get feedback as early and often as I could; that way, I can get them a system they’re happy with, even though I couldn’t flesh out the design before starting the project.
For my first design, I wanted to use the Stampduino as the heart of the system and hook it up to some buttons and an LCD screen, similar to my reflow oven project. The buttons would allow you to turn some UV LEDs on and off as well as set their brightness. I figured the easiest way to control the UV LEDs brightness was by driving a PWM signal into a NMOS transistor that goes between the UV LEDs cathodes and the system ground. But what UV LEDs should I use? Well, my friend told me that the 3D printer was a Anycubic Photon, which uses 405 nm wavelength UV light for curing. I used this info to order a UV LED strip (I’m not sponsored); I picked this one because it has a higher power rating than most other strips on the market, and is waterproof (in case the resin prints are wet). The LED strip conveniently comes with a 12V, 60W power supply, which I’ll use to power the project. I dug through some past projects and found a beefy transistor which would work for my purposes. I then wrote a state machine interface very similar to the reflow oven code, and demoed it to my friend.
I showed that you can set a timer, which controls how long the UV LEDs are on for. My friend requested that I add a speaker so that once the timer is done, the system beeps, alerting the user that the cure has finished. Funnily enough, the speaker circuit is nearly identical to the UV LED circuit: an 8Ω speaker that is tied to ground through an NMOS transistor. This transistor is also driven by a PWM signal, but the PWM wave is actually just a convenient way of creating a square wave, which causes the speaker to create a constant tone. The three differences between the UV LED circuit and the speaker circuit are (1) the speaker is pulled up to 12 volts through a 100Ω current limiting resistor while the UV LED strip connects to it directly (though I’m sure there are current limiting resistors built in to the strip), (2) the speaker has a fly-back diode since the speaker is an inductive load, and (3) the transistor for the speaker is much smaller than the LED strip since the speaker will draw less current than the whole LED strip. The setup for the final prototype is shown below:
Prototype using Stampduino dev board, LCD screen, breadboard with UV LED strip + buttons + transistors, and a speaker
The photo above shows I only used a small section of the LED strip for prototype purposes. The next step is to move the project into a form-factor that works for my friend.
After setting up the hardware, now we have to program the Stampduino. The chips I bought came pre-programmed with Atmel’s bootloader, but if we want to program it through the Arduino IDE, then we’ll need to burn the Arduino bootloader onto it. In order to do this, you’ll need a ISP (in system programming) programmer; in my case, I had an Atmel ICE on hand.
ISP, as it turns out, is very similar to the SPI interface. It has a MOSI, MISO, SCK and chip select. This is used to load the bootloader into the microcontroller’s non-volatile memory as well as read data from the chip. Note that chip select for ISP is the reset pin for the microcontroller; by holding the chip in reset, the chip can be put into a mode that will write provided data to its flash. ATMEGA32U4’s pinout is shown below:
ATMEGA32U4 pinout, ISP pins highlighted
The Atmel ICE has the following pinout:
Atmel ICE AVR port pinout; relevant ATMEGA32U4 pins are written in the table by me
Connect the mini-squid to the Stampduino as indicated in the table above. My setup is pretty crude, but it looks like this:
Powered Stampduino, hooked up to Atmel ICE via squid cable
Now, the Stampduino is ready to be programmed by the Atmel ICE. Do the following steps:
Power up the Stampduino by hooking it up to a USB cable.
Open Atmel Studio 7.0, and open a brand new project (or an example project). The project doesn’t matter; what matters is that you have a project open.
Open Device Programmer (Tools > Device Programming).
Set Tool to Atmel-ICE, Device to Atmega32U4, and Interface to ISP. Then click apply.
Click the read button next to Device Signature to make sure you can talk to the device to be programmed.
Click the memories tab, then the … button under Flash (32 KB). Since we want to burn the Arduino Micro bootloader onto the chip, we’ll need to select that file during this step. When you installed the Arduino IDE, the .hex file that contains the code for the bootloader should have been installed on your computer as well. For me, I found it at C:\Program Files (x86)\Arduino\hardware\arduino\avr\bootloaders\caterina\Caterina-Genuino-Micro.hex. Once the file is selected, hit the Program button.
Now, the bootloader is on the microcontroller, but the chip (probably) isn’t configured properly; to fix this, you need to set the chip’s fuses. To do this, click the Fuses tab and adjust the settings as shown below. Then, click Program.
ATMEGA32U4 fuse settings
I programmed the EXTENDED fuses to 0xFB, but when I read the fuse settings out of an Arduino Micro, I got the screenshot above. My guess is they both work, but according to the datasheet, the high nibble of the EXTENDED fuse byte should be all high:
Select the port that the Stampduino is on (Tools > Port > COMXX (Arduino/Genuino Micro)
Hit the Upload button
One weird thing I noticed is that the very first time you program the Stampduino after it has a bootloader burned onto it, it changes COM ports. It doesn’t do it again until you re-burn the bootloader. Strange.
One inconvenience when writing code for the Stampduino is the pin number:
Remeber that the IDE thinks the board is an Arduino Micro. So that means if you write to pin 11 in the IDE, that means you’re writing to PB7 on the Stampduino. Pin 10 is PB6, pin 9 is PB5, etc. Now, writing to pins 11, 10 and 9 in your application code when you mean PB7, PB6 and PB5 would be extremely confusing to future historians reading the code, so I wrote header file to address this problem:
Stampduino.h
Instead of writing digitalWrite(11, HIGH) when you want to set PB7 high, now you can write digitalWrite(PAD_B7, HIGH) instead, which is much clearer. Note that PAD_E2 cannot be written to in the Arduino Micro, so it’s not easily accessible to the Stampduino either. You can get around this by using the old fashioned method of writing directly to registers.
After the first couple of projects, I realized I was running low on Arduino boards I had on hand. Instead of buying more, I thought this was a good opportunity to design my own Arduino board. This will also be an excellent opportunity to try out my reflow oven on a board that’s not the Pocket Power Supply.
My design goals were: cheap, small and compatible with the Arduino IDE. Ease of use, that is ease of access to the pins, were not a priority. I made this decision because connectors that are easy to access and use are neither cheap nor small. I’m just going to have pads on the board that the user is expected to solder wires to in order to get an electrical connection. In this sense, my Arduino will be closer to a module than a development platform; its designed to be inserted into a system where you already know what pins you need, rather than an easy to use, easy to modify board that can be used for any application.
Fortunately, small and cheap go hand in hand for PCBs; smaller boards are substantially cheaper than larger ones. To further drive down cost, I decided the board should be a two layer board. The goal is to have a board approximately the same size as a postage stamp, hence the name Stampduino. The 1 inch by 1 inch, two layer board easily qualifies for the JLCPCB $2 prototype special offer (I’m not sponsored):
With the design goals established, I started looking for a microcontroller I wanted to use. The easiest way of making a board Arduino IDE compatible is to use the same microcontroller on the Stampduino as existing Arduino boards. I originally wanted to use the same microcontroller as the Arduino Uno since it’s probably the simplest, but I ultimately decided to use the microcontroller on the Arduino Micro:
Arduino Micro
One of the key distinctions between the Uno and Micro is the fact that the Uno actually has two microcontrollers: the ATMEGA328P and the ATMEGA16U2. The microcontroller you actually program through the Arduino IDE is the ATMEGA328P; the ATMEGA16U2 is there just to convert the USB interface to serial; in other words, it’s a USB transceiver. The Arduino Micro only has one microcontroller: the ATMEGA32U4. It can natively support USB, which means the Stampduino will only need one microcontroller and no transceivers. By reducing the number of parts and simplifying the design, I have a better shot of meeting the design goals I set out.
The rest of the circuitry is just support for the microcontroller:
USB connector: I decided to use a micro USB, since that’s what’s most commonly available
Power regulation: just like my Pocket Power Supply project, I have a power multiplexer that lets the circuit choose between USB power and externally supplied power. Both of the two power sources are fed into an LDO, which will generate either 3.3V or 5V, depending on the feedback resistors in place.
Crystal: I wanted my board to be able to do 3.3V or 5V operation. The maximum crystal frequency for 3.3V is 8 MHz, while the maximum crystal frequency is 16 MHz. The pads on the board for the crystal can accommodate crystals for both frequencies.
Misc: I decided to include a couple of pull-ups for the I2C bus as well as indicator LEDs for the sake of convenience to the user. Not a design goal, but improving quality of life wherever possible is always a good thing.
Stampduino Schematic
Feeding the USB’s 5V into an LDO to generate 5V is not a very good design, since the LDO will always output less than what is provided to it. This was done to simplify the circuit and reduce the number of parts needed for power regulation. I decided this was acceptable because (a) USB power is generally slightly above 5 volts, and (b) the Stampduino is intended to ONLY power itself and not provide power for other devices when powered by USB. If you want the Stampduino to output a regulated voltage through the LDO, you should provide external power besides just USB.
Stampduino PCB. Left: top, right: bottom
The board layout was a pain, but I managed to fit everything onto the tiny space with only two layers. I had to make a couple of sacrifices:
Despite my love for 0603 components, due to their ease of soldering and manipulation, I used 0402 size capacitors and resistors. I was curious how my reflow oven would handle 0402 components anyway, but it still makes assembly a lot harder.
The pads to connect wires to were smaller than I wanted. I envisioned 2 mm diameter pads, but as soon as I started the layout I realized I had to make them 1 mm instead. This makes soldering wires to them harder, but I think it’s okay since you’ll only need to solder wires to the board once if you know exactly what you need.
I had to put a lot of silkscreen on the bottom of the board. This makes finding components during debugging and assembly more difficult, but since the design files will be available online, it’s not too bad.
All in all, I’m very happy with the layout. I am especially happy with the mounting holes, which are 0.5 in part. I intentionally made sure they were apart in increments of 0.1 in so they can be attached to 0.1 in pitch perfboards easily by lining up the holes and then putting a 0-80 screw through both of them, though you’ll probably have to widen the hole on the perfboard (most have 0.032 in wide holes, and you’ll need 0.050 in wide holes for 0-80 screws). I am also very happy with the fact that no components are on the bottom; this makes mounting the board flush with the wall of an enclosure very easy.
After waiting breathlessly for the PCBs (got 30 for $5.10), stencil (got 1 for $7) and the parts (got enough parts to make 10 boards for about $40) to arrive, I got to work building the boards. It went pretty well when I used a microscope during the assembly process; I was able to complete 4 boards in 4 hours including set up, applying solder paste, assembling the boards, reflowing them, inspecting them, fixing defects and then testing them. The finished product is shown below:
Stampduino, Rev 1
Like I mentioned, this board is not well suited for development purposes. If I’m experimenting and don’t know exactly what I want to do with the board, then using the Stampduino will be extremely inconvenient. There are two workarounds for this issue:
Use the Arduino Micro, then port the code to the Stampduino once you’re done experimenting. This should work for most cases as long as you are cognizant of the differences between the two boards. This includes the indicator LEDs, the pin numbers used in the Arduino IDE, and making sure the crystal on the Stampduino is 16 MHz, since that’s what’s on the Micro.
Build a development board for the Stampduino. This is what I did and recommend; in order to minimize, hopefully eliminate, the porting effort, I decided to stick the Stampduino to a perfboard and run wires from the pads on the Stampduino to easily accessible headers.
Stampduino Development Platform. The button is a reset button.
After pinning the Stampduino to the perfboard using two pin headers and some double sided tape, I broke out all the pads to connectors one by one. Soldering wires becomes especially difficult if you plan to use every single pad, but it’s definitely doable. After that was done, I decided to slap on some helpful labels as a quality of life improvement.
Now the hardware is all done; the next task is sorting out the software. This will include burning Arduino IDE compatible bootloaders on the ATMEGA32U4 microcontrollers, and seeing how easy it is to develop code for this new board.
I updated the reflow oven software in the following ways:
First, all the code was in a single Arduino IDE file (.ide). I really didn’t like that because it was messy and difficult to navigate. Even worse, I used global variables everywhere, which is very bad form. I’m not a coder, so I didn’t think much of it at the time, but I decided that this could be a good opportunity for me to learn about making my own libraries. Therefore, I broke the single file up into many smaller ones, divided by function:
oven_interp performs the linear interpolation to see what the target temperature should be between defined points in a profile, oven_UI is where the UI state machine is, and PMODTC1 handles the low level communication and conversion for the thermocouple module.
The second change I made concerns linear interpolation: before, only the profile used it (e.g. if the oven should be at 0 °C at 0 seconds and 100 °C at 100 seconds, then the oven should be 30 °C at 30 seconds). For manual mode, if you set the target temperature to 50 °C, then the software would heat the oven until it measured 50 °C. This resulted in overshoot since the heating elements would continue to be on UNTIL the oven was at 50 °C, at which point the thermal inertia caused the oven to continue getting hotter even though the heating elements no longer received any power. Now, manual mode uses linear interpolation as well. Instead of the set point being set to 50 °C, the set point slowly rises (or falls) at 0.66 °C/sec, which reduces the overshoot.
The third change concerns the temperature profiles. I added a profile for the low temperature solder paste, and adjusted both profiles (regular and low temperature) to one the solder oven can keep up with. I did this by increasing the amount of time the oven has to reach certain temperatures, and I think the results look pretty good:
Blue: oven temp, red: programmed profile
I’ve uploaded the new program to github. One change I would like to implement is button debouncing; the interface buttons sometimes cause the menu to think the button has been pressed multiple times, which is annoying. However, it’s not a major issue, so it’s a low priority.
Based off the functional block diagram, I created the following schematic:
The two boards are simple enough that I just built the circuits on perf boards. Note that the +3V3 is not generated by an LDO; the one I ordered had a maximum input voltage of 3.6 volts, so I went with a regular linear regulator I had on hand. How does a 3.3 volt output chip only have a maximum input voltage of 3.6 volts?
Relay board installed inside oven casing
The relay board was installed inside the oven casing since it uses mains voltage and I wanted to keep the user’s hands away from it. Note the thermocouple going into the oven chamber to the left of the board, and the wall wart that generates 5 volts below the board.
User Interface Board
The user interface board was mounted near the top right of the oven; I used the hole left after one of the knobs were removed to route the wires. The LCD covers most of the Arduino Mini, but the Arduino’s headers are still accessible which we’ll use for retrieving data.
Full View of Oven
With that, the oven build was complete. Let’s see how it runs.
First test run
I ran the oven with a bare circuit board inside, which the thermocouple was taped to. The thermal profile I used was from a datasheet for a random solder paste I found on Digikey; the abrupt drop-off is when the oven should turn off. The results were… not great. Clearly the problem was the oven cannot heat up fast enough. There’s a couple of solutions: add more heating elements, add insulation or adjust the programmed temperature profile.
I decided to add more insulation since that would be relatively easy and would increase the efficiency of the oven. The insulation I used was Reflect-a-Gold, which is the go-to insulation used in most other oven projects. The most important sides to insulate were the top and bottom as well as the front and back. The top and bottom are closest to the heating elements, so insulation should be added there, while the back only had one layer of insulation, so I wanted to add insulation there as well. The front, which is the glass door for the oven, was particularly important; during testing I could feel my hand get warm from all the radiation that leaked out of the oven. After insulating the four sides, I decided to use the left over insulation to insulate the sides as well. I also removed the metal heat shields for the heating elements on the bottom to decrease the thermal resistance between the heating elements and the circuit board.
Oven with insulation
As you can see, I left a cutout on the glass so I can look into the oven while it runs. Lastly, I ordered a grill mat to lay between the board and the grill. I figured that the (black) mat would absorb radiation more readily than a PCB, as well as distribute the heat evenly across the board. I cut the mat down to a small piece, barely larger than the size of the test PCB because I didn’t want it to impede air flow or add too much thermal mass to the system. Now, lets try the test again and see what we get:
Second Test, after adding insulation
The results are much better. The oven still has trouble ramping up at the desired speed, but the results look good enough to warrant an actual PCB + solder paste + components test. Note that the oven cannot actively cool itself, so when the profile finishes, I need to open the oven door to let the PCB cool. Not ideal, but good enough for now.
I ordered a stencil for the Pocket Power Supply PCB, and put solder paste on the bare PCB using an old laundry card. Here’s the results:
Disastrous attempt #1
So that went absolutely horrendously. After lining up the PCB to the stencil, I taped the two together and I thought that would work, but apparently not. I suspect the main reason the solder paste got everywhere is because the stencil, which is much larger than the PCB, bows away from the PCB due to gravity, as shown below.
Exaggerated bowing of stencil. Stencil is approximately twice the size of PCB in all dimensions.
Another reason the result was poor was because I was afraid of touching the solder paste; the microscopic balls of solder can seep through your skin, so avoid touching it as much as possible. I didn’t have gloves on at this point, so after the first attempt I went out and bought some nitrile gloves at Home Depot. While I was there, I also bought a pain scraper, which I thought would be better for spreading solder paste than a plastic card because it’s more ergonomic, wider, and more rugged.
In order to address the stencil bowing problem, I grabbed some PCBs I had laying around and surrounded the Pocket Power Supply PCB with them. Since the dummy PCBs were the same thickness as the Pocket Power Supply PCB, the stencil had a nice, large, and flag surface to lay on, which prevented the bowing.
Setup for attempt #2 and #3. The four visible PCBs are dummys to keep the stencil from bowing.
Attempt #2
Attempt #3
Attempt #2 went much much better, but you can see that most of the pads are still pretty messy; USB1, U2, U4 and U5 pads are noticeably bad. I suspect I wasn’t using the scraper to distribute the solder paste properly, since I kept going back and forth over the stencil to scrape as much paste as I could into the holes. For my third attempt, I only moved the scraper across the stencil once or twice, trying to pass over the holes once and only reapplying if the pads weren’t completely and evenly covered by the paste. The left half of #3 looks nearly perfect; there’s some smearing on the right half, particularly noticeable around U4, C14 and C16, but I thought it was good enough for a test run.
Attempt #3 with components
Applying the solder paste to the board and then populating all the parts only took an hour, while the original build took about 5 hours spread over multiple days, most of which I spent trying to solder components with exposed pads. Now, for the real test: let’s put it through the reflow oven.
After reflow process
All the pads are soldered! None of the components had wet solder paste on them, so the oven did its job. However, I did notice immediately that the solder joint quality wasn’t very good. I couldn’t really capture it on camera, but the picture above is the best I could do. Look at U2; pins 1~5 are as is, after the reflow oven, but I touched up pins 6~12. You can see that the retouched pins are shiny, which is what you want in a solder joint. Pins 1~5, along with having a short on pins 2, 3 and 4, are dull. The lighting is bad at showing this in this picture, but trust me: under the microscope you can see that all the joints after the reflow process are dull and “sandy.” Look at C20, for example; solder joints should ideally be smooth and seamless, but the solder joints on C20 looks like the surface of a rock or concrete. Unfortunately, U1 and U5 had shorts between pads as well. However, I blame the shorts on my shaky hands and poor stencil skills, rather than the oven, so they don’t reflect how well the oven works.
Overall, I consider this project a huge success. The main thing I wanted to get out of this project was (1) the ability to solder components with exposed pads, as well as leadless components, to PCBs and (2) make board assembly easier and faster. I examined the components with exposed pads after reflow, and they all had solid connections to their associated pads.
The solder joint quality is the next thing to work on. The solder paste I used (2023628) is NOT the same solder paste that I used to design the oven’s profile, so that may be a reason why the solder quality is poor. If we assume that is not the case, i.e. assume that the profile I programmed works for both types of solder paste, then the problem is the oven cannot follow the profile closely enough to get good solder joints. I have a couple of ideas in mind on how to address that:
Adjust the solder profile: by increasing the time between temperature points, I give the oven more time to ramp to the programmed temperature, which means the oven can accurately produce the programmed profile.
Change the solder paste: there are low temperature solder pastes available that may be more appropriate for my relatively low power oven. These solder pastes reflow at around 170 °C as opposed to 250 °C. If you look at the second test graph, the oven actually performs really well at that temperature range, so that may be the key. The low temperatures will reduce stress on the PCB and ICs as well.
Improve heat transfer: As I mentioned, I used a cut out of a grill mat to increase the amount of heat the PCBs get, as well as distribute the heat evenly. I would like to experiment on this a bit more and see if I can improve it; I read about graphite sheets you can use to pull heat away from hot components, so I’m thinking I can use them to pump heat into PCBs as well.
I’m planning on ordering components to do more testing: the right solder paste (TS391SNL50), a low temp solder paste (TS391LT50), and some graphite sheets (EYG-S121803). I’ll also have to try playing with the solder profile to see if I can improve the solder joint.
For my next project, I want to do something with motors, but I don’t know much about them so I decided to research the topic. This post will summarize what I’ve learned. My research is from Motors for Makers: A Guide to Steppers, Servos and other Electrical Machines by Matthew Scarpino; I highly recommend it for those interested in further reading. It talks about motors, gears, linear actuators, as well as projects you can build using motors, like a quad-copter. You can even learn about generators! (I’m not sponsored)
Overview
All motors work based on the same principle: use magnetic fields and electricity to cause motion. However, there are a lot of nuances to motors:
What kind of magnets do you use? You can have a permanent magnet, which is simple but can’t be controlled, or an electromagnet, which can be controlled but requires control circuitry and power. If the electromagnet is on the moving part of the motor, how do you get it power?
Magnets interact differently with different materials:
Another magnet will can be attracted or repelled, depending on how the poles are aligned
a hunk of iron will be attracted and get as close to the magnet as possible
A piece of wire that is carrying current will act like a magnet; which direction its pole points can be changed by reversing the direction of current flow
A conductor that is moving near the magnet will have current induced in it, also making it act like a magnet. In this case, current through the conductor cannot be directly controlled.
What type of power does the motor use? DC? AC? How many phases?
How do you control the motor? How do you know when and where to provide power?
The list above shows that different types of motors implement the same basic theory in different ways.
For this post, I’ve organized motors based on how they’re powered since that will probably be the first thing anyone looks at to see if a motor is right for their application. Below are DC, polyphase, single phase and universal motors.
DC Motors
DC motors are probably what you’re going to use most in hobby projects since they work very well with batteries and voltage regulators. There are 4 types: brushed, brushless, steppers and servomotors.
Brushed Motors
A brushed motor is as simple as you’re going to get: you have permanent magnets arranged in a circle, and a loop of wire in the middle attached to the shaft. By forcing current through the wires, they become electromagnets and the loop (and shaft) orients itself to the magnets. After the loop has oriented itself, the direction of current flow is reversed, causing the loop to rotate and orient itself again. This process is repeated, resulting in the shaft turning as the loop rotates.
First, lets talk about the commutator. The commutator is an electro-mechanical component that acts like a switch; it feeds the loop of wire current. As the wire rotates, the commutator continues to feed the wire current. When the loop of wire rotates beyond a certain point, the direction of current is automatically reversed by the commutator, keeping the loop energized and the shaft turning. Once the loop has rotated beyond another point, the direction of current is reversed again. The commutator is what gives the brushed motor its name; in order to keep electrical contact between a stationary component (stator) and the a moving one (rotor), the commutator uses brushes of copper (or spring loaded pieces of graphite). Thanks to the commutator, the circuit powering the motor doesn’t need to worry about reversing current when you only want to spin the motor in one direction; just provide power and you’re good to go.
In order to control the motor, use this rule of thumb: the rotation rate of the shaft depends on the voltage across the motor, while the torque output depends on the current through the motor. Now, you could do some calibration where you see how much voltage and current you need for a certain load and then design a circuit to provide exactly that, but the more common way to control a motor is use an H bridge.
Left: no current, Middle: current going one way, Right: current going the other way
An H bridge is 4 switches (realized by transistors) that connect as shown above. The H bridge allows a microcontroller to let current flow one way or another, depending on which direction you want the motor to turn. The H bridge also allows no current to flow, which will disable the motor.
H bridges, besides letting you control direction, also allow you to control speed. The switches are turned on and off by a digital signal. If the digital signal is pulse wave modulated (PWM), then that allows the switches to be on (say) 10% of the time; then the motor will turn at approximately 10% of the maximum rate. The motor speed can be adjusted as desired by changing the duty cycle of the PWM signal.
Brushed DC motor
There are three types of brushed motors: permanent magnet DC motors (PMDC), Series-Wound DC Motors (SWDC) and Shunt-Wound DC Motors (SHWDC). PMDC is what we’ve talked about so far. In an SWDC, the stator’s permanent magnets are replaced by electromagnets that are in series with the rotor windings. In SHWDC, the electromagnets are in parallel with the rotor windings. PMDC are simple but get weaker over time, SWDC have a lot of torque but are difficult to accurately control the rotation speed, and SHWDC have a relatively flat torque-speed curve, making speed control easier over various loads.
Brushless Motors
Brushes were necessary because you needed to provide electrical power to a loop of wire that moved; is there a way to avoid that? Instead of stationary permanent magnets and a moving loop of wire, brushless DC (BLDC) motors have permanent magnets embedded in the rotor and windings of wires that act as electromagnets on the stator. When one winding is energized, the permanent magnets on the rotor align (rotate) to be close to the electromagnet. By de-energizing one winding and then energizing the winding right next to it, you cause the rotor to rotate again. By constantly changing which winding is energized, you can get the rotor to constantly rotate.
Since you no longer need to provide power to a rotating spool of wires, you can throw out the commutator, which wears out over time. However, the commutator also provided the useful function of automatically switching current in the rotor, which resulted in an electromagnet that changed polarity as it rotated. Because that feature is no longer taken care of in the motor, the circuit designer must do that. Most BLDC motors have 3 phases, A, B and C; in order to provide the correct sequence of energized windings, you must apply power across the three phases in the correct order. An example sequence is shown below:
1
2
3
4
5
6
A
Power
Power
None
Return
Return
None
B
Return
None
Power
Power
None
Return
C
None
Return
Return
None
Power
Power
Reversing this sequence will allow you to turn the motor in the opposite direction, which means no H bridge is necessary.
There is another source of complication with the sequence; you have to know when to go from one step to another. Going too quickly will prevent the motor from spinning, while going too slowly will cause the motor to spin in a jerking motion. To know the correct timing, you must know the orientation of the motor while it spins. This can be found out in two ways: you either use a sensor (expensive and bulky but good performance) or use back-EMF (cheaper and smaller).
Designing a motor control system is outside the scope of this post, but I’ll just mention that the two common ways to use back-EMF to control the motor are zero-crossing detection (ZCD) and extended Kalman filter (EKF). But the point is that controlling a BLDC is more complicated than a brushed motor. Fortunately, there are modules you can buy that handle all the details of the sequence and timing for you, called electronic speed control (ESC) systems. All you have to do is provide it with power and an interface (usually PWM) that tell it how quickly you want the motor to spin. ESCs can be programmed to behave differently, so you can adjust them for your application.
Left: inrunner, Right: outrunner
There are two types of BLDC motors: inrunner and outrunner. Inrunner have rotor inside the stator, hence the name. They are generally low torque, high RPM motors. Meanwhile, outrunners have the stator inside the rotor. This design provides ample room on the rotor to have lots of permanent magnets, which means outrunners are high torque, low RPM motors.
Stepper Motors
Stepper motors have the unique ability to rotate at specific increments; for example, they can rotate in 6° steps. They are great for applications that require precise controls, like the movement of a robotic arm or moving a platform into position. Stepper motors are very similar to inrunner BLDC motors in construction; they have a rotor with permanent magnets on it surrounded by a ring of electromagnets on the stator. By energizing one coil, you rotate the rotor; energizing another coil will cause the rotor to rotate again. The primary difference is the control: BLDCs are meant to rotate smoothly and continuously, while steppers move in discrete jerks. Additionally, while BLDCs only use windings and magnets as necessary to get rotation and torque, stepper motors require a lot of windings and magnets to get good angular resolution.
A stepper motor typically has two phases, A and B. There is also the opposite of these phases, A’ and B’, which are actually the same phase but the winding is done in reverse; this means that when A is a north pole, A’ becomes a south pole. The poles winding are arranged so you get the following repeating order: A, B, A’, B’, A, B, A’, B’… Now there are two ways you can make a stepper motor move: full step and microstep.
Full step means you rotate the motor by its angular resolution, so a 6° stepper motor will rotate 6°. You can do this by powering one phase at a time (power A, then power B while un-powering A) or you can do two phases at a time for more torque (power A and B, then power A’ and B’ while un-powering A and B). Note that when A and B are powered, the rotor will align itself to be at its half way point; as an example, a rotor will rotate 3° for a 6° stepper motor if the rotor was aligned with A, and then both A and B were powered.
The example above shows that you can move by smaller increments than the angular resolution, and that’s what microstepping is. By having multiple phases on at a time, and powering some phases more or less than others, you can cause the rotor to rotate by less than one full step. This will allow you to take an 8th of a step, for example.
Hybrid motor
There are three types of stepper motors: permanent magnet (PM) steppers, which are what we’ve been talking about, variable reluctance (VR) steppers, and hybrid (HY) steppers. PM steppers have good torque, but have poor angular resolution. VR steppers replace the permanent magnets with a hunk of metal; since the metal is easy to machine and shape, VR steppers have much higher angular resolution than PM magnets. However, since VR steppers rely on the force attraction between metal and electromagnet, as opposed to permanent magnet and electromagnet, they have much lower torque. Hybrid steppers have the best of both by providing good torque and angular resolution, and are what you see in most applications like 3D printers. They have teeth on their permanent magnets like VR steppers do, as well as on the iron cores on the stator, which increase angular resolution.
Servomotors
Servomotors aren’t technically their own type of motor; they’re closer to packaged systems or modules rather than individual components. Servomotors, usually called servos, are a motor of some type hooked up to a sensor (usually a potentiometer or rotary encoder) and a control circuit. They operate based on the principle of closed loop; an external controller tells the servo what angle to rotate to, and the control circuitry inside the servo will rotate the motor to that position.
Servomotor
Servos are very easy to use because the hard part of motor control has already been done for you; usually you just have to send a PWM signal to tell the motor what position you want, and you’re done. Be sure the servo you want to use can give you the range of motion you need for your application; a lot of the ones I’ve seen are close to 180° or 360° of motion, though I’m sure there ones that can do as many rotations as you want.
Polyphase Motors
Polyphase motors are, as their name suggests, motors that require more than one phase of AC power, usually three. Polyphase motors are used primarily for industrial and heavy-duty applications, and you probably won’t use them for hobby projects.
All 3 phase motors have the same stator; like BLDC motors, the stator has a bunch of electromagnets. What’s important, though, is that the motor has 3 phases that are all 120° apart electrically. When wired correctly, the three phases produce a magnetic field that rotates over time. The equation for the magnetic field’s rotation speed is
n_s = 120 * f / p
n_s is the rotation speed in RPM of the magnetic field, called synchronous speed, f is the frequency of the mains voltage, and p is the number of poles per phase. For example, a three phase motor with 2 poles per phase will have a magnetic field that rotates 3600 times per minute, or 60 times per second.
Asynchronous (Induction) Motors
Faraday’s law of induction states that a changing magnetic field causes current to flow in a conductor. If a close loop conductor, embedded in the rotor, is placed in the stator’s rotating magnetic field, then the rotating field will induce current to flow around the loop. Since a current carrying conductor in a magnetic field will have force applied to it, the magnetic field applies force to the rotor and cause it to start spinning.
Asynchronous motors get their name from the fact that they cannot rotate at the same rate as the magnetic field. If they somehow did, then the conductors would rotate at the same rate as the magnetic field, which means there is no change in magnetic field from the loop’s perspective; this would cause the current in the conductors to drop and the rotor to start slowing down. For this reason, asynchronous motors always rotate at a lower speed than the synchronous speed.
A more complicated type of induction motor is the wound-rotor motor (WRIM) or slip-ring motor. Since the rotor is powered by induced current, the outside circuitry has no way to adjust the rotor’s behavior, which would be necessary if you wanted to adjust the motor’s power curve. These types of motors have slip rings that place the adjustable resistor in the path of the conductor loop. Squirrel cage rotors (used in regular induction motors) have high inductance, so there is a phase difference between the induced voltage and induced current, reducing the amount of torque the motor can produce on startup. The resistors, which increase the loops resistance, provide power factor correction, improving the motors starting torque while reducing startup current. Since these resistors limit the maximum current (and therefore maximum torque) in the rotor, and the phase difference between induced current and induced voltage decreases as the rotor gets faster, the resistors become a problem rather than a solution, so the resistance is reduced after startup.
Left: star configuration, Right: delta configuration
Another way to reduce the startup current is to use a star configuration initially, then switch to delta in the stator windings. In a star configuration, when voltage is applied (say across 1 and 2), the voltage is split between two coils, which reduces the amount of current necessary. However, since current is reduced, the maximum torque output of the motor is also limited. That’s why motor control systems can use contactors (similar to relays) to switch from star configuration, at start up, to delta for regular operation. Delta configuration, since the full voltage appears across each winding, has a greater maximum torque output.
Induction motors, as are all AC motors, are controlled using either eddy-current drives or variable-frequency drives (VFD). Eddy-current drives sit between the motor’s shaft and the output shaft. A controller monitors the output shaft, and if the output is rotating below the desired rate, then it is connected to the motor’s shaft through a clutch. If the output shaft starts to rotate too quickly, then the clutch is disengaged. This closed loop system allows the output shaft to spin at whatever rate the user desires.
VFDs are similar to PWM controlled H bridges used for brushed DC motors. A VFD takes in mains voltage (AC), and rectifies it to a DC voltage. Then, using transistors, the VFD outputs a sinusoidal pulse width modulated (SPWM) power to the motor, one for each phase. This way, by changing the frequency of the sinusoid, the motor effectively gets power that’s at a different frequency from the one provided by the power grid, changing the rotation rate of the magnetic field.
Synchronous Motors
Induction motors require the rotor to rotate at a slower rate than the magnetic field since this is a necessary requirement to induce current in the conductors. Synchronous motors, meanwhile, do not need induced current to provide power to the rotor, so they can rotate at the same rate as the magnetic field.
There are three types of synchronous motors: doubly excited synchronous motors, permanent magnet synchronous motors and synchronous reluctance motors.
Doubly excited synchronous motors have windings on the rotor that receive DC power through slip rings. This turns the windings into electromagnets which align themselves to the rotating magnetic field, causing the rotor to spin at the same rate as the rotating magnetic field. Interestingly, the electromagnets do not provide enough torque to get the motor started, so the rotor also has a squirrel cage. At startup, the squirrel cage, through induction, provide the torque to get started; then the electromagnets provide the extra torque necessary to rotate at the same rate as the magnetic field.
Permanent magnet synchronous motors (PMSM) have permanent magnets on their rotors, which means they operate just like brushless DC motors. The permanent magnets rotate to align themselves with the rotating magnetic field.
Synchronous reluctance motors are just like the variable reluctance stepper motors; the rotor is a large hunk of metal. The metal will rotate to be as close to the energized winding on the stator, and you can rotate the metal by constantly changing which winding is energized. Due to their low torque output, they’re pretty rare.
Synchronous motors are also controlled using eddy-current drives or VFDs; see asynchronous motors section for details.
Single Phase Motors
The discussion for single phase motors will be focused on the stator since that is what distinguishes single phase motors from polyphase ones.
Polyphase power is really useful because a three phase motor can easily create a rotating magnetic field; the phases are conveniently out of phase with each other, and all you need to do is make sure the windings of the stator are also out of phase. However, with single phase motors, you don’t have that luxury; a single phase can only create an oscillating, not rotating, magnetic field. That’s why stators in single phase motors are designed to create a second phase using the first. Note that the second phase isn’t as strong as the first, and they’re both pretty close in phase, but for most applications that is good enough. There are three ways to create this second phase:
Split phase motors: these motors have an auxiliary winding and a switch in parallel with the main winding. The switch is closed when the motor is at low RPM, and disconnects as the motor starts spinning faster. The main winding has low resistance and high inductance, while the auxiliary winding has high resistance and low inductance. This means that even though both winding are receiving the same voltage, their currents are out of phase with each other (typically about 30°). This small phase difference is enough to produce a rotating field which gets the rotor to start turning. Once the rotor starts spinning, the switch disconnects, killing auxiliary winding. After startup, the inertia of the rotor and the oscillating magnetic field from the primary winding is enough to keep the motor going.
Capacitor-start motors: similar to split-phase motors, but it adds a capacitor in-between the auxiliary winding and the switch. The capacitor further increases the phase difference between the main and auxiliary winding, increasing startup torque while decreasing startup current. The switch also removes the auxiliary winding and capacitor from the circuit once the rotor is fast enough. There are two variations of this design:
Permanent split capacitor (PSC) motor removes the switch, so the auxiliary winding and capacitor are always in parallel with the main winding. It has lower starting torque but is more efficient and reliable.
Capacitor-run motor is a PSC motor with a capacitor and switch in parallel with the permanent capacitor. The capacitor and switch increase the capacitance (and therefore phase difference) at startup, and then get removed from the circuit, leaving only the permanent capacitor. They have the high starting torque of capacitor-start motors with the efficiency of PSC motors, but these motors are more expensive.
Shaded-pole motors: a conductive ring, called a shading coil, that is electrically isolated from the stator’s windings is placed on a part of each iron core. As the winding creates an oscillating magnetic field, current is induced in the conductive ring which also generates a magnetic field that is out of phase with the original magnetic field. This will produce a very weak rotating field and is only used for very low torque applications, like turning the hands of a clock. This motor design is very economical.
Universal Motors
Universal motors can work off of DC or single phase AC, and have similar construction to SWDC motors. This means the windings of the stator and the windings of the rotor are in series with each other through a commutator. The reason universal motors can work off of DC or AC is because they only care that the current through the stator and the rotor go the same direction; reversing currents going through both simultaneously will just flip all the poles in the stator and rotor, so not much has changed in terms of producing torque. Since the stator and rotor windings are in series, they will always have the same current, therefore universal motors can work on DC or AC.
The key difference between universal motors and SWDC motors is that universal motors are designed to have a low phase shift between voltage and current. Since SWDC motors only work on DC, the design is not optimized for low inductance. Meanwhile, in a universal motor, the inductances from the stator and rotor windings cause enough phase shift to prevent the motor from working when it is running off of AC. To address this, universal motors have as few windings as possible on the stator’s windings, as well as a compensating winding in series with the stator winding to reduce phase shifts.
Like SWDC motors, universal motors have good staring torque, since increasing current through the stator also increases current through the rotor. Universal motors also share the same drawbacks as SWDC motors, though; the commutator wears out over time, which reduces motor reliability and life-span.