Michael Edwards: Fab Academy 2019

Week 12: Output Devices


Individual Assignments:

  1. Add an output device to a microcontroller board you've designed and program it to do something. Incomplete

Group Assignments:

  1. Measure the power consumption of an output device. Incomplete
  1. Charlieplexing
  2. item2
  3. item3


Efficient I/O

Charlieplexing is a multiplexing technique invented by Charlie Allen. It was created to lower the amount of I/O lines required. On the ATtiny44 there are 14 pins. VCC and GND immediately discount two pins, so we have 12. The MOSI, MISO, SCK and RESET pins can be used as outputs, but are used for the ISP, so we are down to 8 pins. How many LEDs can I drive with 8 pins?

If I just wired each LED to a pin I would use 8 pins to drive 8 LEDs:

The simplest form of Charlieplexing allows two LEDs to be driven by two pins. There is no I/O saving over just directly driving the LEDs. I drew the following schematic to practice Eagle, but the information is from Best Microcontroller Projects. If 00 is driven HIGH and 01 set LOW then LED1 would light. If the pin voltages were reversed then the other LED would light.

The next step is to add one more pin. This allows control of 6 LEDs using tri-state logic. The three states are HIGH, LOW and INPUT. INPUT is a high-impedence state and does not allow (much) current to flow. This disconnects the pin from the circuit. So by driving the pins connected to an LED to HIGH and LOW and setting all other pins connected to the matrix to INPUT, any single LED can be lit. Rapid cycling of this technique gives the illusion of multiple LEDs being lit. Image credit: Matthiaspaul, CC BY-SA 3.0.

The equation to work out how many LEDs can be controlled is (n)(n-1) where n is the number of pins. For the two LED example above this would be 2 * 1 and the six LED example would be 3 * 2. There is obviously a finite amount of LEDs that can be driven and there are almost certainly some other issues that I am not aware of that will limit the amount of LEDs that can be driven.

Technical Reference

ATtiny44/Arduino Pin-Out Numbering

To make the Charlieplexing attempt easier, I've gathered some technical information that I think I'll need. First of all, the ATtiny44 pin mumbers do not align with the Arduino pin numbers. The following table (taken from the FabAcademy Tutorials) matches up the pins.

ATtiny44 Pin #Arduino Pin #Details
1VCC (+)
2Pin 10
3Pin 9
4No number, no access?Reset
5Pin 8PWM
6Pin 7 PWM, Analog Input 7
7Pin 6MOSI, PWM, Analog Input 6
8Pin 5 Analog Input 5, PWM, MISO
9Pin 4 Analog Input 4, SCK
10Pin 3Analog Input 3
11Pin 2 Analog Input 2
12Pin 1Analog Input 1
13Pin 0Analog Input 0, AREF
14GND (-)

Here's a quick image I drew of the polarity markings on SMD LEDs. There are lots more methods for identifying this, but the ones we have in the lab are covered by these markings.

Back to the top

Logging Data to an SD card

SD card module

The SD card is a 128GB microSD card connected through an SD card module. Note: The SD card has a 3.3v operating voltage, but the module has a voltage regulator and level shifter to allow the use of 5v. The connection of the SD reader/writer module is quite simple and uses the ISP header pins. There are 6-pins on the module: GND and VCC to power the module, then 4 pins for SPI communication. MOSI (Master Out, Slave In, marked as MOSO on this particular module), MISO (Master In, Slave Out), SCK (serial clock) and CS (chip select in place of slave select). The printing on the module is slightly wrong, but it's easy to work out what they meant.

According to the Arduino site the "Serial Peripheral Interface (SPI) is a synchronous serial data protocol used by microcontrollers for communicating with" peripherals or other microcontrollers (Arduino, 2019). It looks similar to the ISP (In-System Programming) pins (VCC, GND. RST, MOSI, MISO, SCK) but they are not the same. The SPI connection always has "one master device (usually a microcontroller) which controls the peripheral devices" (Arduino, 2019). The MISO, MOSI and SCK are the same on each device. The SS (slave select) line changes per device (the master enables or disables specific devices). "When a device's SS pin is LOW, it communicates with the master. When it's HIGH it ignores the master" (Arduino, 2019).

The respective Arduino pins are:

Module Pin Abbreviation Arduino Pin
Clock select CS 10
Serial clock SCK 13
Master Out, Slave In MOSI 11
Master In, Slave Out MISO 12


Formatting the SD card needs to be done correctly for the Arduino to recognise the SD card. Windows will format anything above 32GB as exFAT - the Arduino can't read this. The card needs to be formatted as FAT32. The file names can only be 8.3 (example8.txt) else the Arduino returns errors. I don't usually say this, but I prefer to force the formatting in Windows Powershell - it is a lot easier than Linux fdisk which has way more control, but I don't really want it!

  1. Windows 10: Right click the Start button or press Win+X.
  2. Open PowerShell as admin.
  3. Use format /fs:fat32 D: (replace D with whatever disk letter your SD card has been assigned by Windows).


The code opens a file object, starts serial comms and opens the stream to the SD card. There are lots of messages to explain what is going on - this is useful for debugging. In this demo version of the code I am just writing "this is the first line" and "this is the second line" to test that it works. In the final code I will write the data points from the displacement sensor. The code below is based on what I learnt watching this tutorial and this tutorial.

#include <SD.h>
#include <SPI.h>

// Define the file object
File myFile;

// Set the chip select pin
int pinCS = 10;

void setup() {
// Start the serial communication
pinMode(pinCS, OUTPUT);

// SD card init
if (SD.begin())
// Message
Serial.println("SD card is ready to go...");
} else
Serial.println("SD card initialisation failed.");
//Create the file
myFile = SD.open("data.txt", FILE_WRITE);

if (myFile) {
// Message
Serial.println("Writing to file...");
// Write to the file (data from sensor goes here)
myFile.println("This is the first line.");
myFile.println("This is the second line.");

// Close the file
// Message
else {
// Message
Serial.println("Error opening file.");

// Read the file
myFile = SD.open("data.txt");

if (myFile) {
// Message
Serial.println("Read from file:");
while (myFile.available()) {
} else {
// Message
Serial.println("Error reading file.");

void loop() {

Back to the top