UART, SPI, LCD, LED, IMU, and more
PIC microcontrollers (Programmable Interface Controllers) are electronic circuits that can be programmed to perform various tasks. This post includes some mechatronics tasks with PIC32 Microcontroller and MPLAB IDE. You can check out the source codes at my Github
We have 5V between the VBUS and GND pins. Using VBUS as the input to the Pololu, we can get 3.3V out. Add a red LED in series with a 330-ohm resistor to the 3.3V output voltage, and check the voltage again. We’ll use 3.3V and ground a lot, so make the rails on your breadboard 3.3V and ground according to the color code on the breadboard.
MPLAB IDE provides a programming environment and communication to the PIC32. We will make a circuit which initializes B4 as input and A4 as output that is initially off. In the infinite loop, if the value of B4 is pushed, turn on A4 for 0.5s, off for 0.5s, on for 0.5s, and off for 0.5s (so two one-second square wave blinks)
The PIC that we are using does not have a USB peripheral, so we have no way of communicating with our computer directly. The Snap programmer has debugging capabilities, but no generic data transfer method. To get data back and forth, we will use a USB to UART converter chip from Adafruit. Adding the Adafruit CP2104 Friend USB to UART converter allows communication of the PIC32 with the computer.
The Serial Peripheral Interface (SPI) allows the PIC32 to communicate with other devices at high speeds. Numerous devices use SPI as their primary mode of communication, such as RAM, flash, SD cards, ADCs, DACs, and accelerometers. We generated a 2Hz sine wave and a 1Hz triangle wave. Both range from 0V to 3.3V.
An LCD is a two-dimensional array of pixels used to display data. Each pixel has three little screens, tinting the light that passes through them red, green, and blue. A white backlight behind all of the pixels passes through the screens, creating the color you see. We will use a 240 x 240 pixel IPS LCD, 1.8 inches diagonal, communicating using an adjusted type of SPI. The LCD has a built-in controller, a ST7789. With the highest color depth resolution (2 bytes per color), it takes 240 x 240 x 2 = 115200 bytes of data to fill the screen.
We will create an algorithm to take an ASCII character, like ‘H’ (also represented by decimal 72), and draw it so that the top left corner is at any pixel location, using LCD_drawPixel
to write the ASCII matrix contents to the LCD. When we have written a function that can draw one character to the LCD, we can make a char array with sprintf()
, and call the function in a loop to display every character in the string. Finally, we will have an LCD showing “Hello world %d!” starting at (28,32), and below it a progress bar with the length of the displayed integer. Increment the integer from 0 to 100 at 10Hz, or as fast as it will go, displaying the live FPS.
To add a little color to our circuit, we’ll use some WS2812B addressable color LEDs in an 8mm package from Sparkfun. The WS2812B is also called a Neopixel and comes on sticks, rings, matrices, and infinitely long lengths of flexible tape. Traditional color LEDs are very pin-intensive. Each LED is really a red, green, and blue LED cast inside the same plastic lens. Each needs to be set for intensity using a unique PWM, and a microcontroller like the PIC32MX170F256B has only 5 PWM pins, so it couldn’t even drive 2 LEDs. Other brands of microcontrollers have many more PWM-capable pins, but even then it would take a lot of multiplexing to drive a lot of color LEDs.
WS2812B are a nice solution. They have a built-in controller that takes a single digital signal to set the brightness of the red, green, and blue LEDs, and if you immediately send another color, the data is passed through to the next WS2812B. That means you can chain WS2812Bs in series and control each color and brightness uniquely with only one pin from the microcontroller.
ws2812b_setColor()
is the main function. The function takes as input an array of colors and the number of WS2812Bs in the circuit. In the function, you need to loop through each pixel in each color, and into another array, save the time in Timer2 ticks at which the pin should invert to blink out the highs and lows to make the logic Ones and Zeros. Once this array is made, it is a simple process to set Timer2 to start at 0, and inside a loop wait for the timer value to hit each array value, and when it does invert the pin. The while loop adds some extra cycles, which could knock the timing off, so the LOWTIME and HIGHTIME constants are adjustable. Once we can set the colors, use the HSBtoRGB()
function to generate a changing array rainbow of colors to display on your LEDs.
An IMU, or Inertial Measurement Unit, is a sensor that is used to calculate position, velocity, or acceleration. Modern IMUs are MEMS devices, with built-in analog-to-digital converters, and their own dedicated microcontroller to control and process the data. Common IMUs combine accelerometers, gyroscopes, magnetometers, and altimeters. Often they come packaged together in a single chip. The sensors typically communicate over I2C or SPI. We will use the LSM6DS33 accelerometer and gyroscope chip made by ST, soldered onto a breakout board by Adafruit.
This chip measures acceleration (accelerometer) and angular velocity (gyroscopic) data about the X, Y, and Z axes with 16-bit resolution, with a variety of sensitivities. It contains a temperature sensor so that it can self-correct for temperature effects, and we can also access the temperature data as a 16-bit number.