Week 10 - Output Devices
This week we have the following tasks to complete:
- measure the power consumption of an output device
- add an output device to a microcontroller board you've designed and program it to do something
Group Assignment
The weekly group assignment can be accessed here.
OLED Display
For testing I used my devboard from week 08.
Beside the NeoPixel that I used in week 08 I experiment with a 0.96" 128x64 px OLED display by first running a simple "Hello World" program, where I go inspired by Sungmoon Lim. I modified his code and come up with the following:
#include <Wire.h> // include wire library need it for the Adafruit_GFX library
#include <Adafruit_GFX.h> // include Adafruit_GFX library need it for the Adafruit_SSD1306 library
#include <Adafruit_SSD1306.h> // include Adafruit_SSD1306 library tp control the OLED display
#define SCREEN_WIDTH 128 // set OLED display width
#define SCREEN_HEIGHT 64 // set OLED display height
#define OLED_RESET -1 // set the reset pin
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // initialize an Adafruit_SSD1306 object called display with the parameters from above
void setup() {
Serial.begin(115200); // initialize serial communication with a baudrate of 115200
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // checked if a display is available
Serial.println(F("SSD1306 allocation failed")); // if no display is available send an error message to the serial monitor
for(;;);
}
display.clearDisplay(); // clear the display --> set every pixel to black
}
void displayMessage(const char* message) { // function to visualize a message on the display
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE); // set the text color
display.setCursor(0,0); // set the position where the text is shown on the display
display.println(message); // send the input from the function to the display
display.display(); // show data on the display with the parameters from above
}
void loop() {
displayMessage("Hello World"); // display "Hello World" on the display
delay(3000); // delay the next message so there is a chance to read it
displayMessage("Hello FabAcademy"); // display "Hello FabAcademy" on the display
delay(3000); // delay the next message so there is a chance to read it
displayMessage("Hello Ilmenau"); // display "Hello Ilmenau" on the display
delay(3000); // delay the next message so there is a chance to read it
}
The next step is to show something more useful, for that the display will show the value from the rotary encoder.
#include <Wire.h> // include wire library need it for the Adafruit_GFX library
#include <Adafruit_GFX.h> // include Adafruit_GFX library need it for the Adafruit_SSD1306 library
#include <Adafruit_SSD1306.h> // include Adafruit_SSD1306 library tp control the OLED display
#include <Encoder.h> // library for rotary encoder
#define SCREEN_WIDTH 128 // set OLED display width
#define SCREEN_HEIGHT 64 // set OLED display height
#define OLED_RESET -1 // set the reset pin
#define dt D8 // Xiao pin that connects to rotary encoder dt
#define clk D10 // Xiao pin that connects to rotary encoder clk
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // initialize an Adafruit_SSD1306 object called display with the parameters from above
Encoder interface(dt,clk); // initiate rotary encoder
int encoder_value = 0; // value of rotary encoder
void setup() {
Serial.begin(115200); // initialize serial communication with a baudrate of 115200
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // checked if a display is available
Serial.println(F("SSD1306 allocation failed")); // if no display is available send an error message to the serial monitor
for(;;);
}
display.clearDisplay(); // clear the display --> set every pixel to black
}
void displayMessage(int message) { // function to visualize a message on the display
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE); // set the text color
display.setCursor(0,0); // set the position where the text is shown on the display
display.println("Encoder Value:"); // send the input from the function to the display
display.setCursor(0,10); // set the position where the text is shown on the display
display.println(message); // send the input from the function to the display
display.display(); // show data on the display with the parameters from above
}
void loop() {
if (encoder_value != interface.read()){ // read out the value from the rotary encoder
encoder_value = interface.read(); // overwrite the old stored encoder value
}
displayMessage(encoder_value); // display the encoder value on the display
}
In preparation for my final project, I tested a larger 2.42" OLED display in addition to the smaller 0.96" version. To interface with it, I designed and manufactured a small PCB adapter for this display module.
To enable I2C communication, I followed the instructions in the official manual and resoldered two resistors on the back of the display.
The adapter was also necessary because, in addition to the +5V, GND, SCL, and SDA lines, an additional I/O pin is required, as described in the manual and the pin positions are different.
The final output devices are MOSFETs from a previous project, for which I had already designed and ordered a PCB.
Due to communication issues I encountered in Week 11, I created a small adapter board to mount a XIAO ESP32C3 instead of the originally used Wrover module.
At the time I designed this circuit, I wasn’t aware of the MOSFETs available in the FabInventory, so I used MOSFET driver ICs to control the MOSFETs. The ESP32 sends a signal to the driver, which then outputs a higher-power signal to the MOSFET, allowing it to switch a connected light source.
const int green1 = 1; // define pin to control the green led's from the first led strip, 1 represent d1
const int red1 = 2; // define pin to control the red led's from the first led strip, 2 represent d2
const int blue1 = 3; // define pin to control the blue led's from the first led strip, 3 represent d3
const int spot1 = 4; // define pin to control the first raw of spots, 4 represent d4
const int green2 = 6; // define pin to control the green led's from the second led strip, 6 represent d6
const int red2 = 7; // define pin to control the red led's from the second led strip, 7 represent d7
const int blue2 = 8; // define pin to control the blue led's from the second led strip, 8 represent d8
const int spot2 = 9; // define pin to control the second raw of spots, 9 represent d9
void setup() {
Serial.begin(115200); // initial serial communication with a baud rate of 115200
pinMode(green1,OUTPUT); // define pin d1 as an output
pinMode(red1,OUTPUT); // define pin d2 as an output
pinMode(blue1,OUTPUT); // define pin d3 as an output
pinMode(spot1,OUTPUT); // define pin d4 as an output
pinMode(green2,OUTPUT); // define pin d6 as an output
pinMode(red2,OUTPUT); // define pin d7 as an output
pinMode(blue2,OUTPUT); // define pin d8 as an output
pinMode(spot2,OUTPUT); // define pin d9 as an output
}
void loop() {
for (int i = 0; i < 256; i++) { // go through all possible values of a pwm signal
byte r = (i < 85) ? i * 3 : (i < 170) ? 255 - (i - 85) * 3 : 0; // set first set of number ranges for a color cycle
byte g = (i < 85) ? 255 - i * 3 : (i < 170) ? 0 : (i - 170) * 3; // set second set of number ranges for a color cycle
byte b = (i < 85) ? 0 : (i < 170) ? (i - 85) * 3 : 255 - (i - 170) * 3; // set third set of number ranges for a color cycle
analogWrite(red1,r); // output a pwm signal with the value according to the red color in the color cycle on pin d2
analogWrite(green1,g); // output a pwm signal with the value according to the green color in the color cycle on pin d1
analogWrite(blue1,b); // output a pwm signal with the value according to the blue color in the color cycle on pin d3
analogWrite(spot1,i); // output a pwm signal with the value according to the running variable on pin d4
analogWrite(red2,r); // output a pwm signal with the value according to the red color in the color cycle on pin d7
analogWrite(green2,g); // output a pwm signal with the value according to the green color in the color cycle on pin d6
analogWrite(blue2,b); // output a pwm signal with the value according to the blue color in the color cycle on pin d8
analogWrite(spot2,i); // output a pwm signal with the value according to the running variable on pin d9
/*Serial.println(i);
Serial.print("red 1 = ");
Serial.println(red1);
Serial.print("green 1 = ");
Serial.println(green1);
Serial.print("blue 1 = ");
Serial.println(blue1);
Serial.print("spot 1 = ");
Serial.println(spot1);
Serial.print("red 2 = ");
Serial.println(red2);
Serial.print("green 2 = ");
Serial.println(green2);
Serial.print("blue 2 = ");
Serial.println(blue2);
Serial.print("spot 2 = ");
Serial.println(spot2);*/
}
}
For future integrations a second spot channel is added even if there are no second raw of spots connected in the moment. The first rgb led strip is on top of the shelf and the second rgb led strip is in the shelf. The spots are installed over the counter.
What I learned this week
- Working with displays can be easier than I thought.
- It’s beneficial to explore the details of libraries rather than just using them blindly.
What I want to improve next week
- Improve my time management again, I tried to maxed everything out which did't work so I have to go one step back to finish everything in time.
Design Files
dev board project
oled board schematic
oled board traces
oled board holes outline
light controller schematic
adapter schematic
adapter traces
adapter holes outline
To create this page, I used ChatGPT to check my syntax and grammar.
Copyright 2025 < Benedikt Feit > - Creative Commons Attribution Non Commercial
Source code hosted at gitlab.fabcloud.org