Business Card + Clock + ATtiny3227 Dev Board

A business card with a charlieplexed realtime clock and an ATtiny3227 development board.

Similar projects worth following
A business card with contact info and QR Code, plus a charlieplexed realtime clock powered by a CR2016 coin cell with extremely low battery power consumption, it is also a complete ATtiny3227 development board with all the pins break-out.

Two years ago, I designed an NTP Clock (ESP8266-based) module and recently further improve it to extend the battery life from 45-days to 160-days, powered by a 1000-mAh LiPo battery.

I’ve been using Modern AVR chip (i.e. ATtiny 0-2 series, ATmega 0-series, and AVR Dx series) since its launch and like it very much for its easy to program, better feature sets and functionality, lower power consumption, and more memory than the Classes AVR chips (such as ATmega328), I created my own ATtiny3217 Development Board 4 years ago.

This project is a combination of the two projects, by replacing the power-hungry ESP-12 with a newer ATtiny3227, with PCB of a credit card/business card size, and the thickness of only 3.6mm (1mm PCB, plus the battery holder of a CR2016 of 2.6mm).


Adobe Portable Document Format - 109.12 kB - 06/01/2024 at 03:07



sheet - 12.71 kB - 05/31/2024 at 08:38


  • 1 × ATtiny3227
  • 1 × 32.768kHz Crystal
  • 2 × 18pF Capacitor
  • 1 × 1uF Capacitor
  • 1 × 100nF Capacitor

View all 12 components

  • One more thing...

    cheetah_henry06/16/2024 at 01:49 0 comments

    When I was doing the PCB design for the business card, I decided to create a derivative design based on the Business Card, so I created a wristwatch based on the Business Card design.

    The writstwatch shares the same firmware used in the business card project, it has the same BOM with the exception of the two buttons used and without the two 12-pin break-out connector. I found a 16mm-wide wrist belt from Aliexpress and bought a few of them with different colors.

    Since the wristwatch is not part of this contest, so I won't talk much about it here, and you can find the Kicad PCB design files from my tinyAVR-wristwatch repository.

    Have a nice Hackaday!

  • ATtiny3227 Development Board

    cheetah_henry06/16/2024 at 01:23 0 comments

    ATtiny 2-series

    ATtiny3227 as part of the ATtiny 2-series (sometime is also referred as tinyAVR 2-series) is released in the middle of global Covid-19 pandemic, the ATtiny 0 and 1-series were released a couple of years earlier. Don't be fool by the name of ATtiny, it is not the classic ATtiny products such as ATtiny 31 or ATtiny 85, it is actually more powerful than many classic ATmega products such as the ATmega328P used in the Arduino Uno/Nano. Ever since its launch, I likely it very much and had ever since phase-out all my Arduino Uno/Nano/Pro Micro since 2017 with ATtiny 1 and 2-series for all my 8-bit MCU projects.

    When using the board as an ATtiny3227 Development Board, it comes with the following peripherals and features

    • 32kB Program Memory (Flash)
    • 3kB RAM - 256 bytes data EEPROM
    • Capable of operating at 1.8 - 5.5v
    • Running at up to 20 MHz with internal clock
    • 6 channels Event System
    • Configurable Custom Logic (CCL)
    • Single pin UPDI programming interface
    • 12-bit Differential ADC with Programmable Gain Amplifier / 15-channel ADC (Single-ended)
    • 1 x Analog Comparator with internal DAC reference
    • 1 x 16-bit Timer/Counter type A (TCA)
    • 2 x 16-bit Timer/Counter type B (TCB)
    • 1 x 16-bit Real Time Counter (RTC) with Periodic Interrupt Controller (PIT)
    • 2 x USART
    • 1 x SPI
    • 1 x I2C

    Software development can be done with Microchip's MPLAB X IDE or Microchip Studio (Windows-only). It can be used as an Arduino by installing megaTinyCore to the Arduino IDE. Personally, I setup my own development environment with avrdude, VS Code and avr-gcc that I described in my blog.

    The ATtiny3227 requires a UPDI programmer for uploading code to the device. A SerialUPDI can be created using a USB-Serial Adaptor.

    Specifically to this Business Card board, when using it as an ATtiny3227 board, the Slider Switch SW3 allows to select the power source either from the 3V 2016 coin cell battery or from external power source via the Vin pin on the break-out connector. This allows user to connect a 1.8v, 3.3v or 5v power source and program the chip to run up to 20MHz through the setup of the fuse and the configuration of the prescaler in the CLKCTRL register.

    Bare metal programming

    So far what I shown in my software implementation are based on bare metal (i.e. directly access the registers in ATtiny3227) programming, the new ATtinys are easy to program, and I high recommend to read the Tech Brief AVR1000b: Getting Started Writing C code for AVR first. The section 3.1 of the ATtiny3227 Datasheet is a table called "I/O Multiplexing" which is kind of the pinmap of the MCU and probably the most-often-refer-to page for bare metal programming.

    Here is a blinky program when using the board as a ATtiny3227 development board, there is not much different from any blinky program, except that the SW3 should be switch to Vin and connect a 5v power source through the Vin pin on the break-out connector so that the board can be programmed to run at 20MHz. Remember to change the `F_CPU` value in Makefile as well as in .vscode/c_cpp_properties.json to `F_CPU=20000000UL` prior compiling the code if you choose to follow my development environment setup.

    As our board has 12 LEDs, any one of the LEDs can be used as the blinky LED, except that all the LEDs is part of the charlieplexing configuration, so it need to keep the unrelated charlieplexing pins "float" and only configure the two pins corresponding to the LED that you'd like to blink. The code shows the use of LED D12 as the blinky LED.

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include <stdio.h>
    #include <stdlib.h>
    #define BAUD_RATE 115200UL
    static int USART0_sendChar(char c, FILE *steam) {
        while (!(USART0.STATUS & USART_DREIF_bm)); // Wait if Data Register Empty Interrupt Flag is not set
        USART0.TXDATAL = c;
        return 0;
    static void USART0_init(uint32_t baud_rate) {
    Read more »

  • Final Assembly

    cheetah_henry06/12/2024 at 03:28 0 comments

    The PCB has arrived from PCBWay. It looks great with the black background.

    PCB Front

    PCB Component Side

    Since the VQFN package of ATtiny3227 is only 4 x 4 mm, so I ordered the stencil. The final assembly looks great. PCB thickness measurement shows that it is 3.2mm at the battery holder and 3.4mm at the break-out connector side.

    PCB after assembly

    PCB Thickness Measure

    Everything work fine, this including the software as well as the hardware design.  Here is a gif of the clock showing time at 4:39

    and at 4:45

    The project is very much completed by now. I think that I will add one or two logs later on how I setup the toolchain and provide a couple of demonstration on how to use the business card as a ATtiny3227 development board.

  • Software

    cheetah_henry06/09/2024 at 08:59 0 comments

    While waiting for the PCB, it is time to write some actual code for the clock.

    As I've explained the ATtiny3227 Power Down mode and the configuration of RTC, so I won't explain it again, I will focus on the rest of the design.


    Charlieplexing is a multiplexing technique that able to drive n2 - n LEDs with only n GPIO pins, that is, only 4 GPIO pin are required to drive 42 - 4 = 12 LEDs. In the schematic, the LED assignment correspond to the postion of the LED on the clock face, LED D12 is designated as 0, and the PORTB, PIN4-7 of the ATtiny3227 are used as the driving pins for the LED matrix. Charlieplexing is also known as tristate multiplexing, at any giving time, only one LED is light-up based on the states of the driving pins, for example, in order to turn on LED D1, a positive voltage is apply to PB4 and a zero (ground) need to be asserted at PB5, PB6 and PB7 would have to be "disconnected" by putting it in tri-state/high impedence mode. For microcontroller, we could turn those pins to "input" mode which effectively put those pins in high impedence mode.

    In software, this is achieve by defining an array of LED matrix, each consists of two states for `pinConfig` and `pinState`. The `pinConfig` represents the value on which the pin should be configured as INPUT or OUTPUT, the 'pinState' decided on whether the pin should be set to HIGH or LOW. The `mux[LEDS]` contains both the values of `pinConfig` and `pinState` for each LED. For example, to turn on the LED D1 as we previously mentioned, the mux[1] have a value of `{0x30, 0x10}` which when expands to binary would look like `{B00110000, B00010000}` with the MSB represents PB7 and LSB represents PB0. We only care for the upper 4-bits that represents PB7 - PB4. What this means is that for the `pinConfig` value of `B00110000`, both PB4 and PB5 would be set as OUTPUT, PB6 and PB7 would be set to INPUT. The `pinState` of `B00010000` means that only PB4 is set to HIGH, which based on the schematic would turn on the LED D1 and the rest of the LEDs would be off. That's what the `turnOnLED()` function do. To turn off all the LEDs, it is simple, just set all the pins to INPUT mode with the `turnOffLED()`.

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #define LEDS                12
    const uint32_t DISPLAY_TIME = 5000;  // 5000ms
    // Charlieplexing configuration and state matrix
    typedef struct {
      uint8_t pinConfig;
      uint8_t pinState;
    } Mux_t;
    const Mux_t mux[LEDS] = {
      {0x90, 0x80}, // 0
      {0x30, 0x10}, // 1
      {0x30, 0x20}, // 2
      {0x60, 0x20}, // 3
      {0x60, 0x40}, // 4
      {0xc0, 0x40}, // 5
      {0xc0, 0x80}, // 6
      {0x50, 0x10}, // 7
      {0x50, 0x40}, // 8
      {0xA0, 0x20}, // 9
      {0xA0, 0x80}, // 10
      {0x90, 0x10}  // 11
    void turnOnLED(uint8_t led) {
      // enable input buffer
      PORTB.PIN4CTRL = 0;
      PORTB.PIN5CTRL = 0;
      PORTB.PIN6CTRL = 0;
      PORTB.PIN7CTRL = 0;
      // rest all pins to input and set it to low
      PORTB.DIRCLR = (PIN4_bm | PIN5_bm | PIN6_bm | PIN7_bm);
      PORTB.OUTCLR = (PIN4_bm | PIN5_bm | PIN6_bm | PIN7_bm);
      // set pin(s) based on mux.pinConfig and mux.pinState value
      PORTB.DIRSET = mux[led].pinConfig;
      PORTB.OUTSET = mux[led].pinState;
    int main() {
      _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_4X_gc)); // set prescaler to 4 for running at 5MHz
      SLPCTRL.CTRLA |= SLPCTRL_SMODE_PDOWN_gc;    // config sleep controller to PowerDown mode 
      while(1) {
        uint16_t seconds = timeCount;
        uint8_t hours = (seconds / 3600) % 12;
        uint8_t minutes = (seconds / 60) % 60;
        uint8_t fiveMinuteInterval = (minutes / 5) % 12;
        uint8_t flashes = minutes % 5;
        flashLED(fiveMinuteInterval, flashes);
      return 0;

    So as each of the LED represents the hour of the current time, by passing an value of the `hours` to the function `turnOnLED(hours)` would turn on the LED correspondent to the current hour.
    Each LED on the clock face will also repsent the five-minute interval past the hour (e.g. LED...

    Read more »

  • PCB Design Completed

    cheetah_henry06/01/2024 at 06:36 0 comments

    Finished the PCB design. The 3D rendering looks good. Sent to PCBWay for fabrication today. The Kicad design files are now available at my GitHub.

    PCB 3D render (Name Card side)

    PCB 3D render (Component side)

    PCB 3D render (Thickness 3.2mm in total)

  • Hardware

    cheetah_henry05/31/2024 at 09:17 0 comments

    The schematic is quite similar to my  NTP Clock project, consists of 12-LED with charlieplexing, minus the charging circuit, and replace the power hungry ESP8266 with an ATtiny3227 tinyAVR 2-series MCU, with all the pins break-out.

    I setup a test environment which consists of an ATtiny3227 development board, and external 32.768kHz crystal oscillator, and 12 LEDS (I don't have sufficient red LEDs, so the test setup consists of 6 red LEDs and 6 green LEDs).

    I will further explain the hardware design in later logs whenever appropriate when discussing any design considerations. For now, I will talk about the BOM cost and the ATtiny3227 Power Down Mode and the tests that I have done in order to determine the battery life for the Business Card.


    The BOM cost is calculated based on sourcing from DigiKey since they are the sponsor of the 2024 Business Card Challenge contest, with the exception of a couple of components. The SPDT switch and the CR2016 battery holder are based on a component that that I already have with me that were sourced from LCSC, similar part can be found in DigiKey but the footprint might not be 100% align with the parts that I have. Two SMD 1x12 Connector Female Socket are also based on LCSC price as I can't find the identical part from DigiKey. Maybe I didn't find harder enough. The total BOM cost is around $8 including CR2016 as well as an estimated PCB fabrication cost/piece. The cost of PCB is estimated based on PCBWay's  fabrication costs of $5 for 10 pcs, so each piece is at $0.5 and used as the BOM cost.

    ATtiny3227 Power Down Mode

    Before creating PCB or writing software, it is important to understand the power consumption of the circuitry at both active mode and sleep mode, and confirm some of the assumptions that I made in battery life as I planned to use CR2016 which only has the capacity of 98mAh. The bigger battery CR2032 would have a bigger capacity of 235mAh, but the thickness increased. I want to have the business card with slim profile, CR2016 with the battery holder will have a thickness of 2.2mm as compare to the CR2032 one of 3.6mm, without including the PCB thickness which will add another 1mm. 

    The first thing I did is to determine the system clock speed that I should used for the design. For Modern AVR chips (Refer to ATtiny 0, 1 and 2-series, ATmega 0-series, and AVR Dx series), all clocks are active in active mode, and the CPU is running. Power consumption in active mode is proportional to the operating frequency of the system clock. As the charlieplexing clock does not demand high-frequency operation, and therefor can benefit from lowering the system clock.

    The ATtiny3227 (this applies to the entire ATtiny 0, 1 and 2-series) can operate at 20MHz with a Low-Power internal oscillator without the need for external crystal. This oscillator can operate at multiple frequencies, selected by the value of the Frequency Select bits (FREQSEL) in the Oscillator Configuration Fuse (FUSE.OSCCFG). So I configure the clock to run at 20MHz, 10MHz and 5MHz and write a simple program to test the current consumption at ative mode.

    In order to simulate the usage of the actual application, I config the RTC to wake up on every second to increment the `timeCount` which is going to be used for keeping the time in seconds. In order to make sure that the configuration of the RTC work as expected, I initially also config the PORTA PIN7 (which has an LED attached to it on the ATtiny3227 development board) so that it will toggle the LED on every wake-up, once I know the RTC is working, I then comment out the PORTA configuration so that I can measure the current without affecting by the LED blinking.

    #include <avr/io.h>
    #include <avr/interrupt.h>
    volatile uint32_t timeCount = 0;
    ISR (RTC_PIT_vect) { 
      timeCount = (timeCount + 1) % 43200; // count up to 12-hour (12 * 3600) = 43200
      // PORTA.OUTTGL = PIN7_bm;
      RTC.PITINTFLAGS = RTC_PI_bm; // Clear periodic interrupt flag
    Read more »

  • Project Concept

    cheetah_henry05/28/2024 at 02:27 0 comments

    Planned Features

    • Business with contact information and QRCode for website
    • Credit card size of 85.5x54mm
    • 3.2mm thickness including 1mm PCB
    • It is a clock/watch with 12 Charlieplexing LEDs
    • It is also a ATtiny3227 development board with all the pins (22-GPIO pins) break-out. Programmable with megaTinyCore as an Arduino or with bare metal with just VSCode and avrdude. 
    • Powered by a CR2016 coin cell battery (98mAh)
    • Designed for low-power with battery life for year(s).
    • Cheap to produce, target BOM cost of less than $10.

View all 7 project logs

Enjoy this project?



Dan Schnur wrote 06/13/2024 at 02:14 point

Nice idea!   Have you thought of using reverse mount SMD led's and having the clock show on front of the card?   That'd enable you to keep it thin, but have the clock show in a more minimalist way...

  Are you sure? yes | no

cheetah_henry wrote 06/13/2024 at 03:32 point

That would be a nice enhancement/improvement. I didn't know there is such  reverse-mould LED available. 

  Are you sure? yes | no

Dan Schnur wrote 06/13/2024 at 22:47 point

On the last similar project I did, I used 1206 LED's and designed the board with slots behind each one.  After that, I noticed the reverse molded ones and have been looking for an excuse to use them since then.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates