Skip to content

10. Output Devices

This week’s goal was to program an output device, simple or heavily complicated, using the embedded programming board that we designed last week.

Files can be downloaded here.

Requirements

Individual Assignment:

  • Add an output device to a microcontroller board you’ve designed, and program it to do something.

Group Assignment:

  • Measure the power consumption of an output device.

OLED

I decided to try and program an OLED, as that would likely be the output device of choice for my final project. In this week, I just wanted to begin to know how to use it with the ATtiny412, which is our lab’s main chip of choice. I wanted to program the OLED using both an Arduino Uno and the ATtiny412 chip, so I began to look into both. According to the SSD1306 datasheet, the OLED can communicate through Inter-Integrated Circuit (I2C) using a slave address bit, which must be recognized before data can be transmitted or recieved, a I2C bus data signal or SDA, which acts as the channel for data between the trasmitter and reciever, and I2C bus clock signal or SCL, which calibrates the transmission rate for information across SDA according to the clock period of SCL. For much of this process, I chose to work with Connor Cruz since he also chose to do an OLED screen as his output device.

Programming the OLED Through Arduino Uno

Programming the OLED with an Arduino Uno was a pretty simple process with only one large issue. To start, I began to look up tutorials on how to program the OLED, and found a simple one on this page. Unfortunately, due to my haste, I skimmed past a crucial detail that explained what ports of the Arduino Uno I was supposed to plug the jumper cables I was using in. I believed that I needed to use the ports labeled “SCL” and “SDA”, as there were holes on the OLED that had the same labels. The reason that I missed the correct details on the website was that the link I had selected from Google automatically scrolled down to the techincal programming part of it, so I did not read the information that came before. This tutorial explained that the Adafruit SSD1306 library needed to be installed, so I went into Ardunio’s library manager and installed it while making sure to also install all dependencies. Then, I began to write the code for the system, and the steps went like this: include the proper libraries, define the size of the OLED screen, declare the SSD1306 OLED as an object, initialize the display and check if the connection is faulty, and write the proper code involved with displaying text in the correct position and with a set size and color.

To demonstrate the I understood the code to some degree and how to modify it, I changed the loop function to include some text, as the only output before had been the “Hello World” message in the setup function. In the code that I added, I used the “clearDisplay”, setTextSize, setTextColor, setCursor, println, display, and delay functions to write my code.

#include <Wire.h>
#include <Adafruit_GFX.h>  
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width,  in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// declare an SSD1306 display object connected to I2C
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(9600);

  // initialize OLED display with address 0x3C for 128x64
  if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    while (true);
  }

  delay(2000);         // wait for initializing
  oled.clearDisplay(); // clear display

  oled.setTextSize(1);          // text size
  oled.setTextColor(WHITE);     // text color
  oled.setCursor(30, 40);        // position to display
  oled.println("Hello World!"); // text to display
  oled.display();
  delay(1000);         // show on OLED
}

void loop() {
  oled.clearDisplay();
  oled.setTextSize(1);          // text size
  oled.setTextColor(WHITE);     // text color
  oled.setCursor(30, 40);        // position to display
  oled.println("bahhhh");
  oled.display();
  delay(5000);
}  

As you can see in this image (ignore the Xiao RP2040), the jumper cables go from the ports labeled SCL and SDA on the Arduino Uno to the SCL and SDA pins of the OLED, which causes it to turn on and display “Hello World” but, from my perspective, be unchangeable after the intial code is loaded onto it. To fix this, I looked into other documentation and found Ryan Kim’s, who was in the Charlotte Latin Fab Lab a year before me. His documentation showed what the main issue was, as the cables had to be switched to pins A4 for SDA and A5 for SCL in the analog pins section of the board. I made this shift, and found that it worked now!

Two notes are that this video is sped up for the sake up compression and the video shows at the beginning the text already displayed, as the purpose of this video was just to show what happens when the program is first ran (accomplished by pressing the reset button on the Arduino Uno). Now that this section of the process was complete, I could move onto programming the OLED through an ATtiny412.

Programming the OLED Through ATtiny412

To start out with programming the ATtiny412, I followed a similar process at the start as before by trying to look up some tutorials on how to program it. Since I already knew the ATtiny412 pinouts, I decided to wire the OLED before getting too deep into others’ instructions. Fortunately, the two pins on the ATtiny412 that I had created header pins for turned out to be the SCL and SDA pins, which simplified the process greatly and meant that I did not have to create a new board (yet) for this week.

The first steps I took were testing the OLED with some sample code to see if the ATtiny412 was compatible with the OLED, and found Vincent Zhou’s documentation, where he successfully programmed the OLED. Since his code is over 300 lines, I will not put it into my code, so it can be found by just going to his site. When I ran this code, I discovered that it was able to work by moving around the connector pins a bit. For Arduino IDE, I used the ATtiny412 settings that have been previously mentioned in earlier weeks.

Even though I was able to make the OLED turn on and display the code, I was not satisfied with the outcome, as I did not understand the code nor did I feel accomplished. One of the first steps I took was to copy Neil’s code from the schedule, but when I ran this code and uncommented one of the lines as directed by the comments on the code, it did not work. I recieved multiple errors messages stating that different values had not been declared.

Compilation error: 'DDRB' was not declared in this scope

This was similar to an error I encountered when baremetal programming, but this time, with the new aspects of this code, such as the new libraries and the fact that I was using an OLED instead of a simple LED, I did not know what to do. I tried searching up the code error to no avail, as most of the results said that it generally had something to do with the selection of the board in the settings, even though the same selection had worked before.

I decided to look elsewhere to try and find help and found this documentation, where someone else tried using the ATtiny412 to program an OLED, but they ended up referencing Vincent Zhou as well and not including an indicator of their final result.

Just simply trying to run the code from the Arduino Uno created a long list of errors, and by checking some of these, I discovered that the ATtiny412 did not have enough Flash memory for the libraries. One of the main limitations that I encountered was the size of the storage for the ATtiny412 chip, as the libraries I used for the Arduino Uno exceeded the maximum space for the chip. Because of this, I began to look into alternatives that might take up less space.

One failed attempt that I made was to try to modify the Adafruit SSD1306 library by removing potentially unneeded files and similar extraneous items. I copied the library that I already had, and began to try to delete different files, but was quickly stopped when I realized that certain files, such as an integral scripts file, far exceeded the 4KB Flash, 256B SRAM and 128B of EEPROM that the ATtiny412 had. I decided to give up on this lead.

I went to the u8g2 library next, as that was the library that Neil had linked on the schedule, and alongside a tutorial I found that explained the code, I ran the following example. The section labeled “constructor” is meant to reference the specific type of board being used, so I scrolled down and found one labeled SSD1306.

#include <Arduino.h>
#include <SPI.h>
#include <U8g2lib.h>

/* Constructor */
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); // [page buffer, size = 128 bytes]

/* u8g2.begin() is required and will sent the setup/init sequence to the display */
void setup(void) {
  u8g2.begin();
}

/* draw something on the display with the `firstPage()`/`nextPage()` loop*/
void loop(void) {
  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_ncenB14_tr);
    u8g2.drawStr(0,20,"Hello World!");
  } while ( u8g2.nextPage() );
  delay(1000);
}

When I ran this on Arduino, I got another long list of errors with many complicated lines that consisted of file directories and other messages about certain values not fitting within other values. Feeling somewhat fed up with how I kept recieving these irratating issues, I decided to ask ChatGPT for what was going on with these errors. Below is the prompt I typed in alongside ChatGPT’s response.

I am trying to use the U8G2 library to program an OLED, and when I run the code with the proper calibration for the u8g2 setup, I get a series of errors. Please explain these errors.

Code: (excluded for sake of space)

Errors:

c:/users/lando/appdata/local/arduino15/packages/dxcore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino7b1/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: address 0x2386 of C:\Users\lando\AppData\Local\Temp\arduino\sketches\13229355B6F2DFDB93470F84D97FB085/sketch_feb28a.ino.elf section `.text' is not within region `text'     c:/users/lando/appdata/local/arduino15/packages/dxcore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino7b1/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: C:\Users\lando\AppData\Local\Temp\arduino\sketches\13229355B6F2DFDB93470F84D97FB085/sketch_feb28a.ino.elf section `.rodata' will not fit in region `text'     c:/users/lando/appdata/local/arduino15/packages/dxcore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino7b1/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: address 0x804424 of C:\Users\lando\AppData\Local\Temp\arduino\sketches\13229355B6F2DFDB93470F84D97FB085/sketch_feb28a.ino.elf section `.bss' is not within region `data'      c:/users/lando/appdata/local/arduino15/packages/dxcore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino7b1/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: address 0x2386 of C:\Users\lando\AppData\Local\Temp\arduino\sketches\13229355B6F2DFDB93470F84D97FB085/sketch_feb28a.ino.elf section `.text' is not within region `text'     c:/users/lando/appdata/local/arduino15/packages/dxcore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino7b1/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: address 0x804424 of C:\Users\lando\AppData\Local\Temp\arduino\sketches\13229355B6F2DFDB93470F84D97FB085/sketch_feb28a.ino.elf section `.bss' is not within region `data'      c:/users/lando/appdata/local/arduino15/packages/dxcore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino7b1/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: region `text' overflowed by 5172 bytes      c:/users/lando/appdata/local/arduino15/packages/dxcore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino7b1/bin/../lib/gcc/avr/7.3.0/../../../../avr/lib/avrxmega3/short-calls/crtattiny412.o: In function `__vectors':      ../../../../../crt1/gcrt1.S:80:(.vectors+0x1c): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_14' defined in .text section in C:\Users\lando\AppData\Local\Temp\cccIEvNj.ltrans0.ltrans.o      ../../../../../crt1/gcrt1.S:85:(.vectors+0x26): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_19' defined in .text section in C:\Users\lando\AppData\Local\Temp\cccIEvNj.ltrans0.ltrans.o       c:/users/lando/appdata/local/arduino15/packages/dxcore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino7b1/bin/../lib/gcc/avr/7.3.0/../../../../avr/lib/avrxmega3/short-calls/crtattiny412.o:../../../../../crt1/gcrt1.S:314:(.init9+0x0): relocation truncated to fit: R_AVR_13_PCREL against symbol `main' defined in .text.startup section in C:\Users\lando\AppData\Local\Temp\cccIEvNj.ltrans0.ltrans.o        c:/users/lando/appdata/local/arduino15/packages/dxcore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino7b1/bin/../lib/gcc/avr/7.3.0/../../../../avr/lib/avrxmega3/short-calls/crtattiny412.o:../../../../../crt1/gcrt1.S:315:(.init9+0x2): relocation truncated to fit: R_AVR_13_PCREL against symbol `exit' defined in .fini9 section in c:/users/lando/appdata/local/arduino15/packages/dxcore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino7b1/bin/../lib/gcc/avr/7.3.0/avrxmega3/short-calls\libgcc.a(_exit.o)        C:\Users\lando\AppData\Local\Temp\cccIEvNj.ltrans0.ltrans.o: In function `delay':       c:\users\lando\appdata\local\arduino15\packages\dxcore\tools\avr-gcc\7.3.0-atmel3.6.1-azduino7b1\avr\include\util/delay.h:187:(.text+0x13e6): relocation truncated to fit: R_AVR_13_PCREL against `no symbol'       C:\Users\lando\AppData\Local\Temp\cccIEvNj.ltrans0.ltrans.o: In function `delayMicroseconds':       C:\Users\lando\AppData\Local\Arduino15\packages\megaTinyCore\hardware\megaavr\2.6.10\cores\megatinycore/wiring.c:990:(.text+0x13f6): relocation truncated to fit: R_AVR_13_PCREL against `no symbol'        C:\Users\lando\AppData\Local\Temp\cccIEvNj.ltrans0.ltrans.o: In function `global constructors keyed to 65535_0_sketch_feb28a.ino.cpp.o.18245':        <artificial>:(.text.startup+0x12e): relocation truncated to fit: R_AVR_13_PCREL against `no symbol'       <artificial>:(.text.startup+0x180): relocation truncated to fit: R_AVR_13_PCREL against `no symbol'       C:\Users\lando\AppData\Local\Temp\cccIEvNj.ltrans0.ltrans.o: In function `delay':       C:\Users\lando\OneDrive\Documents\Arduino\sketch_feb28a/sketch_feb28a.ino:17:(.text.startup+0x406): relocation truncated to fit: R_AVR_13_PCREL against `no symbol'       c:/users/lando/appdata/local/arduino15/packages/dxcore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino7b1/bin/../lib/gcc/avr/7.3.0/avrxmega3/short-calls\libgcc.a(_ctors.o): In function `__do_global_ctors':        /home/admin/Arduino/toolchain-avr-special-master/gcc-build/avr/avrxmega3/short-calls/libgcc/../../../../../gcc/libgcc/config/avr/lib1funcs.S:2481:(.init6+0xc): relocation truncated to fit: R_AVR_13_PCREL against symbol `__tablejump2__' defined in .text.libgcc section in c:/users/lando/appdata/local/arduino15/packages/dxcore/tools/avr-gcc/7.3.0-atmel3.6.1-azduino7b1/bin/../lib/gcc/avr/7.3.0/avrxmega3/short-calls\libgcc.a(_tablejump2.o)
collect2.exe: error: ld returned 1 exit status

exit status 1

Compilation error: exit status 1

ChatGPT Response:

These errors indicate that your code is encountering problems during the linking stage of compilation. Let's break down the errors:

Region Overflow Errors:

region 'text' overflowed by 5172 bytes: This error suggests that the code you've written is too large to fit into the designated program memory (flash) of the microcontroller.
.rodata' will not fit in region 'text': Similar to the previous error, it indicates that the read-only data section (rodata) is too large to fit in the program memory region.
.bss' is not within region 'data': This error suggests that the uninitialized data section (bss) is too large to fit in the designated data memory region.
Relocation Truncated Errors:

These errors suggest that certain relocations (memory references) cannot be resolved because they would require more bits than available to store the relative address. This can happen when the code is too large to fit into the available memory space.
Other Errors:

Compilation error: exit status 1: This is a generic error message indicating that the compilation process failed. It's likely a result of the previous errors.
To resolve these issues, you may need to optimize your code to reduce its size, or consider using a microcontroller with larger memory capacity. Here are some optimization techniques you can consider:
Use smaller data types where possible (e.g., uint8_t instead of int). Minimize the use of libraries or functions that consume a lot of memory. Remove any unnecessary code or features. Consider using PROGMEM to store constant data in flash memory instead of RAM. If possible, switch to a microcontroller with more program memory if your current one is insufficient. Additionally, you might want to check if there are any compiler flags or settings that can help reduce the code size. Sometimes, enabling optimization flags (-Os for size optimization) can make a significant difference.

To figure out the exact size of this sketch, I went to Tools > Board > megaTinycore > ATtiny1614/1604/814/804/414/404 w/Optiboot. Having selected this new board that has more storage, I could run a compile to see the size of the sketch that I had just ran before. I did so, I recieved text stating: Sketch uses 9522 bytes (59%) of program storage space. Maximum is 15872 bytes. Global variables use 1316 bytes (64%) of dynamic memory, leaving 732 bytes for local variables. Maximum is 2048 bytes. As can be seen by this text, the u8g2 library is signifcantly too large, which is causing big problems for trying to run it on the much smaller ATtiny412.

One solution I found was reccomended to me by Connor Cruz, linked above, who mentioned using the SSD1306Ascii library, which is a text-only OLED library that takes up very little space. I downloaded the library from Arduino IDE’s library manager, and loaded the “Wire128x64” library. If it was not known yet, the dimensions (i.e. pixel no. x pixel no.) of the OLED screen I am using are 128x64. I loaded an example and planned to modify the code later to make it more orignal.

// Simple I2C test for ebay 128x64 oled.

#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"

// 0X3C+SA0 - 0x3C or 0x3D
#define I2C_ADDRESS 0x3C

// Define proper RST_PIN if required.
#define RST_PIN -1

SSD1306AsciiWire oled;
//------------------------------------------------------------------------------
void setup() {
  Wire.begin();
  Wire.setClock(400000L);

#if RST_PIN >= 0
  oled.begin(&Adafruit128x64, I2C_ADDRESS, RST_PIN);
#else // RST_PIN >= 0
  oled.begin(&Adafruit128x64, I2C_ADDRESS);
#endif // RST_PIN >= 0

  oled.setFont(Adafruit5x7);

  uint32_t m = micros();
  oled.clear();
  oled.println("Hello world!");
  oled.println("A long line may be truncated");
  oled.println();
  oled.set2X();
  oled.println("2X demo");
  oled.set1X();
  oled.print("\nmicros: ");
  oled.print(micros() - m);
}
//------------------------------------------------------------------------------
void loop() {}

What this code does, from the top, first includes the proper library files for the proper configuration of sending information to the SSD1306. Then, it defines the slave address as 0x3C for data transmission, and defines a RST, or reset, pin in case an issue occurs. The Wire.begin() function initializes the program for programming and connection, and Wire.setClock() sets the send rate that will relate to the SCL pin. The following if statements check the RST pin from above and correct the oled setup functions if needed. The following code the has the “oled.” prefix is all involved with coding the screen of the OLED, with “uint32_t m = micros();” being used to measure the milliseconds since the program first started so that it can be displayed.

This initially did not work, as even though I knew that power was being supplied through the jumper cables using an LED indicator on a breadboard, the board itself was not turning on. I changed up the wiring some to hopefully get new results, but it did not seem to do anything at first.

I realized that I had made a similar mistake to something insignificant earlier, as I put the jumper cable meant to connect to SCL on a PWR header pin of the connector header pins that only has one cable in the image. I changed the wiring again and reran the code.

Now that I had the it working, I decided try to modify the code some in order to add a level of customization to it and make it more detailed. I altered the program by adding a few lines to show an increasing value and the total time, in milliseconds, that has passed since the start of the program.

// Simple I2C test for ebay 128x64 oled.

#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"

// 0X3C+SA0 - 0x3C or 0x3D
#define I2C_ADDRESS 0x3C

// Define proper RST_PIN if required.
#define RST_PIN -1

int i = 1;
uint32_t m;

SSD1306AsciiWire oled;
//------------------------------------------------------------------------------
void setup() {
  Wire.begin();
  Wire.setClock(400000L);

#if RST_PIN >= 0
  oled.begin(&Adafruit128x64, I2C_ADDRESS, RST_PIN);
#else // RST_PIN >= 0
  oled.begin(&Adafruit128x64, I2C_ADDRESS);
#endif // RST_PIN >= 0

  oled.setFont(Adafruit5x7);

  m = micros();
  oled.clear();
  oled.println("Hello world!");
  oled.println("Landon Broadwell");
  oled.println();
  oled.print("\nmicros: ");
  oled.print(micros() - m);

}
//------------------------------------------------------------------------------
void loop() {
  m = micros();

  oled.clear();
  oled.println("Text Section no." );
  oled.println(i);
  oled.print("\nmicros: ");
  oled.print(m/1000);
  i++;
  delay(1000);
}

Value shows the number of .

Despite this working, I still wanted to do more and try to get the u8g2 library to work. Knowing that the main error stemmed from a storage issue, I chose to use the ATtiny1614.

Programming the OLED Through ATtiny1614.

To program the OLED through ATtiny1614, I had to first create a new board that connected the SCL and SDA pins on the chip to the corresponding ports of the OLED. To assist in creating the board for these pins, I referenced the following pinout diagram.

I went into KiCad and designed a simple schematic with footprints from the KiCad Fab library, which can be found [here] INSERT LINK. The components I used were the ATtiny1614, a 1x03 connector header pin, a 1x04 connector header pin, a 1uF capacitor, a 499 Ohm resistor, and a blue LED.

Then, I opened up the PCB Editor and routed all the connections, making sure that I had an edgecuts layer and that the trace/track width was at the reccomended .5mm.

I used our lab’s milling machine with Bantam Software to mill out the files and create my board. For details on the milling process, visit my week 4 documentation.

After gathering the aformentioned components, I soldered them onto the correct spots while making sure that the orientation of the chip and LED were the proper direction. Once again, for more details on this process, refer to week 4.

Using the same setup as with the ATtiny412, I hooked up the board and saw that the indicator LED was on, which meant that power was being supplied and the board was routed correctly. I used some jumper cables to then connect the OLED from the 1x04 pins I used. Then, with the example code from the tutorial mentioned much earlier when I initially tried to use the u8g2 library, I ran the program.

The first error that I got said: “avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x30”, and showed nine other lines all displaying other error messages with the attempt number being different. I looked up this error and found an Arduino forum that mentioned changing the board type. In the tools menu, I changed the board from “ATtiny1614…w/Optiboot” to “ATtiny3224/1624/1614…”. I believe that the issue that occurred here was that the Optiboot feature was not compatible with how I was trying to program the board.

Then, I reuploaded and got a new error saying “Device ID mismatch! Stopping.” I checked the Tools menu after viewing a Reddit Forum, and saw that, under “Chip”, it was set to ATtiny3224 instead of ATtiny1614, so I made that change and uploaded once more. While it did successfully go through, the board was yet to turn on.

Since I was getting no hardware issues now, I began to look into my code. Knowing the long list of construtor lines that were part of the u8g2 tutorial and were in many of the example codes built into the u8g2 library, I decided to check that. Constructor lines are lines that, when used in this library, initialize the different aspects of the OLED screen being used. Before, I was using this:

U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);

I was not entirely sure of what all of this meant, but I did notice the mention of SPI, which I recognized as the name of a different type of communication system that is different from I2C. To fix this, I copied a different constructor line from the examples that had I2C in the name. There were several, but the code I was using had the “Wire” library incorporated into it, and the example website explained that an “HW” should precede the I2C part of the constructor line when using the Wire library. After figuring this out, I chose the following option:

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

With this being the final setup, I modified the code some more to produce the final result:

#include <Arduino.h>
#include <U8g2lib.h>
#include <SPI.h>
#include <Wire.h>

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

void setup(void) {
  u8g2.begin();
}

void loop(void) {
  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_ncenB14_tr);
    u8g2.drawStr(0,24,"Landon Broadwell!");
    u8g2.drawStr(0,36, "OLED Screen");
  } while ( u8g2.nextPage() );
}

I ran this, and it successfully printed out the correct text at the correct position.

Unfortunately, due to the frame rate of the camera and the display rate of the OLED, part of the text got cut off, but it did fully work when viewing it in real time. Since I had now programmed the OLED in several ways, I was satisfied with what I accomplished this week and had now completed the week.

Group Project

The group project for this week was to measure the voltage consumption and current of an output device. I worked with Connor Cruz, who, as stated previously, also was programming the OLED. My individual contribution was just helping hold the connections with the multimeter and observe the measurements. Our group page can be found here.

Reflection

This was a long but very fun week that I enjoyed being able to go into depth about. The many different methods to program this one OLED demonstrated how deep and varied many of the aspects of the programming world are. Going through the different libraries and methods to program the OLED with different boards granted me a fundamental understanding of how the component works, which will be important for the output system of my final project. Overall, this was a satisfying week with bountiful insights.