Skip to content

9. Output Devices

Group assignment:

  • Measure the power consumption of an output device.

  • Document your work on the group work page and reflect on your individual page what you learned.

Individual assignment:

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

Download Design Files

Click here to download my design files folder

Group Work Reflection

The group work helped me to better understand how different output devices consume power differently; our servo consumed a substantially larger amount than Connor and Landon’s OLED. Depending on the complexity, movement, etc. of components, they consume power differently. To ensure we provide enough power and choose the best components in our final projects, knowing the power consumption of our components and how to find it is very important.

Link to Group Work Page

Research & Planning

Before starting this week, I discussed what sensors Mr. Durrett would suggest for my final project. After discussing with him for awhile, we determined a limit switch button (input) and an OLED screen (output) would work well for my final project. Later, however, after talking to Dr. Taylor, he suggested I use an I2C LCD instead of an OLED. I decided that, since my fellow lab mates were having success with the I2C LCD, it would be a good path foward.

I2C LCD

Angelina Yang had success with programming the I2C LCD so I first staretd by reading through her output devices’s documentation.

I used a serial LCD display with an I2C/IIC serial adapter installed.

Programming with Arduino Uno

This article helped me to better understand how to wire the I2C LCD to the Arduino Uno.

I wired it as shown below:

I then dowloaded the LiquidCrystal I2C library and the hd44780 library. From this I tried uploading a HelloWorld sketch but faced multiple issues.

Once I got the LCD working, I uploaded a code that showed the text “hey y’all!!!”

#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip
byte customChar[8] = {
0b00000,
0b11011,
0b11111,
0b01110,
0b00100,
0b00000,
0b00000,
0b00000
};

int buttonstate = 0 ;

const int LCD_COLS = 16;
const int LCD_ROWS = 2;


void setup()
{
int status;


status = lcd.begin(16, 2);

pinMode(4, INPUT);
lcd.print("Hello, World!");
lcd.setCursor(0, 1);

lcd.home();
}

int seconds = 0;
int minutes = 0;
int count = 0;
void loop() {

buttonstate = digitalRead(4);

if (buttonstate == LOW) {

    lcd.print("hey y'all!!!");

    delay(1000);

    seconds = 0;
    minutes = 0;

    }

    lcd.clear();
}

Problems

1. UPDI initialisation failed & Long upload time

The first error I got was:

pymcuprog-pymcuprog_errors.PymcuprogError: UPDI initialisation failed

I then switched the programmer I was using and tried uploading the code again but it took a very long time to upload. I got this error:

avrdude: stk500_rec(): programmer is not responding

avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp-0x0a

avrdude: stk500_rec(): programmer is not responding

avrdude: stk500 _getsync() attempt 4 of 10: not in sync: resp-0x0a

avrdude: stk500 _rec(): programmer is not responding

avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp-ex0a

avrdude: stk500_rec(): programmer is not responding

avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp-0x0a

avrdude: stk500_recv() : programmer is not responding

avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp-Bx0a

avrdude: stk500_rec(): programmer is not responding

avrdude: stk500 _getsync() attempt 8 of 10: not in sync: resp-ox0a

avrdude: stk500_rec(): programmer is not responding

avrdude: stk500 _getsync() attempt 9 of 10: not in sync: resp-exea

avrdude: stk500_recv() : programmer is not responding

avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp-0x0a

Failed uploading: uploading error: exit status 1

I was super frustrated and confused, I spent hours and hours trying to figure this out before I finally came to the very fortunate but frustrating relization that my Arduino Uno was broken.

  • the fix: got a new Arduino Uno
2. Very dim screen/display

Once I got a new Arduino Uno, I uploaded the code and it worked! Unfortunatley, though, it was so dark it was barely readable. I tried adjusting the potentiometer by rotating it with a phillips head screwdriver which, although it changed the appearance slightly, it did not help the extreme darkness of the screen.

I simply thought that this was normal and I was just having weird vision that day… until Angelina Yang came over and pointed out that this was not normal. So, I got a new I2C LCD.

  • the fix: got a new I2C LCD

Programming with Microcontroller Board

PCB Board

I made a new PCB for this week,

PCB:

Milled:

Soldered:

The components it used were:

  • 1 x Male 1x04 header

  • 1 x Male 1x03 header

  • 1 x ATtiny1614

  • 1 x 1206 1uF Capacitor

  • 1 x 499 ohm smd resistor

  • 1 x 1206 Blue LED

  • 1 x small push button/tactile switch

note that I ended up using Angleina Yang’s PCB which is the same schematic as mine was because we used the same output device. I fried my board twice and was in a bit of a time crunch so she majorly helped me out!

I then wired the LCD to the PCB as shown below:

Programming

I then tried uploading code to it and it worked!

Problems

1. Fried board

I had planned to use my quentorres to act as a programmer for the PCB board, however, it didn’t quite work out… I ended up frying the board and burnt my finger on the ATtiny1614 :’)

  • the fix: checked my schematic/PCB, had my peers look over it, and mill/solder a new board
2. Fried board pt. 2

After frying the previous PCB, I thought that maybe something was wrong with that mill/solder job. I had my peers look over my schematic and PCB with me, and we couldn’t find anything wrong with the design. Thus, I re-milled and soldered a new board.

Milled:

Soldered:

Wired, again:

Then, when trying to upload code to it, I fried this board too (#lovinlife :’) )

3. Quentorres broke

My quentorres board stopped working (yippie! :’) ). David Vaughn had made his own board that served the same function as a programmer than the quentorres did but was more simple. I decided to make his board as my new programmer because I really liked it!

Milled:

Soldered:

The components on it are:

  • 1 x Seeed studio XIAO RP2040

  • 1 x 4.99k ohm resistor

  • 1 x female 3-pin header

  • the fix: made a new board

I ended up not needing to use this board as I had successfully programmed the board with the Quentorres and got the LCD working, however, I will be using this board in the furture :)

Coding

The breakdown of the code/my process with it and the problems I encountered are detailed below:

Liquid Crystal Library: HelloWorld example code

  • Problems: it wouldn’t upload

  • My fix: trying a different code

  • The hindsight-problem-identification: it was the Arduino Uno that didn’t work

The example code came from LiquidCrustal by Arduino, Adafruit, version 1.0.7

As detailed in my hardware problems documentation earlier, my Arduino Uno was not working. This lead to me not being able to get a simple HelloWorld example code to be able to upload. I was worried that, for some reason, maybe my code was the problem (I know it’s an example code, but still, I wasn’t sure). Because of this, I ended up using Angleina Yang’s code that she had got working when she was using the I2C LCD. Through all the hardware issues that I later figured out, it’s likely that my code was not the problem; however, I ended up modifying Angelina’s code to make it more simple which helped me to better understand what each piece of the code did.

Successful Upload

  • Problems: code way too advanced for what I needed & the screen is barely readable

  • My fix: continue to break down the code & use ChatGBT to help identify what parts of the code mean and get a new LCD (hardware issue)

  • The hindsight-problem-identification: hardware issue with the LCD

So, after I fixed the hardware issue with my Arduino Uno, I tried uploading Angelina Yang’s code because I new it worked for her (I was really pulling at strings here trying to figure out what was wrong because the hardware issues had me so frazzled and confused and I felt very hopeless not being able to upload a simple example HelloWorld code 😣).

When I uploaded the code, I first thought it didn’t work; however, after really staring at the screen, I realized it worked and had uploaded! I was very excited, however, I was also confused as to why the screen was so hard to read. I, again, thought it was a me issue and not a hardware issue and just kind of dealt with it until Angelina came to my rescue and pointed out that this was not normal. I then dealt with this issue as documented earlier with the hardware issues.

note that this picture was brightened so that you could see the text on the screen

unedited the screen looked like this:

The code:

// vi:ts=4
// ----------------------------------------------------------------------------
// HelloWorld - simple demonstration of lcd
// Created by Bill Perry 2016-07-02
// bperrybap@opensource.billsworld.billandterrie.com
//
// This example code is unlicensed and is released into the public domain
// ----------------------------------------------------------------------------
//
// This sketch is for LCDs with PCF8574 or MCP23008 chip based backpacks
// WARNING:
//  Use caution when using 3v only processors like arm and ESP8266 processors
//  when interfacing with 5v modules as not doing proper level shifting or
//  incorrectly hooking things up can damage the processor.
// 
// Sketch prints "Hello, World!" on the lcd
//
// If initialization of the LCD fails and the arduino supports a built in LED,
// the sketch will simply blink the built in LED.
//
// NOTE:
//  If the sketch fails to produce the expected results, or blinks the LED,
//  run the included I2CexpDiag sketch to test the i2c signals and the LCD.
//
// ----------------------------------------------------------------------------
// LiquidCrystal compability:
// Since hd44780 is LiquidCrystal API compatible, most existing LiquidCrystal
// sketches should work with hd44780 hd44780_I2Cexp i/o class once the
// includes are changed to use hd44780 and the lcd object constructor is
// changed to use the hd44780_I2Cexp i/o class.

#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip
byte customChar[8] = {
0b00000,
0b11011,
0b11111,
0b01110,
0b00100,
0b00000,
0b00000,
0b00000
};

// If you wish to use an i/o expander at a specific address, you can specify the
// i2c address and let the library auto configure it. If you don't specify
// the address, or use an address of zero, the library will search for the
// i2c address of the device.
// hd44780_I2Cexp lcd(i2c_address); // specify a specific i2c address
//
// It is also possible to create multiple/seperate lcd objects
// and the library can still automatically locate them.
// Example:
// hd4480_I2Cexp lcd1;
// hd4480_I2Cexp lcd2;
// The individual lcds would be referenced as lcd1 and lcd2
// i.e. lcd1.home() or lcd2.clear()
//
// It is also possible to specify the i2c address
// when declaring the lcd object.
// Example:
// hd44780_I2Cexp lcd1(0x20);
// hd44780_I2Cexp lcd2(0x27);
// This ensures that each each lcd object is assigned to a specific
// lcd device rather than letting the library automatically asign it.

// LCD geometry

int buttonstate = 0 ;

const int LCD_COLS = 16;
const int LCD_ROWS = 2;
const int study_minutes = 25;

void setup()
{
int status;

// initialize LCD with number of columns and rows: 
// hd44780 returns a status from begin() that can be used
// to determine if initalization failed.
// the actual status codes are defined in <hd44780.h>
// See the values RV_XXXX
//
// looking at the return status from begin() is optional
// it is being done here to provide feedback should there be an issue
//
// note:
//  begin() will automatically turn on the backlight
//
status = lcd.begin(16, 2);

pinMode(4, INPUT);
lcd.print("Hello, World! :>");
lcd.setCursor(0, 1);
lcd.createChar(0, customChar);
lcd.home();
}

int seconds = 0;
int minutes = 0;
int count = 0;
void loop() {

buttonstate = digitalRead(4);

if (buttonstate == LOW) {
    lcd.print("study time!");
    lcd.write(0);

    delay(1000);

    seconds = 0;
    minutes = 0;

    // count up and display the timer during study period
    while(minutes<study_minutes){ // keep counting until we've reached the amount for a study session
    seconds = 0;
    // print out the timer value in mm:ss format
    while(seconds<60){
        lcd.setCursor(0, 1);
        if(minutes<10){  // if minutes is less than 10, we need to print an extra 0 to the display
        lcd.print("0");
        }
        lcd.print(minutes);
        lcd.print(":");
        if(seconds<10){  // if seconds is less than 10, we need to print an extra 0 to the display
        lcd.print("0");
        }
        lcd.print(seconds);
        // wait for one second then increment the second counter
        delay(1000);
        seconds++;
    }
    // increment the minute counter after 60 seconds have elapsed
    minutes++;

    }


} else {
    lcd.clear();
}

}

Code edit 1

  • Problems: A very complicated code, want a more basic code

  • My fix: Use Chat GBT and some trial and error to understand how to edit the code the way I want

In this portion of the code:

 buttonstate = digitalRead(4);

if (buttonstate == LOW) {
    lcd.print("study time!");
    lcd.write(0);

    delay(1000);

I edited “study time!” to say “Hello worldd!”

 buttonstate = digitalRead(4);

if (buttonstate == LOW) {
    lcd.print("Hello worldd!");
    lcd.write(0);

    delay(1000);

Code edit 2

  • Problems: I didn’t understand why the heart icon kept popping up on the screen after the “Hellow, World!” of the “Hello, World! :>” went away

  • My fix: messed around with the second lcd.print text until I understood the relationship between the first and second lcd.print’s

What I did was I edited the “study time!” to be a shorter text, “hey y’all!” just to see what would happen.

buttonstate = digitalRead(4);

if (buttonstate == LOW) {
    lcd.print("study time!");
    lcd.write(0);

was changed to

buttonstate = digitalRead(4);

if (buttonstate == LOW) {
    lcd.print("hey y'all!");
    lcd.write(0);

What poped up from uploading this code gave me a “ah-ha!” moment:

I realized that the lcd.print earlier on in the code that pops up before the “hey y’all!” would be replaced by the letters of the new lcd.print but, if no new letters were provided for the spots the original text were, it would remain instead of being cleared. Thus, the heart icon and letter ‘d’ remained with this code

pinMode(4, INPUT);
lcd.print("Hello, World! :>");
lcd.setCursor(0, 1);
lcd.createChar(0, customChar);
lcd.home();
}

int seconds = 0;
int minutes = 0;
int count = 0;
void loop() {

buttonstate = digitalRead(4);

if (buttonstate == LOW) {
    lcd.print("hey y'all!");
    lcd.write(0);

Code edit 3

  • Problems: I wanted to confirm my hypothesises about the text length correlation between the lcd.print’s and understand the heart icon.

  • My fix: try a shorter second lcd.print text

To further my previous idea of the lcd.print’s, I edited “hey y’all!” to be even shorter, “hey yla!”:

buttonstate = digitalRead(4);

if (buttonstate == LOW) {
    lcd.print("hey y'all!");
    lcd.write(0);

to

buttonstate = digitalRead(4);

if (buttonstate == LOW) {
    lcd.print("hey y'a!");
    lcd.write(0);

what popped up confirmed my suspicion about the text length but left me more baffled about the heart icon.

The icon’s placement was the…

  • 12th letter in “study time!”

  • 14th letter in “Hello worldd!”

  • 11th letter in “hey y’all!”

  • 9th letter in “hey y’a!”

I decided to just try and figure out how to get rid of the heart icon from here.

Code edit 4

  • Problems: the timer

  • My fix: use ChatGBT to help get rid of it

When I first tried to do this, I ended up getting this showing up on the LCD:

I’m not entirely sure why this happened.

I then got another weird thing on the screen and am, again, unsure of why it happened:

and again:

The code for these looked like:

#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip
byte customChar[8] = {
  0b00000,
  0b11011,
  0b11111,
  0b01110,
  0b00100,
  0b00000,
  0b00000,
  0b00000
};

int buttonstate = 0 ;

const int LCD_COLS = 16;
const int LCD_ROWS = 2;
const int study_minutes = 25;

void setup()
{
int status;


  status = lcd.begin(16, 2);
  
  pinMode(4, INPUT);
  lcd.print("Hello, World! :>");
  lcd.setCursor(0, 1);
  lcd.createChar(0, customChar);
  lcd.home();
}

int seconds = 0;
int minutes = 0;
int count = 0;
void loop() {

 {
    lcd.print("study time!");
    lcd.write(0);


  }
}

Code edit 5

  • Problems: the heart icon/timer

  • My fix: use ChatGBT and trial & error to get rid of it

Finally, after trying a random assortment of methods, I got the LCD to display a simple “hey y’all!!!”

The code:

#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip
byte customChar[8] = {
  0b00000,
  0b11011,
  0b11111,
  0b01110,
  0b00100,
  0b00000,
  0b00000,
  0b00000
};

int buttonstate = 0 ;

const int LCD_COLS = 16;
const int LCD_ROWS = 2;


void setup()
{
int status;


  status = lcd.begin(16, 2);
  
  pinMode(4, INPUT);
  lcd.print("Hello, World!");
  lcd.setCursor(0, 1);

  lcd.home();
}

int seconds = 0;
int minutes = 0;
int count = 0;
void loop() {

  buttonstate = digitalRead(4);
  
  if (buttonstate == LOW) {

    lcd.print("hey y'all!!!");

    delay(1000);

    seconds = 0;
    minutes = 0;

    }

    lcd.clear();
  }

Hero Shot

The final code:

#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip
byte customChar[8] = {
  0b00000,
  0b11011,
  0b11111,
  0b01110,
  0b00100,
  0b00000,
  0b00000,
  0b00000
};

int buttonstate = 0 ;

const int LCD_COLS = 16;
const int LCD_ROWS = 2;


void setup()
{
int status;


  status = lcd.begin(16, 2);
  
  pinMode(4, INPUT);
  lcd.print("Hello, World!");
  lcd.setCursor(0, 1);

  lcd.home();
}

int seconds = 0;
int minutes = 0;
int count = 0;
void loop() {

  buttonstate = digitalRead(4);
  
  if (buttonstate == LOW) {

    lcd.print("hey y'all!!!");

    delay(1000);

    seconds = 0;
    minutes = 0;

    }

    lcd.clear();
  }

Reflection

This week was really rough for me; I was behind on so much and had school work piling up: in summary, it was stress in a nutshell. However, I do think I learned a lot from this week and was really forced to become more efficent, resillient, and knowledgable. It was rough, but I’m happy with the end result and the understanding I gained :)

References

https://fabacademy.org/2024/labs/charlotte/students/angelina-yang/

https://www.instructables.com/Understanding-the-Pull-up-Resistor-With-Arduino/

https://www.arduino.cc/reference/en/libraries/adafruit-ssd1306/

https://fabacademy.org/2021/labs/waag/students/nadieh-bremer/blog/week-13/

https://fabacademy.org/2024/labs/charlotte/students/angelina-yang/assignments/week10/#i2c-lcd

https://fabacademy.org/2024/labs/charlotte/students/david-vaughn/


Last update: May 4, 2024